Version 2.14.0-377.1.beta

Merge '2.14.0-377.0.dev' into beta
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 204df98..faad814 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2021-07-02T15:48:57.033703",
+  "generated": "2021-07-27T19:27:52.638315",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -64,7 +64,7 @@
       "name": "_js_interop_checks",
       "rootUri": "../pkg/_js_interop_checks",
       "packageUri": "lib/",
-      "languageVersion": "2.7"
+      "languageVersion": "2.12"
     },
     {
       "name": "analysis_server",
@@ -142,13 +142,13 @@
       "name": "browser_launcher",
       "rootUri": "../third_party/pkg/browser_launcher",
       "packageUri": "lib/",
-      "languageVersion": "2.2"
+      "languageVersion": "2.12"
     },
     {
       "name": "build_integration",
       "rootUri": "../pkg/build_integration",
       "packageUri": "lib/",
-      "languageVersion": "2.1"
+      "languageVersion": "2.12"
     },
     {
       "name": "charcode",
@@ -250,7 +250,7 @@
       "name": "dev_compiler",
       "rootUri": "../pkg/dev_compiler",
       "packageUri": "lib/",
-      "languageVersion": "2.3"
+      "languageVersion": "2.12"
     },
     {
       "name": "devtools_shared",
@@ -354,12 +354,6 @@
       "languageVersion": "2.12"
     },
     {
-      "name": "http_retry",
-      "rootUri": "../third_party/pkg/http_retry",
-      "packageUri": "lib/",
-      "languageVersion": "2.12"
-    },
-    {
       "name": "http_throttle",
       "rootUri": "../third_party/pkg/http_throttle",
       "packageUri": "lib/",
@@ -731,13 +725,13 @@
       "name": "testing",
       "rootUri": "../pkg/testing",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.12"
     },
     {
       "name": "typed_data",
       "rootUri": "../third_party/pkg/typed_data",
       "packageUri": "lib/",
-      "languageVersion": "2.10"
+      "languageVersion": "2.12"
     },
     {
       "name": "usage",
@@ -755,7 +749,7 @@
       "name": "vm",
       "rootUri": "../pkg/vm",
       "packageUri": "lib/",
-      "languageVersion": "2.7"
+      "languageVersion": "2.12"
     },
     {
       "name": "vm_service",
@@ -797,7 +791,7 @@
       "name": "webkit_inspection_protocol",
       "rootUri": "../third_party/pkg/webkit_inspection_protocol",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.12"
     },
     {
       "name": "yaml",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed07841..b1dcdb8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -159,8 +159,26 @@
 
 #### Linter
 
-Updated the Linter to `1.7.0`, which includes changes that
+Updated the Linter to `1.8.0`, which includes changes that
 
+
+- improve performance for `prefer_is_not_empty`.
+- fix false positives in `no_logic_in_create_state`.
+- improve `package_names` to allow dart identifiers as package names.
+- fix a false-positive in `package_names` (causing keywords to wrongly get flagged).
+- fix `avoid_classes_with_only_static_member` to check for inherited members and also
+  flag classes with only methods.
+- fix `curly_braces_in_flow_control_structures` to properly flag terminating `else-if`
+  blocks.
+- improve `always_specify_types` to support type aliases.
+- fix a false positive in `unnecessary_string_interpolations` w/ nullable interpolated 
+  strings
+- fix a false positive in `avoid_function_literals_in_foreach_calls` for nullable
+  iterables.
+- fix false positives in `avoid_returning_null` w/ NNBD
+- fix false positives in `use_late_for_private_fields_and_variables` in the presence
+  of const constructors.
+- adds a new lint: `eol_at_end_of_file`.
 - fix case-sensitive false positive in `use_full_hex_values_for_flutter_colors`.
 - improve try-block and switch statement flow analysis for
   `use_build_context_synchronously`.
@@ -246,50 +264,15 @@
 [#46545]: https://github.com/dart-lang/sdk/issues/46545
 [1]: https://dart.dev/faq#q-what-browsers-do-you-support-as-javascript-compilation-targets
 
-### Language
+#### Dart Dev Compiler (DDC)
 
-*   Add an unsigned shift right operator `>>>`. Pad with zeroes, ignoring the
-    sign bit. On the web platform `int.>>>` shifts the low 32 bits interpreted
-    as an unsigned integer, so `a >>> b` gives the same result as
-    `a.toUnsigned(32) >>> b` on the VM.
+- **Breaking Change** [#44154][]: Subtyping relations of `package:js` classes
+  have been changed to be more correct and consistent with Dart2JS.
+  Like `anonymous` classes, non-`anonymous` classes will no longer check the
+  underlying type in DDC. The internal type representation of these objects have
+  changed as well, which will affect the `toString` value of these types.
 
-*   Prior to Dart 2.14, metadata (annotations) were not permitted to be
-    specified with generic type arguments.  This restriction is lifted in Dart
-    Dart 2.14.
-
-    ```dart
-    class C<T> {
-      const C();
-    }
-    @C();      // Previously permitted.
-    @C<int>(); // Previously an error, now permitted.
-    ```
-
-*   Prior to Dart 2.14, generic function types were not permitted as arguments
-    to generic classes or functions, nor to be used as generic bounds.  This
-    restriction is lifted in Dart 2.14.
-
-    ```dart
-    T wrapWithLogging<T>(T f) {
-      if (f is void Function<T>(T x)) {
-        return <S>(S x) {
-          print("Call: f<$S>($x)");
-          var r = f<S>(x);
-          print("Return: $x");
-          return r;
-        } as T;
-      } // More cases here
-      return f;
-    }
-    void foo<T>(T x) {
-      print("Foo!");
-    }
-    void main() {
-      // Previously an error, now permitted.
-      var f = wrapWithLogging<void Function<T>(T)>(foo);
-      f<int>(3);
-    }
-    ```
+[#44154]: https://github.com/dart-lang/sdk/issues/44154
 
 ## 2.13.4 - 2021-06-28
 
diff --git a/DEPS b/DEPS
index ac49b8f..613addf 100644
--- a/DEPS
+++ b/DEPS
@@ -39,7 +39,7 @@
 
   # Checked-in SDK version. The checked-in SDK is a Dart SDK distribution in a
   # cipd package used to run Dart scripts in the build and test infrastructure.
-  "sdk_tag": "version:2.13.1",
+  "sdk_tag": "version:2.14.0-293.0.dev",
 
   # 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
@@ -72,22 +72,22 @@
   "gperftools_revision": "180bfa10d7cb38e8b3784d60943d50e8fcef0dcb",
 
   # Revisions of /third_party/* dependencies.
-  "args_rev": "d8fea36c10ef96797be02e3d132d572445cd86f4",
-  "async_rev": "8193eac211905cf33ae1f514022fdbd843836be5",
+  "args_rev": "bf4c8796881b62fd5d3f6d86ab43014f9651eb20",
+  "async_rev": "25a7e2ec39c03622b86918cb9ce3e7d00dd283d1",
   "bazel_worker_rev": "0885637b037979afbf5bcd05fd748b309fd669c0",
   "benchmark_harness_rev": "c546dbd9f639f75cd2f75de8df2eb9f8ea15e8e7",
   "boolean_selector_rev": "665e6921ab246569420376f827bff4585dff0b14",
   "boringssl_gen_rev": "7322fc15cc065d8d2957fccce6b62a509dc4d641",
   "boringssl_rev" : "1607f54fed72c6589d560254626909a64124f091",
   "browser-compat-data_tag": "v1.0.22",
-  "browser_launcher_rev": "12ab9f351a44ac803de9bc17bb2180bb312a9dd7",
+  "browser_launcher_rev": "c6cc1025d6901926cf022e144ba109677e3548f1",
   "charcode_rev": "84ea427711e24abf3b832923959caa7dd9a8514b",
   "chrome_rev" : "19997",
   "cli_util_rev" : "8c504de5deb08fe32ecf51f9662bb37d8c708e57",
   "clock_rev" : "a494269254ba978e7ef8f192c5f7fec3fc05b9d3",
   "collection_rev": "75a7a5510979a3cd70143af85bcc1667ee233674",
-  "convert_rev": "413f591577419d8a8b95d445094a82c926650bd1",
-  "crypto_rev": "1c8ccc07b83b100216dc6dede767371043385648",
+  "convert_rev": "e063fdca4bebffecbb5e6aa5525995120982d9ce",
+  "crypto_rev": "b5024e4de2b1c474dd558bef593ddbf0bfade152",
   "csslib_rev": "e411d862fd8cc50415c1badf2632e017373b3f47",
   "dart2js_info_rev" : "e0acfeb5affdf94c53067e68bd836adf589628fd",
 
@@ -103,7 +103,7 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_rev": "9d9dff90d9a2e0793ad2f795f36c2777f720eda0",
+  "dart_style_rev": "06bfd19593ed84dd288f67e02c6a753e6516288a",
 
   "dartdoc_rev" : "c9621b92c738ec21a348cc2de032858276e9c774",
   "devtools_rev" : "64cffbed6366329ad05e44d48fa2298367643bb6",
@@ -115,38 +115,37 @@
   "html_rev": "00cd3c22dac0e68e6ed9e7e4945101aedb1b3109",
   "http_io_rev": "2fa188caf7937e313026557713f7feffedd4978b",
   "http_multi_server_rev": "de1b312164c24a1690b46c6e97bd47eff40c4649",
-  "http_parser_rev": "7720bfd42a0c096734c5213478fdce92c62f0293",
-  "http_retry_rev": "845771af7bb5ab38ab740ce4a31f3b0c7680302b",
-  "http_rev": "f93c76fabdb03963303762e3fe16cbdf60799cff",
+  "http_parser_rev": "202391286ddc13c4c3c284ac5b511f04697250ed",
+  "http_rev": "778174bca2c13becd88ef3353309190b1e8b9479",
   "http_throttle_tag" : "1.0.2",
   "icu_rev" : "81d656878ec611cb0b42d52c82e9dae93920d9ba",
   "idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
   "intl_tag": "0.17.0-nullsafety",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_rev": "7e00f893440a72de0637970325e4ea44bd1e8c8e",
-  "linter_tag": "422981ffb2fbd4010aa52381676cf745e2844dd9",
+  "linter_tag": "1.8.0",
   "lints_tag": "f9670df2a66e0ec12eb51554e70c1cbf56c8f5d0",
-  "logging_rev": "e2f633b543ef89c54688554b15ca3d7e425b86a2",
+  "logging_rev": "575781ef196e4fed4fb737e38fb4b73d62727187",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_rev": "9c4beaac96d8f008078e00b027915f81b665d2de",
-  "matcher_rev": "1f7b6f0cb15eb6659a1de0513571575a5c8a51d0",
+  "matcher_rev": "b411b22ec2437ba206c7a3006bbaeb519bd343d1",
   "mime_rev": "c931f4bed87221beaece356494b43731445ce7b8",
   "mockito_rev": "d39ac507483b9891165e422ec98d9fb480037c8b",
   "oauth2_rev": "7cd3284049fe5badbec9f2bea2afc41d14c01057",
   "package_config_rev": "a84c0d45401f215fbe9384df923a38f4022a3c45",
-  "path_rev": "407ab76187fade41c31e39c745b39661b710106c",
+  "path_rev": "c20d73c3516d3a0061c90f14b761ff532b9bf707",
   "pedantic_rev": "66f2f6c27581c7936482e83be80b27be2719901c",
   "platform_rev": "c20e6fa315e9f8820e51c0ae721f63aff33b8e17",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
   "process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
-  "protobuf_rev": "0d03fd588df69e9863e2a2efc0059dee8f18d5b2",
-  "pub_rev": "d159e5b9f04a7e4826b6afea7b3364d48aa0dad8",
+  "protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
+  "pub_rev": "70b1a4f9229a36bac6340ec7eae2b2068baac96c",
   "pub_semver_rev": "f50d80ef10c4b2fa5f4c8878036a4d9342c0cc82",
   "resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
   "root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
   "rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
-  "shelf_static_rev": "fb6b7d0ee4ad936a84e503ae6b3703cc99e61d52",
+  "shelf_static_rev": "202ec1a53c9a830c17cf3b718d089cf7eba568ad",
   "shelf_packages_handler_rev": "78302e67c035047e6348e692b0c1182131f0fe35",
   "shelf_proxy_tag": "v1.0.0",
   "shelf_rev": "46483f896cc4308ee3d8e997030ae799b72aa16a",
@@ -164,8 +163,8 @@
   "test_process_tag": "2.0.0",
   "term_glyph_rev": "6a0f9b6fb645ba75e7a00a4e20072678327a0347",
   "test_reflective_loader_rev": "54e930a11c372683792e22bddad79197728c91ce",
-  "test_rev": "030816c32b6fe78d5fb7653afbd9f63cca18bacf",
-  "typed_data_tag": "f94fc57b8e8c0e4fe4ff6cfd8290b94af52d3719",
+  "test_rev": "099dcc4d052a30c6921489cfbefa1c8531d12975",
+  "typed_data_rev": "29ce5a92b03326d0b8035916ac04f528874994bd",
   "usage_rev": "e0780cd8b2f8af69a28dc52678ffe8492da27d06",
   "vector_math_rev": "0c9f5d68c047813a6dcdeb88ba7a42daddf25025",
   "watcher_rev": "3924194385fb215cef483193ed2879a618a3d69c",
@@ -174,7 +173,7 @@
   "web_socket_channel_rev": "6448ce532445a8a458fa191d9346df071ae0acad",
   "WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
   "webdev_rev": "b0aae7b6944d484722e6af164abedd864a2a0afa",
-  "webkit_inspection_protocol_rev": "6b15729292d030f2e5c5861022da4c5a4c11961c",
+  "webkit_inspection_protocol_rev": "dd6fb5d8b536e19cedb384d0bbf1f5631923f1e8",
   "yaml_rev": "b4c4411631bda556ce9a45af1ab0eecaf9f3ac53",
   "zlib_rev": "bf44340d1b6be1af8950bbdf664fec0cf5a831cc",
   "crashpad_rev": "bf327d8ceb6a669607b0dbab5a83a275d03f99ed",
@@ -370,9 +369,6 @@
       "@" + Var("http_multi_server_rev"),
   Var("dart_root") + "/third_party/pkg/http_parser":
       Var("dart_git") + "http_parser.git" + "@" + Var("http_parser_rev"),
-  Var("dart_root") + "/third_party/pkg/http_retry":
-      Var("dart_git") + "http_retry.git" +
-      "@" + Var("http_retry_rev"),
   Var("dart_root") + "/third_party/pkg/http_throttle":
       Var("dart_git") + "http_throttle.git" +
       "@" + Var("http_throttle_tag"),
@@ -460,7 +456,7 @@
       Var("dart_git") + "test_reflective_loader.git" +
       "@" + Var("test_reflective_loader_rev"),
   Var("dart_root") + "/third_party/pkg/typed_data":
-      Var("dart_git") + "typed_data.git" + "@" + Var("typed_data_tag"),
+      Var("dart_git") + "typed_data.git" + "@" + Var("typed_data_rev"),
   Var("dart_root") + "/third_party/pkg/usage":
       Var("dart_git") + "usage.git" + "@" + Var("usage_rev"),
   Var("dart_root") + "/third_party/pkg/vector_math":
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 7687b1d..ec4e5d2 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -109,14 +109,14 @@
     utils = imp.load_source('utils',
                             os.path.join(local_root, 'tools', 'utils.py'))
 
-    prebuilt_dartfmt = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dartfmt')
+    dart = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dart')
 
     windows = utils.GuessOS() == 'win32'
     if windows:
-        prebuilt_dartfmt += '.bat'
+        dart += '.exe'
 
-    if not os.path.isfile(prebuilt_dartfmt):
-        print('WARNING: dartfmt not found: %s' % (prebuilt_dartfmt))
+    if not os.path.isfile(dart):
+        print('WARNING: dart not found: %s' % (dart))
         return []
 
     def HasFormatErrors(filename=None, contents=None):
@@ -129,13 +129,17 @@
                 if '//#' in contents:
                     return False
 
-        args = [prebuilt_dartfmt, '--set-exit-if-changed']
-        if not contents:
-            args += [filename, '-n']
+        args = [
+            dart,
+            'format',
+            '--set-exit-if-changed',
+            '--output=none',
+            '--summary=none',
+            filename,
+        ]
 
         process = subprocess.Popen(
             args, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
-        process.communicate(input=contents)
 
         # Check for exit code 1 explicitly to distinguish it from a syntax error
         # in the file (exit code 65). The repo contains many Dart files that are
@@ -143,7 +147,7 @@
         # parsed and formatted. Don't treat those as errors.
         return process.returncode == 1
 
-    unformatted_files = _CheckFormat(input_api, "dartfmt", ".dart", windows,
+    unformatted_files = _CheckFormat(input_api, "dart format", ".dart", windows,
                                      HasFormatErrors)
 
     if unformatted_files:
diff --git a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
index 1130ac6..ece1bcc 100644
--- a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
@@ -34,8 +34,13 @@
 ];
 
 Future<void> reportArtifactSize(String path, String name) async {
-  final size = await File(path).length();
-  print('SDKArtifactSizes.$name(CodeSize): $size');
+  try {
+    final size = await File(path).length();
+    print('SDKArtifactSizes.$name(CodeSize): $size');
+  } on FileSystemException {
+    // Report dummy data for artifacts that don't exist for specific platforms.
+    print('SDKArtifactSizes.$name(CodeSize): 0');
+  }
 }
 
 Future<void> main() async {
diff --git a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
index 1130ac6..ece1bcc 100644
--- a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
@@ -34,8 +34,13 @@
 ];
 
 Future<void> reportArtifactSize(String path, String name) async {
-  final size = await File(path).length();
-  print('SDKArtifactSizes.$name(CodeSize): $size');
+  try {
+    final size = await File(path).length();
+    print('SDKArtifactSizes.$name(CodeSize): $size');
+  } on FileSystemException {
+    // Report dummy data for artifacts that don't exist for specific platforms.
+    print('SDKArtifactSizes.$name(CodeSize): 0');
+  }
 }
 
 Future<void> main() async {
diff --git a/benchmarks/SendPort/dart/SendPort.dart b/benchmarks/SendPort/dart/SendPort.dart
index a6e6044..fb950b5 100644
--- a/benchmarks/SendPort/dart/SendPort.dart
+++ b/benchmarks/SendPort/dart/SendPort.dart
@@ -175,8 +175,11 @@
 }
 
 class TreeNode {
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final TreeNode? left;
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final TreeNode? right;
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final int value;
 
   TreeNode(this.left, this.right, this.value);
diff --git a/benchmarks/SendPort/dart2/SendPort.dart b/benchmarks/SendPort/dart2/SendPort.dart
index 01d4042..a97acf3 100644
--- a/benchmarks/SendPort/dart2/SendPort.dart
+++ b/benchmarks/SendPort/dart2/SendPort.dart
@@ -177,8 +177,11 @@
 }
 
 class TreeNode {
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final TreeNode left;
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final TreeNode right;
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final int value;
 
   TreeNode(this.left, this.right, this.value);
diff --git a/build/dart/dart_action.gni b/build/dart/dart_action.gni
index c357aad..334a09a 100644
--- a/build/dart/dart_action.gni
+++ b/build/dart/dart_action.gni
@@ -51,6 +51,10 @@
       testonly = invoker.testonly
     }
 
+    if (defined(invoker.pool)) {
+      pool = invoker.pool
+    }
+
     script = "$_dart_root/build/gn_run_binary.py"
 
     if (defined(invoker.inputs)) {
@@ -109,6 +113,7 @@
                              "depfile",
                              "deps",
                              "outputs",
+                             "pool",
                              "testonly",
                              "visibility",
                            ])
@@ -256,6 +261,7 @@
                              "deps",
                              "inputs",
                              "outputs",
+                             "pool",
                              "tool",
                              "testonly",
                              "visibility",
@@ -321,6 +327,7 @@
                                "inputs",
                                "outputs",
                                "packages",
+                               "pool",
                                "script",
                                "testonly",
                                "tool",
@@ -380,6 +387,7 @@
                                "inputs",
                                "outputs",
                                "packages",
+                               "pool",
                                "testonly",
                                "tool",
                                "visibility",
diff --git a/build/fuchsia/dart.cmx b/build/fuchsia/dart.cmx
index d57d9ac..0bd0e668 100644
--- a/build/fuchsia/dart.cmx
+++ b/build/fuchsia/dart.cmx
@@ -1,27 +1,28 @@
 {
-  "program": {
-    "binary": "exe.stripped/dart"
-  },
-  "sandbox": {
-    "features": [
-      "config-data",
-      "deprecated-ambient-replace-as-executable",
-      "root-ssl-certificates",
-      "isolated-cache-storage",
-      "isolated-persistent-storage",
-      "isolated-temp"
-    ],
-    "services": [
-      "fuchsia.deprecatedtimezone.Timezone",
-      "fuchsia.device.NameProvider",
-      "fuchsia.feedback.CrashReporter",
-      "fuchsia.intl.PropertyProvider",
-      "fuchsia.logger.LogSink",
-      "fuchsia.net.NameLookup",
-      "fuchsia.posix.socket.Provider",
-      "fuchsia.sysmem.Allocator",
-      "fuchsia.timezone.Timezone",
-      "fuchsia.tracing.provider.Registry"
-    ]
-  }
+    "program": {
+        "binary": "exe.stripped/dart"
+    },
+    "sandbox": {
+        "features": [
+            "config-data",
+            "deprecated-ambient-replace-as-executable",
+            "isolated-cache-storage",
+            "isolated-persistent-storage",
+            "isolated-temp",
+            "root-ssl-certificates"
+        ],
+        "services": [
+            "fuchsia.deprecatedtimezone.Timezone",
+            "fuchsia.device.NameProvider",
+            "fuchsia.feedback.CrashReporter",
+            "fuchsia.intl.PropertyProvider",
+            "fuchsia.logger.LogSink",
+            "fuchsia.net.NameLookup",
+            "fuchsia.net.name.Lookup",
+            "fuchsia.posix.socket.Provider",
+            "fuchsia.sysmem.Allocator",
+            "fuchsia.timezone.Timezone",
+            "fuchsia.tracing.provider.Registry"
+        ]
+    }
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
index 7299a94..ca0f816 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
@@ -279,7 +279,7 @@
       this.severity, this.uri, this.involvedFiles, this.codeName);
 
   factory DiagnosticMessageFromJson.fromJson(String jsonString) {
-    Map<String, Object> decoded = json.decode(jsonString);
+    Map<String, Object?> decoded = json.decode(jsonString);
     List<String> ansiFormatted =
         new List<String>.from(_asListOfString(decoded["ansiFormatted"]));
     List<String> plainTextFormatted =
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 289ec96..01dd119 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -1328,6 +1328,25 @@
         r"""Extension operations can't be used in constant expressions.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalExternalConstructor =
+    messageConstEvalExternalConstructor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalExternalConstructor = const MessageCode(
+    "ConstEvalExternalConstructor",
+    message:
+        r"""External constructors can't be evaluated in constant expressions.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalExternalFactory = messageConstEvalExternalFactory;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalExternalFactory = const MessageCode(
+    "ConstEvalExternalFactory",
+    message:
+        r"""External factory constructors can't be evaluated in constant expressions.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeConstEvalFailedAssertion = messageConstEvalFailedAssertion;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3992,6 +4011,16 @@
     message: r"""FFI leaf call must not have Handle argument types.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFfiNativeAnnotationMustAnnotateStatic =
+    messageFfiNativeAnnotationMustAnnotateStatic;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFfiNativeAnnotationMustAnnotateStatic =
+    const MessageCode("FfiNativeAnnotationMustAnnotateStatic",
+        message:
+            r"""FfiNative annotations can only be used on static functions.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(String name)> templateFfiNotStatic = const Template<
         Message Function(String name)>(
@@ -6208,6 +6237,18 @@
         message: r"""This is the enclosing class.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeJsInteropExternalExtensionMemberOnTypeInvalid =
+    messageJsInteropExternalExtensionMemberOnTypeInvalid;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageJsInteropExternalExtensionMemberOnTypeInvalid =
+    const MessageCode("JsInteropExternalExtensionMemberOnTypeInvalid",
+        message:
+            r"""JS interop or Native class required for 'external' extension members.""",
+        tip:
+            r"""Try adding a JS interop annotation to the on type class of the extension.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeJsInteropExternalMemberNotJSAnnotated =
     messageJsInteropExternalMemberNotJSAnnotated;
 
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 0688ab2..71472cc 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -5160,7 +5160,10 @@
         // For example a(b)..<T>(c), where token is '<'.
         token = typeArg.parseArguments(token, this);
         next = token.next!;
-        assert(optional('(', next));
+        if (!optional('(', next)) {
+          listener.handleTypeArgumentApplication(token.next!);
+          typeArg = noTypeParamOrArg;
+        }
       }
       TokenType nextType = next.type;
       if (identical(nextType, TokenType.INDEX)) {
@@ -5307,7 +5310,10 @@
             listener.handleNonNullAssertExpression(bangToken);
           }
           token = typeArg.parseArguments(bangToken, this);
-          assert(optional('(', token.next!));
+          if (!optional('(', token.next!)) {
+            listener.handleTypeArgumentApplication(bangToken.next!);
+            typeArg = noTypeParamOrArg;
+          }
         }
         next = token.next!;
       } else if (optional('(', next)) {
@@ -5327,7 +5333,10 @@
             listener.handleNonNullAssertExpression(bangToken);
           }
           token = typeArg.parseArguments(bangToken, this);
-          assert(optional('(', token.next!));
+          if (!optional('(', token.next!)) {
+            listener.handleTypeArgumentApplication(bangToken.next!);
+            typeArg = noTypeParamOrArg;
+          }
         }
         next = token.next!;
       } else {
diff --git a/pkg/_js_interop_checks/lib/js_interop_checks.dart b/pkg/_js_interop_checks/lib/js_interop_checks.dart
index 4f3ba97..975fca7 100644
--- a/pkg/_js_interop_checks/lib/js_interop_checks.dart
+++ b/pkg/_js_interop_checks/lib/js_interop_checks.dart
@@ -12,6 +12,7 @@
         messageJsInteropAnonymousFactoryPositionalParameters,
         messageJsInteropEnclosingClassJSAnnotation,
         messageJsInteropEnclosingClassJSAnnotationContext,
+        messageJsInteropExternalExtensionMemberOnTypeInvalid,
         messageJsInteropExternalMemberNotJSAnnotated,
         messageJsInteropIndexNotSupported,
         messageJsInteropNamedParameters,
@@ -30,6 +31,7 @@
   bool _classHasJSAnnotation = false;
   bool _classHasAnonymousAnnotation = false;
   bool _libraryHasJSAnnotation = false;
+  Map<Reference, Extension>? _libraryExtensionsIndex;
 
   /// Libraries that use `external` to exclude from checks on external.
   static final Iterable<String> _pathsWithAllowedDartExternalUsage = <String>[
@@ -86,7 +88,8 @@
 
   @override
   void defaultMember(Member member) {
-    _checkJSInteropAnnotation(member);
+    _checkInstanceMemberJSAnnotation(member);
+    if (!_isJSInteropMember(member)) _checkDisallowedExternal(member);
     // TODO(43530): Disallow having JS interop annotations on non-external
     // members (class members or otherwise). Currently, they're being ignored.
     super.defaultMember(member);
@@ -105,14 +108,14 @@
                 cls.name, superclass.name),
             cls.fileOffset,
             cls.name.length,
-            cls.location.file);
+            cls.fileUri);
       } else if (!_classHasJSAnnotation && superHasJSAnnotation) {
         _diagnosticsReporter.report(
             templateJsInteropDartClassExtendsJSClass.withArguments(
                 cls.name, superclass.name),
             cls.fileOffset,
             cls.name.length,
-            cls.location.file);
+            cls.fileUri);
       }
     }
     // Since this is a breaking check, it is language-versioned.
@@ -129,10 +132,10 @@
         // a value for `className` that doesn't start with 'self.' or 'window.'.
         var classRegexp = new RegExp(r'^((self|window)\.)*(?<className>.*)$');
         var matches = classRegexp.allMatches(jsClass);
-        jsClass = matches.first.namedGroup('className');
+        jsClass = matches.first.namedGroup('className')!;
       }
-      if (_nativeClasses.containsKey(jsClass)) {
-        var nativeClass = _nativeClasses[jsClass];
+      var nativeClass = _nativeClasses[jsClass];
+      if (nativeClass != null) {
         _diagnosticsReporter.report(
             templateJsInteropNativeClassInAnnotation.withArguments(
                 cls.name,
@@ -140,7 +143,7 @@
                 nativeClass.enclosingLibrary.importUri.toString()),
             cls.fileOffset,
             cls.name.length,
-            cls.location.file);
+            cls.fileUri);
       }
     }
     super.visitClass(cls);
@@ -165,11 +168,12 @@
     super.visitLibrary(lib);
     _libraryIsGlobalNamespace = false;
     _libraryHasJSAnnotation = false;
+    _libraryExtensionsIndex = null;
   }
 
   @override
   void visitProcedure(Procedure procedure) {
-    _checkJSInteropAnnotation(procedure);
+    _checkInstanceMemberJSAnnotation(procedure);
     if (_classHasJSAnnotation && !procedure.isExternal) {
       // If not one of few exceptions, member is not allowed to exclude
       // `external` inside of a JS interop class.
@@ -180,43 +184,48 @@
             messageJsInteropNonExternalMember,
             procedure.fileOffset,
             procedure.name.text.length,
-            procedure.location.file);
+            procedure.fileUri);
       }
     }
-    if (!_isJSInteropMember(procedure)) return;
 
-    if (!procedure.isStatic &&
-        (procedure.name.text == '[]=' || procedure.name.text == '[]')) {
-      _diagnosticsReporter.report(
-          messageJsInteropIndexNotSupported,
-          procedure.fileOffset,
-          procedure.name.text.length,
-          procedure.location.file);
-    }
-
-    var isAnonymousFactory =
-        _classHasAnonymousAnnotation && procedure.isFactory;
-
-    if (isAnonymousFactory) {
-      if (procedure.function != null &&
-          !procedure.function.positionalParameters.isEmpty) {
-        var firstPositionalParam = procedure.function.positionalParameters[0];
-        _diagnosticsReporter.report(
-            messageJsInteropAnonymousFactoryPositionalParameters,
-            firstPositionalParam.fileOffset,
-            firstPositionalParam.name.length,
-            firstPositionalParam.location.file);
-      }
+    if (!_isJSInteropMember(procedure)) {
+      _checkDisallowedExternal(procedure);
     } else {
-      // Only factory constructors for anonymous classes are allowed to have
-      // named parameters.
-      _checkNoNamedParameters(procedure.function);
+      // Check JS interop indexing.
+      if (!procedure.isStatic &&
+          (procedure.name.text == '[]=' || procedure.name.text == '[]')) {
+        _diagnosticsReporter.report(
+            messageJsInteropIndexNotSupported,
+            procedure.fileOffset,
+            procedure.name.text.length,
+            procedure.fileUri);
+      }
+
+      // Check JS Interop positional and named parameters.
+      var isAnonymousFactory =
+          _classHasAnonymousAnnotation && procedure.isFactory;
+      if (isAnonymousFactory) {
+        // ignore: unnecessary_null_comparison
+        if (procedure.function != null &&
+            !procedure.function.positionalParameters.isEmpty) {
+          var firstPositionalParam = procedure.function.positionalParameters[0];
+          _diagnosticsReporter.report(
+              messageJsInteropAnonymousFactoryPositionalParameters,
+              firstPositionalParam.fileOffset,
+              firstPositionalParam.name!.length,
+              firstPositionalParam.location!.file);
+        }
+      } else {
+        // Only factory constructors for anonymous classes are allowed to have
+        // named parameters.
+        _checkNoNamedParameters(procedure.function);
+      }
     }
   }
 
   @override
   void visitConstructor(Constructor constructor) {
-    _checkJSInteropAnnotation(constructor);
+    _checkInstanceMemberJSAnnotation(constructor);
     if (_classHasJSAnnotation &&
         !constructor.isExternal &&
         !constructor.isSynthetic) {
@@ -225,28 +234,32 @@
           messageJsInteropNonExternalConstructor,
           constructor.fileOffset,
           constructor.name.text.length,
-          constructor.location.file);
+          constructor.fileUri);
     }
-    if (!_isJSInteropMember(constructor)) return;
 
-    _checkNoNamedParameters(constructor.function);
+    if (!_isJSInteropMember(constructor)) {
+      _checkDisallowedExternal(constructor);
+    } else {
+      _checkNoNamedParameters(constructor.function);
+    }
   }
 
   /// Reports an error if [functionNode] has named parameters.
   void _checkNoNamedParameters(FunctionNode functionNode) {
+    // ignore: unnecessary_null_comparison
     if (functionNode != null && !functionNode.namedParameters.isEmpty) {
       var firstNamedParam = functionNode.namedParameters[0];
       _diagnosticsReporter.report(
           messageJsInteropNamedParameters,
           firstNamedParam.fileOffset,
-          firstNamedParam.name.length,
-          firstNamedParam.location.file);
+          firstNamedParam.name!.length,
+          firstNamedParam.location!.file);
     }
   }
 
-  /// Reports an error if [member] does not correctly use the JS interop
-  /// annotation or the keyword `external`.
-  void _checkJSInteropAnnotation(Member member) {
+  /// Reports an error if given instance [member] is JS interop, but inside a
+  /// non JS interop class.
+  void _checkInstanceMemberJSAnnotation(Member member) {
     var enclosingClass = member.enclosingClass;
 
     if (!_classHasJSAnnotation &&
@@ -255,26 +268,38 @@
       // If in a class that is not JS interop, this member is not allowed to be
       // JS interop.
       _diagnosticsReporter.report(messageJsInteropEnclosingClassJSAnnotation,
-          member.fileOffset, member.name.text.length, member.location.file,
+          member.fileOffset, member.name.text.length, member.fileUri,
           context: <LocatedMessage>[
             messageJsInteropEnclosingClassJSAnnotationContext.withLocation(
-                enclosingClass.location.file,
+                enclosingClass.fileUri,
                 enclosingClass.fileOffset,
                 enclosingClass.name.length)
           ]);
     }
+  }
 
-    // Check for correct `external` usage.
-    if (member.isExternal &&
-        !_isAllowedExternalUsage(member) &&
-        !hasJSInteropAnnotation(member)) {
-      if (member.enclosingClass != null && !_classHasJSAnnotation ||
-          member.enclosingClass == null && !_libraryHasJSAnnotation) {
+  /// Assumes given [member] is not JS interop, and reports an error if
+  /// [member] is `external` and not an allowed `external` usage.
+  void _checkDisallowedExternal(Member member) {
+    if (member.isExternal) {
+      if (member.isExtensionMember) {
+        if (!_isNativeExtensionMember(member)) {
+          _diagnosticsReporter.report(
+              messageJsInteropExternalExtensionMemberOnTypeInvalid,
+              member.fileOffset,
+              member.name.text.length,
+              member.fileUri);
+        }
+      } else if (!hasJSInteropAnnotation(member) &&
+          !_isAllowedExternalUsage(member)) {
+        // Member could be JS annotated and not considered a JS interop member
+        // if inside a non-JS interop class. Should not report an error in this
+        // case, since a different error will already be produced.
         _diagnosticsReporter.report(
             messageJsInteropExternalMemberNotJSAnnotated,
             member.fileOffset,
             member.name.text.length,
-            member.location.file);
+            member.fileUri);
       }
     }
   }
@@ -290,13 +315,19 @@
   }
 
   /// Returns whether [member] is considered to be a JS interop member.
+  ///
+  /// A JS interop member is `external`, and is in a valid JS interop context,
+  /// which can be:
+  ///   - inside a JS interop class
+  ///   - inside an extension on a JS interop class
+  ///   - a top level member that is JS interop annotated or in a JS interop
+  ///     library
+  /// If a member belongs to a class, the class must be JS interop annotated.
   bool _isJSInteropMember(Member member) {
     if (member.isExternal) {
       if (_classHasJSAnnotation) return true;
+      if (member.isExtensionMember) return _isJSExtensionMember(member);
       if (member.enclosingClass == null) {
-        // In the case where the member does not belong to any class, a JS
-        // annotation is not needed on the library to be considered JS interop
-        // as long as the member has an annotation.
         return hasJSInteropAnnotation(member) || _libraryHasJSAnnotation;
       }
     }
@@ -304,4 +335,31 @@
     // Otherwise, not JS interop.
     return false;
   }
+
+  /// Returns whether given extension [member] is in an extension that is on a
+  /// JS interop class.
+  bool _isJSExtensionMember(Member member) {
+    return _checkExtensionMember(member, hasJSInteropAnnotation);
+  }
+
+  /// Returns whether given extension [member] is in an extension on a Native
+  /// class.
+  bool _isNativeExtensionMember(Member member) {
+    return _checkExtensionMember(member, _nativeClasses.containsValue);
+  }
+
+  /// Returns whether given extension [member] is on a class that passses the
+  /// given [validateExtensionClass].
+  bool _checkExtensionMember(Member member, Function validateExtensionClass) {
+    assert(member.isExtensionMember);
+    if (_libraryExtensionsIndex == null) {
+      _libraryExtensionsIndex = {};
+      member.enclosingLibrary.extensions.forEach((extension) =>
+          extension.members.forEach((memberDescriptor) =>
+              _libraryExtensionsIndex![memberDescriptor.member] = extension));
+    }
+
+    var onType = _libraryExtensionsIndex![member.reference]!.onType;
+    return onType is InterfaceType && validateExtensionClass(onType.classNode);
+  }
 }
diff --git a/pkg/_js_interop_checks/lib/src/js_interop.dart b/pkg/_js_interop_checks/lib/src/js_interop.dart
index 7831f2d..60a8dfd 100644
--- a/pkg/_js_interop_checks/lib/src/js_interop.dart
+++ b/pkg/_js_interop_checks/lib/src/js_interop.dart
@@ -89,7 +89,7 @@
 ///
 /// This function works regardless of whether the CFE is evaluating constants,
 /// or whether the constant is a field reference (such as "anonymous" above).
-Class _annotationClass(Expression node) {
+Class? _annotationClass(Expression node) {
   if (node is ConstantExpression) {
     var constant = node.constant;
     if (constant is InstanceConstant) return constant.classNode;
diff --git a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
index b29d418..4159999 100644
--- a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
+++ b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
@@ -36,26 +36,26 @@
 
   JsUtilOptimizer(this._coreTypes, ClassHierarchy hierarchy)
       : _jsTarget =
-            _coreTypes.index.getTopLevelMember('dart:_foreign_helper', 'JS'),
+            _coreTypes.index.getTopLevelProcedure('dart:_foreign_helper', 'JS'),
         _callMethodTarget =
-            _coreTypes.index.getTopLevelMember('dart:js_util', 'callMethod'),
+            _coreTypes.index.getTopLevelProcedure('dart:js_util', 'callMethod'),
         _callMethodUncheckedTargets = List<Procedure>.generate(
             5,
-            (i) => _coreTypes.index
-                .getTopLevelMember('dart:js_util', '_callMethodUnchecked$i')),
-        _getPropertyTarget =
-            _coreTypes.index.getTopLevelMember('dart:js_util', 'getProperty'),
-        _setPropertyTarget =
-            _coreTypes.index.getTopLevelMember('dart:js_util', 'setProperty'),
+            (i) => _coreTypes.index.getTopLevelProcedure(
+                'dart:js_util', '_callMethodUnchecked$i')),
+        _getPropertyTarget = _coreTypes.index
+            .getTopLevelProcedure('dart:js_util', 'getProperty'),
+        _setPropertyTarget = _coreTypes.index
+            .getTopLevelProcedure('dart:js_util', 'setProperty'),
         _setPropertyUncheckedTarget = _coreTypes.index
-            .getTopLevelMember('dart:js_util', '_setPropertyUnchecked'),
+            .getTopLevelProcedure('dart:js_util', '_setPropertyUnchecked'),
         _allowInteropTarget =
-            _coreTypes.index.getTopLevelMember('dart:js', 'allowInterop'),
+            _coreTypes.index.getTopLevelProcedure('dart:js', 'allowInterop'),
         _allowedInteropJsUtilTargets = _allowedInteropJsUtilMembers.map(
             (member) =>
-                _coreTypes.index.getTopLevelMember('dart:js_util', member)),
+                _coreTypes.index.getTopLevelProcedure('dart:js_util', member)),
         _listEmptyFactory =
-            _coreTypes.index.getMember('dart:core', 'List', 'empty'),
+            _coreTypes.index.getProcedure('dart:core', 'List', 'empty'),
         _staticTypeContext = StatefulStaticTypeContext.stacked(
             TypeEnvironment(_coreTypes, hierarchy)) {}
 
diff --git a/pkg/_js_interop_checks/pubspec.yaml b/pkg/_js_interop_checks/pubspec.yaml
index 1463e1d..bae1992 100644
--- a/pkg/_js_interop_checks/pubspec.yaml
+++ b/pkg/_js_interop_checks/pubspec.yaml
@@ -3,7 +3,7 @@
 publish_to: none
 
 environment:
-  sdk: '>=2.7.0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
   _fe_analyzer_shared:
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index f63580d..2e13ba2 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -4770,13 +4770,13 @@
           The one-based index of the column containing the first character of
           the range.
         </p>
-      </dd><dt class="field"><b>endLine: int</b></dt><dd>
+      </dd><dt class="field"><b>endLine: int<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
           The one-based index of the line containing the character immediately
           following the range.
         </p>
-      </dd><dt class="field"><b>endColumn: int</b></dt><dd>
+      </dd><dt class="field"><b>endColumn: int<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
           The one-based index of the column containing the character immediately
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index db83350..3896905 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -40,6 +40,7 @@
 import 'package:analysis_server/src/server/features.dart';
 import 'package:analysis_server/src/server/sdk_configuration.dart';
 import 'package:analysis_server/src/services/flutter/widget_descriptions.dart';
+import 'package:analysis_server/src/utilities/process.dart';
 import 'package:analysis_server/src/utilities/request_statistics.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -130,6 +131,7 @@
     CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
     InstrumentationService instrumentationService, {
     http.Client? httpClient,
+    ProcessRunner? processRunner,
     RequestStatisticsHelper? requestStatistics,
     DiagnosticServer? diagnosticServer,
     this.detachableFileSystemManager,
@@ -143,6 +145,7 @@
           baseResourceProvider,
           instrumentationService,
           httpClient,
+          processRunner,
           NotificationManager(channel, baseResourceProvider.pathContext),
           requestStatistics: requestStatistics,
           enableBazelWatcher: enableBazelWatcher,
@@ -429,9 +432,11 @@
     bool isPubspec(String filePath) =>
         file_paths.isPubspecYaml(resourceProvider.pathContext, filePath);
 
-    // When a pubspec is opened, trigger package name caching for completion.
-    if (!pubPackageService.isRunning && files.any(isPubspec)) {
-      pubPackageService.beginPackageNamePreload();
+    // When pubspecs are opened, trigger pre-loading of pub package names and
+    // versions.
+    final pubspecs = files.where(isPubspec).toList();
+    if (pubspecs.isNotEmpty) {
+      pubPackageService.beginCachePreloads(pubspecs);
     }
 
     priorityFiles.clear();
@@ -679,83 +684,8 @@
   @override
   void listenAnalysisDriver(analysis.AnalysisDriver analysisDriver) {
     analysisDriver.results.listen((result) {
-      var path = result.path!;
-      filesToFlush.add(path);
-      if (analysisServer.isAnalyzed(path)) {
-        _notificationManager.recordAnalysisErrors(NotificationManager.serverId,
-            path, server.doAnalysisError_listFromEngine(result));
-      }
-      analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
-      analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
-      var unit = result.unit;
-      if (unit != null) {
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.HIGHLIGHTS, path)) {
-          _runDelayed(() {
-            _notificationManager.recordHighlightRegions(
-                NotificationManager.serverId,
-                path,
-                _computeHighlightRegions(unit));
-          });
-        }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.NAVIGATION, path)) {
-          _runDelayed(() {
-            _notificationManager.recordNavigationParams(
-                NotificationManager.serverId,
-                path,
-                _computeNavigationParams(path, unit));
-          });
-        }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.OCCURRENCES, path)) {
-          _runDelayed(() {
-            _notificationManager.recordOccurrences(
-                NotificationManager.serverId, path, _computeOccurrences(unit));
-          });
-        }
-//          if (analysisServer._hasAnalysisServiceSubscription(
-//              AnalysisService.OUTLINE, path)) {
-//            _runDelayed(() {
-//              // TODO(brianwilkerson) Change NotificationManager to store params
-//              // so that fileKind and libraryName can be recorded / passed along.
-//              notificationManager.recordOutlines(NotificationManager.serverId,
-//                  path, _computeOutlineParams(path, unit, result.lineInfo));
-//            });
-//          }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.CLOSING_LABELS, path)) {
-          _runDelayed(() {
-            sendAnalysisNotificationClosingLabels(
-                analysisServer, path, result.lineInfo, unit);
-          });
-        }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.FOLDING, path)) {
-          _runDelayed(() {
-            sendAnalysisNotificationFolding(
-                analysisServer, path, result.lineInfo, unit);
-          });
-        }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.OUTLINE, path)) {
-          _runDelayed(() {
-            sendAnalysisNotificationOutline(analysisServer, result);
-          });
-        }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.OVERRIDES, path)) {
-          _runDelayed(() {
-            sendAnalysisNotificationOverrides(analysisServer, path, unit);
-          });
-        }
-        if (analysisServer._hasFlutterServiceSubscription(
-            FlutterService.OUTLINE, path)) {
-          _runDelayed(() {
-            sendFlutterNotificationOutline(analysisServer, result);
-          });
-        }
-        // TODO(scheglov) Implement notifications for AnalysisService.IMPLEMENTED.
+      if (result is FileResult) {
+        _handleFileResult(result);
       }
     });
     analysisDriver.exceptions.listen(analysisServer.logExceptionResult);
@@ -763,6 +693,18 @@
   }
 
   @override
+  void pubspecChanged(String pubspecPath) {
+    analysisServer.pubPackageService.fetchPackageVersionsViaPubOutdated(
+        pubspecPath,
+        pubspecWasModified: true);
+  }
+
+  @override
+  void pubspecRemoved(String pubspecPath) {
+    analysisServer.pubPackageService.flushPackageCaches(pubspecPath);
+  }
+
+  @override
   void recordAnalysisErrors(String path, List<AnalysisError> errors) {
     filesToFlush.add(path);
     _notificationManager.recordAnalysisErrors(
@@ -788,6 +730,95 @@
     return collector.allOccurrences;
   }
 
+  void _handleFileResult(FileResult result) {
+    var path = result.path;
+    filesToFlush.add(path);
+
+    if (result is AnalysisResultWithErrors) {
+      if (analysisServer.isAnalyzed(path)) {
+        _notificationManager.recordAnalysisErrors(NotificationManager.serverId,
+            path, server.doAnalysisError_listFromEngine(result));
+      }
+    }
+
+    if (result is ResolvedUnitResult) {
+      _handleResolvedUnitResult(result);
+    }
+  }
+
+  void _handleResolvedUnitResult(ResolvedUnitResult result) {
+    var path = result.path;
+
+    analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
+    analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
+
+    var unit = result.unit;
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.HIGHLIGHTS, path)) {
+      _runDelayed(() {
+        _notificationManager.recordHighlightRegions(
+            NotificationManager.serverId, path, _computeHighlightRegions(unit));
+      });
+    }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.NAVIGATION, path)) {
+      _runDelayed(() {
+        _notificationManager.recordNavigationParams(
+            NotificationManager.serverId,
+            path,
+            _computeNavigationParams(path, unit));
+      });
+    }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.OCCURRENCES, path)) {
+      _runDelayed(() {
+        _notificationManager.recordOccurrences(
+            NotificationManager.serverId, path, _computeOccurrences(unit));
+      });
+    }
+    // if (analysisServer._hasAnalysisServiceSubscription(
+    //     AnalysisService.OUTLINE, path)) {
+    //   _runDelayed(() {
+    //     // TODO(brianwilkerson) Change NotificationManager to store params
+    //     // so that fileKind and libraryName can be recorded / passed along.
+    //     notificationManager.recordOutlines(NotificationManager.serverId, path,
+    //         _computeOutlineParams(path, unit, result.lineInfo));
+    //   });
+    // }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.CLOSING_LABELS, path)) {
+      _runDelayed(() {
+        sendAnalysisNotificationClosingLabels(
+            analysisServer, path, result.lineInfo, unit);
+      });
+    }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.FOLDING, path)) {
+      _runDelayed(() {
+        sendAnalysisNotificationFolding(
+            analysisServer, path, result.lineInfo, unit);
+      });
+    }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.OUTLINE, path)) {
+      _runDelayed(() {
+        sendAnalysisNotificationOutline(analysisServer, result);
+      });
+    }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.OVERRIDES, path)) {
+      _runDelayed(() {
+        sendAnalysisNotificationOverrides(analysisServer, path, unit);
+      });
+    }
+    if (analysisServer._hasFlutterServiceSubscription(
+        FlutterService.OUTLINE, path)) {
+      _runDelayed(() {
+        sendFlutterNotificationOutline(analysisServer, result);
+      });
+    }
+  }
+
   /// Run [f] in a new [Future].
   ///
   /// This method is used to delay sending notifications. If there is a more
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index 616bf9d..4b28f5c 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -19,12 +19,14 @@
 import 'package:analysis_server/src/services/completion/dart/extension_cache.dart';
 import 'package:analysis_server/src/services/correction/namespace.dart';
 import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
 import 'package:analysis_server/src/services/pub/pub_package_service.dart';
 import 'package:analysis_server/src/services/search/element_visitors.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analysis_server/src/utilities/file_string_sink.dart';
 import 'package:analysis_server/src/utilities/null_string_sink.dart';
+import 'package:analysis_server/src/utilities/process.dart';
 import 'package:analysis_server/src/utilities/request_statistics.dart';
 import 'package:analysis_server/src/utilities/tee_string_sink.dart';
 import 'package:analyzer/dart/analysis/analysis_context.dart';
@@ -152,14 +154,26 @@
     ResourceProvider baseResourceProvider,
     this.instrumentationService,
     http.Client? httpClient,
+    ProcessRunner? processRunner,
     this.notificationManager, {
     this.requestStatistics,
     bool enableBazelWatcher = false,
   })  : resourceProvider = OverlayResourceProvider(baseResourceProvider),
         pubApi = PubApi(instrumentationService, httpClient,
             Platform.environment['PUB_HOSTED_URL']) {
-    pubPackageService =
-        PubPackageService(instrumentationService, baseResourceProvider, pubApi);
+    // We can only spawn processes (eg. to run pub commands) when backed by
+    // a real file system, otherwise we may try to run commands in folders that
+    // don't really exist. If processRunner was supplied, it's likely a mock
+    // from a test in which case the pub command should still be created.
+    if (baseResourceProvider is PhysicalResourceProvider) {
+      processRunner ??= ProcessRunner();
+    }
+    final pubCommand = processRunner != null
+        ? PubCommand(instrumentationService, processRunner)
+        : null;
+
+    pubPackageService = PubPackageService(
+        instrumentationService, baseResourceProvider, pubApi, pubCommand);
     performance = performanceDuringStartup;
 
     pluginManager = PluginManager(
@@ -380,7 +394,7 @@
     }
 
     var session = getAnalysisDriver(path)?.currentSession;
-    var result = session?.getParsedUnit2(path);
+    var result = session?.getParsedUnit(path);
     return result is ParsedUnitResult ? result : null;
   }
 
diff --git a/pkg/analysis_server/lib/src/cider/rename.dart b/pkg/analysis_server/lib/src/cider/rename.dart
index 6ea1b32..71e8148 100644
--- a/pkg/analysis_server/lib/src/cider/rename.dart
+++ b/pkg/analysis_server/lib/src/cider/rename.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analysis_server/src/services/correction/status.dart';
+import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/source/line_info.dart';
@@ -17,6 +19,14 @@
   CanRenameResponse(this.lineInfo, this.refactoringElement, this.oldName);
 }
 
+class CheckNameResponse {
+  final LineInfo lineInfo;
+  final RefactoringStatus status;
+  final String oldName;
+
+  CheckNameResponse(this.lineInfo, this.status, this.oldName);
+}
+
 class CiderRenameComputer {
   final FileResolver _fileResolver;
 
@@ -51,6 +61,32 @@
     return null;
   }
 
+  CheckNameResponse? checkNewName(String filePath, int line, int column, String name) {
+    var resolvedUnit = _fileResolver.resolve(path: filePath);
+    var lineInfo = resolvedUnit.lineInfo;
+    var offset = lineInfo.getOffsetOfLine(line) + column;
+
+    var node = NodeLocator(offset).searchWithin(resolvedUnit.unit);
+    var element = getElementOfNode(node);
+
+    if (node == null || element == null) {
+      return null;
+    }
+
+    RefactoringStatus? status;
+    if (element is LocalVariableElement) {
+      status = validateVariableName(name);
+    } else if (element is ParameterElement) {
+      status = validateParameterName(name);
+    } else if (element is FunctionElement) {
+      status = validateFunctionName(name);
+    }
+    if (status == null){
+      return null;
+    }
+    return CheckNameResponse(lineInfo, status, element.displayName);
+  }
+
   bool _canRenameElement(Element element) {
     if (element is PropertyAccessorElement) {
       element = element.variable;
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index fedd848..c4247be 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -17,17 +17,9 @@
 
   DartUnitOutlineComputer(this.resolvedUnit, {this.withBasicFlutter = false});
 
-  CompilationUnit get _unit {
-    var unit = resolvedUnit.unit;
-    if (unit == null) {
-      throw StateError('DartUnitOutlineComputer created with invalid result');
-    }
-    return unit;
-  }
-
   /// Returns the computed outline, not `null`.
   Outline compute() {
-    var unit = _unit;
+    var unit = resolvedUnit.unit;
     var unitContents = <Outline>[];
     for (var unitMember in unit.declarations) {
       if (unitMember is ClassDeclaration) {
@@ -87,17 +79,14 @@
 
   Location _getLocationOffsetLength(int offset, int length) {
     var path = resolvedUnit.path;
-    if (path == null) {
-      throw StateError('DartUnitOutlineComputer called with invalid result');
-    }
     var startLocation = resolvedUnit.lineInfo.getLocation(offset);
     var startLine = startLocation.lineNumber;
     var startColumn = startLocation.columnNumber;
     var endLocation = resolvedUnit.lineInfo.getLocation(offset + length);
     var endLine = endLocation.lineNumber;
     var endColumn = endLocation.columnNumber;
-    return Location(
-        path, offset, length, startLine, startColumn, endLine, endColumn);
+    return Location(path, offset, length, startLine, startColumn,
+        endLine: endLine, endColumn: endColumn);
   }
 
   Outline _newClassOutline(ClassDeclaration node, List<Outline> classContents) {
@@ -328,7 +317,7 @@
   }
 
   Outline _newUnitOutline(List<Outline> unitContents) {
-    var unit = _unit;
+    var unit = resolvedUnit.unit;
     var element = Element(
         ElementKind.COMPILATION_UNIT, '<unit>', Element.makeFlags(),
         location: _getLocationNode(unit));
diff --git a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
index 3a2ec51..a29230f 100644
--- a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
+++ b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
@@ -32,12 +32,6 @@
   Future<SourceChange> createEdits(
       List<ImportedElements> importedElementsList) async {
     var unit = libraryResult.unit;
-    var path = libraryResult.path;
-    if (unit == null || path == null) {
-      // We should never reach this point because the libraryResult should be
-      // valid.
-      return SourceChange('');
-    }
     var filteredImportedElements =
         _filterImportedElements(importedElementsList);
     var libraryElement = libraryResult.libraryElement;
@@ -50,7 +44,7 @@
     }
 
     var builder = ChangeBuilder(session: libraryResult.session);
-    await builder.addDartFileEdit(path, (builder) {
+    await builder.addDartFileEdit(libraryResult.path, (builder) {
       for (var importedElements in filteredImportedElements) {
         var matchingImports =
             _findMatchingImports(existingImports, importedElements);
@@ -280,11 +274,6 @@
   /// Partially copied from DartFileEditBuilderImpl.
   _InsertionDescription _getInsertionDescription(String importUri) {
     var unit = libraryResult.unit;
-    if (unit == null) {
-      // We should never reach this point because the libraryResult should be
-      // valid.
-      return _InsertionDescription(0, after: 2);
-    }
     LibraryDirective? libraryDirective;
     var importDirectives = <ImportDirective>[];
     var otherDirectives = <Directive>[];
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 721f37c..28509f0 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -122,6 +122,12 @@
   /// TODO(scheglov) Just pass results in here?
   void listenAnalysisDriver(AnalysisDriver driver);
 
+  /// The `pubspec.yaml` at [path] was added/modified.
+  void pubspecChanged(String path);
+
+  /// The `pubspec.yaml` at [path] was removed.
+  void pubspecRemoved(String path);
+
   /// Record error information for the file with the given [path].
   void recordAnalysisErrors(String path, List<protocol.AnalysisError> errors);
 }
@@ -566,12 +572,21 @@
 
     _instrumentationService.logWatchEvent('<unknown>', path, type.toString());
 
+    final isPubpsec = file_paths.isPubspecYaml(pathContext, path);
     if (file_paths.isAnalysisOptionsYaml(pathContext, path) ||
         file_paths.isDotPackages(pathContext, path) ||
         file_paths.isPackageConfigJson(pathContext, path) ||
-        file_paths.isPubspecYaml(pathContext, path) ||
+        isPubpsec ||
         false) {
       _createAnalysisContexts();
+
+      if (isPubpsec) {
+        if (type == ChangeType.REMOVE) {
+          callbacks.pubspecRemoved(path);
+        } else {
+          callbacks.pubspecChanged(path);
+        }
+      }
       return;
     }
 
@@ -727,6 +742,12 @@
   void listenAnalysisDriver(AnalysisDriver driver) {}
 
   @override
+  void pubspecChanged(String pubspecPath) {}
+
+  @override
+  void pubspecRemoved(String pubspecPath) {}
+
+  @override
   void recordAnalysisErrors(String path, List<protocol.AnalysisError> errors) {}
 }
 
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 2e2bc5d..df5d9f6 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -63,7 +63,7 @@
       server.sendResponse(Response.fileNotAnalyzed(request, file));
       return;
     }
-    var unit = result.unit!;
+    var unit = result.unit;
 
     // Prepare the hovers.
     var hovers = <HoverInformation>[];
@@ -105,7 +105,7 @@
       elements = <ImportedElements>[];
     } else {
       elements =
-          ImportedElementsComputer(result.unit!, params.offset, params.length)
+          ImportedElementsComputer(result.unit, params.offset, params.length)
               .compute();
     }
 
@@ -166,7 +166,7 @@
       var allResults = <AnalysisNavigationParams>[];
       var result = await server.getResolvedUnit(file);
       if (result != null && result.state == ResultState.VALID) {
-        var unit = result.unit!;
+        var unit = result.unit;
         var collector = NavigationCollectorImpl();
         computeDartNavigation(
             server.resourceProvider, collector, unit, offset, length);
@@ -237,7 +237,7 @@
     }
 
     // Ensure the offset provided is a valid location in the file.
-    final unit = result.unit!;
+    final unit = result.unit;
     final computer = DartUnitSignatureComputer(
         server.getDartdocDirectiveInfoFor(result), unit, params.offset);
     if (!computer.offsetIsValid) {
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 78db63a..9a10237 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -330,7 +330,7 @@
       }
       server.requestStatistics?.addItemTimeNow(request, 'resolvedUnit');
       if (resolvedUnit.state == ResultState.VALID) {
-        if (offset < 0 || offset > resolvedUnit.content!.length) {
+        if (offset < 0 || offset > resolvedUnit.content.length) {
           server.sendResponse(Response.invalidParameter(
               request,
               'params.offset',
@@ -339,7 +339,7 @@
           return;
         }
 
-        recordRequest(performance, file, resolvedUnit.content!, offset);
+        recordRequest(performance, file, resolvedUnit.content, offset);
       }
       var declarationsTracker = server.declarationsTracker;
       if (declarationsTracker == null) {
diff --git a/pkg/analysis_server/lib/src/domain_kythe.dart b/pkg/analysis_server/lib/src/domain_kythe.dart
index b03acbb..990588e 100644
--- a/pkg/analysis_server/lib/src/domain_kythe.dart
+++ b/pkg/analysis_server/lib/src/domain_kythe.dart
@@ -47,8 +47,8 @@
         var entries = <KytheEntry>[];
         // TODO(brianwilkerson) Figure out how to get the list of files.
         var files = <String>[];
-        result.unit!.accept(KytheDartVisitor(server.resourceProvider, entries,
-            file, InheritanceManager3(), result.content!));
+        result.unit.accept(KytheDartVisitor(server.resourceProvider, entries,
+            file, InheritanceManager3(), result.content));
         allResults.add(KytheGetKytheEntriesResult(entries, files));
       }
       //
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 223e056..54ffabf 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -24,7 +24,7 @@
   var context = tracker.getContext(analysisContext);
   if (context == null) return;
 
-  var librariesObject = context.getLibraries(resolvedUnit.path!);
+  var librariesObject = context.getLibraries(resolvedUnit.path);
 
   var importedUriSet = resolvedUnit.libraryElement.importedLibraries
       .map((importedLibrary) => importedLibrary.source.uri)
@@ -261,8 +261,8 @@
       0, // length
       declaration.locationStartLine,
       declaration.locationStartColumn,
-      declaration.locationStartLine, // endLine
-      declaration.locationStartColumn, // endColumn
+      endLine: declaration.locationStartLine,
+      endColumn: declaration.locationStartColumn,
     ),
     parameters: declaration.parameters,
     returnType: declaration.returnType,
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index 97ab5bf..7162de9 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -53,7 +53,7 @@
 
     // Compute the patched context file content.
     var targetCode = SourceEdit.applySequence(
-      contextResult.content!,
+      contextResult.content,
       changeBuilder.sourceChange.edits[0].edits,
     );
 
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 0e5ba49..b73448c 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -32,7 +32,6 @@
 import 'package:analysis_server/src/services/correction/status.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart' as engine;
@@ -402,7 +401,7 @@
       return;
     }
     var libraryUnit = result.libraryElement.definingCompilationUnit;
-    if (libraryUnit != result.unit!.declaredElement) {
+    if (libraryUnit != result.unit.declaredElement) {
       // The file in the request is a part of a library. We need to pass the
       // defining compilation unit to the computer, not the part.
       result = await server.getResolvedUnit(libraryUnit.source.fullName);
@@ -484,8 +483,8 @@
       return;
     }
     var fileStamp = -1;
-    var code = result.content!;
-    var unit = result.unit!;
+    var code = result.content;
+    var unit = result.unit;
     var errors = result.errors;
     // check if there are scan/parse errors in the file
     var numScanParseErrors = _getNumberOfScanParseErrors(errors);
@@ -575,8 +574,8 @@
       if (fixes.isNotEmpty) {
         fixes.sort(Fix.SORT_BY_RELEVANCE);
         var lineInfo = LineInfo.fromContent(content);
-        ResolvedUnitResult result = engine.ResolvedUnitResultImpl(session, file,
-            Uri.file(file), true, content, lineInfo, false, null, errors);
+        var result = engine.ErrorsResultImpl(
+            session, file, Uri.file(file), lineInfo, false, errors);
         var serverError = newAnalysisError_fromEngine(result, error);
         var errorFixes = AnalysisErrorFixes(serverError);
         errorFixesList.add(errorFixes);
@@ -611,7 +610,7 @@
             var provider = TopLevelDeclarationsProvider(tracker);
             return provider.get(
               result.session.analysisContext,
-              result.path!,
+              result.path,
               name,
             );
           }, extensionCache: server.getExtensionCacheFor(result));
@@ -628,7 +627,7 @@
 error.errorCode: ${error.errorCode}
 ''';
             throw CaughtExceptionWithFiles(exception, stackTrace, {
-              file: result.content!,
+              file: result.content,
               'parameters': parametersFile,
             });
           }
@@ -674,8 +673,8 @@
       if (fixes.isNotEmpty) {
         fixes.sort(Fix.SORT_BY_RELEVANCE);
         var lineInfo = LineInfo.fromContent(content);
-        ResolvedUnitResult result = engine.ResolvedUnitResultImpl(session, file,
-            Uri.file(file), true, content, lineInfo, false, null, errors);
+        var result = engine.ErrorsResultImpl(
+            session, file, Uri.file(file), lineInfo, false, errors);
         var serverError = newAnalysisError_fromEngine(result, error);
         var errorFixes = AnalysisErrorFixes(serverError);
         errorFixesList.add(errorFixes);
@@ -723,8 +722,8 @@
       if (fixes.isNotEmpty) {
         fixes.sort(Fix.SORT_BY_RELEVANCE);
         var lineInfo = LineInfo.fromContent(content);
-        ResolvedUnitResult result = engine.ResolvedUnitResultImpl(session, file,
-            Uri.file(file), true, content, lineInfo, false, null, errors);
+        var result = engine.ErrorsResultImpl(
+            session, file, Uri.file(file), lineInfo, false, errors);
         var serverError = newAnalysisError_fromEngine(result, error);
         var errorFixes = AnalysisErrorFixes(serverError);
         errorFixesList.add(errorFixes);
@@ -767,7 +766,7 @@
 length: $length
       ''';
         throw CaughtExceptionWithFiles(exception, stackTrace, {
-          file: result.content!,
+          file: result.content,
           'parameters': parametersFile,
         });
       }
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
index 36e5272..74085faa 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
@@ -15,7 +15,7 @@
     var outline = computer.compute();
     // send notification
     var params = protocol.FlutterOutlineParams(
-      resolvedUnit.path!,
+      resolvedUnit.path,
       outline,
     );
     server.sendNotification(params.toNotification());
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
index d216445..8c3dd26 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
@@ -31,7 +31,7 @@
 
     // Create outlines for widgets.
     var visitor = _FlutterOutlineBuilder(this);
-    resolvedUnit.unit!.accept(visitor);
+    resolvedUnit.unit.accept(visitor);
 
     // Associate Flutter outlines with Dart outlines.
     for (var outline in visitor.outlines) {
@@ -66,7 +66,7 @@
 
     var name = parameter.displayName;
 
-    var label = resolvedUnit.content!.substring(argument.offset, argument.end);
+    var label = resolvedUnit.content.substring(argument.offset, argument.end);
     if (label.contains('\n')) {
       label = '…';
     }
diff --git a/pkg/analysis_server/lib/src/lsp/client_configuration.dart b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
index 332330f..9093676 100644
--- a/pkg/analysis_server/lib/src/lsp/client_configuration.dart
+++ b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
@@ -2,10 +2,102 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:collection/collection.dart';
+import 'package:path/path.dart' as path;
+
+/// Provides access to both global and resource-specific client configuration.
+///
+/// Resource-specific config is currently only supported at the WorkspaceFolder
+/// level so when looking up config for a resource, the nearest WorkspaceFolders
+/// config will be used.
+class LspClientConfiguration {
+  /// Global settings for the workspace.
+  ///
+  /// Used as a fallback for resource settings if no specific config is found
+  /// for the resource.
+  LspGlobalClientConfiguration _globalSettings =
+      LspGlobalClientConfiguration({});
+
+  /// Settings for each resource.
+  ///
+  /// Keys are string paths without trailing path separators (eg. 'C:\foo').
+  final Map<String, LspResourceClientConfiguration> _resourceSettings =
+      <String, LspResourceClientConfiguration>{};
+
+  /// Pattern for stripping trailing slashes that may be been provided by the
+  /// client (in WorkspaceFolder URIs) for consistent comparisons.
+  final _trailingSlashPattern = RegExp(r'[\/]+$');
+
+  /// Returns the global configuration for the whole workspace.
+  LspGlobalClientConfiguration get global => _globalSettings;
+
+  /// Returns whether or not the provided new configuration changes any values
+  /// that would require analysis roots to be updated.
+  bool affectsAnalysisRoots(LspGlobalClientConfiguration otherConfig) {
+    return _globalSettings.analysisExcludedFolders !=
+        otherConfig.analysisExcludedFolders;
+  }
+
+  /// Returns config for a given resource.
+  ///
+  /// Because we only support config at the WorkspaceFolder level, this is done
+  /// by finding the nearest WorkspaceFolder to [resourcePath] and using config
+  /// for that.
+  ///
+  /// If no specific config is available, returns [global].
+  LspResourceClientConfiguration forResource(String resourcePath) {
+    final workspaceFolder = _getWorkspaceFolderPath(resourcePath);
+
+    if (workspaceFolder == null) {
+      return _globalSettings;
+    }
+
+    return _resourceSettings[_normaliseFolderPath(workspaceFolder)] ??
+        _globalSettings;
+  }
+
+  /// Replaces all previously known configuration with updated values from the
+  /// client.
+  void replace(
+    Map<String, Object?> globalConfig,
+    Map<String, Map<String, Object?>> workspaceFolderConfig,
+  ) {
+    _globalSettings = LspGlobalClientConfiguration(globalConfig);
+
+    _resourceSettings
+      ..clear()
+      ..addAll(workspaceFolderConfig.map(
+        (key, value) => MapEntry(
+          _normaliseFolderPath(key),
+          LspResourceClientConfiguration(value, _globalSettings),
+        ),
+      ));
+  }
+
+  /// Gets the path for the WorkspaceFolder closest to [resourcePath].
+  String? _getWorkspaceFolderPath(String resourcePath) {
+    final candidates = _resourceSettings.keys
+        .where((wfPath) =>
+            wfPath == _normaliseFolderPath(resourcePath) ||
+            path.isWithin(wfPath, resourcePath))
+        .toList();
+    candidates.sort((a, b) => -a.length.compareTo(b.length));
+    return candidates.firstOrNull;
+  }
+
+  /// Normalises a folder path to never have a trailing path separator.
+  String _normaliseFolderPath(String path) =>
+      path.replaceAll(_trailingSlashPattern, '');
+}
+
 /// Wraps the client (editor) configuration to provide stronger typing and
 /// handling of default values where a setting has not been supplied.
-class LspClientConfiguration {
-  final Map<String, dynamic> _settings = <String, dynamic>{};
+///
+/// Settings in this class are only allowed to be configured at the workspace
+/// level (they will be ignored at the resource level).
+class LspGlobalClientConfiguration extends LspResourceClientConfiguration {
+  LspGlobalClientConfiguration(Map<String, Object?> settings)
+      : super(settings, null);
 
   List<String> get analysisExcludedFolders {
     // This setting is documented as a string array, but because editors are
@@ -20,30 +112,48 @@
     }
   }
 
-  bool get completeFunctionCalls => _settings['completeFunctionCalls'] ?? false;
-  bool get enableSdkFormatter => _settings['enableSdkFormatter'] ?? true;
-  int? get lineLength => _settings['lineLength'];
+  /// Whether methods/functions in completion should include parens and argument
+  /// placeholders when used in an invocation context.
+  bool get completeFunctionCalls =>
+      _settings['completeFunctionCalls'] as bool? ?? false;
 
   /// A preview flag for enabling commit characters for completions.
   ///
   /// This is a temporary setting to allow this feature to be tested without
   /// defaulting to on for everybody.
   bool get previewCommitCharacters =>
-      _settings['previewCommitCharacters'] ?? false;
+      _settings['previewCommitCharacters'] as bool? ?? false;
 
   /// Whether diagnostics should be generated for TODO comments.
-  bool get showTodos => _settings['showTodos'] ?? false;
+  bool get showTodos => _settings['showTodos'] as bool? ?? false;
+}
 
-  /// Returns whether or not the provided new configuration changes any values
-  /// that would require analysis roots to be updated.
-  bool affectsAnalysisRoots(Map<String, dynamic> newConfig) {
-    return _settings['analysisExcludedFolders'] !=
-        newConfig['analysisExcludedFolders'];
-  }
+/// Wraps the client (editor) configuration for a specific resource.
+///
+/// Settings in this class are only allowed to be configured either for a
+/// resource or for the whole workspace.
+///
+/// Right now, we treat "resource" to always mean a WorkspaceFolder since no
+/// known editors allow per-file configuration and it allows us to keep the
+/// settings cached, invalidated only when WorkspaceFolders change.
+class LspResourceClientConfiguration {
+  final Map<String, Object?> _settings;
+  final LspResourceClientConfiguration? _fallback;
 
-  void replace(Map<String, dynamic> newConfig) {
-    _settings
-      ..clear()
-      ..addAll(newConfig);
-  }
+  LspResourceClientConfiguration(this._settings, this._fallback);
+
+  /// Whether to enable the SDK formatter.
+  ///
+  /// If this setting is `false`, the formatter will be unregistered with the
+  /// client.
+  bool get enableSdkFormatter =>
+      _settings['enableSdkFormatter'] as bool? ??
+      _fallback?.enableSdkFormatter ??
+      true;
+
+  /// The line length used when formatting documents.
+  ///
+  /// If null, the formatters default will be used.
+  int? get lineLength =>
+      _settings['lineLength'] as int? ?? _fallback?.lineLength;
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart
index 784e2fe..4d4f523 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart
@@ -12,7 +12,6 @@
 import 'package:analysis_server/src/lsp/progress.dart';
 import 'package:analysis_server/src/services/correction/bulk_fix_processor.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
-import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
 
 class FixAllCommandHandler extends SimpleEditCommandHandler {
   FixAllCommandHandler(LspAnalysisServer server) : super(server);
@@ -48,14 +47,13 @@
       final processor =
           BulkFixProcessor(server.instrumentationService, workspace);
 
-      final collection = AnalysisContextCollectionImpl(
-        includedPaths: [path],
-        resourceProvider: server.resourceProvider,
-        sdkPath: server.sdkManager.defaultSdkDirectory,
-      );
-      final changeBuilder = await processor.fixErrors(collection.contexts);
-      final change = changeBuilder.sourceChange;
+      final context = server.contextManager.getContextFor(path);
+      if (context == null) {
+        return success(null);
+      }
 
+      final changeBuilder = await processor.fixErrorsForFile(context, path);
+      final change = changeBuilder.sourceChange;
       if (change.edits.isEmpty) {
         return success(null);
       }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
index 6b3ac68..2a81ac0 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
@@ -41,8 +41,8 @@
     }
 
     return result.mapResult((result) {
-      final code = result.content!;
-      final unit = result.unit!;
+      final code = result.content;
+      final unit = result.unit;
 
       if (hasScanParseErrors(result.errors)) {
         // It's not uncommon for editors to run this command automatically on-save
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
index ed17c2a..20c4d27 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
@@ -14,6 +14,8 @@
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 
 final _manager = _RefactorManager();
 
@@ -173,6 +175,32 @@
             InlineMethodRefactoring(server.searchEngine, result, offset);
         return success(refactor);
 
+      case RefactoringKind.CONVERT_GETTER_TO_METHOD:
+        final node = NodeLocator(offset).searchWithin(result.unit);
+        final element = server.getElementOfNode(node);
+        if (element != null) {
+          if (element is PropertyAccessorElement) {
+            final refactor = ConvertGetterToMethodRefactoring(
+                server.searchEngine, result.session, element);
+            return success(refactor);
+          }
+        }
+        return error(ServerErrorCodes.InvalidCommandArguments,
+            'Location supplied to $commandName $kind is not longer valid');
+
+      case RefactoringKind.CONVERT_METHOD_TO_GETTER:
+        final node = NodeLocator(offset).searchWithin(result.unit);
+        final element = server.getElementOfNode(node);
+        if (element != null) {
+          if (element is ExecutableElement) {
+            final refactor = ConvertMethodToGetterRefactoring(
+                server.searchEngine, result.session, element);
+            return success(refactor);
+          }
+        }
+        return error(ServerErrorCodes.InvalidCommandArguments,
+            'Location supplied to $commandName $kind is not longer valid');
+
       default:
         return error(ServerErrorCodes.InvalidCommandArguments,
             'Unknown RefactoringKind $kind was supplied to $commandName');
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
index 9a530d3..e270255 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
@@ -23,8 +23,8 @@
       DidChangeWorkspaceFoldersParams.jsonHandler;
 
   @override
-  ErrorOr<void> handle(
-      DidChangeWorkspaceFoldersParams params, CancellationToken token) {
+  Future<ErrorOr<void>> handle(
+      DidChangeWorkspaceFoldersParams params, CancellationToken token) async {
     // Don't do anything if our analysis roots are not based on open workspaces.
     if (!updateAnalysisRoots) {
       return success(null);
@@ -37,7 +37,7 @@
         .map((wf) => Uri.parse(wf.uri).toFilePath())
         .toList();
 
-    server.updateWorkspaceFolders(added, removed);
+    await server.updateWorkspaceFolders(added, removed);
 
     return success(null);
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index 5063d04..9f7152c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -4,12 +4,11 @@
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
-import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
-import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analysis_server/src/plugin/plugin_manager.dart';
 import 'package:analysis_server/src/protocol_server.dart' hide Position;
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/assist_internal.dart';
@@ -21,12 +20,37 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart'
     show InconsistentAnalysisException;
-import 'package:analyzer/error/error.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
+import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:collection/collection.dart' show groupBy;
 
 class CodeActionHandler extends MessageHandler<CodeActionParams,
     List<Either2<Command, CodeAction>>> {
+  // Because server+plugin results are different types and we lose
+  // priorites when converting them to CodeActions, store the priorities
+  // against each action in an expando. This avoids wrapping CodeActions in
+  // another wrapper class (since we can't modify the LSP-spec-generated
+  // CodeAction class).
+  final codeActionPriorities = Expando<int>();
+
+  /// A comparator that can be used to sort [CodeActions]s using priorties
+  /// in [codeActionPriorities]. The highest number priority will be sorted
+  /// before lower number priorityies. Items with the same relevance are sorted
+  /// alphabetically by their title.
+  late final Comparator<CodeAction> _codeActionComparator =
+      (CodeAction a, CodeAction b) {
+    // We should never be sorting actions without priorities.
+    final aPriority = codeActionPriorities[a] ?? 0;
+    final bPriority = codeActionPriorities[b] ?? 0;
+    if (aPriority != bPriority) {
+      return bPriority - aPriority;
+    }
+    return a.title.compareTo(b.title);
+  };
+
   CodeActionHandler(LspAnalysisServer server) : super(server);
 
   @override
@@ -145,12 +169,12 @@
   /// version of each document being modified so it's important to call this
   /// immediately after computing edits to ensure the document is not modified
   /// before the version number is read.
-  CodeAction _createAssistAction(Assist assist) {
+  CodeAction _createAssistAction(SourceChange change) {
     return CodeAction(
-      title: assist.change.message,
-      kind: toCodeActionKind(assist.change.id, CodeActionKind.Refactor),
+      title: change.message,
+      kind: toCodeActionKind(change.id, CodeActionKind.Refactor),
       diagnostics: const [],
-      edit: createWorkspaceEdit(server, assist.change),
+      edit: createWorkspaceEdit(server, change),
     );
   }
 
@@ -158,12 +182,12 @@
   /// version of each document being modified so it's important to call this
   /// immediately after computing edits to ensure the document is not modified
   /// before the version number is read.
-  CodeAction _createFixAction(Fix fix, Diagnostic diagnostic) {
+  CodeAction _createFixAction(SourceChange change, Diagnostic diagnostic) {
     return CodeAction(
-      title: fix.change.message,
-      kind: toCodeActionKind(fix.change.id, CodeActionKind.QuickFix),
+      title: change.message,
+      kind: toCodeActionKind(change.id, CodeActionKind.QuickFix),
       diagnostics: [diagnostic],
-      edit: createWorkspaceEdit(server, fix.change),
+      edit: createWorkspaceEdit(server, change),
     );
   }
 
@@ -220,6 +244,7 @@
   Future<List<Either2<Command, CodeAction>>> _getAssistActions(
     bool Function(CodeActionKind?) shouldIncludeKind,
     bool supportsLiteralCodeActions,
+    String path,
     Range range,
     int offset,
     int length,
@@ -234,13 +259,28 @@
         length,
       );
       final processor = AssistProcessor(context);
-      final assists = await processor.compute();
-      assists.sort(Assist.SORT_BY_RELEVANCE);
+      final serverFuture = processor.compute();
+      final pluginFuture = _getPluginAssistChanges(path, offset, length);
 
-      final assistActions =
-          _dedupeActions(assists.map(_createAssistAction), range.start);
+      final assists = await serverFuture;
+      final pluginChanges = await pluginFuture;
 
-      return assistActions
+      final codeActions = <CodeAction>[];
+      codeActions.addAll(assists.map((assist) {
+        final action = _createAssistAction(assist.change);
+        codeActionPriorities[action] = assist.kind.priority;
+        return action;
+      }));
+      codeActions.addAll(pluginChanges.map((change) {
+        final action = _createAssistAction(change.change);
+        codeActionPriorities[action] = change.priority;
+        return action;
+      }));
+
+      final dedupedCodeActions = _dedupeActions(codeActions, range.start);
+      dedupedCodeActions.sort(_codeActionComparator);
+
+      return dedupedCodeActions
           .where((action) => shouldIncludeKind(action.kind))
           .map((action) => Either2<Command, CodeAction>.t2(action))
           .toList();
@@ -266,11 +306,11 @@
     final results = await Future.wait([
       _getSourceActions(shouldIncludeKind, supportsLiterals,
           supportsWorkspaceApplyEdit, path),
-      _getAssistActions(
-          shouldIncludeKind, supportsLiterals, range, offset, length, unit),
+      _getAssistActions(shouldIncludeKind, supportsLiterals, path, range,
+          offset, length, unit),
       _getRefactorActions(
           shouldIncludeKind, supportsLiterals, path, offset, length, unit),
-      _getFixActions(shouldIncludeKind, supportsLiterals,
+      _getFixActions(shouldIncludeKind, supportsLiterals, path, offset,
           supportedDiagnosticTags, range, unit),
     ]);
     final flatResults = results.expand((x) => x).toList();
@@ -281,22 +321,23 @@
   Future<List<Either2<Command, CodeAction>>> _getFixActions(
     bool Function(CodeActionKind?) shouldIncludeKind,
     bool supportsLiteralCodeActions,
+    String path,
+    int offset,
     Set<DiagnosticTag> supportedDiagnosticTags,
     Range range,
     ResolvedUnitResult unit,
   ) async {
+    final clientSupportsCodeDescription =
+        server.clientCapabilities?.diagnosticCodeDescription ?? false;
+    // TODO(dantup): We may be missing fixes for pubspec, analysis_options,
+    //   android manifests (see _computeServerErrorFixes in EditDomainHandler).
     final lineInfo = unit.lineInfo;
     final codeActions = <CodeAction>[];
     final fixContributor = DartFixContributor();
 
-    try {
-      final errorCodeCounts = <ErrorCode, int>{};
-      // Count the errors by code so we know whether to include a fix-all.
-      for (final error in unit.errors) {
-        errorCodeCounts[error.errorCode] =
-            (errorCodeCounts[error.errorCode] ?? 0) + 1;
-      }
+    final pluginFuture = _getPluginFixActions(unit, offset);
 
+    try {
       for (final error in unit.errors) {
         // Server lineNumber is one-based so subtract one.
         var errorLine = lineInfo.getLocation(error.offset).lineNumber - 1;
@@ -309,28 +350,50 @@
           var tracker = server.declarationsTracker!;
           return TopLevelDeclarationsProvider(tracker).get(
             unit.session.analysisContext,
-            unit.path!,
+            unit.path,
             name,
           );
         }, extensionCache: server.getExtensionCacheFor(unit));
         final fixes = await fixContributor.computeFixes(context);
         if (fixes.isNotEmpty) {
-          fixes.sort(Fix.SORT_BY_RELEVANCE);
-
           final diagnostic = toDiagnostic(
             unit,
             error,
             supportedTags: supportedDiagnosticTags,
-            clientSupportsCodeDescription:
-                server.clientCapabilities?.diagnosticCodeDescription ?? false,
+            clientSupportsCodeDescription: clientSupportsCodeDescription,
           );
           codeActions.addAll(
-            fixes.map((fix) => _createFixAction(fix, diagnostic)),
+            fixes.map((fix) {
+              final action = _createFixAction(fix.change, diagnostic);
+              codeActionPriorities[action] = fix.kind.priority;
+              return action;
+            }),
           );
         }
       }
 
+      Diagnostic pluginErrorToDiagnostic(AnalysisError error) {
+        return pluginToDiagnostic(
+          (_) => lineInfo,
+          error,
+          supportedTags: supportedDiagnosticTags,
+          clientSupportsCodeDescription: clientSupportsCodeDescription,
+        );
+      }
+
+      final pluginFixes = await pluginFuture;
+      final pluginFixActions = pluginFixes.expand(
+        (fix) => fix.fixes.map((fixChange) {
+          final action = _createFixAction(
+              fixChange.change, pluginErrorToDiagnostic(fix.error));
+          codeActionPriorities[action] = fixChange.priority;
+          return action;
+        }),
+      );
+      codeActions.addAll(pluginFixActions);
+
       final dedupedActions = _dedupeActions(codeActions, range.start);
+      dedupedActions.sort(_codeActionComparator);
 
       return dedupedActions
           .where((action) => shouldIncludeKind(action.kind))
@@ -344,6 +407,61 @@
     }
   }
 
+  Future<Iterable<plugin.PrioritizedSourceChange>> _getPluginAssistChanges(
+      String path, int offset, int length) async {
+    final requestParams = plugin.EditGetAssistsParams(path, offset, length);
+    final driver = server.getAnalysisDriver(path);
+
+    Map<PluginInfo, Future<plugin.Response>> pluginFutures;
+    if (driver == null) {
+      pluginFutures = <PluginInfo, Future<plugin.Response>>{};
+    } else {
+      pluginFutures = server.pluginManager.broadcastRequest(
+        requestParams,
+        contextRoot: driver.analysisContext!.contextRoot,
+      );
+    }
+
+    final pluginChanges = <plugin.PrioritizedSourceChange>[];
+    final responses =
+        await waitForResponses(pluginFutures, requestParameters: requestParams);
+
+    for (final response in responses) {
+      final result = plugin.EditGetAssistsResult.fromResponse(response);
+      pluginChanges.addAll(result.assists);
+    }
+
+    return pluginChanges;
+  }
+
+  Future<Iterable<plugin.AnalysisErrorFixes>> _getPluginFixActions(
+      ResolvedUnitResult unit, int offset) async {
+    final file = unit.path;
+    final requestParams = plugin.EditGetFixesParams(file, offset);
+    final driver = server.getAnalysisDriver(file);
+
+    Map<PluginInfo, Future<plugin.Response>> pluginFutures;
+    if (driver == null) {
+      pluginFutures = <PluginInfo, Future<plugin.Response>>{};
+    } else {
+      pluginFutures = server.pluginManager.broadcastRequest(
+        requestParams,
+        contextRoot: driver.analysisContext!.contextRoot,
+      );
+    }
+
+    final pluginFixes = <plugin.AnalysisErrorFixes>[];
+    final responses =
+        await waitForResponses(pluginFutures, requestParameters: requestParams);
+
+    for (final response in responses) {
+      final result = plugin.EditGetFixesResult.fromResponse(response);
+      pluginFixes.addAll(result.fixes);
+    }
+
+    return pluginFixes;
+  }
+
   Future<List<Either2<Command, CodeAction>>> _getRefactorActions(
     bool Function(CodeActionKind) shouldIncludeKind,
     bool supportsLiteralCodeActions,
@@ -428,6 +546,28 @@
         }
       }
 
+      // Converts/Rewrites
+      if (shouldIncludeKind(CodeActionKind.RefactorRewrite)) {
+        final node = NodeLocator(offset).searchWithin(unit.unit);
+        final element = server.getElementOfNode(node);
+        // Getter to Method
+        if (element is PropertyAccessorElement) {
+          refactorActions.add(createRefactor(
+              CodeActionKind.RefactorRewrite,
+              'Convert Getter to Method',
+              RefactoringKind.CONVERT_GETTER_TO_METHOD));
+        }
+
+        // Method to Getter
+        if (element is ExecutableElement &&
+            element is! PropertyAccessorElement) {
+          refactorActions.add(createRefactor(
+              CodeActionKind.RefactorRewrite,
+              'Convert Method to Getter',
+              RefactoringKind.CONVERT_METHOD_TO_GETTER));
+        }
+      }
+
       return refactorActions;
     } on InconsistentAnalysisException {
       // If an InconsistentAnalysisException occurs, it's likely the user modified
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 ccf8bb2..2ab3d5d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -205,7 +205,7 @@
   ) async {
     final performance = CompletionPerformance();
     performance.path = unit.path;
-    performance.setContentsAndOffset(unit.content!, offset);
+    performance.setContentsAndOffset(unit.content, offset);
     server.performanceStats.completion.add(performance);
 
     return await performance.runRequestOperation((perf) async {
@@ -261,7 +261,7 @@
         /// insert dupes.
         final completeFunctionCalls = _hasExistingArgList(target.entity)
             ? false
-            : server.clientConfiguration.completeFunctionCalls;
+            : server.clientConfiguration.global.completeFunctionCalls;
 
         final results = serverSuggestions.map(
           (item) {
@@ -292,7 +292,7 @@
               // depending on how the spec is updated.
               // https://github.com/microsoft/vscode-languageserver-node/issues/673
               includeCommitCharacters:
-                  server.clientConfiguration.previewCommitCharacters,
+                  server.clientConfiguration.global.previewCommitCharacters,
               completeFunctionCalls: completeFunctionCalls,
             );
           },
@@ -374,7 +374,7 @@
                   importingUris.first == '${library.uri}';
             }).map((item) => declarationToCompletionItem(
                       capabilities,
-                      unit.path!,
+                      unit.path,
                       offset,
                       includedSet,
                       library,
@@ -390,8 +390,8 @@
                       // this should be removed (or made conditional based on a capability)
                       // depending on how the spec is updated.
                       // https://github.com/microsoft/vscode-languageserver-node/issues/673
-                      includeCommitCharacters:
-                          server.clientConfiguration.previewCommitCharacters,
+                      includeCommitCharacters: server
+                          .clientConfiguration.global.previewCommitCharacters,
                       completeFunctionCalls: completeFunctionCalls,
                     ));
             results.addAll(setResults);
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 1463107..30935d6 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
@@ -111,7 +111,7 @@
 
         analyzer.LibraryElement requestedLibraryElement;
         {
-          final result = await session.getLibraryByUri2(library.uriStr);
+          final result = await session.getLibraryByUri(library.uriStr);
           if (result is LibraryElementResult) {
             requestedLibraryElement = result.element;
           } else {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
index ff213a4..ae96228 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
@@ -34,7 +34,7 @@
 
     return offset.mapResult((requestedOffset) {
       final collector = OccurrencesCollectorImpl();
-      addDartOccurrences(collector, unit.result.unit!);
+      addDartOccurrences(collector, unit.result.unit);
 
       // Find an occurrence that has an instance that spans the position.
       for (final occurrence in collector.allOccurrences) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
index 1ed3a71..3148284 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
@@ -32,8 +32,8 @@
       return success(null);
     }
 
-    return generateEditsForFormatting(
-        result, server.clientConfiguration.lineLength);
+    final lineLength = server.clientConfiguration.forResource(path).lineLength;
+    return generateEditsForFormatting(result, lineLength);
   }
 
   @override
@@ -43,12 +43,15 @@
       return success(null);
     }
 
-    if (!server.clientConfiguration.enableSdkFormatter) {
-      return error(ServerErrorCodes.FeatureDisabled,
-          'Formatter was disabled by client settings');
-    }
-
     final path = pathOfDoc(params.textDocument);
-    return path.mapResult((path) => formatFile(path));
+    return path.mapResult((path) {
+      if (!server.clientConfiguration.forResource(path).enableSdkFormatter) {
+        // Because we now support formatting for just some WorkspaceFolders
+        // we should silently do nothing for those that are disabled.
+        return success(null);
+      }
+
+      return formatFile(path);
+    });
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
index d6f7247..f92433a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
@@ -32,9 +32,8 @@
       return success(null);
     }
 
-    return generateEditsForFormatting(
-        result, server.clientConfiguration.lineLength,
-        range: range);
+    final lineLength = server.clientConfiguration.forResource(path).lineLength;
+    return generateEditsForFormatting(result, lineLength, range: range);
   }
 
   @override
@@ -44,12 +43,14 @@
       return success(null);
     }
 
-    if (!server.clientConfiguration.enableSdkFormatter) {
-      return error(ServerErrorCodes.FeatureDisabled,
-          'Formatter was disabled by client settings');
-    }
-
     final path = pathOfDoc(params.textDocument);
-    return path.mapResult((path) => formatRange(path, params.range));
+    return path.mapResult((path) {
+      if (!server.clientConfiguration.forResource(path).enableSdkFormatter) {
+        // Because we now support formatting for just some WorkspaceFolders
+        // we should silently do nothing for those that are disabled.
+        return success(null);
+      }
+      return formatRange(path, params.range);
+    });
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
index 75b7a41..23a7cad 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
@@ -32,8 +32,8 @@
       return success(null);
     }
 
-    return generateEditsForFormatting(
-        result, server.clientConfiguration.lineLength);
+    final lineLength = server.clientConfiguration.forResource(path).lineLength;
+    return generateEditsForFormatting(result, lineLength);
   }
 
   @override
@@ -43,12 +43,14 @@
       return success(null);
     }
 
-    if (!server.clientConfiguration.enableSdkFormatter) {
-      return error(ServerErrorCodes.FeatureDisabled,
-          'Formatter was disabled by client settings');
-    }
-
     final path = pathOfDoc(params.textDocument);
-    return path.mapResult((path) => formatFile(path));
+    return path.mapResult((path) {
+      if (!server.clientConfiguration.forResource(path).enableSdkFormatter) {
+        // Because we now support formatting for just some WorkspaceFolders
+        // we should silently do nothing for those that are disabled.
+        return success(null);
+      }
+      return formatFile(path);
+    });
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
index c533db2..1195c9b 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -83,10 +83,6 @@
 
   ErrorOr<Hover?> _getHover(ResolvedUnitResult unit, int offset) {
     final compilationUnit = unit.unit;
-    if (compilationUnit == null) {
-      return success(null);
-    }
-
     final computer = DartUnitHoverComputer(
         server.getDartdocDirectiveInfoFor(unit), compilationUnit, offset);
     final hover = computer.compute();
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
index d842bbb..b0e3ca3 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
@@ -28,10 +28,8 @@
       server,
     );
 
-    await server.fetchClientConfigurationAndPerformDynamicRegistration();
-
     if (!server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles) {
-      server.updateWorkspaceFolders(openWorkspacePaths, const []);
+      await server.updateWorkspaceFolders(openWorkspacePaths, const []);
     }
 
     return success(null);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
index b302227..93c78da 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
@@ -83,7 +83,7 @@
         convert(results, toLocation).whereNotNull().toList();
 
     final compilationUnit = unit.unit;
-    if (compilationUnit != null && params.context.includeDeclaration == true) {
+    if (params.context.includeDeclaration == true) {
       // Also include the definition for the symbol at this location.
       referenceResults.addAll(_getDeclarations(compilationUnit, offset));
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
index 34f4193..25a78ca 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
@@ -62,7 +62,7 @@
       // signature help for that.
       final typeArgsSignature = _tryGetTypeArgsSignatureHelp(
         dartDocInfo,
-        unit.result.unit!,
+        unit.result.unit,
         offset,
         autoTriggered,
         formats,
@@ -72,7 +72,7 @@
       }
 
       final computer =
-          DartUnitSignatureComputer(dartDocInfo, unit.result.unit!, offset);
+          DartUnitSignatureComputer(dartDocInfo, unit.result.unit, offset);
       if (!computer.offsetIsValid) {
         return success(null); // No error, just no valid hover.
       }
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 ab57310..2dcd219 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -35,6 +35,7 @@
 import 'package:analysis_server/src/services/completion/completion_performance.dart'
     show CompletionPerformance;
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
+import 'package:analysis_server/src/utilities/process.dart';
 import 'package:analyzer/dart/analysis/context_locator.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/error/error.dart';
@@ -126,6 +127,7 @@
     CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
     InstrumentationService instrumentationService, {
     http.Client? httpClient,
+    ProcessRunner? processRunner,
     DiagnosticServer? diagnosticServer,
     // Disable to avoid using this in unit tests.
     bool enableBazelWatcher = false,
@@ -137,6 +139,7 @@
           baseResourceProvider,
           instrumentationService,
           httpClient,
+          processRunner,
           LspNotificationManager(channel, baseResourceProvider.pathContext),
           enableBazelWatcher: enableBazelWatcher,
         ) {
@@ -184,10 +187,10 @@
       RefactoringWorkspace(driverMap.values, searchEngine);
 
   void addPriorityFile(String filePath) {
-    // When a pubspec is opened, trigger package name caching for completion.
-    if (!pubPackageService.isRunning &&
-        file_paths.isPubspecYaml(resourceProvider.pathContext, filePath)) {
-      pubPackageService.beginPackageNamePreload();
+    // When pubspecs are opened, trigger pre-loading of pub package names and
+    // versions.
+    if (file_paths.isPubspecYaml(resourceProvider.pathContext, filePath)) {
+      pubPackageService.beginCachePreloads([filePath]);
     }
 
     final didAdd = priorityFiles.add(filePath);
@@ -205,33 +208,49 @@
   /// register/unregister requests for any supported/enabled dynamic registrations.
   Future<void> fetchClientConfigurationAndPerformDynamicRegistration() async {
     if (clientCapabilities?.configuration ?? false) {
+      // Take a copy of workspace folders because we need to match up the
+      // responses to the request by index and it's possible _workspaceFolders
+      // will change after we sent the request but before we get the response.
+      final folders = _workspaceFolders.toList();
+
       // Fetch all configuration we care about from the client. This is just
       // "dart" for now, but in future this may be extended to include
       // others (for example "flutter").
       final response = await sendRequest(
           Method.workspace_configuration,
           ConfigurationParams(items: [
+            // Dart settings for each workspace folder.
+            for (final folder in folders)
+              ConfigurationItem(
+                scopeUri: Uri.file(folder).toString(),
+                section: 'dart',
+              ),
+            // Global Dart settings. This comes last to simplify matching up the
+            // indexes in the results (folder[i] is the i'th item).
             ConfigurationItem(section: 'dart'),
           ]));
 
       final result = response.result;
 
-      // Expect the result to be a single list (to match the single
-      // ConfigurationItem we requested above) and that it should be
-      // a standard map of settings.
+      // Expect the result to be a list with 1 + folders.length items to
+      // match the request above, and each should be a standard map of settings.
       // If the above code is extended to support multiple sets of config
-      // this will need tweaking to handle each group appropriately.
+      // this will need tweaking to handle the item for each section.
       if (result != null &&
           result is List<dynamic> &&
-          result.length == 1 &&
-          result.first is Map<String, dynamic>) {
-        final newConfig = result.first;
-        final refreshRoots =
-            clientConfiguration.affectsAnalysisRoots(newConfig);
+          result.length == 1 + folders.length) {
+        // Config is stored as a map keyed by the workspace folder, and a key of
+        // null for the global config
+        final workspaceFolderConfig = {
+          for (var i = 0; i < folders.length; i++)
+            folders[i]: result[i] as Map<String, Object?>? ?? {},
+        };
+        final newGlobalConfig = result.last as Map<String, Object?>? ?? {};
 
-        clientConfiguration.replace(newConfig);
+        final oldGlobalConfig = clientConfiguration.global;
+        clientConfiguration.replace(newGlobalConfig, workspaceFolderConfig);
 
-        if (refreshRoots) {
+        if (clientConfiguration.affectsAnalysisRoots(oldGlobalConfig)) {
           _refreshAnalysisRoots();
         }
       }
@@ -638,14 +657,16 @@
     sendServerErrorNotification('Socket error', error, stack);
   }
 
-  void updateWorkspaceFolders(
-      List<String> addedPaths, List<String> removedPaths) {
+  Future<void> updateWorkspaceFolders(
+      List<String> addedPaths, List<String> removedPaths) async {
     // TODO(dantup): This is currently case-sensitive!
 
     _workspaceFolders
       ..addAll(addedPaths)
       ..removeAll(removedPaths);
 
+    await fetchClientConfigurationAndPerformDynamicRegistration();
+
     _refreshAnalysisRoots();
   }
 
@@ -699,7 +720,7 @@
         ? _workspaceFolders.toSet()
         : _getRootsForOpenFiles();
 
-    final excludedPaths = clientConfiguration.analysisExcludedFolders
+    final excludedPaths = clientConfiguration.global.analysisExcludedFolders
         .expand((excludePath) => resourceProvider.pathContext
                 .isAbsolute(excludePath)
             ? [excludePath]
@@ -825,42 +846,8 @@
     }
 
     analysisDriver.results.listen((result) {
-      var path = result.path;
-      if (path == null) {
-        // This shouldn't occur - result.path is marked with a TODO to become
-        // non-nullable.
-        return;
-      }
-      filesToFlush.add(path);
-      if (analysisServer.isAnalyzed(path)) {
-        final serverErrors = protocol.doAnalysisError_listFromEngine(result);
-        recordAnalysisErrors(path, serverErrors);
-      }
-      analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
-      analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
-      final unit = result.unit;
-      if (unit != null) {
-        if (analysisServer.shouldSendClosingLabelsFor(path)) {
-          final labels = DartUnitClosingLabelsComputer(result.lineInfo, unit)
-              .compute()
-              .map((l) => toClosingLabel(result.lineInfo, l))
-              .toList();
-
-          analysisServer.publishClosingLabels(path, labels);
-        }
-        if (analysisServer.shouldSendOutlineFor(path)) {
-          final outline = DartUnitOutlineComputer(
-            result,
-            withBasicFlutter: true,
-          ).compute();
-          final lspOutline = toOutline(result.lineInfo, outline);
-          analysisServer.publishOutline(path, lspOutline);
-        }
-        if (analysisServer.shouldSendFlutterOutlineFor(path)) {
-          final outline = FlutterOutlineComputer(result).compute();
-          final lspOutline = toFlutterOutline(result.lineInfo, outline);
-          analysisServer.publishFlutterOutline(path, lspOutline);
-        }
+      if (result is FileResult) {
+        _handleFileResult(result);
       }
     });
     analysisDriver.exceptions.listen(analysisServer.logExceptionResult);
@@ -868,6 +855,18 @@
   }
 
   @override
+  void pubspecChanged(String pubspecPath) {
+    analysisServer.pubPackageService.fetchPackageVersionsViaPubOutdated(
+        pubspecPath,
+        pubspecWasModified: true);
+  }
+
+  @override
+  void pubspecRemoved(String pubspecPath) {
+    analysisServer.pubPackageService.flushPackageCaches(pubspecPath);
+  }
+
+  @override
   void recordAnalysisErrors(String path, List<protocol.AnalysisError> errors) {
     final errorsToSend = errors.where(_shouldSendError).toList();
     filesToFlush.add(path);
@@ -875,7 +874,53 @@
         .recordAnalysisErrors(NotificationManager.serverId, path, errorsToSend);
   }
 
+  void _handleFileResult(FileResult result) {
+    var path = result.path;
+    filesToFlush.add(path);
+
+    if (result is AnalysisResultWithErrors) {
+      if (analysisServer.isAnalyzed(path)) {
+        final serverErrors = protocol.doAnalysisError_listFromEngine(result);
+        recordAnalysisErrors(path, serverErrors);
+      }
+    }
+
+    if (result is ResolvedUnitResult) {
+      _handleResolvedUnitResult(result);
+    }
+  }
+
+  void _handleResolvedUnitResult(ResolvedUnitResult result) {
+    var path = result.path;
+
+    analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
+    analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
+
+    final unit = result.unit;
+    if (analysisServer.shouldSendClosingLabelsFor(path)) {
+      final labels = DartUnitClosingLabelsComputer(result.lineInfo, unit)
+          .compute()
+          .map((l) => toClosingLabel(result.lineInfo, l))
+          .toList();
+
+      analysisServer.publishClosingLabels(path, labels);
+    }
+    if (analysisServer.shouldSendOutlineFor(path)) {
+      final outline = DartUnitOutlineComputer(
+        result,
+        withBasicFlutter: true,
+      ).compute();
+      final lspOutline = toOutline(result.lineInfo, outline);
+      analysisServer.publishOutline(path, lspOutline);
+    }
+    if (analysisServer.shouldSendFlutterOutlineFor(path)) {
+      final outline = FlutterOutlineComputer(result).compute();
+      final lspOutline = toFlutterOutline(result.lineInfo, outline);
+      analysisServer.publishFlutterOutline(path, lspOutline);
+    }
+  }
+
   bool _shouldSendError(protocol.AnalysisError error) =>
       error.code != ErrorType.TODO.name.toLowerCase() ||
-      analysisServer.clientConfiguration.showTodos;
+      analysisServer.clientConfiguration.global.showTodos;
 }
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 429920f..da9bb2a 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -49,6 +49,15 @@
   ],
 };
 
+/// Pattern for docComplete text on completion items that can be upgraded to
+/// the "detail" field so that it can be shown more prominently by clients.
+///
+/// This is typically used for labels like _latest compatible_ and _latest_ in
+/// the pubspec version items. These go into docComplete so that they appear
+/// reasonably for non-LSP clients where there is no equivalent of the detail
+/// field.
+final _upgradableDocCompletePattern = RegExp(r'^_([\w ]{0,20})_$');
+
 lsp.Either2<String, lsp.MarkupContent> asStringOrMarkupContent(
     Set<lsp.MarkupKind>? preferredFormats, String content) {
   return preferredFormats == null
@@ -866,19 +875,30 @@
         range: toRange(lineInfo, label.offset, label.length),
         label: label.label);
 
-lsp.CodeActionKind toCodeActionKind(String? id, lsp.CodeActionKind fallback) {
+/// Converts [id] to a [CodeActionKind] using [fallbackOrPrefix] as a fallback
+/// or a prefix if the ID is not already a fix/refactor.
+lsp.CodeActionKind toCodeActionKind(
+    String? id, lsp.CodeActionKind fallbackOrPrefix) {
   if (id == null) {
-    return fallback;
+    return fallbackOrPrefix;
   }
   // Dart fixes and assists start with "dart.assist." and "dart.fix." but in LSP
   // we want to use the predefined prefixes for CodeActions.
-  final newId = id
+  var newId = id
       .replaceAll('dart.assist', lsp.CodeActionKind.Refactor.toString())
       .replaceAll('dart.fix', lsp.CodeActionKind.QuickFix.toString())
       .replaceAll(
           'analysisOptions.assist', lsp.CodeActionKind.Refactor.toString())
       .replaceAll(
           'analysisOptions.fix', lsp.CodeActionKind.QuickFix.toString());
+
+  // If the ID does not start with either of the kinds above, prefix it as
+  // it will be an unqualified ID from a plugin.
+  if (!newId.startsWith(lsp.CodeActionKind.Refactor.toString()) &&
+      !newId.startsWith(lsp.CodeActionKind.QuickFix.toString())) {
+    newId = '$fallbackOrPrefix.$newId';
+  }
+
   return lsp.CodeActionKind(newId);
 }
 
@@ -956,7 +976,21 @@
   final insertText = insertTextInfo.first;
   final insertTextFormat = insertTextInfo.last;
   final isMultilineCompletion = insertText.contains('\n');
-  final cleanedDoc = cleanDartdoc(suggestion.docComplete);
+
+  var cleanedDoc = cleanDartdoc(suggestion.docComplete);
+  var detail = getCompletionDetail(suggestion, completionKind,
+      supportsCompletionDeprecatedFlag || supportsDeprecatedTag);
+
+  // To improve the display of some items (like pubspec version numbers),
+  // short labels in the format `_foo_` in docComplete are "upgraded" to the
+  // detail field.
+  final labelMatch = cleanedDoc != null
+      ? _upgradableDocCompletePattern.firstMatch(cleanedDoc)
+      : null;
+  if (labelMatch != null) {
+    cleanedDoc = null;
+    detail = labelMatch.group(1);
+  }
 
   // Because we potentially send thousands of these items, we should minimise
   // the generated JSON as much as possible - for example using nulls in place
@@ -971,8 +1005,7 @@
     commitCharacters:
         includeCommitCharacters ? dartCompletionCommitCharacters : null,
     data: resolutionData,
-    detail: getCompletionDetail(suggestion, completionKind,
-        supportsCompletionDeprecatedFlag || supportsDeprecatedTag),
+    detail: detail,
     documentation: cleanedDoc != null
         ? asStringOrMarkupContent(formats, cleanedDoc)
         : null,
diff --git a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
index ca0b352..89f26d4 100644
--- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
+++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
@@ -136,9 +136,10 @@
       LspClientCapabilities clientCapabilities) {
     final codeActionLiteralSupport = clientCapabilities.literalCodeActions;
     final renameOptionsSupport = clientCapabilities.renameValidation;
-    final enableFormatter = _server.clientConfiguration.enableSdkFormatter;
+    final enableFormatter =
+        _server.clientConfiguration.global.enableSdkFormatter;
     final previewCommitCharacters =
-        _server.clientConfiguration.previewCommitCharacters;
+        _server.clientConfiguration.global.previewCommitCharacters;
 
     final dynamicRegistrations =
         ClientDynamicRegistrations(clientCapabilities.raw);
@@ -321,9 +322,10 @@
 
     final registrations = <Registration>[];
 
-    final enableFormatter = _server.clientConfiguration.enableSdkFormatter;
+    final enableFormatter =
+        _server.clientConfiguration.global.enableSdkFormatter;
     final previewCommitCharacters =
-        _server.clientConfiguration.previewCommitCharacters;
+        _server.clientConfiguration.global.previewCommitCharacters;
 
     /// Helper for creating registrations with IDs.
     void register(bool condition, Method method, [ToJsonable? options]) {
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 05538df..94f0005 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -94,7 +94,7 @@
     AnalysisServer server, ResolvedUnitResult resolvedUnit) {
   _sendNotification(server, () {
     protocol.FileKind fileKind;
-    var unit = resolvedUnit.unit!;
+    var unit = resolvedUnit.unit;
     if (unit.directives.any((d) => d is PartOfDirective)) {
       fileKind = protocol.FileKind.PART;
     } else {
@@ -112,7 +112,7 @@
 
     // send notification
     var params = protocol.AnalysisOutlineParams(
-        resolvedUnit.path!, fileKind, outline,
+        resolvedUnit.path, fileKind, outline,
         libraryName: libraryName);
     server.sendNotification(params.toNotification());
   });
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index c03f74b..7ad36bd 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -27,7 +27,7 @@
 /// Returns a list of AnalysisErrors corresponding to the given list of Engine
 /// errors.
 List<AnalysisError> doAnalysisError_listFromEngine(
-    engine.ResolvedUnitResult result) {
+    engine.AnalysisResultWithErrors result) {
   return mapEngineErrors(result, result.errors, newAnalysisError_fromEngine);
 }
 
@@ -79,9 +79,10 @@
 
 /// Translates engine errors through the ErrorProcessor.
 List<T> mapEngineErrors<T>(
-    engine.ResolvedUnitResult result,
+    engine.AnalysisResultWithErrors result,
     List<engine.AnalysisError> errors,
-    T Function(engine.ResolvedUnitResult result, engine.AnalysisError error,
+    T Function(
+            engine.AnalysisResultWithErrors result, engine.AnalysisError error,
             [engine.ErrorSeverity errorSeverity])
         constructor) {
   var analysisOptions = result.session.analysisContext.analysisOptions;
@@ -106,7 +107,7 @@
 ///
 /// If an [errorSeverity] is specified, it will override the one in [error].
 AnalysisError newAnalysisError_fromEngine(
-    engine.ResolvedUnitResult result, engine.AnalysisError error,
+    engine.AnalysisResultWithErrors result, engine.AnalysisError error,
     [engine.ErrorSeverity? errorSeverity]) {
   var errorCode = error.errorCode;
   // prepare location
@@ -125,8 +126,8 @@
     var endLine = endLocation.lineNumber;
     var endColumn = endLocation.columnNumber;
 
-    location = Location(
-        file, offset, length, startLine, startColumn, endLine, endColumn);
+    location = Location(file, offset, length, startLine, startColumn,
+        endLine: endLine, endColumn: endColumn);
   }
 
   // Default to the error's severity if none is specified.
@@ -155,7 +156,7 @@
 
 /// Create a DiagnosticMessage based on an [engine.DiagnosticMessage].
 DiagnosticMessage newDiagnosticMessage(
-    engine.ResolvedUnitResult result, engine.DiagnosticMessage message) {
+    engine.AnalysisResultWithErrors result, engine.DiagnosticMessage message) {
   var file = message.filePath;
   var offset = message.offset;
   var length = message.length;
@@ -170,8 +171,8 @@
 
   return DiagnosticMessage(
       message.messageText(includeUrl: true),
-      Location(
-          file, offset, length, startLine, startColumn, endLine, endColumn));
+      Location(file, offset, length, startLine, startColumn,
+          endLine: endLine, endColumn: endColumn));
 }
 
 /// Create a Location based on an [engine.Element].
@@ -316,5 +317,6 @@
     //  should be able to throw an exception. Try removing the try statement.
   }
   return Location(unitElement.source.fullName, range.offset, range.length,
-      startLine, startColumn, endLine, endColumn);
+      startLine, startColumn,
+      endLine: endLine, endColumn: endColumn);
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_core.dart b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
index 2c71a1e..d6fe971 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -44,7 +44,7 @@
   ResourceProvider get resourceProvider => result.session.resourceProvider;
 
   @override
-  Source get source => result.unit!.declaredElement!.source;
+  Source get source => result.unit.declaredElement!.source;
 
   @override
   String? get sourceContents => result.content;
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 fce6916..b71fa3e 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
@@ -100,7 +100,7 @@
   }) async {
     request.checkAborted();
     var pathContext = request.resourceProvider.pathContext;
-    if (!file_paths.isDart(pathContext, request.result.path!)) {
+    if (!file_paths.isDart(pathContext, request.result.path)) {
       return const <CompletionSuggestion>[];
     }
 
@@ -458,7 +458,7 @@
     return performance.run(
       'build DartCompletionRequest',
       (_) {
-        var unit = request.result.unit!;
+        var unit = request.result.unit;
         var libSource = unit.declaredElement!.library.source;
         var objectType = request.result.typeProvider.objectType;
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart b/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart
index 4457f2e..0ca62d6 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart
@@ -29,7 +29,7 @@
 
   /// Fill the cache with data from the [result].
   void cacheFromResult(ResolvedUnitResult result) {
-    var compilationUnit = result.unit?.declaredElement;
+    var compilationUnit = result.unit.declaredElement;
     if (compilationUnit != null) {
       documentationCache.remove(_keyForUnit(compilationUnit));
       _cacheFromElement(compilationUnit);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart
index 96decc0..38481dc 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart
@@ -21,7 +21,7 @@
 
   /// Fill the cache with data from the [result].
   void cacheFromResult(ResolvedUnitResult result) {
-    var element = result.unit?.declaredElement;
+    var element = result.unit.declaredElement;
     if (element != null) {
       _cacheFromElement(element);
       for (var library in result.libraryElement.importedLibraries) {
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 c767698..f14d554 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
@@ -158,7 +158,7 @@
       return;
     }
 
-    var libraryUnits = request.result.unit?.declaredElement?.library.units;
+    var libraryUnits = request.result.unit.declaredElement?.library.units;
     if (libraryUnits == null) {
       return;
     }
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 467c954..9bcd314 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
@@ -704,7 +704,7 @@
       ExecutableElement element, bool invokeSuper) async {
     var displayTextBuffer = StringBuffer();
     var builder = ChangeBuilder(session: request.result.session);
-    await builder.addDartFileEdit(request.result.path!, (builder) {
+    await builder.addDartFileEdit(request.result.path, (builder) {
       builder.addReplacement(range.node(targetId), (builder) {
         builder.writeOverride(
           element,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index d045443..26a1a94 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -158,7 +158,8 @@
     bool isDeprecated = false}) {
   var name = id.name;
   // TODO(danrubel) use lineInfo to determine startLine and startColumn
-  var location = Location(source.fullName, id.offset, id.length, 0, 0, 0, 0);
+  var location = Location(source.fullName, id.offset, id.length, 0, 0,
+      endLine: 0, endColumn: 0);
   var flags = protocol.Element.makeFlags(
       isAbstract: isAbstract,
       isDeprecated: isDeprecated,
@@ -194,7 +195,7 @@
 }
 
 String getRequestLineIndent(DartCompletionRequest request) {
-  var content = request.result.content!;
+  var content = request.result.content;
   var lineStartOffset = request.offset;
   var notWhitespaceOffset = request.offset;
   for (; lineStartOffset > 0; lineStartOffset--) {
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
index 8aa88e2..988a42d 100644
--- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -264,7 +264,7 @@
 
   String get eol => utils.endOfLine;
 
-  String get file => completionContext.resolveResult.path!;
+  String get file => completionContext.resolveResult.path;
 
   String get key => completionContext.key;
 
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index 9bd0039..e337213 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -120,7 +120,7 @@
 
   String get eol => utils.endOfLine;
 
-  String get file => statementContext.resolveResult.path!;
+  String get file => statementContext.resolveResult.path;
 
   LineInfo get lineInfo => statementContext.resolveResult.lineInfo;
 
@@ -128,7 +128,7 @@
 
   Source get source => unitElement.source;
 
-  CompilationUnit get unit => statementContext.resolveResult.unit!;
+  CompilationUnit get unit => statementContext.resolveResult.unit;
 
   CompilationUnitElement get unitElement => unit.declaredElement!;
 
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
index 7f60edd..bd175b9 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
@@ -30,6 +30,7 @@
         AnalyzerOptions.chromeOsManifestChecks: EmptyProducer(),
       }),
       AnalyzerOptions.plugins: EmptyProducer(),
+      AnalyzerOptions.propagateLinterExceptions: EmptyProducer(),
       AnalyzerOptions.strong_mode: MapProducer({
         AnalyzerOptions.declarationCasts: EmptyProducer(),
         AnalyzerOptions.implicitCasts: EmptyProducer(),
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
index 960346f..5d7f681 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
@@ -176,9 +176,11 @@
   const Producer();
 
   /// A utility method used to create a suggestion for the [identifier].
-  CompletionSuggestion identifier(String identifier, {int relevance = 1000}) =>
+  CompletionSuggestion identifier(String identifier,
+          {int relevance = 1000, String? docComplete}) =>
       CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER, relevance,
-          identifier, identifier.length, 0, false, false);
+          identifier, identifier.length, 0, false, false,
+          docComplete: docComplete);
 
   /// A utility method used to create a suggestion for the package [packageName].
   CompletionSuggestion packageName(String packageName,
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
index 724bb6f..a34d791 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
@@ -37,18 +37,25 @@
   @override
   Iterable<CompletionSuggestion> suggestions(
       YamlCompletionRequest request) sync* {
-    // TOOD(dantup): Consider supporting async completion requests so this
-    // could call packageDetails() (with a short timeout, and pub retries
-    // disabled). A user that explicitly invokes completion in the location
-    // of a version may be prepared to wait a short period for a web request
-    // to get completion versions (this is also the only way for non-LSP
-    // clients to get them, since there are no resolve calls).
+    final versions = request.pubPackageService
+        ?.cachedPubOutdatedVersions(request.filePath, package);
+    final resolvable = versions?.resolvableVersion;
+    var latest = versions?.latestVersion;
+
+    // If we didn't get a latest version from the "pub outdated" results, we can
+    // use the result from the Pub API if we've called it (this will usually
+    // only be the case for LSP where a resolve() call was sent).
     //
-    // Supporting this will require making the completion async further up.
-    final details = request.pubPackageService?.cachedPackageDetails(package);
-    final version = details?.latestVersion;
-    if (version != null) {
-      yield identifier('^$version');
+    // This allows us (in some cases) to still show version numbers even if the
+    // package was newly added to pubspec and not saved, so not yet in the
+    // "pub outdated" results.
+    latest ??= request.pubPackageService?.cachedPubApiLatestVersion(package);
+
+    if (resolvable != null && resolvable != latest) {
+      yield identifier('^$resolvable', docComplete: '_latest compatible_');
+    }
+    if (latest != null) {
+      yield identifier('^$latest', docComplete: '_latest_');
     }
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/base_processor.dart b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
index 543d8c9..fb8a04f 100644
--- a/pkg/analysis_server/lib/src/services/correction/base_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
@@ -33,7 +33,7 @@
     this.selectionLength = 0,
     required this.resolvedResult,
     required this.workspace,
-  })  : file = resolvedResult.path!,
+  })  : file = resolvedResult.path,
         session = resolvedResult.session,
         sessionHelper = AnalysisSessionHelper(resolvedResult.session),
         typeProvider = resolvedResult.typeProvider,
diff --git a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
index b43cfbc..7313659 100644
--- a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
@@ -172,7 +172,7 @@
             file_paths.isGenerated(path)) {
           continue;
         }
-        var library = await context.currentSession.getResolvedLibrary2(path);
+        var library = await context.currentSession.getResolvedLibrary(path);
         if (library is ResolvedLibraryResult) {
           await _fixErrorsInLibrary(library);
         }
@@ -182,6 +182,22 @@
     return builder;
   }
 
+  /// Return a change builder that has been used to create fixes for the
+  /// diagnostics in [file] in the given [context].
+  Future<ChangeBuilder> fixErrorsForFile(
+      AnalysisContext context, String path) async {
+    var pathContext = context.contextRoot.resourceProvider.pathContext;
+
+    if (file_paths.isDart(pathContext, path) && !file_paths.isGenerated(path)) {
+      var library = await context.currentSession.getResolvedLibrary(path);
+      if (library is ResolvedLibraryResult) {
+        await _fixErrorsInLibrary(library);
+      }
+    }
+
+    return builder;
+  }
+
   /// Return a change builder that has been used to create all fixes for a
   /// specific diagnostic code in the given [unit].
   Future<ChangeBuilder> fixOfTypeInUnit(
@@ -269,7 +285,7 @@
   /// library associated with the analysis [result].
   Future<void> _fixErrorsInLibrary(ResolvedLibraryResult result) async {
     var analysisOptions = result.session.analysisContext.analysisOptions;
-    for (var unitResult in result.units!) {
+    for (var unitResult in result.units) {
       var overrideSet = _readOverrideSet(unitResult);
       for (var error in unitResult.errors) {
         var processor = ErrorProcessor.getProcessor(analysisOptions, error);
@@ -336,7 +352,7 @@
       await compute(producer);
       var newHash = computeChangeHash();
       if (newHash != oldHash) {
-        changeMap.add(result.path!, code);
+        changeMap.add(result.path, code);
       }
     }
 
@@ -401,7 +417,7 @@
     if (useConfigFiles) {
       var provider = result.session.resourceProvider;
       var context = provider.pathContext;
-      var dartFileName = result.path!;
+      var dartFileName = result.path;
       var configFileName = '${context.withoutExtension(dartFileName)}.config';
       var configFile = provider.getFile(configFileName);
       try {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
index bc10e17..14485d2 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
@@ -249,12 +249,12 @@
     this.overrideSet,
     this.selectionOffset = -1,
     this.selectionLength = 0,
-  })  : file = resolvedResult.path!,
+  })  : file = resolvedResult.path,
         session = resolvedResult.session,
         sessionHelper = AnalysisSessionHelper(resolvedResult.session),
         typeProvider = resolvedResult.typeProvider,
         selectionEnd = selectionOffset + selectionLength,
-        unit = resolvedResult.unit!,
+        unit = resolvedResult.unit,
         utils = CorrectionUtils(resolvedResult);
 
   /// Return `true` if the lint with the given [name] is enabled.
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart
index 1ccaff4..8a6b2c8 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart
@@ -17,8 +17,9 @@
     var body = getEnclosingFunctionBody();
     if (body == null ||
         body is EmptyFunctionBody ||
-        body.isAsynchronous ||
-        body.isGenerator) {
+        // Do not offer a correction if there is an `async`, `async*`, `sync*`,
+        // or the fictional `sync` keyword.
+        body.keyword != null) {
       return;
     }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
index 0f22239..c841c0f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
@@ -27,7 +27,7 @@
     }
 
     var libraryPath = resolvedResult.libraryElement.source.fullName;
-    var partPath = resolvedResult.path!;
+    var partPath = resolvedResult.path;
     var relativePath = relative(libraryPath, from: dirname(partPath));
     var uri = Uri.file(relativePath).toString();
     var replacementRange = range.node(libraryName);
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
index 2f320ef..9009561 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
@@ -154,7 +154,7 @@
       // use different utils
       var targetPath = targetClassElement.source.fullName;
       var targetResolveResult =
-          await resolvedResult.session.getResolvedUnit2(targetPath);
+          await resolvedResult.session.getResolvedUnit(targetPath);
       if (targetResolveResult is! ResolvedUnitResult) {
         return;
       }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
index 1b02c88..318a934 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
@@ -39,7 +39,7 @@
   Iterable<CorrectionProducer> _wrapMultipleWidgets() sync* {
     var selectionRange = SourceRange(selectionOffset, selectionLength);
     var analyzer = SelectionAnalyzer(selectionRange);
-    resolvedResult.unit!.accept(analyzer);
+    resolvedResult.unit.accept(analyzer);
 
     var widgetExpressions = <Expression>[];
     if (analyzer.hasSelectedNodes) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
index 69137bf..00b0dd7d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
@@ -450,7 +450,7 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    var result = await sessionHelper.session.getLibraryByUri2(uri.toString());
+    var result = await sessionHelper.session.getLibraryByUri(uri.toString());
     if (result is LibraryElementResult) {
       var library = result.element;
       if (library
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart b/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart
index caca5ec..d5cf7c0 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart
@@ -25,7 +25,7 @@
   @override
   Future<void> compute(ChangeBuilder builder) async {
     var organizer =
-        ImportOrganizer(resolvedResult.content!, unit, resolvedResult.errors);
+        ImportOrganizer(resolvedResult.content, unit, resolvedResult.errors);
     // todo (pq): consider restructuring organizer to allow a passed-in change
     //  builder
     for (var edit in organizer.organize()) {
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
index 9f1c68a..9a156c4 100644
--- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -52,7 +52,7 @@
 
   /// Analyze the selection, compute [status] and nodes.
   void analyze() {
-    resolveResult.unit!.accept(this);
+    resolveResult.unit.accept(this);
   }
 
   /// Records fatal error with given message and [Location].
@@ -73,7 +73,7 @@
     {
       var selectionStart = selection.offset;
       var selectionEnd = selection.end;
-      var commentRanges = getCommentRanges(resolveResult.unit!);
+      var commentRanges = getCommentRanges(resolveResult.unit);
       for (var commentRange in commentRanges) {
         if (commentRange.contains(selectionStart)) {
           invalidSelection('Selection begins inside a comment.');
@@ -208,9 +208,9 @@
 
   /// Returns `true` if there are [Token]s in the given [SourceRange].
   bool _hasTokens(SourceRange range) {
-    var fullText = resolveResult.content!;
+    var fullText = resolveResult.content;
     var rangeText = fullText.substring(range.offset, range.end);
-    return _getTokens(rangeText, resolveResult.unit!.featureSet).isNotEmpty;
+    return _getTokens(rangeText, resolveResult.unit.featureSet).isNotEmpty;
   }
 
   /// Returns `true` if [nodes] contains [node].
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 7259632..7fc3b9f 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -37,7 +37,7 @@
     LibraryElement targetLibrary, Set<Source> libraries) async {
   var libraryPath = targetLibrary.source.fullName;
 
-  var resolveResult = await session.getResolvedUnit2(libraryPath);
+  var resolveResult = await session.getResolvedUnit(libraryPath);
   if (resolveResult is! ResolvedUnitResult) {
     return;
   }
@@ -537,9 +537,9 @@
   String? _endOfLine;
 
   CorrectionUtils(ResolvedUnitResult result)
-      : unit = result.unit!,
+      : unit = result.unit,
         _library = result.libraryElement,
-        _buffer = result.content!;
+        _buffer = result.content;
 
   /// Returns the EOL to use for this [CompilationUnit].
   String get endOfLine {
@@ -860,14 +860,13 @@
   /// used by the generated source, but not imported.
   String? getTypeSource(DartType type, Set<Source> librariesToImport,
       {StringBuffer? parametersBuffer}) {
-    var aliasElement = type.aliasElement;
-    var aliasArguments = type.aliasArguments;
-    if (aliasElement != null && aliasArguments != null) {
+    var alias = type.alias;
+    if (alias != null) {
       return _getTypeCodeElementArguments(
         librariesToImport: librariesToImport,
-        element: aliasElement,
+        element: alias.element,
         isNullable: type.nullabilitySuffix == NullabilitySuffix.question,
-        typeArguments: aliasArguments,
+        typeArguments: alias.typeArguments,
       );
     }
 
diff --git a/pkg/analysis_server/lib/src/services/flutter/property.dart b/pkg/analysis_server/lib/src/services/flutter/property.dart
index 11af175..2a6586d 100644
--- a/pkg/analysis_server/lib/src/services/flutter/property.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/property.dart
@@ -118,7 +118,7 @@
       );
     }
 
-    await builder.addDartFileEdit(resolvedUnit.path!, (builder) {
+    await builder.addDartFileEdit(resolvedUnit.path, (builder) {
       _changeCode(builder, (builder) {
         var expression = value.expression;
         if (expression != null) {
@@ -155,7 +155,7 @@
       }
 
       var beginOffset = argumentExpression.offset;
-      await builder.addDartFileEdit(resolvedUnit.path!, (builder) {
+      await builder.addDartFileEdit(resolvedUnit.path, (builder) {
         builder.addDeletion(
           SourceRange(beginOffset, endOffset - beginOffset),
         );
@@ -559,7 +559,7 @@
 
     var builder = ChangeBuilder(session: property.resolvedUnit.session);
 
-    await builder.addDartFileEdit(property.resolvedUnit.path!, (builder) {
+    await builder.addDartFileEdit(property.resolvedUnit.path, (builder) {
       property._changeCode(builder, (builder) {
         if (leftCode == rightCode && topCode == bottomCode) {
           builder.writeReference(classEdgeInsets);
@@ -659,7 +659,7 @@
 
   String? _expressionCode(Expression? expression) {
     if (expression != null) {
-      var content = property.resolvedUnit.content!;
+      var content = property.resolvedUnit.content;
       return content.substring(expression.offset, expression.end);
     }
     return null;
diff --git a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
index f38a7cc..77da5dda 100644
--- a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
@@ -336,7 +336,7 @@
 
     String? valueExpressionCode;
     if (valueExpression != null) {
-      valueExpressionCode = resolvedUnit.content!.substring(
+      valueExpressionCode = resolvedUnit.content.substring(
         valueExpression.offset,
         valueExpression.end,
       );
diff --git a/pkg/analysis_server/lib/src/services/pub/pub_command.dart b/pkg/analysis_server/lib/src/services/pub/pub_command.dart
new file mode 100644
index 0000000..a649d65
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/pub/pub_command.dart
@@ -0,0 +1,149 @@
+// 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:convert';
+import 'dart:io';
+
+import 'package:analysis_server/src/utilities/process.dart';
+import 'package:analyzer/instrumentation/service.dart';
+import 'package:path/path.dart' as path;
+
+/// A class for interacting with the `pub` command.
+///
+/// `pub` commands will be queued and not run concurrently.
+class PubCommand {
+  static const String _pubEnvironmentKey = 'PUB_ENVIRONMENT';
+  final InstrumentationService _instrumentationService;
+  late final ProcessRunner _processRunner;
+  late final String _pubPath;
+  late final String _pubEnvironmentValue;
+
+  /// Tracks the last queued command to avoid overlapping because pub does not
+  /// do its own locking when accessing the cache.
+  ///
+  /// https://github.com/dart-lang/pub/issues/1178
+  ///
+  /// This does not prevent running concurrently with commands spawned by other
+  /// tools (such as the IDE).
+  var _lastQueuedCommand = Future<void>.value();
+
+  PubCommand(this._instrumentationService, this._processRunner) {
+    _pubPath = path.join(
+      path.dirname(Platform.resolvedExecutable),
+      Platform.isWindows ? 'pub.bat' : 'pub',
+    );
+
+    // When calling the `pub` command, we must add an identifier to the
+    // PUB_ENVIRONMENT environment variable (joined with colons).
+    const _pubEnvString = 'analysis_server.pub_api';
+    final existingPubEnv = Platform.environment[_pubEnvironmentKey];
+    _pubEnvironmentValue = [
+      if (existingPubEnv?.isNotEmpty ?? false) existingPubEnv,
+      _pubEnvString,
+    ].join(':');
+  }
+
+  /// Runs `pub outdated --show-all` and returns the results.
+  ///
+  /// If any error occurs executing the command, returns an empty list.
+  Future<List<PubOutdatedPackageDetails>> outdatedVersions(
+      String pubspecPath) async {
+    final packageDirectory = path.dirname(pubspecPath);
+    final result = await _runPubJsonCommand(
+        ['outdated', '--show-all', '--json'],
+        workingDirectory: packageDirectory);
+
+    if (result == null) {
+      return [];
+    }
+
+    final packages =
+        (result['packages'] as List<dynamic>?)?.cast<Map<String, Object?>>();
+    if (packages == null) {
+      return [];
+    }
+
+    return packages
+        .map(
+          (json) => PubOutdatedPackageDetails(
+            json['package'] as String,
+            currentVersion: _version(json, 'current'),
+            latestVersion: _version(json, 'latest'),
+            resolvableVersion: _version(json, 'resolvable'),
+            upgradableVersion: _version(json, 'upgradable'),
+          ),
+        )
+        .toList();
+  }
+
+  /// Runs a pub command and decodes JSON from `stdout`.
+  ///
+  /// Returns null if:
+  ///   - exit code is non-zero
+  ///   - returned text cannot be decoded as JSON
+  Future<Map<String, Object?>?> _runPubJsonCommand(List<String> args,
+      {required String workingDirectory}) async {
+    // Atomically replace the lastQueuedCommand future with our own to ensure
+    // only one command waits on any previous commands future.
+    final completer = Completer<void>();
+    final lastCommand = _lastQueuedCommand;
+    _lastQueuedCommand = completer.future;
+    // And wait for that previous command to finish.
+    await lastCommand.catchError((_) {});
+
+    try {
+      final command = [_pubPath, ...args];
+
+      _instrumentationService.logInfo('Running pub command $command');
+      final result = await _processRunner.run(_pubPath, args,
+          workingDirectory: workingDirectory,
+          environment: {_pubEnvironmentKey: _pubEnvironmentValue});
+
+      if (result.exitCode != 0) {
+        _instrumentationService.logError(
+            'pub command returned ${result.exitCode} exit code: ${result.stderr}.');
+        return null;
+      }
+
+      try {
+        final results = jsonDecode(result.stdout);
+        _instrumentationService.logInfo('pub command completed successfully');
+        return results;
+      } catch (e) {
+        _instrumentationService
+            .logError('pub command returned invalid JSON: $e.');
+        return null;
+      }
+    } catch (e) {
+      _instrumentationService.logError('pub command failed to run: $e.');
+      return null;
+    } finally {
+      completer.complete();
+    }
+  }
+
+  String? _version(Map<String, Object?> json, String type) {
+    final versionType = json[type] as Map<String, Object?>?;
+    final version =
+        versionType != null ? versionType['version'] as String? : null;
+    return version;
+  }
+}
+
+class PubOutdatedPackageDetails {
+  final String packageName;
+  final String? currentVersion;
+  final String? latestVersion;
+  final String? resolvableVersion;
+  final String? upgradableVersion;
+
+  PubOutdatedPackageDetails(
+    this.packageName, {
+    required this.currentVersion,
+    required this.latestVersion,
+    required this.resolvableVersion,
+    required this.upgradableVersion,
+  });
+}
diff --git a/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart b/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
index d0990db..4b6ef3a8 100644
--- a/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
+++ b/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
@@ -6,10 +6,11 @@
 import 'dart:convert';
 
 import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/service.dart';
 import 'package:meta/meta.dart';
+import 'package:path/path.dart' as path;
 
 /// Information about Pub packages that can be converted to/from JSON and
 /// cached to disk.
@@ -130,16 +131,26 @@
 
 /// A service for providing Pub package information.
 ///
-/// Uses a [PubApi] to communicate with Pub and caches to disk using [cacheResourceProvider].
+/// Uses a [PubApi] to communicate with the Pub API and a [PubCommand] to
+/// interact with the local `pub` command.
+///
+/// Expensive results are cached to disk using [resourceProvider].
 class PubPackageService {
   final InstrumentationService _instrumentationService;
   final PubApi _api;
+
+  /// A wrapper over the "pub" command line too.
+  ///
+  /// This can be null when not running on a real file system because it may
+  /// try to interact with folders that don't really exist.
+  final PubCommand? _command;
+
   Timer? _nextPackageNameListRequestTimer;
   Timer? _nextWriteDiskCacheTimer;
 
-  /// [ResourceProvider] used for caching. This should generally be a
-  /// [PhysicalResourceProvider] outside of tests.
-  final ResourceProvider cacheResourceProvider;
+  /// [ResourceProvider] used for accessing the disk for caches and checking
+  /// project types. This will be a [PhysicalResourceProvider] outside of tests.
+  final ResourceProvider resourceProvider;
 
   /// The current cache of package information. Initially `null`, but
   /// overwritten after first read of cache from disk or fetch from the API.
@@ -148,25 +159,50 @@
 
   int _packageDetailsRequestsInFlight = 0;
 
-  PubPackageService(
-      this._instrumentationService, this.cacheResourceProvider, this._api);
+  /// A cache of version numbers from running the "pub outdated" command used
+  /// for completion in pubspec.yaml.
+  final _pubspecPackageVersions =
+      <String, Map<String, PubOutdatedPackageDetails>>{};
 
-  /// Gets the last set of package results or an empty List if no results.
+  PubPackageService(this._instrumentationService, this.resourceProvider,
+      this._api, this._command);
+
+  /// Gets the last set of package results from the Pub API or an empty List if
+  /// no results.
+  ///
+  /// This data is used for completion of package names in pubspec.yaml
+  /// and for clients that support lazy resolution of completion items may also
+  /// include their descriptions and/or version numbers.
   List<PubPackage> get cachedPackages =>
       packageCache?.packages.values.toList() ?? [];
 
-  bool get isRunning => _nextPackageNameListRequestTimer != null;
+  @visibleForTesting
+  bool get isPackageNamesTimerRunning =>
+      _nextPackageNameListRequestTimer != null;
 
   @visibleForTesting
   File get packageCacheFile {
-    final cacheFolder = cacheResourceProvider
+    final cacheFolder = resourceProvider
         .getStateLocation('.pub-package-details-cache')!
       ..create();
     return cacheFolder.getChildAssumingFile('packages.json');
   }
 
-  /// Begin a request to pre-load the package name list.
+  /// Begins preloading caches for package names and pub versions.
+  void beginCachePreloads(List<String> pubspecs) {
+    beginPackageNamePreload();
+    for (final pubspec in pubspecs) {
+      fetchPackageVersionsViaPubOutdated(pubspec, pubspecWasModified: false);
+    }
+  }
+
+  /// Begin a timer to pre-load and update the package name list if one has not
+  /// already been started.
   void beginPackageNamePreload() {
+    if (isPackageNamesTimerRunning) {
+      return;
+    }
+
     // If first time, try to read from disk.
     var cache = packageCache;
     if (cache == null) {
@@ -179,11 +215,69 @@
         Timer(cache.cacheTimeRemaining, _fetchFromServer);
   }
 
-  /// Gets the cached package details for package [packageName].
+  /// Gets the latest cached package version fetched from the Pub API for the
+  /// package [packageName].
+  String? cachedPubApiLatestVersion(String packageName) =>
+      packageCache?.packages[packageName]?.latestVersion;
+
+  /// Gets the package versions cached using "pub outdated" for the package
+  /// [packageName] for the project using [pubspecPath].
   ///
-  /// Returns null if no package details are cached.
-  PubPackage? cachedPackageDetails(String packageName) =>
-      packageCache?.packages[packageName];
+  /// Versions in here might only be available for packages that are in the
+  /// pubspec on disk. Newly-added packages in the overlay might not be
+  /// available.
+  PubOutdatedPackageDetails? cachedPubOutdatedVersions(
+      String pubspecPath, String packageName) {
+    final pubspecCache = _pubspecPackageVersions[pubspecPath];
+    return pubspecCache != null ? pubspecCache[packageName] : null;
+  }
+
+  /// Begin a request to pre-load package versions using the "pub outdated"
+  /// command.
+  ///
+  /// If [pubspecWasModified] is true, the command will always be run. Otherwise it
+  /// will only be run if data is not already cached.
+  Future<void> fetchPackageVersionsViaPubOutdated(String pubspecPath,
+      {required bool pubspecWasModified}) async {
+    final pubCommand = _command;
+    if (pubCommand == null) {
+      return;
+    }
+
+    // If we already have a cache for the file and it was not modified (only
+    // opened) we do not need to re-run the command.
+    if (!pubspecWasModified &&
+        _pubspecPackageVersions.containsKey(pubspecPath)) {
+      return;
+    }
+
+    // Check if this pubspec is inside a DEPS-managed folder, and if so
+    // just cache an empty set of results since Pub is not managing
+    // dependencies.
+    if (_hasAncestorDEPSFile(pubspecPath)) {
+      _pubspecPackageVersions.putIfAbsent(pubspecPath, () => {});
+      return;
+    }
+
+    final results = await pubCommand.outdatedVersions(pubspecPath);
+    final cache = _pubspecPackageVersions.putIfAbsent(pubspecPath, () => {});
+    for (final package in results) {
+      // We use the versions from the "pub outdated" results but only cache them
+      // in-memory for this specific pubspec, as the resolved version may be
+      // restricted by constraints/dependencies in the pubspec. The "pub"
+      // command does caching of the JSON versions to make "pub outdated" fast.
+      cache[package.packageName] = package;
+    }
+  }
+
+  /// Clears package caches for [pubspecPath].
+  ///
+  /// Does not remove other caches that are not pubspec-specific (for example
+  /// the latest version pulled directly from the Pub API independant of
+  /// pubspec).
+  Future<void> flushPackageCaches(String pubspecPath) async {
+    _pubspecPackageVersions.remove(pubspecPath);
+  }
 
   /// Gets package details for package [packageName].
   ///
@@ -267,6 +361,19 @@
     }
   }
 
+  /// Checks whether there is a DEPS file in any folder walking up from the
+  /// pubspec at [pubspecPath].
+  bool _hasAncestorDEPSFile(String pubspecPath) {
+    var folder = path.dirname(pubspecPath);
+    do {
+      if (resourceProvider.getFile(path.join(folder, 'DEPS')).exists) {
+        return true;
+      }
+      folder = path.dirname(folder);
+    } while (folder != path.dirname(folder));
+    return false;
+  }
+
   /// Writes the package cache to disk after
   /// [PackageDetailsCache._writeCacheDebounceDuration] has elapsed, restarting
   /// the timer each time this method is called.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
index 2432c5b..7d361dc 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -61,12 +61,12 @@
     utils = CorrectionUtils(resolveResult);
   }
 
-  String get file => resolveResult.path!;
+  String get file => resolveResult.path;
 
   @override
   String get refactoringName => 'Extract Local Variable';
 
-  CompilationUnit get unit => resolveResult.unit!;
+  CompilationUnit get unit => resolveResult.unit;
 
   CompilationUnitElement get unitElement => unit.declaredElement!;
 
@@ -231,7 +231,7 @@
       return RefactoringStatus.fatal(
           'The selection offset must be greater than zero.');
     }
-    if (selectionOffset + selectionLength >= resolveResult.content!.length) {
+    if (selectionOffset + selectionLength >= resolveResult.content.length) {
       return RefactoringStatus.fatal(
           'The selection end offset must be less then the length of the file.');
     }
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index a2c9a19..ebb50c0 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -297,7 +297,7 @@
       // add replace edit
       var edit = newSourceEdit_range(range, invocationSource);
       doSourceChange_addElementEdit(
-          change, resolveResult.unit!.declaredElement!, edit);
+          change, resolveResult.unit.declaredElement!, edit);
     }
     // add method declaration
     {
@@ -378,7 +378,7 @@
         var offset = _parentMember!.end;
         var edit = SourceEdit(offset, 0, '$eol$eol$prefix$declarationSource');
         doSourceChange_addElementEdit(
-            change, resolveResult.unit!.declaredElement!, edit);
+            change, resolveResult.unit.declaredElement!, edit);
       }
     }
     // done
@@ -450,7 +450,7 @@
       return RefactoringStatus.fatal(
           'The selection offset must be greater than zero.');
     }
-    if (selectionOffset + selectionLength >= resolveResult.content!.length) {
+    if (selectionOffset + selectionLength >= resolveResult.content.length) {
       return RefactoringStatus.fatal(
           'The selection end offset must be less then the length of the file.');
     }
@@ -658,12 +658,11 @@
     var originalSource = utils.getText(range.offset, range.length);
     var pattern = _SourcePattern();
     var replaceEdits = <SourceEdit>[];
-    resolveResult.unit!
-        .accept(_GetSourcePatternVisitor(range, pattern, replaceEdits));
+    resolveResult.unit.accept(_GetSourcePatternVisitor(range, pattern, replaceEdits));
     replaceEdits = replaceEdits.reversed.toList();
     var source = SourceEdit.applySequence(originalSource, replaceEdits);
     pattern.normalizedSource =
-        _getNormalizedSource(source, resolveResult.unit!.featureSet);
+        _getNormalizedSource(source, resolveResult.unit.featureSet);
     return pattern;
   }
 
@@ -706,7 +705,7 @@
     var result = RefactoringStatus();
     var assignedUsedVariables = <VariableElement>[];
 
-    var unit = resolveResult.unit!;
+    var unit = resolveResult.unit;
     _visibleRangeMap = VisibleRangesComputer.forNode(unit);
     unit.accept(
       _InitializeParametersVisitor(this, assignedUsedVariables),
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
index 36304e9..6fe4778 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -85,7 +85,7 @@
   }
 
   FeatureSet get _featureSet {
-    return resolveResult.unit!.featureSet;
+    return resolveResult.unit.featureSet;
   }
 
   Flutter get _flutter => Flutter.instance;
@@ -144,7 +144,7 @@
   Future<SourceChange> createChange() async {
     var builder =
         ChangeBuilder(session: sessionHelper.session, eol: utils.endOfLine);
-    await builder.addDartFileEdit(resolveResult.path!, (builder) {
+    await builder.addDartFileEdit(resolveResult.path, (builder) {
       final expression = _expression;
       final statements = _statements;
       if (expression != null) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
index c7577b6..e0f3df71 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
@@ -114,7 +114,7 @@
   @override
   Future<SourceChange> createChange() {
     var change = SourceChange(refactoringName);
-    var unitElement = resolveResult.unit!.declaredElement!;
+    var unitElement = resolveResult.unit.declaredElement!;
     var state = _initialState!;
     // remove declaration
     {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
index 1cff243..f3e4b67 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -363,7 +363,7 @@
     _methodNode = methodNode;
 
     var resolvedUnit = declaration.resolvedUnit!;
-    _methodUnit = resolvedUnit.unit!;
+    _methodUnit = resolvedUnit.unit;
     _methodUtils = CorrectionUtils(resolvedUnit);
 
     if (methodNode is MethodDeclaration) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
index b8535bd..f768861 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
@@ -71,7 +71,7 @@
   @override
   Future<SourceChange> createChange() async {
     var changeBuilder = ChangeBuilder(session: resolvedUnit.session);
-    var element = resolvedUnit.unit!.declaredElement;
+    var element = resolvedUnit.unit.declaredElement;
     if (element == null) {
       return changeBuilder.sourceChange;
     }
@@ -85,21 +85,21 @@
     if (element == libraryElement.definingCompilationUnit) {
       // Handle part-of directives in this library
       var libraryResult = await driver.currentSession
-          .getResolvedLibraryByElement2(libraryElement);
+          .getResolvedLibraryByElement(libraryElement);
       if (libraryResult is! ResolvedLibraryResult) {
         return changeBuilder.sourceChange;
       }
-      var definingUnitResult = libraryResult.units!.first;
-      for (var result in libraryResult.units!) {
+      var definingUnitResult = libraryResult.units.first;
+      for (var result in libraryResult.units) {
         if (result.isPart) {
-          var partOfs = result.unit!.directives
+          var partOfs = result.unit.directives
               .whereType<PartOfDirective>()
               .map((e) => e.uri)
               .whereNotNull()
               .where((uri) => _isRelativeUri(uri.stringValue));
           if (partOfs.isNotEmpty) {
             await changeBuilder.addDartFileEdit(
-                result.unit!.declaredElement!.source.fullName, (builder) {
+                result.unit.declaredElement!.source.fullName, (builder) {
               partOfs.forEach((uri) {
                 var newLocation =
                     pathContext.join(newDir, pathos.basename(newFile));
@@ -113,9 +113,8 @@
       }
 
       if (newDir != oldDir) {
-        await changeBuilder.addDartFileEdit(definingUnitResult.path!,
-            (builder) {
-          for (var directive in definingUnitResult.unit!.directives) {
+        await changeBuilder.addDartFileEdit(definingUnitResult.path, (builder) {
+          for (var directive in definingUnitResult.unit.directives) {
             if (directive is UriBasedDirective) {
               _updateUriReference(builder, directive, oldDir, newDir);
             }
@@ -124,7 +123,7 @@
       }
     } else if (newDir != oldDir) {
       // Otherwise, we need to update any relative part-of references.
-      var partOfs = resolvedUnit.unit!.directives
+      var partOfs = resolvedUnit.unit.directives
           .whereType<PartOfDirective>()
           .map((e) => e.uri)
           .whereNotNull()
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
index 422d944..91654f8 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
@@ -334,9 +334,6 @@
         }
 
         var unit = result.unit;
-        if (unit == null) {
-          return const [];
-        }
 
         var collector = _LocalElementsCollector(name);
         unit.accept(collector);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
index 5367235..f0b65ab 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
@@ -165,9 +165,6 @@
         }
 
         var unit = result.unit;
-        if (unit == null) {
-          return const [];
-        }
 
         var collector = _LocalElementsCollector(name);
         unit.accept(collector);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
index 2dfbd42..4042b04 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
@@ -108,7 +108,7 @@
   ImportDirective? _findNode() {
     var library = element.library;
     var path = library.source.fullName;
-    var unitResult = session.getParsedUnit2(path);
+    var unitResult = session.getParsedUnit(path);
     if (unitResult is! ParsedUnitResult) {
       return null;
     }
@@ -122,7 +122,7 @@
   /// it. Otherwise return `null`.
   SimpleIdentifier? _getInterpolationIdentifier(SourceReference reference) {
     var source = reference.element.source!;
-    var unitResult = session.getParsedUnit2(source.fullName);
+    var unitResult = session.getParsedUnit(source.fullName);
     if (unitResult is! ParsedUnitResult) {
       return null;
     }
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 610be65..999bc4d 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -246,7 +246,7 @@
     var result = await driver.getResult2(filePath);
     if (result is ResolvedUnitResult) {
       var writer = AstWriter(buf);
-      result.unit!.accept(writer);
+      result.unit.accept(writer);
     } else {
       p(
           'An AST could not be produced for the file '
@@ -836,7 +836,7 @@
     var result = await driver.getResult2(filePath);
     CompilationUnitElement? compilationUnitElement;
     if (result is ResolvedUnitResult) {
-      compilationUnitElement = result.unit?.declaredElement;
+      compilationUnitElement = result.unit.declaredElement;
     }
     if (compilationUnitElement != null) {
       var writer = ElementWriter(buf);
diff --git a/pkg/analysis_server/lib/src/utilities/mocks.dart b/pkg/analysis_server/lib/src/utilities/mocks.dart
index 5022dcd..9c581cd 100644
--- a/pkg/analysis_server/lib/src/utilities/mocks.dart
+++ b/pkg/analysis_server/lib/src/utilities/mocks.dart
@@ -146,6 +146,8 @@
   plugin.AnalysisUpdateContentParams? analysisUpdateContentParams;
   plugin.RequestParams? broadcastedRequest;
   Map<PluginInfo, Future<plugin.Response>>? broadcastResults;
+  Map<PluginInfo, Future<plugin.Response>>? Function(plugin.RequestParams)?
+      handleRequest;
 
   @override
   List<PluginInfo> plugins = [];
@@ -192,7 +194,9 @@
       plugin.RequestParams params,
       {analyzer.ContextRoot? contextRoot}) {
     broadcastedRequest = params;
-    return broadcastResults ?? <PluginInfo, Future<plugin.Response>>{};
+    return handleRequest?.call(params) ??
+        broadcastResults ??
+        <PluginInfo, Future<plugin.Response>>{};
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/utilities/process.dart b/pkg/analysis_server/lib/src/utilities/process.dart
new file mode 100644
index 0000000..70ea179
--- /dev/null
+++ b/pkg/analysis_server/lib/src/utilities/process.dart
@@ -0,0 +1,32 @@
+// 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:convert';
+import 'dart:io';
+
+/// An abstraction over [Process] from 'dart:io' to allow mocking in tests.
+class ProcessRunner {
+  Future<ProcessResult> run(
+    String executable,
+    List<String> arguments, {
+    String? workingDirectory,
+    Map<String, String>? environment,
+    bool includeParentEnvironment = true,
+    bool runInShell = false,
+    Encoding? stdoutEncoding = systemEncoding,
+    Encoding? stderrEncoding = systemEncoding,
+  }) async {
+    return Process.run(
+      executable,
+      arguments,
+      workingDirectory: workingDirectory,
+      environment: environment,
+      includeParentEnvironment: includeParentEnvironment,
+      runInShell: runInShell,
+      stdoutEncoding: stdoutEncoding,
+      stderrEncoding: stderrEncoding,
+    );
+  }
+}
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index f628981..fb9d441 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -90,7 +90,7 @@
     var analysisContext = contextFor(testPackageRootPath);
     var files = analysisContext.contextRoot.analyzedFiles().toList();
     for (var path in files) {
-      await analysisContext.currentSession.getResolvedUnit2(path);
+      await analysisContext.currentSession.getResolvedUnit(path);
     }
   }
 
@@ -172,7 +172,7 @@
   Future<ResolvedUnitResult> resolveFile(String path) async {
     path = convertPath(path);
     var session = contextFor(path).currentSession;
-    return await session.getResolvedUnit2(path) as ResolvedUnitResult;
+    return await session.getResolvedUnit(path) as ResolvedUnitResult;
   }
 
   @mustCallSuper
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index e479d9c..b18416c 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -70,10 +70,10 @@
   }
 
   Future<void> resolveTestFile() async {
-    var result = await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
+    var result = await session.getResolvedUnit(testFile) as ResolvedUnitResult;
     testAnalysisResult = result;
-    testCode = result.content!;
-    testUnit = result.unit!;
+    testCode = result.content;
+    testUnit = result.unit;
     if (verifyNoTestUnitErrors) {
       expect(result.errors.where((AnalysisError error) {
         return error.errorCode != HintCode.DEAD_CODE &&
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index 53ba68b..ff64169 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -73,7 +73,7 @@
     var fixes = plugin.AnalysisErrorFixes(AnalysisError(
         AnalysisErrorSeverity.ERROR,
         AnalysisErrorType.HINT,
-        Location('', 0, 0, 0, 0, 0, 0),
+        Location('', 0, 0, 0, 0, endLine: 0, endColumn: 0),
         'message',
         'code'));
     var result = plugin.EditGetFixesResult(<plugin.AnalysisErrorFixes>[fixes]);
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 3c0e282..3c3eecb 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1104,15 +1104,16 @@
 ///   "length": int
 ///   "startLine": int
 ///   "startColumn": int
-///   "endLine": int
-///   "endColumn": int
+///   "endLine": optional int
+///   "endColumn": optional int
 /// }
 final Matcher isLocation = LazyMatcher(() => MatchesJsonObject('Location', {
       'file': isFilePath,
       'offset': isInt,
       'length': isInt,
       'startLine': isInt,
-      'startColumn': isInt,
+      'startColumn': isInt
+    }, optionalFields: {
       'endLine': isInt,
       'endColumn': isInt
     }));
diff --git a/pkg/analysis_server/test/lsp/client_configuration_test.dart b/pkg/analysis_server/test/lsp/client_configuration_test.dart
new file mode 100644
index 0000000..86788dc
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/client_configuration_test.dart
@@ -0,0 +1,62 @@
+// 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/lsp/client_configuration.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';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ClientConfigurationTest);
+  });
+}
+
+@reflectiveTest
+class ClientConfigurationTest with ResourceProviderMixin {
+  void test_folderConfig() {
+    final folder = convertPath('/home/test');
+    final file = convertPath('/home/test/file.dart');
+    final config = LspClientConfiguration();
+    config.replace(
+      {'lineLength': 100},
+      {
+        folder: {'lineLength': 200}
+      },
+    );
+    expect(config.forResource(file).lineLength, equals(200));
+  }
+
+  void test_folderConfig_globalFallback() {
+    final file = convertPath('/home/test/file.dart');
+    final config = LspClientConfiguration();
+    config.replace({'lineLength': 100}, {});
+    // Should fall back to the global config.
+    expect(config.forResource(file).lineLength, equals(100));
+  }
+
+  void test_folderConfig_nested() {
+    final folderOne = convertPath('/one');
+    final folderTwo = convertPath('/one/two');
+    final folderThree = convertPath('/one/two/three');
+    final file = convertPath('/one/two/three/file.dart');
+    final config = LspClientConfiguration();
+    config.replace(
+      {'lineLength': 50},
+      {
+        folderOne: {'lineLength': 100},
+        folderThree: {'lineLength': 300},
+        folderTwo: {'lineLength': 200},
+      },
+    );
+    // Should use the inner-most folder (folderThree).
+    expect(config.forResource(file).lineLength, equals(300));
+  }
+
+  void test_globalConfig() {
+    final config = LspClientConfiguration();
+    config.replace({'lineLength': 100}, {});
+    expect(config.global.lineLength, equals(100));
+  }
+}
diff --git a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
index 67323f9..2797109 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -7,6 +7,8 @@
 import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:collection/collection.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -166,6 +168,87 @@
     expect(codeActions, isEmpty);
   }
 
+  Future<void> test_plugin() async {
+    // This code should get an assist to replace 'foo' with 'bar'.'
+    const content = '[[foo]]';
+    const expectedContent = 'bar';
+
+    final pluginResult = plugin.EditGetAssistsResult([
+      plugin.PrioritizedSourceChange(
+        0,
+        plugin.SourceChange(
+          "Change 'foo' to 'bar'",
+          edits: [
+            plugin.SourceFileEdit(mainFilePath, 0,
+                edits: [plugin.SourceEdit(0, 3, 'bar')])
+          ],
+          id: 'fooToBar',
+        ),
+      )
+    ]);
+    configureTestPlugin(
+      handler: (request) =>
+          request is plugin.EditGetAssistsParams ? pluginResult : null,
+    );
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+    );
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final assist = findEditAction(codeActions,
+        CodeActionKind('refactor.fooToBar'), "Change 'foo' to 'bar'")!;
+
+    final edit = assist.edit!;
+    expect(edit.changes, isNotNull);
+
+    // Ensure applying the changes will give us the expected content.
+    final contents = {
+      mainFilePath: withoutMarkers(content),
+    };
+    applyChanges(contents, edit.changes!);
+    expect(contents[mainFilePath], equals(expectedContent));
+  }
+
+  Future<void> test_plugin_sortsWithServer() async {
+    // Produces a server assist of "Convert to single quoted string" (with a
+    // priority of 30).
+    const content = 'import "[[dart:async]]";';
+
+    // Provide two plugin results that should sort either side of the server assist.
+    final pluginResult = plugin.EditGetAssistsResult([
+      plugin.PrioritizedSourceChange(10, plugin.SourceChange('Low')),
+      plugin.PrioritizedSourceChange(100, plugin.SourceChange('High')),
+    ]);
+    configureTestPlugin(
+      handler: (request) =>
+          request is plugin.EditGetAssistsParams ? pluginResult : null,
+    );
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+    );
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeActionTitles = codeActions.map((action) =>
+        action.map((command) => command.title, (action) => action.title));
+
+    expect(
+      codeActionTitles,
+      containsAllInOrder([
+        'High',
+        'Convert to single quoted string',
+        'Low',
+      ]),
+    );
+  }
+
   Future<void> test_snippetTextEdits_supported() async {
     // This tests experimental support for including Snippets in TextEdits.
     // https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
diff --git a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
index 2a9184a..925b13b 100644
--- a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:linter/src/rules.dart';
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
@@ -350,6 +352,111 @@
     final codeActions = await getCodeActions(otherFileUri.toString());
     expect(codeActions, isEmpty);
   }
+
+  Future<void> test_plugin() async {
+    // This code should get a fix to replace 'foo' with 'bar'.'
+    const content = '[[foo]]';
+    const expectedContent = 'bar';
+
+    final pluginResult = plugin.EditGetFixesResult([
+      plugin.AnalysisErrorFixes(
+        plugin.AnalysisError(
+          plugin.AnalysisErrorSeverity.ERROR,
+          plugin.AnalysisErrorType.HINT,
+          plugin.Location(mainFilePath, 0, 3, 0, 0),
+          "Do not use 'foo'",
+          'do_not_use_foo',
+        ),
+        fixes: [
+          plugin.PrioritizedSourceChange(
+            0,
+            plugin.SourceChange(
+              "Change 'foo' to 'bar'",
+              edits: [
+                plugin.SourceFileEdit(mainFilePath, 0,
+                    edits: [plugin.SourceEdit(0, 3, 'bar')])
+              ],
+              id: 'fooToBar',
+            ),
+          )
+        ],
+      )
+    ]);
+    configureTestPlugin(
+      handler: (request) =>
+          request is plugin.EditGetFixesParams ? pluginResult : null,
+    );
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+    );
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final assist = findEditAction(codeActions,
+        CodeActionKind('quickfix.fooToBar'), "Change 'foo' to 'bar'")!;
+
+    final edit = assist.edit!;
+    expect(edit.changes, isNotNull);
+
+    // Ensure applying the changes will give us the expected content.
+    final contents = {
+      mainFilePath: withoutMarkers(content),
+    };
+    applyChanges(contents, edit.changes!);
+    expect(contents[mainFilePath], equals(expectedContent));
+  }
+
+  Future<void> test_plugin_sortsWithServer() async {
+    // Produces a server fix for removing unused import with a default
+    // priority of 50.
+    const content = '''
+[[import]] 'dart:convert';
+''';
+
+    // Provide two plugin results that should sort either side of the server fix.
+    final pluginResult = plugin.EditGetFixesResult([
+      plugin.AnalysisErrorFixes(
+        plugin.AnalysisError(
+          plugin.AnalysisErrorSeverity.ERROR,
+          plugin.AnalysisErrorType.HINT,
+          plugin.Location(mainFilePath, 0, 3, 0, 0),
+          'Dummy error',
+          'dummy',
+        ),
+        fixes: [
+          plugin.PrioritizedSourceChange(10, plugin.SourceChange('Low')),
+          plugin.PrioritizedSourceChange(100, plugin.SourceChange('High')),
+        ],
+      )
+    ]);
+    configureTestPlugin(
+      handler: (request) =>
+          request is plugin.EditGetFixesParams ? pluginResult : null,
+    );
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+    );
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeActionTitles = codeActions.map((action) =>
+        action.map((command) => command.title, (action) => action.title));
+
+    expect(
+      codeActionTitles,
+      containsAllInOrder([
+        'High',
+        'Remove unused import',
+        'Low',
+      ]),
+    );
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index 5ebc918..e8921f7 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -20,10 +20,76 @@
     defineReflectiveTests(ExtractVariableRefactorCodeActionsTest);
     defineReflectiveTests(InlineLocalVariableRefactorCodeActionsTest);
     defineReflectiveTests(InlineMethodRefactorCodeActionsTest);
+    defineReflectiveTests(ConvertGetterToMethodCodeActionsTest);
+    defineReflectiveTests(ConvertMethodToGetterCodeActionsTest);
   });
 }
 
 @reflectiveTest
+class ConvertGetterToMethodCodeActionsTest extends AbstractCodeActionsTest {
+  final refactorTitle = 'Convert Getter to Method';
+
+  Future<void> test_refactor() async {
+    const content = '''
+int get ^test => 42;
+main() {
+  var a = test;
+  var b = test;
+}
+''';
+    const expectedContent = '''
+int test() => 42;
+main() {
+  var a = test();
+  var b = test();
+}
+''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        position: positionFromMarker(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, refactorTitle)!;
+
+    await verifyCodeActionEdits(
+        codeAction, withoutMarkers(content), expectedContent);
+  }
+}
+
+@reflectiveTest
+class ConvertMethodToGetterCodeActionsTest extends AbstractCodeActionsTest {
+  final refactorTitle = 'Convert Method to Getter';
+
+  Future<void> test_refactor() async {
+    const content = '''
+int ^test() => 42;
+main() {
+  var a = test();
+  var b = test();
+}
+''';
+    const expectedContent = '''
+int get test => 42;
+main() {
+  var a = test;
+  var b = test;
+}
+''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        position: positionFromMarker(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, refactorTitle)!;
+
+    await verifyCodeActionEdits(
+        codeAction, withoutMarkers(content), expectedContent);
+  }
+}
+
+@reflectiveTest
 class ExtractMethodRefactorCodeActionsTest extends AbstractCodeActionsTest {
   final extractMethodTitle = 'Extract Method';
 
@@ -176,7 +242,12 @@
 }
     ''';
     newFile(mainFilePath, content: withoutMarkers(content));
-    await initialize();
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+        emptyTextDocumentClientCapabilities,
+        [CodeActionKind.Empty], // Support everything (empty prefix matches all)
+      ),
+    );
 
     final ofKind = (CodeActionKind kind) => getCodeActions(
           mainFileUri.toString(),
@@ -184,13 +255,31 @@
           kinds: [kind],
         );
 
-    // The code above will return a RefactorExtract that should be included
-    // by both Refactor and RefactorExtract, but not RefactorExtractFoo or
-    // RefactorRewrite
-    expect(await ofKind(CodeActionKind.Refactor), isNotEmpty);
-    expect(await ofKind(CodeActionKind.RefactorExtract), isNotEmpty);
-    expect(await ofKind(CodeActionKind('refactor.extract.foo')), isEmpty);
-    expect(await ofKind(CodeActionKind.RefactorRewrite), isEmpty);
+    // Helper that requests CodeActions for [kind] and ensures all results
+    // returned have either an equal kind, or a kind that is prefixed with the
+    // requested kind followed by a dot.
+    Future<void> checkResults(CodeActionKind kind) async {
+      final results = await ofKind(kind);
+      for (final result in results) {
+        final resultKind = result.map(
+          (cmd) => throw 'Expected CodeAction, got Command: ${cmd.title}',
+          (action) => action.kind,
+        );
+        expect(
+          '$resultKind',
+          anyOf([
+            equals('$kind'),
+            startsWith('$kind.'),
+          ]),
+        );
+      }
+    }
+
+    // Check a few of each that will produces multiple matches and no matches.
+    await checkResults(CodeActionKind.Refactor);
+    await checkResults(CodeActionKind.RefactorExtract);
+    await checkResults(CodeActionKind('refactor.extract.foo'));
+    await checkResults(CodeActionKind.RefactorRewrite);
   }
 
   Future<void> test_generatesNames() async {
diff --git a/pkg/analysis_server/test/lsp/completion.dart b/pkg/analysis_server/test/lsp/completion.dart
index 75c85b1..6d70a26 100644
--- a/pkg/analysis_server/test/lsp/completion.dart
+++ b/pkg/analysis_server/test/lsp/completion.dart
@@ -8,6 +8,9 @@
 import 'server_abstract.dart';
 
 mixin CompletionTestMixin on AbstractLspAnalysisServerTest {
+  /// The last set of completion results fetched.
+  List<CompletionItem> completionResults = [];
+
   int sortTextSorter(CompletionItem item1, CompletionItem item2) =>
       (item1.sortText ?? item1.label).compareTo(item2.sortText ?? item2.label);
 
@@ -40,23 +43,24 @@
     if (openCloseFile) {
       await openFile(fileUri, withoutMarkers(content));
     }
-    final res = await getCompletion(fileUri, positionFromMarker(content));
+    completionResults =
+        await getCompletion(fileUri, positionFromMarker(content));
     if (openCloseFile) {
       await closeFile(fileUri);
     }
 
     // Sort the completions by sortText and filter to those we expect, so the ordering
     // can be compared.
-    final sortedResults = res
+    final sortedResults = completionResults
         .where((r) => expectCompletions.contains(r.label))
         .toList()
-          ..sort(sortTextSorter);
+      ..sort(sortTextSorter);
 
     expect(sortedResults.map((item) => item.label), equals(expectCompletions));
 
     // Check the edits apply correctly.
     if (applyEditsFor != null) {
-      var item = res.singleWhere((c) => c.label == applyEditsFor);
+      var item = completionResults.singleWhere((c) => c.label == applyEditsFor);
       final insertFormat = item.insertTextFormat;
 
       if (resolve) {
diff --git a/pkg/analysis_server/test/lsp/completion_yaml_test.dart b/pkg/analysis_server/test/lsp/completion_yaml_test.dart
index 9d26755..52bf479 100644
--- a/pkg/analysis_server/test/lsp/completion_yaml_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_yaml_test.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:io';
+
 import 'package:analysis_server/src/services/pub/pub_api.dart';
 import 'package:http/http.dart';
 import 'package:linter/src/rules.dart';
@@ -367,7 +369,7 @@
     );
   }
 
-  Future<void> test_package_version() async {
+  Future<void> test_package_versions_fromApi() async {
     httpClient.sendHandler = (BaseRequest request) async {
       if (request.url.path.startsWith(PubApi.packageNameListPath)) {
         return Response(samplePackageList, 200);
@@ -418,6 +420,163 @@
     );
   }
 
+  Future<void> test_package_versions_fromPubOutdated() async {
+    final json = r'''
+    {
+      "packages": [
+        {
+          "package":    "one",
+          "latest":     { "version": "3.2.1" },
+          "resolvable": { "version": "1.2.4" }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, json, '');
+
+    final content = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+  one: ^''';
+
+    final expected = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+  one: ^1.2.4''';
+
+    await initialize();
+    await openFile(pubspecFileUri, withoutMarkers(content));
+    await pumpEventQueue(times: 500);
+
+    await verifyCompletions(
+      pubspecFileUri,
+      content,
+      expectCompletions: ['^1.2.4', '^3.2.1'],
+      applyEditsFor: '^1.2.4',
+      expectedContent: expected,
+      openCloseFile: false,
+    );
+  }
+
+  Future<void> test_package_versions_fromPubOutdated_afterChange() async {
+    final initialJson = r'''
+    {
+      "packages": [
+        {
+          "package":    "one",
+          "latest":     { "version": "3.2.1" },
+          "resolvable": { "version": "1.2.3" }
+        }
+      ]
+    }
+    ''';
+    final updatedJson = r'''
+    {
+      "packages": [
+        {
+          "package":    "one",
+          "latest":     { "version": "2.1.0" },
+          "resolvable": { "version": "2.3.4" }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, initialJson, '');
+
+    final content = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+  one: ^''';
+
+    final expected = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+  one: ^2.3.4''';
+
+    newFile(pubspecFilePath, content: content);
+    await initialize();
+    await openFile(pubspecFileUri, withoutMarkers(content));
+    await pumpEventQueue(times: 500);
+
+    // Modify the underlying file which should trigger an update of the
+    // cached data.
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, updatedJson, '');
+    modifyFile(pubspecFilePath, '$content# trailing comment');
+    await pumpEventQueue(times: 500);
+
+    await verifyCompletions(
+      pubspecFileUri,
+      content,
+      expectCompletions: ['^2.3.4', '^2.1.0'],
+      applyEditsFor: '^2.3.4',
+      expectedContent: expected,
+      openCloseFile: false,
+    );
+
+    // Also veryify the detail fields were populated as expected.
+    expect(
+      completionResults.singleWhere((c) => c.label == '^2.3.4').detail,
+      equals('latest compatible'),
+    );
+    expect(
+      completionResults.singleWhere((c) => c.label == '^2.1.0').detail,
+      equals('latest'),
+    );
+  }
+
+  Future<void> test_package_versions_fromPubOutdated_afterDelete() async {
+    final initialJson = r'''
+    {
+      "packages": [
+        {
+          "package":    "one",
+          "latest":     { "version": "3.2.1" },
+          "resolvable": { "version": "1.2.3" }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, initialJson, '');
+
+    final content = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+  one: ^''';
+
+    newFile(pubspecFilePath, content: content);
+    await initialize();
+    await openFile(pubspecFileUri, withoutMarkers(content));
+    await pumpEventQueue(times: 500);
+
+    // Delete the underlying file which should trigger eviction of the cache.
+    deleteFile(pubspecFilePath);
+    await pumpEventQueue(times: 500);
+
+    await verifyCompletions(
+      pubspecFileUri,
+      content,
+      expectCompletions: [],
+      openCloseFile: false,
+    );
+
+    // There should have been no version numbers.
+    expect(completionResults, isEmpty);
+  }
+
   Future<void> test_topLevel() async {
     final content = '''
 version: 1.0.0
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index 0f7ecf1..96c7f5a 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -30,12 +30,15 @@
     final pluginError = plugin.AnalysisError(
       plugin.AnalysisErrorSeverity.ERROR,
       plugin.AnalysisErrorType.STATIC_TYPE_WARNING,
-      plugin.Location(pluginAnalyzedFilePath, 0, 6, 0, 0, 0, 6),
+      plugin.Location(pluginAnalyzedFilePath, 0, 6, 0, 0,
+          endLine: 0, endColumn: 6),
       'Test error from plugin',
       'ERR1',
       contextMessages: [
-        plugin.DiagnosticMessage('Related error',
-            plugin.Location(pluginAnalyzedFilePath, 31, 4, 1, 12, 1, 16))
+        plugin.DiagnosticMessage(
+            'Related error',
+            plugin.Location(pluginAnalyzedFilePath, 31, 4, 1, 12,
+                endLine: 1, endColumn: 16))
       ],
     );
     final pluginResult =
@@ -317,7 +320,7 @@
     final pluginError = plugin.AnalysisError(
       plugin.AnalysisErrorSeverity.ERROR,
       plugin.AnalysisErrorType.STATIC_TYPE_WARNING,
-      plugin.Location(mainFilePath, 0, 1, 0, 0, 0, 1),
+      plugin.Location(mainFilePath, 0, 1, 0, 0, endLine: 0, endColumn: 1),
       pluginErrorMessage,
       'ERR1',
     );
diff --git a/pkg/analysis_server/test/lsp/format_test.dart b/pkg/analysis_server/test/lsp/format_test.dart
index 741a740..5ba380f 100644
--- a/pkg/analysis_server/test/lsp/format_test.dart
+++ b/pkg/analysis_server/test/lsp/format_test.dart
@@ -309,6 +309,97 @@
     await expectFormattedContents(mainFileUri, contents, expectedLongLines);
   }
 
+  Future<void> test_lineLength_outsideWorkspaceFolders() async {
+    const contents = '''
+main() {
+  print('123456789 ''123456789 ''123456789 ');
+}
+''';
+    const expectedContents = '''
+main() {
+  print(
+      '123456789 '
+      '123456789 '
+      '123456789 ');
+}
+''';
+
+    await provideConfig(
+      () => initialize(
+        // Use empty roots so the test file is not inside any known
+        // WorkspaceFolder.
+        allowEmptyRootUri: true,
+        workspaceCapabilities: withDidChangeConfigurationDynamicRegistration(
+            withConfigurationSupport(emptyWorkspaceClientCapabilities)),
+      ),
+      // Global config (this should be used).
+      {'lineLength': 10},
+    );
+    await openFile(mainFileUri, contents);
+    await expectFormattedContents(mainFileUri, contents, expectedContents);
+  }
+
+  Future<void> test_lineLength_workspaceFolderSpecified() async {
+    const contents = '''
+main() {
+  print('123456789 ''123456789 ''123456789 ');
+}
+''';
+    const expectedContents = '''
+main() {
+  print(
+      '123456789 '
+      '123456789 '
+      '123456789 ');
+}
+''';
+
+    await provideConfig(
+      () => initialize(
+          workspaceCapabilities: withDidChangeConfigurationDynamicRegistration(
+              withConfigurationSupport(emptyWorkspaceClientCapabilities))),
+      // Global config.
+      {'lineLength': 200},
+      folderConfig: {
+        // WorkspaceFolder config for this project (this should be used).
+        projectFolderPath: {'lineLength': 10},
+      },
+    );
+    await openFile(mainFileUri, contents);
+    await expectFormattedContents(mainFileUri, contents, expectedContents);
+  }
+
+  Future<void> test_lineLength_workspaceFolderUnspecified() async {
+    const contents = '''
+main() {
+  print('123456789 ''123456789 ''123456789 ');
+}
+''';
+    const expectedContents = '''
+main() {
+  print(
+      '123456789 '
+      '123456789 '
+      '123456789 ');
+}
+''';
+
+    await provideConfig(
+      () => initialize(
+          workspaceCapabilities: withDidChangeConfigurationDynamicRegistration(
+              withConfigurationSupport(emptyWorkspaceClientCapabilities))),
+      // Global config (this should be used).
+      {'lineLength': 10},
+      folderConfig: {
+        // WorkspaceFolder config for this project that doesn't specific
+        // lineLength.
+        projectFolderPath: {'someOtherValue': 'foo'},
+      },
+    );
+    await openFile(mainFileUri, contents);
+    await expectFormattedContents(mainFileUri, contents, expectedContents);
+  }
+
   Future<void> test_minimalEdits_addWhitespace() async {
     // Check we only get one edit to add the required whitespace and not
     // an entire document replacement.
diff --git a/pkg/analysis_server/test/lsp/pub_package_service_test.dart b/pkg/analysis_server/test/lsp/pub_package_service_test.dart
index b00f285..c22a0f5 100644
--- a/pkg/analysis_server/test/lsp/pub_package_service_test.dart
+++ b/pkg/analysis_server/test/lsp/pub_package_service_test.dart
@@ -2,10 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:io';
+
 import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
 import 'package:analysis_server/src/services/pub/pub_package_service.dart';
 import 'package:analyzer/instrumentation/service.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:collection/collection.dart';
 import 'package:http/http.dart';
+import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -15,6 +21,7 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PubApiTest);
+    defineReflectiveTests(PubCommandTest);
     defineReflectiveTests(PubPackageServiceTest);
   });
 }
@@ -78,6 +85,168 @@
 }
 
 @reflectiveTest
+class PubCommandTest with ResourceProviderMixin {
+  late MockProcessRunner processRunner;
+  late PubCommand pubCommand;
+  late String pubspecPath, pubspec2Path;
+
+  void setUp() {
+    pubspecPath = convertPath('/home/project/pubspec.yaml');
+    pubspec2Path = convertPath('/home/project2/pubspec.yaml');
+    processRunner = MockProcessRunner();
+    pubCommand = PubCommand(InstrumentationService.NULL_SERVICE, processRunner);
+  }
+
+  Future<void> test_doesNotRunConcurrently() async {
+    var isRunning = false;
+    processRunner.runHandler = (executable, args, {dir, env}) async {
+      expect(isRunning, isFalse,
+          reason: 'pub commands should not run concurrently');
+      isRunning = true;
+      await pumpEventQueue(times: 500);
+      isRunning = false;
+      return ProcessResult(0, 0, '', '');
+    };
+    await Future.wait([
+      pubCommand.outdatedVersions(pubspecPath),
+      pubCommand.outdatedVersions(pubspecPath),
+    ]);
+  }
+
+  Future<void> test_outdated_args() async {
+    processRunner.runHandler = (executable, args, {dir, env}) {
+      var expectedPubPath = path.join(
+        path.dirname(Platform.resolvedExecutable),
+        Platform.isWindows ? 'pub.bat' : 'pub',
+      );
+      expect(executable, equals(expectedPubPath));
+      expect(
+          args,
+          equals([
+            'outdated',
+            '--show-all',
+            '--json',
+          ]));
+      expect(dir, equals(convertPath('/home/project')));
+      expect(
+          env!['PUB_ENVIRONMENT'],
+          anyOf(equals('analysis_server.pub_api'),
+              endsWith(':analysis_server.pub_api')));
+      return ProcessResult(0, 0, '', '');
+    };
+    await pubCommand.outdatedVersions(pubspecPath);
+  }
+
+  Future<void> test_outdated_invalidJson() async {
+    processRunner.runHandler = (String executable, List<String> args,
+            {dir, env}) =>
+        ProcessResult(1, 0, 'NOT VALID JSON', '');
+    final result = await pubCommand.outdatedVersions(pubspecPath);
+    expect(result, isEmpty);
+  }
+
+  Future<void> test_outdated_missingFields() async {
+    final validJson = r'''
+    {
+      "packages": [
+        {
+          "package":    "foo",
+          "current":    { "version": "1.0.0" },
+          "upgradable": { "version": "2.0.0" },
+          "resolvable": { }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, validJson, '');
+    final result = await pubCommand.outdatedVersions(pubspecPath);
+    expect(result, hasLength(1));
+    final package = result.first;
+    expect(package.packageName, equals('foo'));
+    expect(package.currentVersion, equals('1.0.0'));
+    expect(package.upgradableVersion, equals('2.0.0'));
+    expect(package.resolvableVersion, isNull);
+    expect(package.latestVersion, isNull);
+  }
+
+  Future<void> test_outdated_multiplePubspecs() async {
+    final pubspecJson1 = r'''
+    {
+      "packages": [
+        {
+          "package":    "foo",
+          "resolvable": { "version": "1.1.1" }
+        }
+      ]
+    }
+    ''';
+    final pubspecJson2 = r'''
+    {
+      "packages": [
+        {
+          "package":    "foo",
+          "resolvable": { "version": "2.2.2" }
+        }
+      ]
+    }
+    ''';
+
+    processRunner.runHandler = (executable, args, {dir, env}) {
+      // Return different json based on the directory we were invoked in.
+      final json =
+          dir == path.dirname(pubspecPath) ? pubspecJson1 : pubspecJson2;
+      return ProcessResult(1, 0, json, '');
+    };
+    final result1 = await pubCommand.outdatedVersions(pubspecPath);
+    final result2 = await pubCommand.outdatedVersions(pubspec2Path);
+    expect(result1.first.resolvableVersion, equals('1.1.1'));
+    expect(result2.first.resolvableVersion, equals('2.2.2'));
+  }
+
+  Future<void> test_outdated_nonZeroExitCode() async {
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 123, '{}', '');
+    final result = await pubCommand.outdatedVersions(pubspecPath);
+    expect(result, isEmpty);
+  }
+
+  Future<void> test_validJson() async {
+    final validJson = r'''
+    {
+      "packages": [
+        {
+          "package":    "foo",
+          "current":    { "version": "1.0.0" },
+          "upgradable": { "version": "2.0.0" },
+          "resolvable": { "version": "3.0.0" },
+          "latest":     { "version": "4.0.0" }
+        },
+        {
+          "package":    "bar",
+          "current":    { "version": "1.0.0" },
+          "upgradable": { "version": "2.0.0" },
+          "resolvable": { "version": "3.0.0" },
+          "latest":     { "version": "4.0.0" }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, validJson, '');
+    final result = await pubCommand.outdatedVersions(pubspecPath);
+    expect(result, hasLength(2));
+    result.forEachIndexed((index, package) {
+      expect(package.packageName, equals(index == 0 ? 'foo' : 'bar'));
+      expect(package.currentVersion, equals('1.0.0'));
+      expect(package.upgradableVersion, equals('2.0.0'));
+      expect(package.resolvableVersion, equals('3.0.0'));
+      expect(package.latestVersion, equals('4.0.0'));
+    });
+  }
+}
+
+@reflectiveTest
 class PubPackageServiceTest extends AbstractLspAnalysisServerTest {
   /// A sample API response for package names. This should match the JSON served
   /// at https://pub.dev/api/package-name-completion-data.
@@ -194,13 +363,13 @@
   Future<void> test_packageCache_initializesOnPubspecOpen() async {
     await initialize();
 
-    expect(server.pubPackageService.isRunning, isFalse);
+    expect(server.pubPackageService.isPackageNamesTimerRunning, isFalse);
     expect(server.pubPackageService.packageCache, isNull);
     expectPackages([]);
     await openFile(pubspecFileUri, '');
     await pumpEventQueue();
 
-    expect(server.pubPackageService.isRunning, isTrue);
+    expect(server.pubPackageService.isPackageNamesTimerRunning, isTrue);
     expect(server.pubPackageService.packageCache, isNotNull);
     expectPackages([]);
   }
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index ad2d20b..2e49ae5 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -48,6 +48,7 @@
   late MockLspServerChannel channel;
   late TestPluginManager pluginManager;
   late LspAnalysisServer server;
+  late MockProcessRunner processRunner;
   late MockHttpClient httpClient;
 
   /// The number of context builds that had already occurred the last time
@@ -62,12 +63,25 @@
   DiscoveredPluginInfo configureTestPlugin({
     plugin.ResponseResult? respondWith,
     plugin.Notification? notification,
+    plugin.ResponseResult? Function(plugin.RequestParams)? handler,
     Duration respondAfter = Duration.zero,
   }) {
     final info = DiscoveredPluginInfo('a', 'b', 'c', server.notificationManager,
         server.instrumentationService);
     pluginManager.plugins.add(info);
 
+    if (handler != null) {
+      pluginManager.handleRequest = (request) {
+        final response = handler(request);
+        return response == null
+            ? null
+            : <PluginInfo, Future<plugin.Response>>{
+                info: Future.delayed(respondAfter)
+                    .then((_) => response.toResponse('-', 1))
+              };
+      };
+    }
+
     if (respondWith != null) {
       pluginManager.broadcastResults = <PluginInfo, Future<plugin.Response>>{
         info: Future.delayed(respondAfter)
@@ -151,6 +165,7 @@
 
   void setUp() {
     httpClient = MockHttpClient();
+    processRunner = MockProcessRunner();
     channel = MockLspServerChannel(debugPrintCommunication);
     // Create an SDK in the mock file system.
     MockSdk(resourceProvider: resourceProvider);
@@ -162,7 +177,8 @@
         DartSdkManager(convertPath('/sdk')),
         CrashReportingAttachmentsBuilder.empty,
         InstrumentationService.NULL_SERVICE,
-        httpClient: httpClient);
+        httpClient: httpClient,
+        processRunner: processRunner);
     server.pluginManager = pluginManager;
 
     projectFolderPath = convertPath('/home/test');
@@ -1458,14 +1474,34 @@
 
   /// Calls the supplied function and responds to any `workspace/configuration`
   /// request with the supplied config.
-  Future<ResponseMessage> provideConfig(Future<ResponseMessage> Function() f,
-      FutureOr<Map<String, dynamic>> config) {
+  Future<ResponseMessage> provideConfig(
+    Future<ResponseMessage> Function() f,
+    FutureOr<Map<String, Object?>> globalConfig, {
+    FutureOr<Map<String, Map<String, Object?>>>? folderConfig,
+  }) {
     return handleExpectedRequest<ResponseMessage, ConfigurationParams,
-        List<Map<String, dynamic>>>(
+        List<Map<String, Object?>>>(
       Method.workspace_configuration,
       ConfigurationParams.fromJson,
       f,
-      handler: (configurationParams) async => [await config],
+      handler: (configurationParams) async {
+        // We must respond to the request for config with items that match the
+        // request. For any item in the request without a folder, we will return
+        // the global config. For any item in the request with a folder we will
+        // return the config for that item in the map, or fall back to the global
+        // config if it does not exist.
+        final global = await globalConfig;
+        final folders = await folderConfig;
+        return configurationParams.items.map(
+          (requestedConfig) {
+            final uri = requestedConfig.scopeUri;
+            final path = uri != null ? Uri.parse(uri).toFilePath() : null;
+            // Use the config the test provided for this path, or fall back to
+            // global.
+            return (folders != null ? folders[path] : null) ?? global;
+          },
+        ).toList();
+      },
     );
   }
 
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index fbdd56c..752d3f1 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -8,6 +8,7 @@
 import 'analyzer_status_test.dart' as analyzer_status;
 import 'cancel_request_test.dart' as cancel_request;
 import 'change_workspace_folders_test.dart' as change_workspace_folders;
+import 'client_configuration_test.dart' as client_configuration;
 import 'closing_labels_test.dart' as closing_labels;
 import 'code_actions_assists_test.dart' as code_actions_assists;
 import 'code_actions_fixes_test.dart' as code_actions_fixes;
@@ -48,6 +49,7 @@
     analyzer_status.main();
     cancel_request.main();
     change_workspace_folders.main();
+    client_configuration.main();
     closing_labels.main();
     code_actions_assists.main();
     code_actions_fixes.main();
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index d6cfa2c..e1f3ecd 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -3,9 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
 
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/utilities/process.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:http/http.dart' as http;
 import 'package:test/test.dart';
@@ -47,6 +50,32 @@
   }
 }
 
+class MockProcessRunner implements ProcessRunner {
+  FutureOr<ProcessResult> Function(String executable, List<String> arguments,
+          {String? dir, Map<String, String>? env})? runHandler =
+      (executable, arguments, {dir, env}) => throw UnimplementedError();
+
+  @override
+  dynamic noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+
+  @override
+  Future<ProcessResult> run(
+    String executable,
+    List<String> arguments, {
+    String? workingDirectory,
+    Map<String, String>? environment,
+    bool includeParentEnvironment = true,
+    bool runInShell = false,
+    Encoding? stdoutEncoding = systemEncoding,
+    Encoding? stderrEncoding = systemEncoding,
+  }) async {
+    return runHandler!(executable, arguments,
+        dir: workingDirectory, env: environment);
+  }
+}
+
 class MockSource implements Source {
   @override
   final String fullName;
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 49cae54..ac31994 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -361,7 +361,7 @@
   Map<String, FileResult> fileResults = {};
 
   void addFileResult(FileResult result) {
-    fileResults[result.path!] = result;
+    fileResults[result.path] = result;
   }
 
   @override
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 0a651c2..546faf8 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
@@ -536,7 +536,7 @@
       DartCompletionRequest request);
 
   Future computeSuggestions({int times = 200}) async {
-    result = await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
+    result = await session.getResolvedUnit(testFile) as ResolvedUnitResult;
     var baseRequest = CompletionRequestImpl(
         result, completionOffset, CompletionPerformance());
 
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
index 4dd13ee..257fb5b 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -50,7 +50,7 @@
 
     // Build the request
     var baseRequest = CompletionRequestImpl(
-        await session.getResolvedUnit2(testFile) as ResolvedUnitResult,
+        await session.getResolvedUnit(testFile) as ResolvedUnitResult,
         completionOffset,
         CompletionPerformance());
     await baseRequest.performance.runRequestOperation((performance) async {
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
index a147a80..7696ad5 100644
--- a/pkg/analysis_server/test/services/correction/organize_directives_test.dart
+++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -582,8 +582,8 @@
 
   Future<void> _computeUnitAndErrors(String code) async {
     addTestSource(code);
-    var result = await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
-    testUnit = result.unit!;
+    var result = await session.getResolvedUnit(testFile) as ResolvedUnitResult;
+    testUnit = result.unit;
     testErrors = result.errors;
   }
 }
diff --git a/pkg/analysis_server/test/services/correction/sort_members_test.dart b/pkg/analysis_server/test/services/correction/sort_members_test.dart
index a766800..e434168 100644
--- a/pkg/analysis_server/test/services/correction/sort_members_test.dart
+++ b/pkg/analysis_server/test/services/correction/sort_members_test.dart
@@ -925,7 +925,7 @@
 
   Future<void> _parseTestUnit(String code) async {
     addTestSource(code);
-    var result = session.getParsedUnit2(testFile) as ParsedUnitResult;
+    var result = session.getParsedUnit(testFile) as ParsedUnitResult;
     testUnit = result.unit;
   }
 }
diff --git a/pkg/analysis_server/test/services/correction/status_test.dart b/pkg/analysis_server/test/services/correction/status_test.dart
index 41c0eec..055c0e4 100644
--- a/pkg/analysis_server/test/services/correction/status_test.dart
+++ b/pkg/analysis_server/test/services/correction/status_test.dart
@@ -98,7 +98,7 @@
   }
 
   void test_addFatalError_withLocation() {
-    var location = Location('/test.dart', 1, 2, 3, 4, 5, 6);
+    var location = Location('/test.dart', 1, 2, 3, 4, endLine: 5, endColumn: 6);
     var refactoringStatus = RefactoringStatus();
     // initial state
     expect(refactoringStatus.severity, null);
@@ -210,7 +210,7 @@
   }
 
   void test_newError() {
-    var location = Location('/test.dart', 1, 2, 3, 4, 5, 6);
+    var location = Location('/test.dart', 1, 2, 3, 4, endLine: 5, endColumn: 6);
     var refactoringStatus = RefactoringStatus.error('msg', location);
     var problem = refactoringStatus.problem!;
     var problemLocation = problem.location!;
diff --git a/pkg/analysis_server/test/services/refactoring/move_file_test.dart b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
index ad4b7ef..5094b24 100644
--- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -67,7 +67,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test/lib/222/new_name.dart', oldFile: file.path);
     await _assertSuccessfulRefactoring();
@@ -90,7 +90,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test0/test1/test3/lib/111/name.dart',
         oldFile: file.path);
@@ -114,7 +114,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test0/test1/test2/test3/lib/111/name.dart',
         oldFile: file.path);
@@ -138,7 +138,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test0/test1/lib/111/name.dart',
         oldFile: file.path);
@@ -160,7 +160,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test/lib/222/new_name.dart', oldFile: file.path);
     await _assertSuccessfulRefactoring();
@@ -181,7 +181,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test/lib/new_name.dart', oldFile: file.path);
     await _assertSuccessfulRefactoring();
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 99aa552..512db98 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -41,8 +41,8 @@
     result = await resolveFile(path);
     expect(result.state, ResultState.VALID);
 
-    findNode = FindNode(result.content!, result.unit!);
-    findElement = FindElement(result.unit!);
+    findNode = FindNode(result.content, result.unit);
+    findElement = FindElement(result.unit);
   }
 
   /// Put the [code] into the test file, and resolve it.
diff --git a/pkg/analysis_server/test/src/cider/completion_test.dart b/pkg/analysis_server/test/src/cider/completion_test.dart
index b83e4ef..7a50af7 100644
--- a/pkg/analysis_server/test/src/cider/completion_test.dart
+++ b/pkg/analysis_server/test/src/cider/completion_test.dart
@@ -806,7 +806,7 @@
   /// for completion we don't resolve unnecessary node.
   void _configureToCheckNotResolved({required Set<String> identifiers}) {
     _testResolvedUnit = (resolvedUnitResult) {
-      var unit = resolvedUnitResult.unit!;
+      var unit = resolvedUnitResult.unit;
       unit.accept(
         FunctionAstVisitor(
           simpleIdentifier: (node) {
diff --git a/pkg/analysis_server/test/src/cider/fixes_test.dart b/pkg/analysis_server/test/src/cider/fixes_test.dart
index fa71e62..4e57e14 100644
--- a/pkg/analysis_server/test/src/cider/fixes_test.dart
+++ b/pkg/analysis_server/test/src/cider/fixes_test.dart
@@ -48,7 +48,7 @@
 ''');
 
     // The file was resolved only once, even though we have 2 errors.
-    expect(fileResolver.testView!.resolvedFiles, [convertPath(testPath)]);
+    expect(fileResolver.testView!.resolvedLibraries, [convertPath(testPath)]);
   }
 
   Future<void> test_createMethod() async {
diff --git a/pkg/analysis_server/test/src/cider/rename_test.dart b/pkg/analysis_server/test/src/cider/rename_test.dart
index 31c96d5..028aaea 100644
--- a/pkg/analysis_server/test/src/cider/rename_test.dart
+++ b/pkg/analysis_server/test/src/cider/rename_test.dart
@@ -107,6 +107,65 @@
     expect(refactor.refactoringElement.offset, _correctionContext.offset);
   }
 
+  void test_checkName_function() {
+    var result = _checkName(r'''
+int ^foo() => 2;
+''', 'bar');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 0);
+    expect(result?.oldName, 'foo');
+  }
+
+  void test_checkName_local() {
+    var result = _checkName(r'''
+void foo() {
+  var ^a = 0; var b = a + 1;
+}
+''', 'bar');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 0);
+    expect(result?.oldName, 'a');
+  }
+
+  void test_checkName_local_invalid() {
+    var result = _checkName(r'''
+void foo() {
+  var ^a = 0; var b = a + 1;
+}
+''', 'Aa');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 1);
+    expect(result?.oldName, 'a');
+  }
+
+  void test_checkName_parameter() {
+    var result = _checkName(r'''
+void foo(String ^a) {
+  var b = a + 1;
+}
+''', 'bar');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 0);
+    expect(result?.oldName, 'a');
+  }
+
+  CheckNameResponse? _checkName(String content, String newName) {
+    _updateFile(content);
+
+    return CiderRenameComputer(
+      fileResolver,
+    ).checkNewName(
+      convertPath(testPath),
+      _correctionContext.line,
+      _correctionContext.character,
+      newName,
+    );
+  }
+
   CanRenameResponse? _compute(String content) {
     _updateFile(content);
 
diff --git a/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart b/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
index 37057d0..83a9954 100644
--- a/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
@@ -398,8 +398,8 @@
   Future<List<ClosingLabel>> _computeElements(String sourceContent) async {
     newFile(sourcePath, content: sourceContent);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
-    var computer = DartUnitClosingLabelsComputer(result.lineInfo, result.unit!);
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+    var computer = DartUnitClosingLabelsComputer(result.lineInfo, result.unit);
     return computer.compute();
   }
 }
diff --git a/pkg/analysis_server/test/src/computer/folding_computer_test.dart b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
index 62e7ad9..f63607d 100644
--- a/pkg/analysis_server/test/src/computer/folding_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
@@ -582,8 +582,8 @@
   Future<List<FoldingRegion>> _computeRegions(String sourceContent) async {
     newFile(sourcePath, content: sourceContent);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
-    var computer = DartUnitFoldingComputer(result.lineInfo, result.unit!);
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+    var computer = DartUnitFoldingComputer(result.lineInfo, result.unit);
     return computer.compute();
   }
 }
diff --git a/pkg/analysis_server/test/src/computer/highlights_computer_test.dart b/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
index 2012268..46a6c44 100644
--- a/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
@@ -114,7 +114,7 @@
     this.content = content;
     newFile(sourcePath, content: content);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
 
     if (hasErrors) {
       expect(result.errors, isNotEmpty);
@@ -122,7 +122,7 @@
       expect(result.errors, isEmpty);
     }
 
-    var computer = DartUnitHighlightsComputer(result.unit!);
+    var computer = DartUnitHighlightsComputer(result.unit);
     highlights = computer.compute();
   }
 }
diff --git a/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart b/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
index ebdde35..fed52b7 100644
--- a/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
@@ -50,7 +50,7 @@
   Future<void> createBuilder(String content) async {
     originalContent = content;
     newFile(path, content: content);
-    var result = await session.getResolvedUnit2(path) as ResolvedUnitResult;
+    var result = await session.getResolvedUnit(path) as ResolvedUnitResult;
     computer = ImportElementsComputer(resourceProvider, result);
   }
 
diff --git a/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart b/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
index 2cd24c1..a63d9bc 100644
--- a/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
@@ -471,9 +471,9 @@
     // TODO(brianwilkerson) Automatically extract the selection from the content.
     newFile(sourcePath, content: content);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
     var computer = ImportedElementsComputer(
-        result.unit!, content.indexOf(selection), selection.length);
+        result.unit, content.indexOf(selection), selection.length);
     importedElements = computer.compute();
   }
 }
diff --git a/pkg/analysis_server/test/src/computer/outline_computer_test.dart b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
index 6db141d..a005ff2 100644
--- a/pkg/analysis_server/test/src/computer/outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
@@ -32,7 +32,7 @@
     testCode = code;
     newFile(testPath, content: code);
     var resolveResult =
-        await session.getResolvedUnit2(testPath) as ResolvedUnitResult;
+        await session.getResolvedUnit(testPath) as ResolvedUnitResult;
     return DartUnitOutlineComputer(
       resolveResult,
       withBasicFlutter: true,
diff --git a/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart b/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart
index cbb6cf8..27e9e7f 100644
--- a/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart
@@ -194,8 +194,8 @@
       String sourceContent, int offset) async {
     newFile(sourcePath, content: sourceContent);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
-    var computer = DartSelectionRangeComputer(result.unit!, offset);
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+    var computer = DartSelectionRangeComputer(result.unit, offset);
     return computer.compute();
   }
 
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
index f186301..c224c12 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
@@ -517,7 +517,7 @@
     testCode = code;
     newFile(testPath, content: code);
     resolveResult =
-        await session.getResolvedUnit2(testPath) as ResolvedUnitResult;
+        await session.getResolvedUnit(testPath) as ResolvedUnitResult;
     computer = FlutterOutlineComputer(resolveResult);
     return computer.compute();
   }
diff --git a/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart b/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
index 631dcac..4ad6049 100644
--- a/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
+++ b/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
@@ -79,7 +79,8 @@
   Element element(int stringIndex, int intIndex, {ElementKind? kind}) =>
       Element(kind ?? ElementKind.CLASS, strings[stringIndex++], intIndex++,
           location: Location(fileName(stringIndex++), intIndex++, intIndex++,
-              intIndex++, intIndex++, intIndex++, intIndex++),
+              intIndex++, intIndex++,
+              endLine: intIndex++, endColumn: intIndex++),
           parameters: strings[stringIndex++],
           returnType: strings[stringIndex++],
           typeParameters: strings[stringIndex++]);
@@ -99,8 +100,8 @@
       intIndex++,
       intIndex++,
       intIndex++,
-      intIndex++,
-      intIndex++);
+      endLine: intIndex++,
+      endColumn: intIndex++);
 
   /// On return, increment [stringIndex] by 5 and [intIndex] by 7.
   Occurrences occurrences(int stringIndex, int intIndex) {
diff --git a/pkg/analysis_server/test/src/plugin/result_merger_test.dart b/pkg/analysis_server/test/src/plugin/result_merger_test.dart
index 934e335..9affdc3 100644
--- a/pkg/analysis_server/test/src/plugin/result_merger_test.dart
+++ b/pkg/analysis_server/test/src/plugin/result_merger_test.dart
@@ -29,7 +29,8 @@
     AnalysisError createError(int offset) {
       var severity = AnalysisErrorSeverity.ERROR;
       var type = AnalysisErrorType.HINT;
-      var location = Location('test.dart', offset, 2, 3, 4, 5, 6);
+      var location =
+          Location('test.dart', offset, 2, 3, 4, endLine: 5, endColumn: 6);
       return AnalysisError(severity, type, location, '', '');
     }
 
@@ -68,7 +69,8 @@
     AnalysisError createError(int offset) {
       var severity = AnalysisErrorSeverity.ERROR;
       var type = AnalysisErrorType.HINT;
-      var location = Location('test.dart', offset, 2, 3, 4, 5, 6);
+      var location =
+          Location('test.dart', offset, 2, 3, 4, endLine: 5, endColumn: 6);
       return AnalysisError(severity, type, location, '', '');
     }
 
@@ -265,7 +267,7 @@
 
   void test_mergeOutline() {
     Element element(ElementKind kind, int offset) {
-      var location = Location('', offset, 0, 0, 0, 0, 0);
+      var location = Location('', offset, 0, 0, 0, endLine: 0, endColumn: 0);
       return Element(kind, '', 0, location: location);
     }
 
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
index 4f4923f..4eab94d 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
@@ -2,8 +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 'dart:io';
+
 import 'package:analysis_server/src/services/completion/yaml/pubspec_generator.dart';
 import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
 import 'package:analysis_server/src/services/pub/pub_package_service.dart';
 import 'package:analyzer/instrumentation/service.dart';
 import 'package:http/http.dart';
@@ -22,6 +25,7 @@
 @reflectiveTest
 class PubspecGeneratorTest extends YamlGeneratorTest {
   late MockHttpClient httpClient;
+  late MockProcessRunner processRunner;
 
   late PubPackageService pubPackageService;
 
@@ -34,10 +38,12 @@
 
   void setUp() {
     httpClient = MockHttpClient();
+    processRunner = MockProcessRunner();
     pubPackageService = PubPackageService(
         InstrumentationService.NULL_SERVICE,
         resourceProvider,
-        PubApi(InstrumentationService.NULL_SERVICE, httpClient, null));
+        PubApi(InstrumentationService.NULL_SERVICE, httpClient, null),
+        PubCommand(InstrumentationService.NULL_SERVICE, processRunner));
   }
 
   void tearDown() {
@@ -339,4 +345,46 @@
 ''');
     assertSuggestion('two: ');
   }
+
+  void test_packageVersion() async {
+    final json = r'''
+    {
+      "packages": [
+        {
+          "package":    "one",
+          "latest":     { "version": "3.2.1" },
+          "resolvable": { "version": "1.2.4" }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, json, '');
+
+    pubPackageService.beginCachePreloads([convertPath('/home/test/$fileName')]);
+    await pumpEventQueue(times: 500);
+
+    getCompletions('''
+dependencies:
+  one: ^
+''');
+    assertSuggestion('^1.2.4');
+    assertSuggestion('^3.2.1');
+  }
+
+  /// Ensure in a repo with a DEPS file like the SDK, we do not run pub
+  /// processes to cache the version numbers.
+  void test_packageVersion_withDEPSfile() async {
+    var didRun = false;
+    processRunner.runHandler = (executable, args, {dir, env}) {
+      didRun = true;
+      return ProcessResult(1, 0, '', '');
+    };
+
+    newFile('/home/DEPS');
+    pubPackageService.beginCachePreloads([convertPath('/home/test/$fileName')]);
+    await pumpEventQueue(times: 500);
+
+    expect(didRun, isFalse);
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
index 0120636..fc933c1 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
@@ -136,6 +136,17 @@
 ''');
   }
 
+  Future<void> test_sync() async {
+    // This code is erroneous; the test ensures there is no error thrown when
+    // computing assists.
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+Iterable<String> f() sync {}
+''');
+    await assertNoAssistAt('{}');
+  }
+
+
   Future<void> test_syncStar() async {
     await resolveTestCode('''
 Iterable<String> f() sync* {}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
index 5103661..f6ccc74 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
@@ -72,7 +72,7 @@
 }
 void g(int x, int y) {}
 ''');
-    var unit = testAnalysisResult.unit!;
+    var unit = testAnalysisResult.unit;
     var function = unit.declarations[0] as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
index e2c4988..4022696 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
@@ -6,7 +6,6 @@
 import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
-import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -441,7 +440,7 @@
   Future<void> test_rename_removed() async {
     setPackageContent('''
 class C {
-  C.new([C c]);
+  C.updated([C c]);
 }
 ''');
     addPackageDataFile('''
@@ -455,7 +454,7 @@
     inClass: 'C'
   changes:
     - kind: 'rename'
-      newName: 'new'
+      newName: 'updated'
 ''');
     await resolveTestCode('''
 import '$importUri';
@@ -463,7 +462,7 @@
 ''');
     await assertHasFix('''
 import '$importUri';
-C c() => C.new(C.new());
+C c() => C.updated(C.updated());
 ''');
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart
index d182ab1..42d762b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart
@@ -36,7 +36,7 @@
     var testFile = convertPath('/home/test/lib/test.dart');
     addSource(testFile, '');
     var result = await session.getResolvedLibraryValid(testFile);
-    var sets = manager.forLibrary(result.element!);
+    var sets = manager.forLibrary(result.element);
     expect(sets, hasLength(2));
   }
 
@@ -47,7 +47,7 @@
     var testFile = convertPath('/home/test/lib/test.dart');
     addSource(testFile, '');
     var result = await session.getResolvedLibraryValid(testFile);
-    var sets = manager.forLibrary(result.element!);
+    var sets = manager.forLibrary(result.element);
     expect(sets, hasLength(0));
   }
 
@@ -70,6 +70,6 @@
 
 extension on AnalysisSession {
   Future<ResolvedLibraryResult> getResolvedLibraryValid(String path) async {
-    return await getResolvedLibrary2(path) as ResolvedLibraryResult;
+    return await getResolvedLibrary(path) as ResolvedLibraryResult;
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index 366f8d1..00f2730 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -262,7 +262,7 @@
 
   Future<void> addUnimportedFile(String filePath, String content) async {
     addSource(filePath, content);
-    var result = await session.getResolvedUnit2(convertPath(filePath));
+    var result = await session.getResolvedUnit(convertPath(filePath));
     extensionCache.cacheFromResult(result as ResolvedUnitResult);
   }
 
diff --git a/pkg/analysis_server/test/src/services/flutter/widget_description.dart b/pkg/analysis_server/test/src/services/flutter/widget_description.dart
index 8cdbfff..33f47ad 100644
--- a/pkg/analysis_server/test/src/services/flutter/widget_description.dart
+++ b/pkg/analysis_server/test/src/services/flutter/widget_description.dart
@@ -24,7 +24,7 @@
     expect(fileEdit.file, testAnalysisResult.path);
 
     var actual = SourceEdit.applySequence(
-      testAnalysisResult.content!,
+      testAnalysisResult.content,
       fileEdit.edits,
     );
     expect(actual, expected);
@@ -50,7 +50,7 @@
 
   Future<protocol.FlutterGetWidgetDescriptionResult?> getDescription(
       String search) async {
-    var content = testAnalysisResult.content!;
+    var content = testAnalysisResult.content;
 
     var offset = content.indexOf(search);
     if (offset == -1) {
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart
index 542d8fe..16d1e81 100644
--- a/pkg/analysis_server/test/stress/completion/completion_runner.dart
+++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -80,11 +80,11 @@
         }
         fileCount++;
         output.write('.');
-        var result = await context.currentSession.getResolvedUnit2(path)
+        var result = await context.currentSession.getResolvedUnit(path)
             as ResolvedUnitResult;
-        var content = result.content!;
+        var content = result.content;
         var lineInfo = result.lineInfo;
-        var identifiers = _identifiersIn(result.unit!);
+        var identifiers = _identifiersIn(result.unit);
 
         for (var identifier in identifiers) {
           identifierCount++;
@@ -94,7 +94,7 @@
                 content.substring(identifier.end);
             resourceProvider.setOverlay(path,
                 content: modifiedContent, modificationStamp: stamp++);
-            result = await context.currentSession.getResolvedUnit2(path)
+            result = await context.currentSession.getResolvedUnit(path)
                 as ResolvedUnitResult;
           }
 
diff --git a/pkg/analysis_server/test/test_all.dart b/pkg/analysis_server/test/test_all.dart
index 4c5a33f..3e5769cc 100644
--- a/pkg/analysis_server/test/test_all.dart
+++ b/pkg/analysis_server/test/test_all.dart
@@ -26,6 +26,7 @@
 import 'socket_server_test.dart' as socket_server;
 import 'src/test_all.dart' as src;
 import 'tool/test_all.dart' as tool;
+import 'verify_no_solo_test.dart' as verify_no_solo;
 import 'verify_sorted_test.dart' as verify_sorted;
 import 'verify_tests_test.dart' as verify_tests;
 
@@ -52,6 +53,7 @@
     socket_server.main();
     src.main();
     tool.main();
+    verify_no_solo.main();
     verify_sorted.main();
     verify_tests.main();
     defineReflectiveSuite(() {
diff --git a/pkg/analysis_server/test/verify_no_solo_test.dart b/pkg/analysis_server/test/verify_no_solo_test.dart
new file mode 100644
index 0000000..150c731
--- /dev/null
+++ b/pkg/analysis_server/test/verify_no_solo_test.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.
+
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer_utilities/package_root.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('analysis_server', () {
+    buildTests(packagePath: 'analysis_server');
+  });
+
+  group('analyzer', () {
+    buildTests(packagePath: 'analyzer');
+  });
+
+  group('analyzer_cli', () {
+    buildTests(packagePath: 'analyzer_cli');
+  });
+
+  group('analyzer_plugin', () {
+    buildTests(packagePath: 'analyzer_plugin');
+  });
+}
+
+void buildTests({required String packagePath}) {
+  var provider = PhysicalResourceProvider.INSTANCE;
+  var pkgRootPath = provider.pathContext.normalize(packageRoot);
+
+  var testsPath = _toPlatformPath(pkgRootPath, '$packagePath/test');
+
+  var collection = AnalysisContextCollection(
+    includedPaths: <String>[testsPath],
+    resourceProvider: provider,
+  );
+  var contexts = collection.contexts;
+  if (contexts.length != 1) {
+    fail('The directory $testsPath contains multiple analysis contexts.');
+  }
+
+  test('no @soloTest', () {
+    var failures = <String>[];
+    buildTestsIn(contexts[0].currentSession, testsPath,
+        provider.getFolder(testsPath), failures);
+
+    if (failures.isNotEmpty) {
+      fail('@soloTest annotation found in:\n${failures.join('\n')}');
+    }
+  });
+}
+
+void buildTestsIn(AnalysisSession session, String testDirPath, Folder directory,
+    List<String> failures) {
+  var pathContext = session.resourceProvider.pathContext;
+  var children = directory.getChildren();
+  children.sort((first, second) => first.shortName.compareTo(second.shortName));
+  for (var child in children) {
+    if (child is Folder) {
+      buildTestsIn(session, testDirPath, child, failures);
+    } else if (child is File && child.shortName.endsWith('_test.dart')) {
+      var path = child.path;
+      var relativePath = pathContext.relative(path, from: testDirPath);
+
+      var result = session.getParsedUnit(path);
+      if (result is! ParsedUnitResult) {
+        fail('Could not parse $path');
+      }
+      var unit = result.unit;
+      var errors = result.errors;
+      if (errors.isNotEmpty) {
+        fail('Errors found when parsing $path');
+      }
+      var tracker = SoloTestTracker();
+      unit.accept(tracker);
+      if (tracker.found) {
+        failures.add(relativePath);
+      }
+    }
+  }
+}
+
+String _toPlatformPath(String pathPath, String relativePosixPath) {
+  var pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
+  return pathContext.joinAll([
+    pathPath,
+    ...relativePosixPath.split('/'),
+  ]);
+}
+
+/// A [RecursiveAstVisitor] that tracks whether any node is annotated with
+/// an annotation named 'soloTest'.
+class SoloTestTracker extends RecursiveAstVisitor<void> {
+  bool found = false;
+
+  @override
+  void visitAnnotation(Annotation node) {
+    if (node.name.name == 'soloTest') {
+      found = true;
+    }
+    super.visitAnnotation(node);
+  }
+}
diff --git a/pkg/analysis_server/test/verify_sorted_test.dart b/pkg/analysis_server/test/verify_sorted_test.dart
index 9cf62ed..dc12ccc 100644
--- a/pkg/analysis_server/test/verify_sorted_test.dart
+++ b/pkg/analysis_server/test/verify_sorted_test.dart
@@ -134,7 +134,7 @@
       }
       var relativePath = pathContext.relative(path, from: testDirPath);
       test(relativePath, () {
-        var result = session.getParsedUnit2(path);
+        var result = session.getParsedUnit(path);
         if (result is! ParsedUnitResult) {
           fail('Could not parse $path');
         }
diff --git a/pkg/analysis_server/tool/code_completion/code_metrics.dart b/pkg/analysis_server/tool/code_completion/code_metrics.dart
index 5ff17b9..565a9fd 100644
--- a/pkg/analysis_server/tool/code_completion/code_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/code_metrics.dart
@@ -1394,7 +1394,7 @@
       if (file_paths.isDart(pathContext, filePath)) {
         try {
           var resolvedUnitResult =
-              await context.currentSession.getResolvedUnit2(filePath);
+              await context.currentSession.getResolvedUnit(filePath);
           //
           // Check for errors that cause the file to be skipped.
           //
@@ -1411,7 +1411,7 @@
             continue;
           }
 
-          resolvedUnitResult.unit!.accept(collector);
+          resolvedUnitResult.unit.accept(collector);
         } catch (exception) {
           print('Exception caught analyzing: "$filePath"');
           print(exception.toString());
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index d32c961..46638b1 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1293,7 +1293,7 @@
     for (var filePath in context.contextRoot.analyzedFiles()) {
       if (file_paths.isDart(pathContext, filePath)) {
         try {
-          var result = await context.currentSession.getResolvedUnit2(filePath)
+          var result = await context.currentSession.getResolvedUnit(filePath)
               as ResolvedUnitResult;
 
           var analysisError = getFirstErrorOrNull(result);
@@ -1315,11 +1315,11 @@
     }
     for (var result in results) {
       _resolvedUnitResult = result;
-      var filePath = result.path!;
+      var filePath = result.path;
       // Use the ExpectedCompletionsVisitor to compute the set of expected
       // completions for this CompilationUnit.
       final visitor = ExpectedCompletionsVisitor(filePath);
-      _resolvedUnitResult.unit!.accept(visitor);
+      _resolvedUnitResult.unit.accept(visitor);
 
       for (var expectedCompletion in visitor.expectedCompletions) {
         var resolvedUnitResult = _resolvedUnitResult;
@@ -1328,14 +1328,14 @@
         // have the context reanalyze the file
         if (options.overlay != CompletionMetricsOptions.OVERLAY_NONE) {
           var overlayContents = _getOverlayContents(
-              _resolvedUnitResult.content!, expectedCompletion);
+              _resolvedUnitResult.content, expectedCompletion);
 
           _provider.setOverlay(filePath,
               content: overlayContents,
               modificationStamp: overlayModificationStamp++);
           context.driver.changeFile(filePath);
           resolvedUnitResult = await context.currentSession
-              .getResolvedUnit2(filePath) as ResolvedUnitResult;
+              .getResolvedUnit(filePath) as ResolvedUnitResult;
         }
 
         // As this point the completion suggestions are computed,
diff --git a/pkg/analysis_server/tool/code_completion/flutter_metrics.dart b/pkg/analysis_server/tool/code_completion/flutter_metrics.dart
index ee267a5..edab701 100644
--- a/pkg/analysis_server/tool/code_completion/flutter_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/flutter_metrics.dart
@@ -207,7 +207,7 @@
       if (file_paths.isDart(pathContext, filePath)) {
         try {
           var resolvedUnitResult =
-              await context.currentSession.getResolvedUnit2(filePath);
+              await context.currentSession.getResolvedUnit(filePath);
           //
           // Check for errors that cause the file to be skipped.
           //
@@ -224,7 +224,7 @@
             continue;
           }
 
-          resolvedUnitResult.unit!.accept(collector);
+          resolvedUnitResult.unit.accept(collector);
         } catch (exception, stackTrace) {
           print('');
           print('Exception caught analyzing: "$filePath"');
diff --git a/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart b/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
index 6b0b3c1..8494fb4 100644
--- a/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
+++ b/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
@@ -184,7 +184,7 @@
       if (file_paths.isDart(pathContext, filePath)) {
         try {
           var resolvedUnitResult =
-              await context.currentSession.getResolvedUnit2(filePath);
+              await context.currentSession.getResolvedUnit(filePath);
           //
           // Check for errors that cause the file to be skipped.
           //
@@ -208,7 +208,7 @@
             continue;
           }
 
-          resolvedUnitResult.unit!.accept(collector);
+          resolvedUnitResult.unit.accept(collector);
         } catch (exception, stacktrace) {
           print('Exception caught analyzing: "$filePath"');
           print(exception);
diff --git a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
index 0975c8a..8a24e94 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
@@ -1940,7 +1940,7 @@
       if (file_paths.isDart(pathContext, filePath)) {
         try {
           var resolvedUnitResult =
-              await context.currentSession.getResolvedUnit2(filePath);
+              await context.currentSession.getResolvedUnit(filePath);
           //
           // Check for errors that cause the file to be skipped.
           //
@@ -1964,7 +1964,7 @@
             continue;
           }
 
-          resolvedUnitResult.unit!.accept(collector);
+          resolvedUnitResult.unit.accept(collector);
         } catch (exception, stacktrace) {
           print('Exception caught analyzing: "$filePath"');
           print(exception);
diff --git a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
index 52b219e..3e2af94 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
@@ -317,7 +317,7 @@
 
   /// Initialize this collector prior to visiting the unit in the [result].
   void initializeFrom(ResolvedUnitResult result) {
-    unit = result.unit!;
+    unit = result.unit;
   }
 
   @override
@@ -1459,7 +1459,7 @@
       if (file_paths.isDart(pathContext, filePath)) {
         try {
           var resolvedUnitResult =
-              await context.currentSession.getResolvedUnit2(filePath);
+              await context.currentSession.getResolvedUnit(filePath);
           //
           // Check for errors that cause the file to be skipped.
           //
@@ -1484,7 +1484,7 @@
           }
 
           collector.initializeFrom(resolvedUnitResult);
-          resolvedUnitResult.unit!.accept(collector);
+          resolvedUnitResult.unit.accept(collector);
         } catch (exception, stacktrace) {
           print('Exception caught analyzing: "$filePath"');
           print(exception);
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index 5376013..bac9b69 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -94,8 +94,8 @@
 | textDocument/codeAction (organiseImports) | ✅ | ✅ | | ✅ | ✅ |
 | textDocument/codeAction (fixAll) | ✅ | ✅ | | ✅ | ✅ |
 | textDocument/codeAction (refactors) | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/codeAction (assists) | ✅ | ✅ | | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `Refactor`
-| textDocument/codeAction (fixes) | ✅ | ✅ | | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `QuickFix`
+| textDocument/codeAction (assists) | ✅ | ✅ | ✅ | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `Refactor`
+| textDocument/codeAction (fixes) | ✅ | ✅ | ✅ | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `QuickFix`
 | textDocument/codeLens | | | | | |
 | codeLens/resolve | | | | | |
 | textDocument/documentLink | | | | | |
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Location.java b/pkg/analysis_server/tool/spec/generated/java/types/Location.java
index 1df7d78..13e14bd 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Location.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Location.java
@@ -63,17 +63,17 @@
   /**
    * The one-based index of the line containing the character immediately following the range.
    */
-  private final int endLine;
+  private final Integer endLine;
 
   /**
    * The one-based index of the column containing the character immediately following the range.
    */
-  private final int endColumn;
+  private final Integer endColumn;
 
   /**
    * Constructor for {@link Location}.
    */
-  public Location(String file, int offset, int length, int startLine, int startColumn, int endLine, int endColumn) {
+  public Location(String file, int offset, int length, int startLine, int startColumn, Integer endLine, Integer endColumn) {
     this.file = file;
     this.offset = offset;
     this.length = length;
@@ -93,8 +93,8 @@
         other.length == length &&
         other.startLine == startLine &&
         other.startColumn == startColumn &&
-        other.endLine == endLine &&
-        other.endColumn == endColumn;
+        ObjectUtilities.equals(other.endLine, endLine) &&
+        ObjectUtilities.equals(other.endColumn, endColumn);
     }
     return false;
   }
@@ -105,8 +105,8 @@
     int length = jsonObject.get("length").getAsInt();
     int startLine = jsonObject.get("startLine").getAsInt();
     int startColumn = jsonObject.get("startColumn").getAsInt();
-    int endLine = jsonObject.get("endLine").getAsInt();
-    int endColumn = jsonObject.get("endColumn").getAsInt();
+    Integer endLine = jsonObject.get("endLine") == null ? null : jsonObject.get("endLine").getAsInt();
+    Integer endColumn = jsonObject.get("endColumn") == null ? null : jsonObject.get("endColumn").getAsInt();
     return new Location(file, offset, length, startLine, startColumn, endLine, endColumn);
   }
 
@@ -125,14 +125,14 @@
   /**
    * The one-based index of the column containing the character immediately following the range.
    */
-  public int getEndColumn() {
+  public Integer getEndColumn() {
     return endColumn;
   }
 
   /**
    * The one-based index of the line containing the character immediately following the range.
    */
-  public int getEndLine() {
+  public Integer getEndLine() {
     return endLine;
   }
 
@@ -191,8 +191,12 @@
     jsonObject.addProperty("length", length);
     jsonObject.addProperty("startLine", startLine);
     jsonObject.addProperty("startColumn", startColumn);
-    jsonObject.addProperty("endLine", endLine);
-    jsonObject.addProperty("endColumn", endColumn);
+    if (endLine != null) {
+      jsonObject.addProperty("endLine", endLine);
+    }
+    if (endColumn != null) {
+      jsonObject.addProperty("endColumn", endColumn);
+    }
     return jsonObject;
   }
 
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 dfbd44c..76b7a2c 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -2884,8 +2884,8 @@
 ///   "length": int
 ///   "startLine": int
 ///   "startColumn": int
-///   "endLine": int
-///   "endColumn": int
+///   "endLine": optional int
+///   "endColumn": optional int
 /// }
 ///
 /// Clients may not extend, implement or mix-in this class.
@@ -2909,14 +2909,15 @@
 
   /// The one-based index of the line containing the character immediately
   /// following the range.
-  int endLine;
+  int? endLine;
 
   /// The one-based index of the column containing the character immediately
   /// following the range.
-  int endColumn;
+  int? endColumn;
 
-  Location(this.file, this.offset, this.length, this.startLine,
-      this.startColumn, this.endLine, this.endColumn);
+  Location(
+      this.file, this.offset, this.length, this.startLine, this.startColumn,
+      {this.endLine, this.endColumn});
 
   factory Location.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -2954,21 +2955,17 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'startColumn');
       }
-      int endLine;
+      int? endLine;
       if (json.containsKey('endLine')) {
         endLine = jsonDecoder.decodeInt(jsonPath + '.endLine', json['endLine']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'endLine');
       }
-      int endColumn;
+      int? endColumn;
       if (json.containsKey('endColumn')) {
         endColumn =
             jsonDecoder.decodeInt(jsonPath + '.endColumn', json['endColumn']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'endColumn');
       }
-      return Location(
-          file, offset, length, startLine, startColumn, endLine, endColumn);
+      return Location(file, offset, length, startLine, startColumn,
+          endLine: endLine, endColumn: endColumn);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'Location', json);
     }
@@ -2982,8 +2979,14 @@
     result['length'] = length;
     result['startLine'] = startLine;
     result['startColumn'] = startColumn;
-    result['endLine'] = endLine;
-    result['endColumn'] = endColumn;
+    var endLine = this.endLine;
+    if (endLine != null) {
+      result['endLine'] = endLine;
+    }
+    var endColumn = this.endColumn;
+    if (endColumn != null) {
+      result['endColumn'] = endColumn;
+    }
     return result;
   }
 
diff --git a/pkg/analysis_server_client/test/verify_sorted_test.dart b/pkg/analysis_server_client/test/verify_sorted_test.dart
index dfa4c4a..f4f4c57 100644
--- a/pkg/analysis_server_client/test/verify_sorted_test.dart
+++ b/pkg/analysis_server_client/test/verify_sorted_test.dart
@@ -55,7 +55,7 @@
       }
       var relativePath = pathContext.relative(path, from: testDirPath);
       test(relativePath, () {
-        var result = session.getParsedUnit2(path);
+        var result = session.getParsedUnit(path);
         if (result is! ParsedUnitResult) {
           fail('Could not parse $path');
         }
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 6ccdf32..337ad88 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,20 @@
+## 2.1.0-dev
+* Changed `AnalysisResult.path` to be non-nullable.
+* Changed `ParsedLibraryResult.units` to be non-nullable.
+* Changed `ResolvedLibraryResult.element` to be non-nullable.
+* Changed `ResolvedLibraryResult.units` to be non-nullable.
+* Changed `ResolvedUnitResult.content` to be non-nullable.
+* Changed `ResolvedUnitResult.unit` to be non-nullable.
+* Deprecated and renamed `AnalysisSession.getXyz2()` into `getXyz()`.
+* Changed `AnalysisDriver.results` to `Stream<Object>`.
+  It used to always produce `ResolvedUnitResult`s, but sometimes its
+  `content` and `unit` were `null`, when the result actually had only errors.
+  Now it produces either `ResolvedUnitResult`, or `ErrorsResult`, or
+  some other results that might be added in the future.
+* Added `DartType.alias` with information about instantiated type alias.
+  The type alias element and arguments are present or absent together.
+* Deprecated `DartType.aliasElement` and `DartType.aliasArguments`.
+
 ## 2.0.0
 * Removed deprecated `Scope.lookup2()`.
 * Removed deprecated setters in API of AST.
diff --git a/pkg/analyzer/doc/tutorial/ast.md b/pkg/analyzer/doc/tutorial/ast.md
index 3e9e3fa..ed449d8 100644
--- a/pkg/analyzer/doc/tutorial/ast.md
+++ b/pkg/analyzer/doc/tutorial/ast.md
@@ -55,7 +55,7 @@
 
 ```dart
 void processFile(AnalysisSession session, String path) {
-  var result = session.getParsedUnit2(path);
+  var result = session.getParsedUnit(path);
   if (result is ParsedUnitResult) {
     CompilationUnit unit = result.unit;
   }
@@ -67,7 +67,7 @@
 
 ```dart
 void processFile(AnalysisSession session, String path) async {
-  var result = await session.getResolvedUnit2(path);
+  var result = await session.getResolvedUnit(path);
   if (result is ResolvedUnitResult) {
     CompilationUnit unit = result.unit;
   }
diff --git a/pkg/analyzer/doc/tutorial/element.md b/pkg/analyzer/doc/tutorial/element.md
index 6c5509f..912d65b 100644
--- a/pkg/analyzer/doc/tutorial/element.md
+++ b/pkg/analyzer/doc/tutorial/element.md
@@ -46,7 +46,7 @@
 
 ```dart
 void analyzeSingleFile(AnalysisSession session, String path) async {
-  var result = await session.getUnitElement2(path);
+  var result = await session.getUnitElement(path);
   if (result is UnitElementResult) {
     CompilationUnitElement element = result.element;
   }
diff --git a/pkg/analyzer/example/analyze.dart b/pkg/analyzer/example/analyze.dart
index a94f27e..72acdf5 100644
--- a/pkg/analyzer/example/analyze.dart
+++ b/pkg/analyzer/example/analyze.dart
@@ -32,7 +32,7 @@
         continue;
       }
 
-      final errorsResult = await context.currentSession.getErrors2(filePath);
+      final errorsResult = await context.currentSession.getErrors(filePath);
       if (errorsResult is ErrorsResult) {
         for (final error in errorsResult.errors) {
           if (error.errorCode.type != ErrorType.TODO) {
diff --git a/pkg/analyzer/lib/dart/analysis/results.dart b/pkg/analyzer/lib/dart/analysis/results.dart
index 287c470..13500ba 100644
--- a/pkg/analyzer/lib/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/dart/analysis/results.dart
@@ -17,9 +17,7 @@
 abstract class AnalysisResult {
   /// The absolute and normalized path of the file that was analyzed.
   /// If [state] is not [ResultState.VALID], throws [StateError].
-  ///
-  /// TODO(migration): should not be nullable
-  String? get path;
+  String get path;
 
   /// Return the session used to compute this result.
   /// If [state] is not [ResultState.VALID], throws [StateError].
@@ -164,9 +162,7 @@
 abstract class ParsedLibraryResult
     implements SomeParsedLibraryResult, AnalysisResult {
   /// The parsed units of the library.
-  ///
-  /// TODO(migration): should not be null, probably empty list
-  List<ParsedUnitResult>? get units;
+  List<ParsedUnitResult> get units;
 
   /// Return the declaration of the [element], or `null` if the [element]
   /// is synthetic. Throw [ArgumentError] if the [element] is not defined in
@@ -214,13 +210,13 @@
 abstract class ResolvedLibraryResult
     implements SomeResolvedLibraryResult, AnalysisResult {
   /// The element representing this library.
-  LibraryElement? get element;
+  LibraryElement get element;
 
   /// The type provider used when resolving the library.
   TypeProvider get typeProvider;
 
   /// The resolved units of the library.
-  List<ResolvedUnitResult>? get units;
+  List<ResolvedUnitResult> get units;
 
   /// Return the declaration of the [element], or `null` if the [element]
   /// is synthetic. Throw [ArgumentError] if the [element] is not defined in
@@ -235,7 +231,7 @@
 abstract class ResolvedUnitResult
     implements SomeResolvedUnitResult, AnalysisResultWithErrors {
   /// The content of the file that was scanned, parsed and resolved.
-  String? get content;
+  String get content;
 
   /// Return `true` if the file exists.
   bool get exists;
@@ -250,7 +246,7 @@
   TypeSystem get typeSystem;
 
   /// The fully resolved compilation unit for the [content].
-  CompilationUnit? get unit;
+  CompilationUnit get unit;
 }
 
 /// An indication of whether an analysis result is valid, and if not why.
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 680ba37..ade0e8e 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -35,47 +35,105 @@
   ///
   /// If the file cannot be analyzed by this session, then the result will have
   /// a result state indicating the nature of the problem.
+  Future<SomeErrorsResult> getErrors(String path);
+
+  /// Return a future that will complete with information about the errors
+  /// contained in the file with the given absolute, normalized [path].
+  ///
+  /// If the file cannot be analyzed by this session, then the result will have
+  /// a result state indicating the nature of the problem.
+  @Deprecated('Use getErrors() instead')
   Future<SomeErrorsResult> getErrors2(String path);
 
   /// Return information about the file at the given absolute, normalized
   /// [path].
+  SomeFileResult getFile(String path);
+
+  /// Return information about the file at the given absolute, normalized
+  /// [path].
+  @Deprecated('Use getFile() instead')
   SomeFileResult getFile2(String path);
 
   /// Return a future that will complete with information about the library
   /// element representing the library with the given [uri].
+  Future<SomeLibraryElementResult> getLibraryByUri(String uri);
+
+  /// Return a future that will complete with information about the library
+  /// element representing the library with the given [uri].
+  @Deprecated('Use getLibraryByUri() instead')
   Future<SomeLibraryElementResult> getLibraryByUri2(String uri);
 
   /// Return information about the results of parsing units of the library file
   /// with the given absolute, normalized [path].
+  SomeParsedLibraryResult getParsedLibrary(String path);
+
+  /// Return information about the results of parsing units of the library file
+  /// with the given absolute, normalized [path].
+  @Deprecated('Use getParsedLibrary() instead')
   SomeParsedLibraryResult getParsedLibrary2(String path);
 
   /// Return information about the results of parsing units of the library file
   /// with the given library [element].
+  SomeParsedLibraryResult getParsedLibraryByElement(LibraryElement element);
+
+  /// Return information about the results of parsing units of the library file
+  /// with the given library [element].
+  @Deprecated('Use getParsedLibraryByElement() instead')
   SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element);
 
   /// Return information about the results of parsing the file with the given
   /// absolute, normalized [path].
+  SomeParsedUnitResult getParsedUnit(String path);
+
+  /// Return information about the results of parsing the file with the given
+  /// absolute, normalized [path].
+  @Deprecated('Use getParsedUnit() instead')
   SomeParsedUnitResult getParsedUnit2(String path);
 
   /// Return a future that will complete with information about the results of
   /// resolving all of the files in the library with the given absolute,
   /// normalized [path].
+  Future<SomeResolvedLibraryResult> getResolvedLibrary(String path);
+
+  /// Return a future that will complete with information about the results of
+  /// resolving all of the files in the library with the given absolute,
+  /// normalized [path].
+  @Deprecated('Use getResolvedLibrary() instead')
   Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path);
 
   /// Return a future that will complete with information about the results of
   /// resolving all of the files in the library with the library [element].
   ///
   /// Throw [ArgumentError] if the [element] was not produced by this session.
+  Future<SomeResolvedLibraryResult> getResolvedLibraryByElement(
+      LibraryElement element);
+
+  /// Return a future that will complete with information about the results of
+  /// resolving all of the files in the library with the library [element].
+  ///
+  /// Throw [ArgumentError] if the [element] was not produced by this session.
+  @Deprecated('Use getResolvedLibraryByElement() instead')
   Future<SomeResolvedLibraryResult> getResolvedLibraryByElement2(
       LibraryElement element);
 
   /// Return a future that will complete with information about the results of
   /// resolving the file with the given absolute, normalized [path].
+  Future<SomeResolvedUnitResult> getResolvedUnit(String path);
+
+  /// Return a future that will complete with information about the results of
+  /// resolving the file with the given absolute, normalized [path].
+  @Deprecated('Use getResolvedUnit() instead')
   Future<SomeResolvedUnitResult> getResolvedUnit2(String path);
 
   /// Return a future that will complete with information about the results of
   /// building the element model for the file with the given absolute,
   /// normalized [path].
+  Future<SomeUnitElementResult> getUnitElement(String path);
+
+  /// Return a future that will complete with information about the results of
+  /// building the element model for the file with the given absolute,
+  /// normalized [path].
+  @Deprecated('Use getUnitElement() instead')
   Future<SomeUnitElementResult> getUnitElement2(String path);
 }
 
diff --git a/pkg/analyzer/lib/dart/analysis/utilities.dart b/pkg/analyzer/lib/dart/analysis/utilities.dart
index 3fd296d..8cee120 100644
--- a/pkg/analyzer/lib/dart/analysis/utilities.dart
+++ b/pkg/analyzer/lib/dart/analysis/utilities.dart
@@ -115,7 +115,7 @@
     {required String path, ResourceProvider? resourceProvider}) async {
   AnalysisContext context =
       _createAnalysisContext(path: path, resourceProvider: resourceProvider);
-  return await context.currentSession.getResolvedUnit2(path);
+  return await context.currentSession.getResolvedUnit(path);
 }
 
 /// Return a newly create analysis context in which the file at the given [path]
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index ab82e26..2df5ebb 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -1061,7 +1061,7 @@
 /// [PostfixExpression] when the operator is an increment operator.
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class CompoundAssignmentExpression {
+abstract class CompoundAssignmentExpression implements Expression {
   /// The element that is used to read the value.
   ///
   /// If this node is not a compound assignment, this element is `null`.
@@ -2471,7 +2471,7 @@
 
   /// Return `true` if the given [name] is visible only within the library in
   /// which it is declared.
-  static bool isPrivateName(String name) => name.startsWith('_');
+  static bool isPrivateName(String name) => name.isNotEmpty && name[0] == "_";
 }
 
 /// The basic structure of an if element.
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index 44efa9f..5e9079a 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -28,12 +28,19 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class DartType {
+  /// If this type is an instantiation of a type alias, information about
+  /// the alias element, and the type arguments.
+  /// Otherwise return `null`.
+  InstantiatedTypeAliasElement? get alias;
+
   /// If this type is an instantiation of a type alias, return the type
   /// arguments used for the instantiation. Otherwise return `null`.
+  @Deprecated('Use alias instead')
   List<DartType>? get aliasArguments;
 
   /// If this type is an instantiation of a type alias, return it.
   /// Otherwise return `null`.
+  @Deprecated('Use alias instead')
   TypeAliasElement? get aliasElement;
 
   /// Return the name of this type as it should appear when presented to users
@@ -245,6 +252,17 @@
   FunctionType instantiate(List<DartType> argumentTypes);
 }
 
+/// Information about an instantiated [TypeAliasElement] and the type
+/// arguments with which it is instantiated.
+abstract class InstantiatedTypeAliasElement {
+  /// The alias element that is instantiated to produce a [DartType].
+  TypeAliasElement get element;
+
+  /// The type arguments with which the [element] was instantiated.
+  /// This list will be empty if the [element] is not generic.
+  List<DartType> get typeArguments;
+}
+
 /// The type introduced by either a class or an interface, or a reference to
 /// such a type.
 ///
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 6a6fa5a..0a2b2c8 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -146,6 +146,7 @@
   CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER,
   CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION,
   CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE,
+  CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION,
   CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT,
   CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME,
   CompileTimeErrorCode.DUPLICATE_DEFINITION,
@@ -454,6 +455,7 @@
   CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
   CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
   CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
+  CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
   CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
   CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION,
   CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
@@ -469,6 +471,7 @@
   FfiCode.EMPTY_STRUCT,
   FfiCode.EXTRA_ANNOTATION_ON_STRUCT_FIELD,
   FfiCode.EXTRA_SIZE_ANNOTATION_CARRAY,
+  FfiCode.FFI_NATIVE_ONLY_STATIC,
   FfiCode.FIELD_IN_STRUCT_WITH_INITIALIZER,
   FfiCode.FIELD_INITIALIZER_IN_STRUCT,
   FfiCode.FIELD_MUST_BE_EXTERNAL_IN_STRUCT,
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 9bb60eb..ec0aaa7 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -5,387 +5,9 @@
 import 'dart:collection';
 import 'dart:core';
 
-import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/analysis_options/analysis_options_provider.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/driver.dart'
-    show AnalysisDriver, AnalysisDriverScheduler;
-import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
-import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/hint/sdk_constraint_extractor.dart';
-import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/summary_sdk.dart';
-import 'package:analyzer/src/task/options.dart';
-import 'package:analyzer/src/workspace/basic.dart';
-import 'package:analyzer/src/workspace/bazel.dart';
-import 'package:analyzer/src/workspace/gn.dart';
-import 'package:analyzer/src/workspace/package_build.dart';
-import 'package:analyzer/src/workspace/pub.dart';
-import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:yaml/yaml.dart';
 
-/// A utility class used to build an analysis context for a given directory.
-///
-/// The construction of analysis contexts is as follows:
-///
-/// 1. Determine how package: URI's are to be resolved. This follows the lookup
-///    algorithm defined by the [package specification][1].
-///
-/// 2. Using the results of step 1, look in each package for an embedder file
-///    (_embedder.yaml). If one exists then it defines the SDK. If multiple such
-///    files exist then use the first one found. Otherwise, use the default SDK.
-///
-/// 3. Look for an analysis options file (`analysis_options.yaml`) and process
-///    the options in the file.
-///
-/// 4. Create a new context. Initialize its source factory based on steps 1, 2
-///    and 3. Initialize its analysis options from step 4.
-///
-/// [1]: https://github.com/dart-lang/dart_enhancement_proposals/blob/master/Accepted/0005%20-%20Package%20Specification/DEP-pkgspec.md.
-class ContextBuilder {
-  /// The [ResourceProvider] by which paths are converted into [Resource]s.
-  final ResourceProvider resourceProvider;
-
-  /// The manager used to manage the DartSdk's that have been created so that
-  /// they can be shared across contexts.
-  final DartSdkManager sdkManager;
-
-  /// The options used by the context builder.
-  final ContextBuilderOptions builderOptions;
-
-  /// The scheduler used by any analysis drivers created through this interface.
-  late final AnalysisDriverScheduler analysisDriverScheduler;
-
-  /// The performance log used by any analysis drivers created through this
-  /// interface.
-  late final PerformanceLog performanceLog;
-
-  /// If `true`, additional analysis data useful for testing is stored.
-  bool retainDataForTesting = false;
-
-  /// The byte store used by any analysis drivers created through this interface.
-  late final ByteStore byteStore;
-
-  /// Whether any analysis driver created through this interface should support
-  /// indexing and search.
-  bool enableIndex = false;
-
-  /// Sometimes `BUILD` files are not preserved, and other files are created
-  /// instead. But looking for them is expensive, so we want to avoid this
-  /// in cases when `BUILD` files are always available.
-  bool lookForBazelBuildFileSubstitutes = true;
-
-  /// Initialize a newly created builder to be ready to build a context rooted in
-  /// the directory with the given [rootDirectoryPath].
-  ContextBuilder(this.resourceProvider, this.sdkManager,
-      {ContextBuilderOptions? options})
-      : builderOptions = options ?? ContextBuilderOptions();
-
-  /// Return an analysis driver that is configured correctly to analyze code in
-  /// the directory with the given [path].
-  AnalysisDriver buildDriver(
-    ContextRoot contextRoot,
-    Workspace workspace, {
-    void Function(AnalysisOptionsImpl)? updateAnalysisOptions,
-    FileContentCache? fileContentCache,
-  }) {
-    String path = contextRoot.root;
-
-    var options = getAnalysisOptions(path, workspace, contextRoot: contextRoot);
-
-    if (updateAnalysisOptions != null) {
-      updateAnalysisOptions(options);
-    }
-    //_processAnalysisOptions(context, optionMap);
-
-    SummaryDataStore? summaryData;
-    var librarySummaryPaths = builderOptions.librarySummaryPaths;
-    if (librarySummaryPaths != null) {
-      summaryData = SummaryDataStore(librarySummaryPaths);
-    }
-
-    final sf =
-        createSourceFactoryFromWorkspace(workspace, summaryData: summaryData);
-
-    AnalysisDriver driver = AnalysisDriver.tmp1(
-      scheduler: analysisDriverScheduler,
-      logger: performanceLog,
-      resourceProvider: resourceProvider,
-      byteStore: byteStore,
-      sourceFactory: sf,
-      analysisOptions: options,
-      packages: createPackageMap(
-        resourceProvider: resourceProvider,
-        options: builderOptions,
-        rootPath: path,
-      ),
-      enableIndex: enableIndex,
-      externalSummaries: summaryData,
-      retainDataForTesting: retainDataForTesting,
-      fileContentCache: fileContentCache,
-    );
-
-    declareVariablesInDriver(driver);
-    return driver;
-  }
-
-//  void _processAnalysisOptions(
-//      AnalysisContext context, Map<String, YamlNode> optionMap) {
-//    List<OptionsProcessor> optionsProcessors =
-//        AnalysisEngine.instance.optionsPlugin.optionsProcessors;
-//    try {
-//      optionsProcessors.forEach(
-//          (OptionsProcessor p) => p.optionsProcessed(context, optionMap));
-//
-//      // Fill in lint rule defaults in case lints are enabled and rules are
-//      // not specified in an options file.
-//      if (context.analysisOptions.lint && !containsLintRuleEntry(optionMap)) {
-//        setLints(context, linterPlugin.contributedRules);
-//      }
-//
-//      // Ask engine to further process options.
-//      if (optionMap != null) {
-//        configureContextOptions(context, optionMap);
-//      }
-//    } on Exception catch (e) {
-//      optionsProcessors.forEach((OptionsProcessor p) => p.onError(e));
-//    }
-//  }
-
-  SourceFactory createSourceFactory(String rootPath, Workspace workspace,
-      {SummaryDataStore? summaryData}) {
-    DartSdk sdk = findSdk(workspace);
-    if (summaryData != null && sdk is SummaryBasedDartSdk) {
-      summaryData.addBundle(null, sdk.bundle);
-    }
-    return workspace.createSourceFactory(sdk, summaryData);
-  }
-
-  SourceFactory createSourceFactoryFromWorkspace(Workspace workspace,
-      {SummaryDataStore? summaryData}) {
-    DartSdk sdk = findSdk(workspace);
-    if (summaryData != null && sdk is SummaryBasedDartSdk) {
-      summaryData.addBundle(null, sdk.bundle);
-    }
-    return workspace.createSourceFactory(sdk, summaryData);
-  }
-
-  /// Add any [declaredVariables] to the list of declared variables used by the
-  /// given analysis [driver].
-  void declareVariablesInDriver(AnalysisDriver driver) {
-    var variables = builderOptions.declaredVariables;
-    if (variables.isNotEmpty) {
-      driver.declaredVariables = DeclaredVariables.fromMap(variables);
-      driver.configure();
-    }
-  }
-
-  /// Return the SDK that should be used to analyze code. Use the given
-  /// [workspace] to locate the SDK.
-  DartSdk findSdk(Workspace? workspace) {
-    String? summaryPath = builderOptions.dartSdkSummaryPath;
-    if (summaryPath != null) {
-      return SummaryBasedDartSdk(summaryPath, true,
-          resourceProvider: resourceProvider);
-    }
-
-    DartSdk folderSdk;
-    {
-      String sdkPath = sdkManager.defaultSdkDirectory;
-      SdkDescription description = SdkDescription(sdkPath);
-      folderSdk = sdkManager.getSdk(description, () {
-        return FolderBasedDartSdk(
-          resourceProvider,
-          resourceProvider.getFolder(sdkPath),
-        );
-      });
-    }
-
-    if (workspace != null) {
-      var partialSourceFactory = workspace.createSourceFactory(null, null);
-      var embedderYamlSource = partialSourceFactory.forUri(
-        'package:sky_engine/_embedder.yaml',
-      );
-      if (embedderYamlSource != null) {
-        var embedderYamlPath = embedderYamlSource.fullName;
-        var libFolder = resourceProvider.getFile(embedderYamlPath).parent2;
-        EmbedderYamlLocator locator =
-            EmbedderYamlLocator.forLibFolder(libFolder);
-        Map<Folder, YamlMap> embedderMap = locator.embedderYamls;
-        if (embedderMap.isNotEmpty) {
-          EmbedderSdk embedderSdk = EmbedderSdk(
-            resourceProvider,
-            embedderMap,
-            languageVersion: folderSdk.languageVersion,
-          );
-          return embedderSdk;
-        }
-      }
-    }
-
-    return folderSdk;
-  }
-
-  /// Return the analysis options that should be used to analyze code in the
-  /// directory with the given [path]. Use [verbosePrint] to echo verbose
-  /// information about the analysis options selection process.
-  AnalysisOptionsImpl getAnalysisOptions(String path, Workspace workspace,
-      {void Function(String text)? verbosePrint, ContextRoot? contextRoot}) {
-    void verbose(String text) {
-      if (verbosePrint != null) {
-        verbosePrint(text);
-      }
-    }
-
-    SourceFactory sourceFactory = workspace.createSourceFactory(null, null);
-    AnalysisOptionsProvider optionsProvider =
-        AnalysisOptionsProvider(sourceFactory);
-
-    AnalysisOptionsImpl options = AnalysisOptionsImpl();
-
-    var optionsPath = builderOptions.defaultAnalysisOptionsFilePath;
-    if (optionsPath != null) {
-      var optionsFile = resourceProvider.getFile(optionsPath);
-      try {
-        contextRoot?.optionsFilePath = optionsFile.path;
-        var optionsMap = optionsProvider.getOptionsFromFile(optionsFile);
-        applyToAnalysisOptions(options, optionsMap);
-        verbose('Loaded analysis options from ${optionsFile.path}');
-      } catch (e) {
-        // Ignore exceptions thrown while trying to load the options file.
-        verbose('Exception: $e\n  when loading ${optionsFile.path}');
-      }
-    } else {
-      verbose('Using default analysis options');
-    }
-
-    var pubspecFile = _findPubspecFile(path);
-    if (pubspecFile != null) {
-      var extractor = SdkConstraintExtractor(pubspecFile);
-      var sdkVersionConstraint = extractor.constraint();
-      if (sdkVersionConstraint != null) {
-        options.sdkVersionConstraint = sdkVersionConstraint;
-      }
-    }
-
-    return options;
-  }
-
-  /// Return the `pubspec.yaml` file that should be used when analyzing code in
-  /// the directory with the given [path], possibly `null`.
-  File? _findPubspecFile(String path) {
-    var folder = resourceProvider.getFolder(path);
-    for (var current in folder.withAncestors) {
-      var file = current.getChildAssumingFile('pubspec.yaml');
-      if (file.exists) {
-        return file;
-      }
-    }
-  }
-
-  /// Return [Packages] to analyze a resource with the [rootPath].
-  static Packages createPackageMap({
-    required ResourceProvider resourceProvider,
-    required ContextBuilderOptions options,
-    required String rootPath,
-  }) {
-    var configPath = options.defaultPackageFilePath;
-    if (configPath != null) {
-      var configFile = resourceProvider.getFile(configPath);
-      return parsePackagesFile(resourceProvider, configFile);
-    } else {
-      var resource = resourceProvider.getResource(rootPath);
-      return findPackagesFrom(resourceProvider, resource);
-    }
-  }
-
-  /// If [packages] is provided, it will be used for the [Workspace],
-  /// otherwise the packages file from [options] will be used, or discovered
-  /// from [rootPath].
-  ///
-  /// TODO(scheglov) Make [packages] required, remove [options] and discovery.
-  static Workspace createWorkspace({
-    required ResourceProvider resourceProvider,
-    required ContextBuilderOptions options,
-    Packages? packages,
-    required String rootPath,
-    bool lookForBazelBuildFileSubstitutes = true,
-  }) {
-    packages ??= ContextBuilder.createPackageMap(
-      resourceProvider: resourceProvider,
-      options: options,
-      rootPath: rootPath,
-    );
-    var packageMap = <String, List<Folder>>{};
-    for (var package in packages.packages) {
-      packageMap[package.name] = [package.libFolder];
-    }
-
-    if (_hasPackageFileInPath(resourceProvider, rootPath)) {
-      // A Bazel or Gn workspace that includes a '.packages' file is treated
-      // like a normal (non-Bazel/Gn) directory. But may still use
-      // package:build or Pub.
-      return PackageBuildWorkspace.find(
-              resourceProvider, packageMap, rootPath) ??
-          PubWorkspace.find(resourceProvider, packageMap, rootPath) ??
-          BasicWorkspace.find(resourceProvider, packageMap, rootPath);
-    }
-    Workspace? workspace = BazelWorkspace.find(resourceProvider, rootPath,
-        lookForBuildFileSubstitutes: lookForBazelBuildFileSubstitutes);
-    workspace ??= GnWorkspace.find(resourceProvider, rootPath);
-    workspace ??=
-        PackageBuildWorkspace.find(resourceProvider, packageMap, rootPath);
-    workspace ??= PubWorkspace.find(resourceProvider, packageMap, rootPath);
-    workspace ??= BasicWorkspace.find(resourceProvider, packageMap, rootPath);
-    return workspace;
-  }
-
-  /// Return `true` if either the directory at [rootPath] or a parent of that
-  /// directory contains a `.packages` file.
-  static bool _hasPackageFileInPath(
-      ResourceProvider resourceProvider, String rootPath) {
-    var folder = resourceProvider.getFolder(rootPath);
-    return folder.withAncestors.any((current) {
-      return current.getChildAssumingFile('.packages').exists;
-    });
-  }
-}
-
-/// Options used by a [ContextBuilder].
-class ContextBuilderOptions {
-  /// The file path of the file containing the summary of the SDK that should be
-  /// used to "analyze" the SDK. This option should only be specified by
-  /// command-line tools such as 'dartanalyzer' or 'ddc'.
-  String? dartSdkSummaryPath;
-
-  /// The file path of the analysis options file that should be used in place of
-  /// any file in the root directory or a parent of the root directory, or `null`
-  /// if the normal lookup mechanism should be used.
-  String? defaultAnalysisOptionsFilePath;
-
-  /// A table mapping variable names to values for the declared variables.
-  Map<String, String> declaredVariables = {};
-
-  /// The file path of the .packages file that should be used in place of any
-  /// file found using the normal (Package Specification DEP) lookup mechanism,
-  /// or `null` if the normal lookup mechanism should be used.
-  String? defaultPackageFilePath;
-
-  /// A list of the paths of summary files that are to be used, or `null` if no
-  /// summary information is available.
-  List<String>? librarySummaryPaths;
-
-  /// Initialize a newly created set of options
-  ContextBuilderOptions();
-}
-
 /// Given a package map, check in each package's lib directory for the existence
 /// of an `_embedder.yaml` file. If the file contains a top level YamlMap, it
 /// will be added to the [embedderYamls] map.
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index 0ca758d..3e2f98b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -7,9 +7,9 @@
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/src/context/builder.dart' as old
-    show ContextBuilder, ContextBuilderOptions;
-import 'package:analyzer/src/context/context_root.dart' as old;
+import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
+import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart'
     show ByteStore, MemoryByteStore;
 import 'package:analyzer/src/dart/analysis/driver.dart'
@@ -18,8 +18,15 @@
 import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart'
     show PerformanceLog;
+import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
-import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager;
+import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/hint/sdk_constraint_extractor.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
+import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:cli_util/cli_util.dart';
 
 /// An implementation of a context builder.
@@ -57,46 +64,57 @@
     byteStore ??= MemoryByteStore();
     performanceLog ??= PerformanceLog(StringBuffer());
 
-    DartSdkManager sdkManager = DartSdkManager(sdkPath);
-
     if (scheduler == null) {
       scheduler = AnalysisDriverScheduler(performanceLog);
       scheduler.start();
     }
 
-    // TODO(brianwilkerson) Move the required implementation from the old
-    // ContextBuilder to this class and remove the old class.
-    old.ContextBuilderOptions options = old.ContextBuilderOptions();
-    if (declaredVariables != null) {
-      options.declaredVariables = _toMap(declaredVariables);
-    }
-    if (sdkSummaryPath != null) {
-      options.dartSdkSummaryPath = sdkSummaryPath;
-    }
+    SummaryDataStore? summaryData;
     if (librarySummaryPaths != null) {
-      options.librarySummaryPaths = librarySummaryPaths;
+      summaryData = SummaryDataStore(librarySummaryPaths);
     }
-    options.defaultAnalysisOptionsFilePath = contextRoot.optionsFile?.path;
-    options.defaultPackageFilePath = contextRoot.packagesFile?.path;
 
-    old.ContextBuilder builder =
-        old.ContextBuilder(resourceProvider, sdkManager, options: options);
-    builder.analysisDriverScheduler = scheduler;
-    builder.byteStore = byteStore;
-    builder.enableIndex = enableIndex;
-    builder.performanceLog = performanceLog;
-    builder.retainDataForTesting = retainDataForTesting;
-
-    old.ContextRoot oldContextRoot = old.ContextRoot(
-        contextRoot.root.path, contextRoot.excludedPaths.toList(),
-        pathContext: resourceProvider.pathContext);
-    AnalysisDriver driver = builder.buildDriver(
-      oldContextRoot,
-      contextRoot.workspace,
-      fileContentCache: fileContentCache,
-      updateAnalysisOptions: updateAnalysisOptions,
+    var workspace = contextRoot.workspace;
+    var sdk = _createSdk(
+      workspace: workspace,
+      sdkPath: sdkPath,
+      sdkSummaryPath: sdkSummaryPath,
     );
 
+    // TODO(scheglov) Ensure that "librarySummaryPaths" not null only
+    // when "sdkSummaryPath" is not null.
+    if (sdk is SummaryBasedDartSdk) {
+      summaryData?.addBundle(null, sdk.bundle);
+    }
+
+    var sourceFactory = workspace.createSourceFactory(sdk, summaryData);
+
+    var options = _getAnalysisOptions(contextRoot, sourceFactory);
+    if (updateAnalysisOptions != null) {
+      updateAnalysisOptions(options);
+    }
+
+    var driver = AnalysisDriver.tmp1(
+      scheduler: scheduler,
+      logger: performanceLog,
+      resourceProvider: resourceProvider,
+      byteStore: byteStore,
+      sourceFactory: sourceFactory,
+      analysisOptions: options,
+      packages: _createPackageMap(
+        contextRoot: contextRoot,
+      ),
+      enableIndex: enableIndex,
+      externalSummaries: summaryData,
+      retainDataForTesting: retainDataForTesting,
+      fileContentCache: fileContentCache,
+    );
+
+    if (declaredVariables != null) {
+      driver.declaredVariables = declaredVariables;
+      driver.configure();
+    }
+
     // AnalysisDriver reports results into streams.
     // We need to drain these streams to avoid memory leak.
     if (drainStreams) {
@@ -111,13 +129,103 @@
     return context;
   }
 
-  /// Convert the [declaredVariables] into a map for use with the old context
-  /// builder.
-  Map<String, String> _toMap(DeclaredVariables declaredVariables) {
-    Map<String, String> map = <String, String>{};
-    for (String name in declaredVariables.variableNames) {
-      map[name] = declaredVariables.get(name)!;
+  /// Return [Packages] to analyze the [contextRoot].
+  ///
+  /// TODO(scheglov) Get [Packages] from [Workspace]?
+  Packages _createPackageMap({
+    required ContextRoot contextRoot,
+  }) {
+    var configFile = contextRoot.packagesFile;
+    if (configFile != null) {
+      return parsePackagesFile(resourceProvider, configFile);
+    } else {
+      return Packages.empty;
     }
-    return map;
+  }
+
+  /// Return the SDK that that should be used to analyze code.
+  DartSdk _createSdk({
+    required Workspace workspace,
+    String? sdkPath,
+    String? sdkSummaryPath,
+  }) {
+    if (sdkSummaryPath != null) {
+      return SummaryBasedDartSdk(sdkSummaryPath, true,
+          resourceProvider: resourceProvider);
+    }
+
+    var folderSdk = FolderBasedDartSdk(
+      resourceProvider,
+      resourceProvider.getFolder(sdkPath!),
+    );
+
+    {
+      // TODO(scheglov) We already had partial SourceFactory in ContextLocatorImpl.
+      var partialSourceFactory = workspace.createSourceFactory(null, null);
+      var embedderYamlSource = partialSourceFactory.forUri(
+        'package:sky_engine/_embedder.yaml',
+      );
+      if (embedderYamlSource != null) {
+        var embedderYamlPath = embedderYamlSource.fullName;
+        var libFolder = resourceProvider.getFile(embedderYamlPath).parent2;
+        var locator = EmbedderYamlLocator.forLibFolder(libFolder);
+        var embedderMap = locator.embedderYamls;
+        if (embedderMap.isNotEmpty) {
+          return EmbedderSdk(
+            resourceProvider,
+            embedderMap,
+            languageVersion: folderSdk.languageVersion,
+          );
+        }
+      }
+    }
+
+    return folderSdk;
+  }
+
+  /// Return the `pubspec.yaml` file that should be used when analyzing code in
+  /// the [contextRoot], possibly `null`.
+  ///
+  /// TODO(scheglov) Get it from [Workspace]?
+  File? _findPubspecFile(ContextRoot contextRoot) {
+    for (var current in contextRoot.root.withAncestors) {
+      var file = current.getChildAssumingFile('pubspec.yaml');
+      if (file.exists) {
+        return file;
+      }
+    }
+  }
+
+  /// Return the analysis options that should be used to analyze code in the
+  /// [contextRoot].
+  ///
+  /// TODO(scheglov) We have already loaded it once in [ContextLocatorImpl].
+  AnalysisOptionsImpl _getAnalysisOptions(
+    ContextRoot contextRoot,
+    SourceFactory sourceFactory,
+  ) {
+    var options = AnalysisOptionsImpl();
+
+    var optionsFile = contextRoot.optionsFile;
+    if (optionsFile != null) {
+      try {
+        var provider = AnalysisOptionsProvider(sourceFactory);
+        var optionsMap = provider.getOptionsFromFile(optionsFile);
+        applyToAnalysisOptions(options, optionsMap);
+      } catch (e) {
+        // ignore
+      }
+    }
+
+    var pubspecFile = _findPubspecFile(contextRoot);
+    if (pubspecFile != null) {
+      var extractor = SdkConstraintExtractor(pubspecFile);
+      var sdkVersionConstraint = extractor.constraint();
+      if (sdkVersionConstraint != null) {
+        options.sdkVersionConstraint = sdkVersionConstraint;
+      }
+    }
+
+    return options;
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
index c1dfa14..7927eca 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -10,14 +10,16 @@
 import 'package:analyzer/file_system/physical_file_system.dart'
     show PhysicalResourceProvider;
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
-import 'package:analyzer/src/context/builder.dart' as old;
-import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/context_root.dart';
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer/src/util/yaml.dart';
 import 'package:analyzer/src/workspace/basic.dart';
+import 'package:analyzer/src/workspace/bazel.dart';
+import 'package:analyzer/src/workspace/gn.dart';
+import 'package:analyzer/src/workspace/package_build.dart';
+import 'package:analyzer/src/workspace/pub.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:glob/glob.dart';
 import 'package:path/path.dart';
@@ -366,12 +368,34 @@
       packages = Packages.empty;
     }
 
-    return old.ContextBuilder.createWorkspace(
-      resourceProvider: resourceProvider,
-      packages: packages,
-      options: ContextBuilderOptions(), // TODO(scheglov) remove it
-      rootPath: folder.path,
-    );
+    // TODO(scheglov) Can we use Packages instead?
+    var packageMap = <String, List<Folder>>{};
+    for (var package in packages.packages) {
+      packageMap[package.name] = [package.libFolder];
+    }
+
+    var rootPath = folder.path;
+
+    // TODO(scheglov) Do we need this?
+    if (_hasPackageFileInPath(rootPath)) {
+      // A Bazel or Gn workspace that includes a '.packages' file is treated
+      // like a normal (non-Bazel/Gn) directory. But may still use
+      // package:build or Pub.
+      return PackageBuildWorkspace.find(
+              resourceProvider, packageMap, rootPath) ??
+          PubWorkspace.find(resourceProvider, packageMap, rootPath) ??
+          BasicWorkspace.find(resourceProvider, packageMap, rootPath);
+    }
+
+    Workspace? workspace;
+    workspace = BazelWorkspace.find(resourceProvider, rootPath,
+        lookForBuildFileSubstitutes: false);
+    workspace ??= GnWorkspace.find(resourceProvider, rootPath);
+    workspace ??=
+        PackageBuildWorkspace.find(resourceProvider, packageMap, rootPath);
+    workspace ??= PubWorkspace.find(resourceProvider, packageMap, rootPath);
+    workspace ??= BasicWorkspace.find(resourceProvider, packageMap, rootPath);
+    return workspace;
   }
 
   File? _findDefaultOptionsFile(Workspace workspace) {
@@ -491,6 +515,15 @@
     return _getFile(folder, file_paths.dotPackages);
   }
 
+  /// Return `true` if either the directory at [rootPath] or a parent of that
+  /// directory contains a `.packages` file.
+  bool _hasPackageFileInPath(String rootPath) {
+    var folder = resourceProvider.getFolder(rootPath);
+    return folder.withAncestors.any((current) {
+      return current.getChildAssumingFile('.packages').exists;
+    });
+  }
+
   /// Add to the given lists of [folders] and [files] all of the resources in
   /// the given list of [paths] that exist and are not contained within one of
   /// the folders.
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 79bc69f..ed78b2e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/dart/analysis/analysis_context.dart' as api;
 import 'package:analyzer/dart/analysis/declared_variables.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/error/error.dart';
 import 'package:analyzer/error/listener.dart';
@@ -81,7 +80,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 = 161;
+  static const int DATA_VERSION = 167;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
@@ -201,10 +200,10 @@
   final _partsToAnalyze = <String>{};
 
   /// The controller for the [results] stream.
-  final _resultController = StreamController<ResolvedUnitResult>();
+  final _resultController = StreamController<Object>();
 
   /// The stream that will be written to when analysis results are produced.
-  late final Stream<ResolvedUnitResult> _onResults;
+  late final Stream<Object> _onResults;
 
   /// Resolution signatures of the most recently produced results for files.
   final Map<String, String> _lastProducedSignatures = {};
@@ -383,6 +382,13 @@
   /// an analysis result is produced for every added file prior to the next time
   /// the analysis state transitions to "idle".
   ///
+  /// [ResolvedUnitResult]s are produced for:
+  /// 1. Files requested using [getResult2].
+  /// 2. Files passed to [addFile] which are also in [priorityFiles].
+  ///
+  /// [ErrorsResult]s are produced for:
+  /// 1. Files passed to [addFile] which are not in [priorityFiles].
+  ///
   /// At least one analysis result is produced for every file passed to
   /// [addFile] or [changeFile] prior to the next time the analysis state
   /// transitions to "idle", unless the file is later removed from analysis
@@ -394,7 +400,7 @@
   ///
   /// Results might be produced even for files that have never been added
   /// using [addFile], for example when [getResult2] was called for a file.
-  Stream<ResolvedUnitResult> get results => _onResults;
+  Stream<Object> get results => _onResults;
 
   /// Return the search support for the driver.
   Search get search => _search;
@@ -463,7 +469,6 @@
         _unitElementRequestedParts.isNotEmpty) {
       return AnalysisDriverPriority.general;
     }
-    clearLibraryContext();
     return AnalysisDriverPriority.nothing;
   }
 
@@ -994,11 +999,11 @@
         }
         // Notify the completers.
         _requestedFiles.remove(path)!.forEach((completer) {
-          completer.complete(result);
+          completer.complete(result.unitResult!);
         });
         // Remove from to be analyzed and produce it now.
         _fileTracker.fileWasAnalyzed(path);
-        _resultController.add(result);
+        _resultController.add(result.unitResult!);
       } catch (exception, stackTrace) {
         _reportException(path, exception, stackTrace);
         _fileTracker.fileWasAnalyzed(path);
@@ -1123,7 +1128,7 @@
             if (result == null) {
               _partsToAnalyze.add(path);
             } else {
-              _resultController.add(result);
+              _resultController.add(result.unitResult!);
             }
           } catch (exception, stackTrace) {
             _reportException(path, exception, stackTrace);
@@ -1144,12 +1149,12 @@
             withUnit: false, skipIfSameSignature: true);
         if (result == null) {
           _partsToAnalyze.add(path);
-        } else if (result == AnalysisResult._UNCHANGED) {
+        } else if (result.isUnchangedErrors) {
           // We found that the set of errors is the same as we produced the
           // last time, so we don't need to produce it again now.
         } else {
-          _resultController.add(result);
-          _lastProducedSignatures[result.path!] = result._signature;
+          _resultController.add(result.errorsResult!);
+          _lastProducedSignatures[path] = result._signature;
         }
       } catch (exception, stackTrace) {
         _reportException(path, exception, stackTrace);
@@ -1168,11 +1173,11 @@
             withUnit: true, asIsIfPartWithoutLibrary: true)!;
         // Notify the completers.
         _requestedParts.remove(path)!.forEach((completer) {
-          completer.complete(result);
+          completer.complete(result.unitResult!);
         });
         // Remove from to be analyzed and produce it now.
         _partsToAnalyze.remove(path);
-        _resultController.add(result);
+        _resultController.add(result.unitResult!);
       } catch (exception, stackTrace) {
         _reportException(path, exception, stackTrace);
         _partsToAnalyze.remove(path);
@@ -1189,10 +1194,16 @@
       String path = _partsToAnalyze.first;
       _partsToAnalyze.remove(path);
       try {
-        var result = _computeAnalysisResult(path,
-            withUnit: _priorityFiles.contains(path),
-            asIsIfPartWithoutLibrary: true)!;
-        _resultController.add(result);
+        var withUnit = _priorityFiles.contains(path);
+        if (withUnit) {
+          var result = _computeAnalysisResult(path,
+              withUnit: true, asIsIfPartWithoutLibrary: true)!;
+          _resultController.add(result.unitResult!);
+        } else {
+          var result = _computeAnalysisResult(path,
+              withUnit: false, asIsIfPartWithoutLibrary: true)!;
+          _resultController.add(result.errorsResult!);
+        }
       } catch (exception, stackTrace) {
         _reportException(path, exception, stackTrace);
         _clearLibraryContextAfterException();
@@ -1294,8 +1305,9 @@
   /// Return the cached or newly computed analysis result of the file with the
   /// given [path].
   ///
-  /// The result will have the fully resolved unit and will always be newly
-  /// compute only if [withUnit] is `true`.
+  /// The [withUnit] flag control which result will be returned.
+  /// When `true`, [AnalysisResult.unitResult] will be set.
+  /// Otherwise [AnalysisResult.errorsResult] will be set.
   ///
   /// Return `null` if the file is a part of an unknown library, so cannot be
   /// analyzed yet. But [asIsIfPartWithoutLibrary] is `true`, then the file is
@@ -1305,7 +1317,7 @@
   /// the resolved signature of the file in its library is the same as the one
   /// that was the most recently produced to the client.
   AnalysisResult? _computeAnalysisResult(String path,
-      {bool withUnit = false,
+      {required bool withUnit,
       bool asIsIfPartWithoutLibrary = false,
       bool skipIfSameSignature = false}) {
     FileState file = _fsState.getFileForPath(path);
@@ -1328,7 +1340,7 @@
     if (skipIfSameSignature) {
       assert(!withUnit);
       if (_lastProducedSignatures[path] == signature) {
-        return AnalysisResult._UNCHANGED;
+        return AnalysisResult.unchangedErrors(signature);
       }
     }
 
@@ -1388,7 +1400,7 @@
             content: withUnit ? file.content : null,
             resolvedUnit: withUnit ? resolvedUnit : null);
         if (withUnit && _priorityFiles.contains(path)) {
-          _priorityResults[path] = result;
+          _priorityResults[path] = result.unitResult!;
         }
         return result;
       } catch (exception, stackTrace) {
@@ -1410,8 +1422,7 @@
       return null;
     }
 
-    return ErrorsResultImpl(currentSession, path, analysisResult.uri,
-        analysisResult.lineInfo, analysisResult.isPart, analysisResult.errors);
+    return analysisResult.errorsResult;
   }
 
   AnalysisDriverUnitIndex _computeIndex(String path) {
@@ -1660,7 +1671,9 @@
     var unit = AnalysisDriverResolvedUnit.fromBuffer(bytes);
     List<AnalysisError> errors = _getErrorsFromSerialized(file, unit.errors);
     _updateHasErrorOrWarningFlag(file, errors);
-    return AnalysisResult(
+    var index = unit.index!;
+    if (content != null && resolvedUnit != null) {
+      var resolvedUnitResult = ResolvedUnitResultImpl(
         currentSession,
         file.path,
         file.uri,
@@ -1668,10 +1681,21 @@
         content,
         file.lineInfo,
         file.isPart,
-        signature,
         resolvedUnit,
         errors,
-        unit.index);
+      );
+      return AnalysisResult.unit(signature, resolvedUnitResult, index);
+    } else {
+      var errorsResult = ErrorsResultImpl(
+        currentSession,
+        file.path,
+        file.uri,
+        file.lineInfo,
+        file.isPart,
+        errors,
+      );
+      return AnalysisResult.errors(signature, errorsResult, index);
+    }
   }
 
   /// Return [AnalysisError]s for the given [serialized] errors.
@@ -1720,21 +1744,19 @@
   AnalysisResult _newMissingDartLibraryResult(
       FileState file, String missingUri) {
     // TODO(scheglov) Find a better way to report this.
-    return AnalysisResult(
-        currentSession,
-        file.path,
-        file.uri,
-        file.exists,
-        null,
-        file.lineInfo,
-        file.isPart,
-        'missing',
-        null,
-        [
-          AnalysisError(file.source, 0, 0,
-              CompileTimeErrorCode.MISSING_DART_LIBRARY, [missingUri])
-        ],
-        null);
+    var errorsResult = ErrorsResultImpl(
+      currentSession,
+      file.path,
+      file.uri,
+      file.lineInfo,
+      file.isPart,
+      [
+        AnalysisError(file.source, 0, 0,
+            CompileTimeErrorCode.MISSING_DART_LIBRARY, [missingUri])
+      ],
+    );
+    return AnalysisResult.errors(
+        'missing', errorsResult, AnalysisDriverUnitIndexBuilder());
   }
 
   void _reportException(String path, Object exception, StackTrace stackTrace) {
@@ -2115,38 +2137,50 @@
 
 /// The result of analyzing of a single file.
 ///
-/// These results are self-consistent, i.e. [content], [lineInfo], the
-/// resolved [unit] correspond to each other. All referenced elements, even
+/// These results are self-consistent, i.e. the file content, line info, the
+/// resolved unit correspond to each other. All referenced elements, even
 /// external ones, are also self-consistent. But none of the results is
 /// guaranteed to be consistent with the state of the files.
 ///
 /// Every result is independent, and is not guaranteed to be consistent with
 /// any previously returned result, even inside of the same library.
-class AnalysisResult extends ResolvedUnitResultImpl {
-  static final _UNCHANGED = _UnchangedAnalysisResult();
-
+class AnalysisResult {
   /// The signature of the result based on the content of the file, and the
   /// transitive closure of files imported and exported by the library of
   /// the requested file.
   final String _signature;
 
+  final bool isUnchangedErrors;
+
+  /// Is not `null` if this result is a result with errors.
+  /// Otherwise is `null`, and usually [unitResult] is set.
+  final ErrorsResultImpl? errorsResult;
+
+  /// Is not `null` if this result is a result with a resolved unit.
+  /// Otherwise is `null`, and usually [errorsResult] is set.
+  final ResolvedUnitResultImpl? unitResult;
+
   /// The index of the unit.
   final AnalysisDriverUnitIndex? _index;
 
-  AnalysisResult(
-      AnalysisSession session,
-      String path,
-      Uri uri,
-      bool exists,
-      String? content,
-      LineInfo lineInfo,
-      bool isPart,
-      this._signature,
-      CompilationUnit? unit,
-      List<AnalysisError> errors,
-      this._index)
-      : super(session, path, uri, exists, content, lineInfo, isPart, unit,
-            errors);
+  AnalysisResult.errors(
+      this._signature, this.errorsResult, AnalysisDriverUnitIndex index)
+      : isUnchangedErrors = false,
+        unitResult = null,
+        _index = index;
+
+  AnalysisResult.unchangedErrors(this._signature)
+      : isUnchangedErrors = true,
+        errorsResult = null,
+        unitResult = null,
+        _index = null;
+
+  AnalysisResult.unit(this._signature, ResolvedUnitResultImpl unitResult,
+      AnalysisDriverUnitIndex index)
+      : isUnchangedErrors = false,
+        errorsResult = null,
+        unitResult = unitResult,
+        _index = index;
 }
 
 /// An object that watches for the creation and removal of analysis drivers.
@@ -2488,8 +2522,3 @@
     return true;
   }
 }
-
-class _UnchangedAnalysisResult implements AnalysisResult {
-  @override
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 40b742f..b21980f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -414,12 +414,8 @@
   /// Read the file content and ensure that all of the file properties are
   /// consistent with the read content, including API signature.
   ///
-  /// If [allowCached] is `true`, don't read the content of the file if it
-  /// is already cached (in another [FileSystemState], because otherwise we
-  /// would not create this new instance of [FileState] and refresh it).
-  ///
   /// Return `true` if the API signature changed since the last refresh.
-  bool refresh({bool allowCached = false}) {
+  bool refresh() {
     counterFileStateRefresh++;
 
     var timerWasRunning = timerFileStateRefresh.isRunning;
@@ -429,10 +425,6 @@
 
     _invalidateCurrentUnresolvedData();
 
-    if (!allowCached) {
-      _fsState.markFileForReading(path);
-    }
-
     {
       var rawFileState = _fsState._fileContentCache.get(path);
       _content = rawFileState.content;
@@ -862,7 +854,7 @@
       _uriToFile[uri] = file;
       _addFileWithPath(path, file);
       _pathToCanonicalFile[path] = file;
-      file.refresh(allowCached: true);
+      file.refresh();
     }
     return file;
   }
@@ -908,7 +900,7 @@
           packageLanguageVersion);
       _uriToFile[uri] = file;
       _addFileWithPath(path, file);
-      file.refresh(allowCached: true);
+      file.refresh();
     }
     return Either2.t1(file);
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index e10f9be..af4dab4 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -332,7 +332,6 @@
 
     var enableTiming = _analysisOptions.enableTiming;
     var nodeRegistry = NodeLintRegistry(enableTiming);
-    var visitors = <AstVisitor>[];
 
     var context = LinterContextImpl(
       allUnits,
@@ -354,14 +353,9 @@
 
     // Run lints that handle specific node types.
     unit.accept(LinterVisitor(
-        nodeRegistry, ExceptionHandlingDelegatingAstVisitor.logException));
-
-    // Run visitor based lints.
-    if (visitors.isNotEmpty) {
-      AstVisitor visitor = ExceptionHandlingDelegatingAstVisitor(
-          visitors, ExceptionHandlingDelegatingAstVisitor.logException);
-      unit.accept(visitor);
-    }
+        nodeRegistry,
+        LinterExceptionHandler(_analysisOptions.propagateLinterExceptions)
+            .logException));
   }
 
   void _computeVerifyErrors(FileState file, CompilationUnit unit) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
index bcd371c..9db2ec6 100644
--- a/pkg/analyzer/lib/src/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
@@ -18,7 +17,7 @@
   final AnalysisSession session;
 
   @override
-  final String? path;
+  final String path;
 
   @override
   final Uri uri;
@@ -74,130 +73,17 @@
   LibraryElementResultImpl(this.element);
 }
 
-/// The implementation of [AnalysisResult] when not [ResultState.VALID].
-class NotValidAnalysisResultImpl implements AnalysisResult {
-  @override
-  final ResultState state;
-
-  NotValidAnalysisResultImpl(this.state);
-
-  @override
-  String? get path {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  AnalysisSession get session {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  Uri get uri {
-    throw StateError('This result is not valid');
-  }
-}
-
-/// The implementation of [ErrorsResult] when not [ResultState.VALID].
-class NotValidErrorsResultImpl extends NotValidFileResultImpl
-    implements ErrorsResult {
-  NotValidErrorsResultImpl(ResultState state) : super(state);
-
-  @override
-  List<AnalysisError> get errors {
-    throw StateError('This result is not valid');
-  }
-}
-
-/// The implementation of [FileResult] when not [ResultState.VALID].
-class NotValidFileResultImpl extends NotValidAnalysisResultImpl
-    implements FileResult {
-  NotValidFileResultImpl(ResultState state) : super(state);
-
-  @override
-  bool get isPart {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  LineInfo get lineInfo {
-    throw StateError('This result is not valid');
-  }
-}
-
-/// The implementation of [ResolvedUnitResult] when not [ResultState.VALID].
-class NotValidResolvedUnitResultImpl extends NotValidFileResultImpl
-    implements ResolvedUnitResult {
-  NotValidResolvedUnitResultImpl(ResultState state) : super(state);
-
-  @override
-  String? get content {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  List<AnalysisError> get errors {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  bool get exists {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  LibraryElement get libraryElement {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  TypeProvider get typeProvider {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  TypeSystem get typeSystem {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  CompilationUnit? get unit {
-    throw StateError('This result is not valid');
-  }
-}
-
-/// The implementation of [UnitElementResult] when not [ResultState.VALID].
-class NotValidUnitElementResultImpl extends NotValidAnalysisResultImpl
-    implements UnitElementResult {
-  NotValidUnitElementResultImpl(ResultState state) : super(state);
-
-  @override
-  CompilationUnitElement get element {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  String get signature {
-    throw StateError('This result is not valid');
-  }
-}
-
 class ParsedLibraryResultImpl extends AnalysisResultImpl
     implements ParsedLibraryResult {
   @override
-  final List<ParsedUnitResult>? units;
+  final List<ParsedUnitResult> units;
 
   ParsedLibraryResultImpl(
-      AnalysisSession session, String? path, Uri uri, this.units)
+      AnalysisSession session, String path, Uri uri, this.units)
       : super(session, path, uri);
 
-  ParsedLibraryResultImpl.external(AnalysisSession session, Uri uri)
-      : this(session, null, uri, null);
-
   @override
   ResultState get state {
-    if (path == null) {
-      return ResultState.NOT_A_FILE;
-    }
     return ResultState.VALID;
   }
 
@@ -215,7 +101,7 @@
     }
 
     var elementPath = element.source!.fullName;
-    var unitResult = units!.firstWhere(
+    var unitResult = units.firstWhere(
       (r) => r.path == elementPath,
       orElse: () {
         var elementStr = element.getDisplayString(withNullability: true);
@@ -273,28 +159,22 @@
 class ResolvedLibraryResultImpl extends AnalysisResultImpl
     implements ResolvedLibraryResult {
   @override
-  final LibraryElement? element;
+  final LibraryElement element;
 
   @override
-  final List<ResolvedUnitResult>? units;
+  final List<ResolvedUnitResult> units;
 
   ResolvedLibraryResultImpl(
-      AnalysisSession session, String? path, Uri uri, this.element, this.units)
+      AnalysisSession session, String path, Uri uri, this.element, this.units)
       : super(session, path, uri);
 
-  ResolvedLibraryResultImpl.external(AnalysisSession session, Uri uri)
-      : this(session, null, uri, null, null);
-
   @override
   ResultState get state {
-    if (path == null) {
-      return ResultState.NOT_A_FILE;
-    }
     return ResultState.VALID;
   }
 
   @override
-  TypeProvider get typeProvider => element!.typeProvider;
+  TypeProvider get typeProvider => element.typeProvider;
 
   @override
   ElementDeclarationResult? getElementDeclaration(Element element) {
@@ -310,7 +190,7 @@
     }
 
     var elementPath = element.source!.fullName;
-    var unitResult = units!.firstWhere(
+    var unitResult = units.firstWhere(
       (r) => r.path == elementPath,
       orElse: () {
         var elementStr = element.getDisplayString(withNullability: true);
@@ -319,18 +199,13 @@
         buffer.writeln(' is not defined in this library.');
         // TODO(scheglov) https://github.com/dart-lang/sdk/issues/45430
         buffer.writeln('elementPath: $elementPath');
-        buffer.writeln('unitPaths: ${units!.map((e) => e.path).toList()}');
+        buffer.writeln('unitPaths: ${units.map((e) => e.path).toList()}');
         throw ArgumentError('$buffer');
       },
     );
 
-    var unit = unitResult.unit;
-    if (unit == null) {
-      throw StateError('The result has no unit');
-    }
-
     var locator = _DeclarationByElementLocator(element);
-    unit.accept(locator);
+    unitResult.unit.accept(locator);
     var declaration = locator.result;
 
     if (declaration == null) {
@@ -347,10 +222,10 @@
   final bool exists;
 
   @override
-  final String? content;
+  final String content;
 
   @override
-  final CompilationUnit? unit;
+  final CompilationUnit unit;
 
   @override
   final List<AnalysisError> errors;
@@ -369,10 +244,6 @@
 
   @override
   LibraryElement get libraryElement {
-    final unit = this.unit;
-    if (unit == null) {
-      throw StateError('The result has no unit');
-    }
     return unit.declaredElement!.library;
   }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 20df7ad..8d7a200 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -381,7 +381,7 @@
       var unitResult = await _driver.getResult2(unitPath);
       if (unitResult is ResolvedUnitResult) {
         var visitor = _ImportElementReferencesVisitor(element, unitElement);
-        unitResult.unit!.accept(visitor);
+        unitResult.unit.accept(visitor);
         results.addAll(visitor.results);
       }
     }
@@ -400,7 +400,7 @@
       String unitPath = unitElement.source.fullName;
       var unitResult = await _driver.getResult2(unitPath);
       if (unitResult is ResolvedUnitResult) {
-        CompilationUnit unit = unitResult.unit!;
+        CompilationUnit unit = unitResult.unit;
         for (Directive directive in unit.directives) {
           if (directive is PartOfDirective && directive.element == element) {
             results.add(
@@ -433,9 +433,6 @@
       return const <SearchResult>[];
     }
     var unit = unitResult.unit;
-    if (unit == null) {
-      return const <SearchResult>[];
-    }
 
     // Prepare the node.
     var node = NodeLocator(element.nameOffset).searchWithin(unit);
@@ -487,7 +484,7 @@
       var unitResult = await _driver.getResult2(unitPath);
       if (unitResult is ResolvedUnitResult) {
         var visitor = _LocalReferencesVisitor(element, unitElement);
-        unitResult.unit!.accept(visitor);
+        unitResult.unit.accept(visitor);
         results.addAll(visitor.results);
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 288882e..5bc5a9c 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -55,31 +55,55 @@
   driver.AnalysisDriver getDriver() => _driver;
 
   @override
-  Future<SomeErrorsResult> getErrors2(String path) {
+  Future<SomeErrorsResult> getErrors(String path) {
     _checkConsistency();
     return _driver.getErrors2(path);
   }
 
+  @Deprecated('Use getErrors() instead')
   @override
-  SomeFileResult getFile2(String path) {
+  Future<SomeErrorsResult> getErrors2(String path) {
+    return getErrors(path);
+  }
+
+  @override
+  SomeFileResult getFile(String path) {
     _checkConsistency();
     return _driver.getFileSync2(path);
   }
 
+  @Deprecated('Use getFile() instead')
   @override
-  Future<SomeLibraryElementResult> getLibraryByUri2(String uri) {
+  SomeFileResult getFile2(String path) {
+    return getFile(path);
+  }
+
+  @override
+  Future<SomeLibraryElementResult> getLibraryByUri(String uri) {
     _checkConsistency();
     return _driver.getLibraryByUri2(uri);
   }
 
+  @Deprecated('Use getLibraryByUri() instead')
   @override
-  SomeParsedLibraryResult getParsedLibrary2(String path) {
+  Future<SomeLibraryElementResult> getLibraryByUri2(String uri) {
+    return getLibraryByUri(uri);
+  }
+
+  @override
+  SomeParsedLibraryResult getParsedLibrary(String path) {
     _checkConsistency();
     return _driver.getParsedLibrary2(path);
   }
 
+  @Deprecated('Use getParsedLibrary() instead')
   @override
-  SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element) {
+  SomeParsedLibraryResult getParsedLibrary2(String path) {
+    return getParsedLibrary(path);
+  }
+
+  @override
+  SomeParsedLibraryResult getParsedLibraryByElement(LibraryElement element) {
     _checkConsistency();
 
     if (element.session != this) {
@@ -89,20 +113,38 @@
     return _driver.getParsedLibraryByUri2(element.source.uri);
   }
 
+  @Deprecated('Use getParsedLibraryByElement() instead')
   @override
-  SomeParsedUnitResult getParsedUnit2(String path) {
+  SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element) {
+    return getParsedLibraryByElement(element);
+  }
+
+  @override
+  SomeParsedUnitResult getParsedUnit(String path) {
     _checkConsistency();
     return _driver.parseFileSync2(path);
   }
 
+  @Deprecated('Use getParsedUnit() instead')
   @override
-  Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path) {
+  SomeParsedUnitResult getParsedUnit2(String path) {
+    return getParsedUnit(path);
+  }
+
+  @override
+  Future<SomeResolvedLibraryResult> getResolvedLibrary(String path) {
     _checkConsistency();
     return _driver.getResolvedLibrary2(path);
   }
 
+  @Deprecated('Use getResolvedLibrary() instead')
   @override
-  Future<SomeResolvedLibraryResult> getResolvedLibraryByElement2(
+  Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path) {
+    return getResolvedLibrary(path);
+  }
+
+  @override
+  Future<SomeResolvedLibraryResult> getResolvedLibraryByElement(
     LibraryElement element,
   ) {
     _checkConsistency();
@@ -116,18 +158,38 @@
     return _driver.getResolvedLibraryByUri2(element.source.uri);
   }
 
+  @Deprecated('Use getResolvedLibraryByElement() instead')
   @override
-  Future<SomeResolvedUnitResult> getResolvedUnit2(String path) {
+  Future<SomeResolvedLibraryResult> getResolvedLibraryByElement2(
+    LibraryElement element,
+  ) {
+    return getResolvedLibraryByElement(element);
+  }
+
+  @override
+  Future<SomeResolvedUnitResult> getResolvedUnit(String path) {
     _checkConsistency();
     return _driver.getResult2(path);
   }
 
+  @Deprecated('Use getResolvedUnit() instead')
   @override
-  Future<SomeUnitElementResult> getUnitElement2(String path) {
+  Future<SomeResolvedUnitResult> getResolvedUnit2(String path) {
+    return getResolvedUnit(path);
+  }
+
+  @override
+  Future<SomeUnitElementResult> getUnitElement(String path) {
     _checkConsistency();
     return _driver.getUnitElement2(path);
   }
 
+  @Deprecated('Use getUnitElement() instead')
+  @override
+  Future<SomeUnitElementResult> getUnitElement2(String path) {
+    return getUnitElement(path);
+  }
+
   /// Check to see that results from this session will be consistent, and throw
   /// an [InconsistentAnalysisException] if they might not be.
   void _checkConsistency() {
diff --git a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
index 020af5d..a7bc83a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
@@ -22,7 +22,7 @@
   /// from the library with the given [libraryUri], or `null` if the library
   /// does not export a class with such name.
   Future<ClassElement?> getClass(String libraryUri, String className) async {
-    var libraryResult = await session.getLibraryByUri2(libraryUri);
+    var libraryResult = await session.getLibraryByUri(libraryUri);
     if (libraryResult is LibraryElementResult) {
       var element = libraryResult.element.exportNamespace.get(className);
       if (element is ClassElement) {
@@ -50,7 +50,7 @@
     }
 
     var unitPath = element.source!.fullName;
-    return resolvedLibrary.units!.singleWhere((resolvedUnit) {
+    return resolvedLibrary.units.singleWhere((resolvedUnit) {
       return resolvedUnit.path == unitPath;
     });
   }
@@ -60,7 +60,7 @@
   /// library does not export a top-level accessor with such name.
   Future<PropertyAccessorElement?> getTopLevelPropertyAccessor(
       String uri, String name) async {
-    var libraryResult = await session.getLibraryByUri2(uri);
+    var libraryResult = await session.getLibraryByUri(uri);
     if (libraryResult is LibraryElementResult) {
       var element = libraryResult.element.exportNamespace.get(name);
       if (element is PropertyAccessorElement) {
@@ -74,7 +74,7 @@
   Future<ResolvedLibraryResult?> _getResolvedLibrary(String path) async {
     var result = _resolvedLibraries[path];
     if (result == null) {
-      var some = await session.getResolvedLibrary2(path);
+      var some = await session.getResolvedLibrary(path);
       if (some is ResolvedLibraryResult) {
         result = _resolvedLibraries[path] = some;
       }
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 874c8f5..9256fa8 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -5892,8 +5892,7 @@
 
     final parent = this.parent;
     if (parent is CompoundAssignmentExpression) {
-      var assignment = parent as CompoundAssignmentExpression;
-      element = assignment.writeElement ?? assignment.readElement;
+      element = parent.writeElement ?? parent.readElement;
     }
 
     if (element is ExecutableElement) {
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 605628f..4387e37 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -1302,38 +1302,19 @@
   }
 }
 
-/// A [DelegatingAstVisitor] that will additionally catch all exceptions from
-/// the delegates without stopping the visiting. A function must be provided
-/// that will be invoked for each such exception.
+/// Class capable of handling exceptions generated during linting.
 ///
 /// Clients may not extend, implement or mix-in this class.
-class ExceptionHandlingDelegatingAstVisitor<T> extends DelegatingAstVisitor<T> {
-  /// The function that will be executed for each exception that is thrown by
-  /// one of the visit methods on the delegate.
-  final ExceptionInDelegateHandler handler;
+class LinterExceptionHandler {
+  /// Indicates whether linter exceptions should be propagated to the caller (by
+  /// re-throwing them)
+  final bool propagateLinterExceptions;
 
-  /// Initialize a newly created visitor to use each of the given delegate
-  /// visitors to visit the nodes of an AST structure.
-  ExceptionHandlingDelegatingAstVisitor(
-      Iterable<AstVisitor<T>> delegates, this.handler)
-      : super(delegates);
+  LinterExceptionHandler(this.propagateLinterExceptions);
 
-  @override
-  T? visitNode(AstNode node) {
-    delegates.forEach((delegate) {
-      try {
-        node.accept(delegate);
-      } catch (exception, stackTrace) {
-        handler(node, delegate, exception, stackTrace);
-      }
-    });
-    node.visitChildren(this);
-    return null;
-  }
-
-  /// A function that can be used with instances of this class to log and then
-  /// ignore any exceptions that are thrown by any of the delegates.
-  static void logException(
+  /// A method that can be passed to the `LinterVisitor` constructor to handle
+  /// exceptions that occur during linting.
+  void logException(
       AstNode node, Object visitor, dynamic exception, StackTrace stackTrace) {
     StringBuffer buffer = StringBuffer();
     buffer.write('Exception while using a ${visitor.runtimeType} to visit a ');
@@ -1351,6 +1332,9 @@
     // TODO(39284): should this exception be silent?
     AnalysisEngine.instance.instrumentationService.logException(
         SilentException(buffer.toString(), exception, stackTrace));
+    if (propagateLinterExceptions) {
+      throw exception;
+    }
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 2bdca7a..549e1bc 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
+import 'dart:typed_data';
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/session.dart';
@@ -14,6 +15,7 @@
 import 'package:analyzer/dart/element/scope.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/ast/ast_factory.dart';
@@ -610,6 +612,42 @@
   @override
   bool get isDartCoreObject => !isMixin && supertype == null;
 
+  bool get isEnumLike {
+    // Must be a concrete class.
+    if (isAbstract || isMixin) {
+      return false;
+    }
+
+    // With only private non-factory constructors.
+    for (var constructor in constructors) {
+      if (constructor.isPublic || constructor.isFactory) {
+        return false;
+      }
+    }
+
+    // With 2+ static const fields with the type of this class.
+    var numberOfElements = 0;
+    for (var field in fields) {
+      if (field.isStatic && field.isConst && field.type == thisType) {
+        numberOfElements++;
+      }
+    }
+    if (numberOfElements < 2) {
+      return false;
+    }
+
+    // No subclasses in the library.
+    for (var unit in library.units) {
+      for (var class_ in unit.classes) {
+        if (class_.supertype?.element == this) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
   @override
   bool get isMixinApplication {
     return hasModifier(Modifier.MIXIN_APPLICATION);
@@ -910,6 +948,10 @@
 
   static ConstructorElement? getNamedConstructorFromList(
       String name, List<ConstructorElement> constructors) {
+    if (name == 'new') {
+      // An unnamed constructor declared with `C.new(` is modeled as unnamed.
+      name = '';
+    }
     for (ConstructorElement element in constructors) {
       if (element.name == name) {
         return element;
@@ -1367,7 +1409,7 @@
 /// A concrete implementation of a [ConstructorElement].
 class ConstructorElementImpl extends ExecutableElementImpl
     with ConstructorElementMixin
-    implements ConstructorElement {
+    implements ConstructorElement, HasMacroGenerationData {
   /// The constructor to which this constructor is redirecting.
   ConstructorElement? _redirectedConstructor;
 
@@ -1376,6 +1418,9 @@
   List<ConstructorInitializer> _constantInitializers = const [];
 
   @override
+  MacroGenerationData? macro;
+
+  @override
   int? periodOffset;
 
   @override
@@ -2010,9 +2055,6 @@
   /// The length of the element's code, or `null` if the element is synthetic.
   int? _codeLength;
 
-  /// The language version for the library.
-  LibraryLanguageVersion? _languageVersion;
-
   /// Initialize a newly created element to have the given [name] at the given
   /// [_nameOffset].
   ElementImpl(String? name, this._nameOffset, {this.reference}) {
@@ -3435,6 +3477,13 @@
   }
 }
 
+/// This interface is implemented by [Element]s that can be added by macros.
+abstract class HasMacroGenerationData {
+  /// If this element was added by a macro, the code of a declaration that
+  /// was produced by the macro.
+  MacroGenerationData? macro;
+}
+
 /// A concrete implementation of a [HideElementCombinator].
 class HideElementCombinatorImpl implements HideElementCombinator {
   @override
@@ -3575,6 +3624,9 @@
   @override
   final AnalysisSession session;
 
+  /// The language version for the library.
+  LibraryLanguageVersion? _languageVersion;
+
   bool hasTypeProviderSystemSet = false;
 
   @override
@@ -3958,6 +4010,64 @@
     return getTypeFromParts(className, _definingCompilationUnit, _parts);
   }
 
+  /// Indicates whether it is unnecessary to report an undefined identifier
+  /// error for an identifier reference with the given [name] and optional
+  /// [prefix].
+  ///
+  /// This method is intended to reduce spurious errors in circumstances where
+  /// an undefined identifier occurs as the result of a missing (most likely
+  /// code generated) file.  It will only return `true` in a circumstance where
+  /// the current library is guaranteed to have at least one other error (due to
+  /// a missing part or import), so there is no risk that ignoring the undefined
+  /// identifier would cause an invalid program to be treated as valid.
+  bool shouldIgnoreUndefined({
+    required String? prefix,
+    required String name,
+  }) {
+    for (var importElement in imports) {
+      if (importElement.prefix?.name == prefix &&
+          importElement.importedLibrary?.isSynthetic != false) {
+        var showCombinators = importElement.combinators
+            .whereType<ShowElementCombinator>()
+            .toList();
+        if (prefix != null && showCombinators.isEmpty) {
+          return true;
+        }
+        for (var combinator in showCombinators) {
+          if (combinator.shownNames.contains(name)) {
+            return true;
+          }
+        }
+      }
+    }
+
+    if (prefix == null && name.startsWith(r'_$')) {
+      for (var partElement in parts) {
+        if (partElement.isSynthetic && isGeneratedSource(partElement.source)) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  /// Convenience wrapper around [shouldIgnoreUndefined] that calls it for a
+  /// given (possibly prefixed) identifier [node].
+  bool shouldIgnoreUndefinedIdentifier(Identifier node) {
+    if (node is PrefixedIdentifier) {
+      return shouldIgnoreUndefined(
+        prefix: node.prefix.name,
+        name: node.identifier.name,
+      );
+    }
+
+    return shouldIgnoreUndefined(
+      prefix: null,
+      name: (node as SimpleIdentifier).name,
+    );
+  }
+
   @override
   T toLegacyElementIfOptOut<T extends Element>(T element) {
     if (isNonNullableByDefault) return element;
@@ -4049,8 +4159,36 @@
       visitor.visitLocalVariableElement(this);
 }
 
+/// Information about a macro-produced [Element].
+class MacroGenerationData {
+  /// The sequential id of this macro-produced element, for an element created
+  /// for a declaration that was macro-generated later this value is greater.
+  ///
+  /// This is different from [ElementImpl.id], which is also incrementing,
+  /// but shows the order in which elements were built from declarations,
+  /// not the order of declarations, and we process all field declarations
+  /// before method declarations.
+  final int id;
+
+  /// The code that was produced by the macro. It is used to compose full
+  /// code of a unit to display to the user, so that new declarations are
+  /// added to the unit or existing classes.
+  ///
+  /// When a class is generated, its code might have some members, or might
+  /// be empty, and new elements might be macro-generated into it.
+  final String code;
+
+  /// When we build elements from macro-produced code, we remember informative
+  /// data, such as offsets - to store it into bytes. This field is set to
+  /// an empty list when reading from bytes.
+  final Uint8List informative;
+
+  MacroGenerationData(this.id, this.code, this.informative);
+}
+
 /// A concrete implementation of a [MethodElement].
-class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
+class MethodElementImpl extends ExecutableElementImpl
+    implements MethodElement, HasMacroGenerationData {
   /// Is `true` if this method is `operator==`, and there is no explicit
   /// type specified for its formal parameter, in this method or in any
   /// overridden methods other than the one declared in `Object`.
@@ -4060,6 +4198,9 @@
   /// this variable is not a subject of type inference, or there was no error.
   TopLevelInferenceError? typeInferenceError;
 
+  @override
+  MacroGenerationData? macro;
+
   /// Initialize a newly created method element to have the given [name] at the
   /// given [offset].
   MethodElementImpl(String name, int offset) : super(name, offset);
@@ -4863,11 +5004,14 @@
 
 /// A concrete implementation of a [PropertyAccessorElement].
 class PropertyAccessorElementImpl extends ExecutableElementImpl
-    implements PropertyAccessorElement {
+    implements PropertyAccessorElement, HasMacroGenerationData {
   /// The variable associated with this accessor.
   @override
   late PropertyInducingElement variable;
 
+  @override
+  MacroGenerationData? macro;
+
   /// Initialize a newly created property accessor element to have the given
   /// [name] and [offset].
   PropertyAccessorElementImpl(String name, int offset) : super(name, offset);
@@ -5423,23 +5567,29 @@
         parameters: type.parameters,
         returnType: type.returnType,
         nullabilitySuffix: resultNullability,
-        aliasElement: this,
-        aliasArguments: typeArguments,
+        alias: InstantiatedTypeAliasElementImpl(
+          element: this,
+          typeArguments: typeArguments,
+        ),
       );
     } else if (type is InterfaceType) {
       return InterfaceTypeImpl(
         element: type.element,
         typeArguments: type.typeArguments,
         nullabilitySuffix: resultNullability,
-        aliasElement: this,
-        aliasArguments: typeArguments,
+        alias: InstantiatedTypeAliasElementImpl(
+          element: this,
+          typeArguments: typeArguments,
+        ),
       );
     } else if (type is TypeParameterType) {
       return TypeParameterTypeImpl(
         element: type.element,
         nullabilitySuffix: resultNullability,
-        aliasElement: this,
-        aliasArguments: typeArguments,
+        alias: InstantiatedTypeAliasElementImpl(
+          element: this,
+          typeArguments: typeArguments,
+        ),
       );
     } else {
       return (type as TypeImpl).withNullability(resultNullability);
diff --git a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
index b05ab3d..f4077d4 100644
--- a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
+++ b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
@@ -583,7 +583,7 @@
           if (typeElement != null && typeElement.hasOptionalTypeArgs) {
             return;
           }
-          var typeAliasElement = type.aliasElement;
+          var typeAliasElement = type.alias?.element;
           if (typeAliasElement != null &&
               typeAliasElement.hasOptionalTypeArgs) {
             return;
diff --git a/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart b/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
index 5709733..2db9a85 100644
--- a/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
@@ -53,8 +53,9 @@
       }
     }
 
-    if (type.aliasElement != null) {
-      return _typeAliasInstantiation(type, variance);
+    var alias = type.alias;
+    if (alias != null) {
+      return _instantiatedTypeAlias(type, alias, variance);
     } else if (type is InterfaceType) {
       return _interfaceType(type, variance);
     } else if (type is FunctionType) {
@@ -83,6 +84,34 @@
     );
   }
 
+  DartType _instantiatedTypeAlias(
+    DartType type,
+    InstantiatedTypeAliasElement alias,
+    Variance variance,
+  ) {
+    var aliasElement = alias.element;
+    var aliasArguments = alias.typeArguments;
+
+    var typeParameters = aliasElement.typeParameters;
+    assert(typeParameters.length == aliasArguments.length);
+
+    var newTypeArguments = <DartType>[];
+    for (var i = 0; i < typeParameters.length; i++) {
+      var typeParameter = typeParameters[i] as TypeParameterElementImpl;
+      newTypeArguments.add(
+        process(
+          aliasArguments[i],
+          typeParameter.variance.combine(variance),
+        ),
+      );
+    }
+
+    return aliasElement.instantiate(
+      typeArguments: newTypeArguments,
+      nullabilitySuffix: type.nullabilitySuffix,
+    );
+  }
+
   DartType _interfaceType(InterfaceType type, Variance variance) {
     var typeParameters = type.element.typeParameters;
     if (typeParameters.isEmpty) {
@@ -105,30 +134,6 @@
     );
   }
 
-  DartType _typeAliasInstantiation(DartType type, Variance variance) {
-    var aliasElement = type.aliasElement!;
-    var aliasArguments = type.aliasArguments!;
-
-    var typeParameters = aliasElement.typeParameters;
-    assert(typeParameters.length == aliasArguments.length);
-
-    var newTypeArguments = <DartType>[];
-    for (var i = 0; i < typeParameters.length; i++) {
-      var typeParameter = typeParameters[i] as TypeParameterElementImpl;
-      newTypeArguments.add(
-        process(
-          aliasArguments[i],
-          typeParameter.variance.combine(variance),
-        ),
-      );
-    }
-
-    return aliasElement.instantiate(
-      typeArguments: newTypeArguments,
-      nullabilitySuffix: type.nullabilitySuffix,
-    );
-  }
-
   /// Runs an instance of the visitor on the given [type] and returns the
   /// resulting type.  If the type contains no instances of Top or Bottom, the
   /// original type object is returned to avoid unnecessary allocation.
diff --git a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
index c1c1a79..638ad0f 100644
--- a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
@@ -29,13 +29,14 @@
 
   DartType? createFunctionType({
     required FunctionType type,
-    required List<DartType>? newAliasArguments,
+    required InstantiatedTypeAliasElement? newAlias,
     required List<TypeParameterElement>? newTypeParameters,
     required List<ParameterElement>? newParameters,
     required DartType? newReturnType,
     required NullabilitySuffix? newNullability,
   }) {
-    if (newNullability == null &&
+    if (newAlias == null &&
+        newNullability == null &&
         newReturnType == null &&
         newParameters == null) {
       return null;
@@ -46,8 +47,7 @@
       parameters: newParameters ?? type.parameters,
       returnType: newReturnType ?? type.returnType,
       nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
-      aliasElement: type.aliasElement,
-      aliasArguments: newAliasArguments ?? type.aliasArguments,
+      alias: newAlias ?? type.alias,
     );
   }
 
@@ -74,11 +74,11 @@
 
   DartType? createInterfaceType({
     required InterfaceType type,
-    required List<DartType>? newAliasArguments,
+    required InstantiatedTypeAliasElement? newAlias,
     required List<DartType>? newTypeArguments,
     required NullabilitySuffix? newNullability,
   }) {
-    if (newAliasArguments == null &&
+    if (newAlias == null &&
         newTypeArguments == null &&
         newNullability == null) {
       return null;
@@ -88,8 +88,7 @@
       element: type.element,
       typeArguments: newTypeArguments ?? type.typeArguments,
       nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
-      aliasElement: type.aliasElement,
-      aliasArguments: newAliasArguments ?? type.aliasArguments,
+      alias: newAlias ?? type.alias,
     );
   }
 
@@ -136,8 +135,7 @@
       element: type.element,
       nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
       promotedBound: newPromotedBound ?? promotedBound,
-      aliasElement: type.aliasElement,
-      aliasArguments: type.aliasArguments,
+      alias: type.alias,
     );
   }
 
@@ -152,8 +150,7 @@
     return TypeParameterTypeImpl(
       element: type.element,
       nullabilitySuffix: newNullability,
-      aliasElement: type.aliasElement,
-      aliasArguments: type.aliasArguments,
+      alias: type.alias,
     );
   }
 
@@ -215,16 +212,24 @@
 
     var newReturnType = visitType(node.returnType);
 
-    List<DartType>? newAliasArguments;
-    var aliasArguments = node.aliasArguments;
-    if (aliasArguments != null) {
+    InstantiatedTypeAliasElement? newAlias;
+    var alias = node.alias;
+    if (alias != null) {
+      List<DartType>? newArguments;
+      var aliasArguments = alias.typeArguments;
       for (var i = 0; i < aliasArguments.length; i++) {
         var substitution = aliasArguments[i].accept(this);
         if (substitution != null) {
-          newAliasArguments ??= aliasArguments.toList(growable: false);
-          newAliasArguments[i] = substitution;
+          newArguments ??= aliasArguments.toList(growable: false);
+          newArguments[i] = substitution;
         }
       }
+      if (newArguments != null) {
+        newAlias = InstantiatedTypeAliasElementImpl(
+          element: alias.element,
+          typeArguments: newArguments,
+        );
+      }
     }
 
     changeVariance();
@@ -253,7 +258,7 @@
 
     return createFunctionType(
       type: node,
-      newAliasArguments: newAliasArguments,
+      newAlias: newAlias,
       newTypeParameters: newTypeParameters,
       newParameters: newParameters,
       newReturnType: newReturnType,
@@ -351,13 +356,20 @@
   DartType? visitInterfaceType(InterfaceType type) {
     var newNullability = visitNullability(type);
 
-    var aliasElement = type.aliasElement;
-    var newAliasArguments = aliasElement != null
-        ? _typeArguments(
-            aliasElement.typeParameters,
-            type.aliasArguments,
-          )
-        : null;
+    InstantiatedTypeAliasElement? newAlias;
+    var alias = type.alias;
+    if (alias != null) {
+      var newArguments = _typeArguments(
+        alias.element.typeParameters,
+        alias.typeArguments,
+      );
+      if (newArguments != null) {
+        newAlias = InstantiatedTypeAliasElementImpl(
+          element: alias.element,
+          typeArguments: newArguments,
+        );
+      }
+    }
 
     var newTypeArguments = _typeArguments(
       type.element.typeParameters,
@@ -366,7 +378,7 @@
 
     return createInterfaceType(
       type: type,
-      newAliasArguments: newAliasArguments,
+      newAlias: newAlias,
       newTypeArguments: newTypeArguments,
       newNullability: newNullability,
     );
@@ -453,12 +465,8 @@
 
   List<DartType>? _typeArguments(
     List<TypeParameterElement> parameters,
-    List<DartType>? arguments,
+    List<DartType> arguments,
   ) {
-    if (arguments == null) {
-      return null;
-    }
-
     if (arguments.length != parameters.length) {
       return null;
     }
diff --git a/pkg/analyzer/lib/src/dart/element/scope.dart b/pkg/analyzer/lib/src/dart/element/scope.dart
index 1f15606..4df2190 100644
--- a/pkg/analyzer/lib/src/dart/element/scope.dart
+++ b/pkg/analyzer/lib/src/dart/element/scope.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/scope.dart';
-import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart' as impl;
 
@@ -104,38 +103,6 @@
     _element.units.forEach(_addUnitElements);
   }
 
-  bool shouldIgnoreUndefined({
-    required String? prefix,
-    required String name,
-  }) {
-    for (var importElement in _element.imports) {
-      if (importElement.prefix?.name == prefix &&
-          importElement.importedLibrary?.isSynthetic != false) {
-        var showCombinators = importElement.combinators
-            .whereType<ShowElementCombinator>()
-            .toList();
-        if (prefix != null && showCombinators.isEmpty) {
-          return true;
-        }
-        for (var combinator in showCombinators) {
-          if (combinator.shownNames.contains(name)) {
-            return true;
-          }
-        }
-      }
-    }
-
-    if (prefix == null && name.startsWith(r'_$')) {
-      for (var partElement in _element.parts) {
-        if (partElement.isSynthetic && isGeneratedSource(partElement.source)) {
-          return true;
-        }
-      }
-    }
-
-    return false;
-  }
-
   void _addExtension(ExtensionElement element) {
     _addGetter(element);
     if (!extensions.contains(element)) {
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index a123137..846f845 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -109,13 +109,12 @@
     required List<ParameterElement> parameters,
     required DartType returnType,
     required NullabilitySuffix nullabilitySuffix,
-    TypeAliasElement? aliasElement,
-    List<DartType>? aliasArguments,
+    InstantiatedTypeAliasElement? alias,
   })  : typeFormals = typeFormals,
         parameters = _sortNamedParameters(parameters),
         returnType = returnType,
         nullabilitySuffix = nullabilitySuffix,
-        super(null, aliasElement: aliasElement, aliasArguments: aliasArguments);
+        super(null, alias: alias);
 
   @override
   int get hashCode {
@@ -297,8 +296,7 @@
       parameters: parameters,
       returnType: returnType,
       nullabilitySuffix: nullabilitySuffix,
-      aliasElement: aliasElement,
-      aliasArguments: aliasArguments,
+      alias: alias,
     );
   }
 
@@ -610,6 +608,19 @@
   }
 }
 
+class InstantiatedTypeAliasElementImpl implements InstantiatedTypeAliasElement {
+  @override
+  final TypeAliasElement element;
+
+  @override
+  final List<DartType> typeArguments;
+
+  InstantiatedTypeAliasElementImpl({
+    required this.element,
+    required this.typeArguments,
+  });
+}
+
 /// A concrete implementation of an [InterfaceType].
 class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
   @override
@@ -631,12 +642,10 @@
     required ClassElement element,
     required this.typeArguments,
     required this.nullabilitySuffix,
-    TypeAliasElement? aliasElement,
-    List<DartType>? aliasArguments,
+    InstantiatedTypeAliasElement? alias,
   }) : super(
           element,
-          aliasElement: aliasElement,
-          aliasArguments: aliasArguments,
+          alias: alias,
         );
 
   @override
@@ -1615,19 +1624,26 @@
 /// representing the declared type of elements in the element model.
 abstract class TypeImpl implements DartType {
   @override
-  final List<DartType>? aliasArguments;
-
-  @override
-  final TypeAliasElement? aliasElement;
+  InstantiatedTypeAliasElement? alias;
 
   /// The element representing the declaration of this type, or `null` if the
   /// type has not, or cannot, be associated with an element.
   final Element? _element;
 
   /// Initialize a newly created type to be declared by the given [element].
-  TypeImpl(this._element, {this.aliasElement, this.aliasArguments})
-      : assert(aliasElement == null && aliasArguments == null ||
-            aliasElement != null && aliasArguments != null);
+  TypeImpl(this._element, {this.alias});
+
+  @Deprecated('Use alias instead')
+  @override
+  List<DartType>? get aliasArguments {
+    return alias?.typeArguments;
+  }
+
+  @Deprecated('Use alias instead')
+  @override
+  TypeAliasElement? get aliasElement {
+    return alias?.element;
+  }
 
   @deprecated
   @override
@@ -1774,12 +1790,10 @@
     required TypeParameterElement element,
     required this.nullabilitySuffix,
     this.promotedBound,
-    TypeAliasElement? aliasElement,
-    List<DartType>? aliasArguments,
+    InstantiatedTypeAliasElement? alias,
   }) : super(
           element,
-          aliasElement: aliasElement,
-          aliasArguments: aliasArguments,
+          alias: alias,
         );
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index 326f73a..9057b2c 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -444,9 +444,13 @@
 
     var returnType = type.returnType.accept(inner);
 
-    var aliasArguments = type.aliasArguments;
-    var newAliasArguments =
-        aliasArguments != null ? _mapList(aliasArguments) : null;
+    var alias = type.alias;
+    var newAlias = alias != null
+        ? InstantiatedTypeAliasElementImpl(
+            element: alias.element,
+            typeArguments: _mapList(alias.typeArguments),
+          )
+        : null;
 
     if (useCounter == before) return type;
 
@@ -455,8 +459,7 @@
       parameters: parameters,
       returnType: returnType,
       nullabilitySuffix: type.nullabilitySuffix,
-      aliasElement: type.aliasElement,
-      aliasArguments: newAliasArguments,
+      alias: newAlias,
     );
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/type_demotion.dart b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
index 4b1cc1a..4839abe 100644
--- a/pkg/analyzer/lib/src/dart/element/type_demotion.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
@@ -38,8 +38,7 @@
         return TypeParameterTypeImpl(
           element: type.element,
           nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
-          aliasElement: type.aliasElement,
-          aliasArguments: type.aliasArguments,
+          alias: type.alias,
         );
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index a299c7d..711f2ab 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -628,7 +628,7 @@
             appendParameters(type.returnType);
             type.parameters.map((p) => p.type).forEach(appendParameters);
             // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44218
-            type.aliasArguments?.forEach(appendParameters);
+            type.alias?.typeArguments.forEach(appendParameters);
           } else if (type is InterfaceType) {
             type.typeArguments.forEach(appendParameters);
           }
diff --git a/pkg/analyzer/lib/src/dart/error/ffi_code.dart b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
index 639a3f3..d8600d8 100644
--- a/pkg/analyzer/lib/src/dart/error/ffi_code.dart
+++ b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
@@ -69,6 +69,14 @@
   /**
    * No parameters.
    */
+  static const FfiCode FFI_NATIVE_ONLY_STATIC = FfiCode(
+      name: 'FFI_NATIVE_ONLY_STATIC',
+      message: "FfiNative annotations can only be used on static functions.",
+      correction: "Change the method to static.");
+
+  /**
+   * No parameters.
+   */
   static const FfiCode FIELD_IN_STRUCT_WITH_INITIALIZER = FfiCode(
       name: 'FIELD_IN_STRUCT_WITH_INITIALIZER',
       message:
diff --git a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
index 4d79d83..ef663ca 100644
--- a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
+++ b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
@@ -181,18 +181,18 @@
   }
 
   @override
-  Future<SomeLibraryElementResult> getLibraryByUri2(String uriStr) async {
+  Future<SomeLibraryElementResult> getLibraryByUri(String uriStr) async {
     var element = analysisContext.fileResolver.getLibraryByUri(uriStr: uriStr);
     return LibraryElementResultImpl(element);
   }
 
   @override
-  Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path) async {
+  Future<SomeResolvedLibraryResult> getResolvedLibrary(String path) async {
     return analysisContext.fileResolver.resolveLibrary(path: path);
   }
 
   @override
-  Future<SomeResolvedUnitResult> getResolvedUnit2(String path) async {
+  Future<SomeResolvedUnitResult> getResolvedUnit(String path) async {
     return analysisContext.fileResolver.resolve(path: path);
   }
 
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index 2d5a144..327af6e 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -332,7 +332,6 @@
     ErrorReporter errorReporter = _getErrorReporter(file);
 
     var nodeRegistry = NodeLintRegistry(_analysisOptions.enableTiming);
-    var visitors = <AstVisitor>[];
     final workspacePackage = _getPackage(currentUnit.unit);
     var context = LinterContextImpl(
         allUnits,
@@ -350,14 +349,9 @@
 
     // Run lints that handle specific node types.
     unit.accept(LinterVisitor(
-        nodeRegistry, ExceptionHandlingDelegatingAstVisitor.logException));
-
-    // Run visitor based lints.
-    if (visitors.isNotEmpty) {
-      AstVisitor visitor = ExceptionHandlingDelegatingAstVisitor(
-          visitors, ExceptionHandlingDelegatingAstVisitor.logException);
-      unit.accept(visitor);
-    }
+        nodeRegistry,
+        LinterExceptionHandler(_analysisOptions.propagateLinterExceptions)
+            .logException));
   }
 
   void _computeVerifyErrors(FileState file, CompilationUnit unit) {
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 2608588..d52742b 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -39,6 +39,7 @@
 import 'package:analyzer/src/util/performance/operation_performance.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:collection/collection.dart';
+import 'package:meta/meta.dart';
 import 'package:yaml/yaml.dart';
 
 const M = 1024 * 1024 /*1 MiB*/;
@@ -109,7 +110,8 @@
   /// It is used to allow assists and fixes without resolving the same file
   /// multiple times, as we compute more than one assist, or fixes when there
   /// are more than one error on a line.
-  final Map<String, ResolvedLibraryResult> _cachedResults = {};
+  @visibleForTesting
+  final Map<String, ResolvedLibraryResult> cachedResults = {};
 
   FileResolver(
     PerformanceLog logger,
@@ -164,7 +166,7 @@
     }
 
     // Forget all results, anything is potentially affected.
-    _cachedResults.clear();
+    cachedResults.clear();
 
     // Remove this file and all files that transitively depend on it.
     var removedFiles = <FileState>[];
@@ -208,7 +210,7 @@
       result.forEach((filePath) {
         var resolved = resolve(path: filePath);
         var collector = ReferencesCollector(element);
-        resolved.unit?.accept(collector);
+        resolved.unit.accept(collector);
         var offsets = collector.offsets;
         if (offsets.isNotEmpty) {
           references.add(CiderSearchMatch(filePath, offsets));
@@ -445,24 +447,16 @@
         }
       }
 
-      var libraryUnit = resolveLibrary(
+      var libraryResult = resolveLibrary(
         completionLine: completionLine,
         completionColumn: completionColumn,
         path: libraryFile.path,
-        completionPath: path,
+        completionPath: completionLine != null ? path : null,
         performance: performance,
       );
-      var result = libraryUnit.units!
-          .firstWhereOrNull((element) => element.path == path);
-      // TODO(scheglov) Fix and remove.
-      if (result == null) {
-        throw StateError('''
-libraryFile.path: ${libraryFile.path}
-path: $path
-units: ${libraryUnit.units!.map((e) => '(${e.uri} = ${e.path})').toList()}
-''');
-      }
-      return result;
+      return libraryResult.units.firstWhere(
+        (unitResult) => unitResult.path == path,
+      );
     });
   }
 
@@ -478,7 +472,7 @@
 
     performance ??= OperationPerformanceImpl('<default>');
 
-    var cachedResult = _cachedResults[path];
+    var cachedResult = cachedResults[path];
     if (cachedResult != null) {
       return cachedResult;
     }
@@ -513,7 +507,7 @@
         );
       });
 
-      testView?.addResolvedFile(path);
+      testView?.addResolvedLibrary(path);
 
       late Map<FileState, UnitAnalysisResult> results;
 
@@ -570,7 +564,11 @@
       var libraryUnit = resolvedUnits.first;
       var result = ResolvedLibraryResultImpl(contextObjects!.analysisSession,
           path, libraryUnit.uri, libraryUnit.libraryElement, resolvedUnits);
-      _cachedResults[path] = result;
+
+      if (completionPath == null) {
+        cachedResults[path] = result;
+      }
+
       return result;
     });
   }
@@ -764,13 +762,13 @@
 }
 
 class FileResolverTestView {
-  /// The paths of files which were resolved.
+  /// The paths of libraries which were resolved.
   ///
-  /// The file path is added every time when it is resolved.
-  final List<String> resolvedFiles = [];
+  /// The library path is added every time when it is resolved.
+  final List<String> resolvedLibraries = [];
 
-  void addResolvedFile(String path) {
-    resolvedFiles.add(path);
+  void addResolvedLibrary(String path) {
+    resolvedLibraries.add(path);
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 84260a2..76697c1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
@@ -25,13 +26,17 @@
   /// The resolver driving this participant.
   final ResolverVisitor _resolver;
 
+  /// Helper for extension method resolution.
+  final ExtensionMemberResolver _extensionResolver;
+
   final bool _isNonNullableByDefault;
 
   /// The type representing the type 'type'.
   final InterfaceType _typeType;
 
   FunctionReferenceResolver(this._resolver, this._isNonNullableByDefault)
-      : _typeType = _resolver.typeProvider.typeType;
+      : _extensionResolver = _resolver.extensionResolver,
+        _typeType = _resolver.typeProvider.typeType;
 
   ErrorReporter get _errorReporter => _resolver.errorReporter;
 
@@ -43,192 +48,44 @@
     node.typeArguments?.accept(_resolver);
 
     if (function is SimpleIdentifierImpl) {
-      var element = _resolver.nameScope.lookup(function.name).getter;
-
-      // Classes and type aliases are checked first so as to include a
-      // PropertyAccess parent check, which does not need to be done for
-      // functions.
-      if (element is ClassElement || element is TypeAliasElement) {
-        // A type-instantiated constructor tearoff like `C<int>.name` or
-        // `prefix.C<int>.name` is initially represented as a [PropertyAccess]
-        // with a [FunctionReference] target.
-        if (node.parent is PropertyAccess) {
-          _resolveConstructorReference(node);
-          return;
-        } else if (element is ClassElement) {
-          function.staticElement = element;
-          _resolveDirectTypeLiteral(node, function, element);
-          return;
-        } else if (element is TypeAliasElement) {
-          function.staticElement = element;
-          _resolveTypeAlias(node: node, element: element, typeAlias: function);
-          return;
-        }
-      } else if (element is ExecutableElement) {
-        function.staticElement = element;
-        _resolve(node: node, name: element.name, rawType: element.type);
-        return;
-      } else if (element is VariableElement) {
-        var functionType = element.type;
-        if (functionType is FunctionType) {
-          function.accept(_resolver);
-          _resolve(node: node, name: element.name ?? '', rawType: functionType);
-          return;
-        }
-      }
-    }
-
-    // TODO(srawlins): Handle `function` being a [SuperExpression].
-
-    if (function is PrefixedIdentifierImpl) {
-      var prefixElement =
-          _resolver.nameScope.lookup(function.prefix.name).getter;
-      function.prefix.staticElement = prefixElement;
-      if (prefixElement is PrefixElement) {
-        var functionName = function.identifier.name;
-        var functionElement = prefixElement.scope.lookup(functionName).getter;
-        if (functionElement == null) {
-          _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
-            function.identifier,
-            [function.identifier.name, function.prefix.name],
-          );
-          function.staticType = DynamicTypeImpl.instance;
-          node.staticType = DynamicTypeImpl.instance;
-          return;
-        } else {
-          functionElement = _resolver.toLegacyElement(functionElement);
-          _resolveReceiverPrefix(
-              node, prefixElement, function, functionElement);
-          return;
-        }
-      } else if (prefixElement is VariableElement) {
-        function.prefix.staticType = prefixElement.type;
-      } else if (prefixElement is PropertyAccessorElement) {
-        function.prefix.staticType = prefixElement.returnType;
-      }
-
-      var methodElement = _resolveTypeProperty(
-        receiver: function.prefix,
-        receiverElement: prefixElement,
-        name: function.identifier,
-        nameErrorEntity: function,
-      );
-
-      if (methodElement is MethodElement) {
-        function.identifier.staticElement = methodElement;
-        function.staticType = methodElement.type;
-        _resolve(
-          node: node,
-          name: function.identifier.name,
-          rawType: methodElement.type,
-        );
-        return;
-      }
-
-      // TODO(srawlins): Need to report cases where [methodElement] is not
-      // generic. The 'test_instanceGetter_explicitReceiver' test case needs to
-      // be updated to handle this.
+      _resolveSimpleIdentifierFunction(node, function);
+    } else if (function is PrefixedIdentifierImpl) {
+      _resolvePrefixedIdentifierFunction(node, function);
+    } else if (function is PropertyAccessImpl) {
+      _resolvePropertyAccessFunction(node, function);
+    } else {
+      // TODO(srawlins): Handle `function` being a [SuperExpression].
 
       function.accept(_resolver);
-      node.staticType = DynamicTypeImpl.instance;
-      return;
+      _resolveDisallowedExpression(node, node.function.staticType);
     }
-
-    if (function is PropertyAccessImpl) {
-      function.accept(_resolver);
-      var target = function.target;
-      DartType targetType;
-      if (target is SuperExpressionImpl) {
-        targetType = target.typeOrThrow;
-      } else if (target is ThisExpressionImpl) {
-        targetType = target.typeOrThrow;
-      } else if (target is SimpleIdentifierImpl) {
-        var targetElement = _resolver.nameScope.lookup(target.name).getter;
-        if (targetElement is VariableElement) {
-          targetType = targetElement.type;
-        } else if (targetElement is PropertyAccessorElement) {
-          targetType = targetElement.returnType;
-        } else {
-          // TODO(srawlins): Can we get here?
-          node.staticType = DynamicTypeImpl.instance;
-          return;
-        }
-      } else if (target is PrefixedIdentifierImpl) {
-        var prefixElement =
-            _resolver.nameScope.lookup(target.prefix.name).getter;
-        if (prefixElement is PrefixElement) {
-          var prefixName = target.identifier.name;
-          var targetElement = prefixElement.scope.lookup(prefixName).getter;
-
-          var methodElement = _resolveTypeProperty(
-            receiver: target,
-            receiverElement: targetElement,
-            name: function.propertyName,
-            nameErrorEntity: function,
-          );
-
-          if (methodElement == null) {
-            // TODO(srawlins): Can we get here?
-            node.staticType = DynamicTypeImpl.instance;
-            return;
-          } else {
-            _resolveReceiverPrefix(node, prefixElement, target, methodElement);
-            return;
-          }
-        } else {
-          // TODO(srawlins): Can we get here?
-          node.staticType = DynamicTypeImpl.instance;
-          return;
-        }
-      } else {
-        // TODO(srawlins): Can we get here?
-        node.staticType = DynamicTypeImpl.instance;
-        return;
-      }
-
-      var propertyElement = _resolver.typePropertyResolver
-          .resolve(
-            receiver: function.realTarget,
-            receiverType: targetType,
-            name: function.propertyName.name,
-            propertyErrorEntity: function.propertyName,
-            nameErrorEntity: function,
-          )
-          .getter;
-
-      var functionType = function.typeOrThrow;
-      if (functionType is FunctionType && propertyElement != null) {
-        _resolve(
-          node: node,
-          name: propertyElement.name,
-          rawType: functionType,
-        );
-        return;
-      }
-
-      // TODO(srawlins): Handle type variables bound to function type, like
-      // `T extends void Function<U>(U)`.
-    }
-
-    // TODO(srawlins): Enumerate and handle all cases that fall through to
-    // here; ultimately it should just be a case of "unknown identifier."
-    function.accept(_resolver);
-    node.staticType = DynamicTypeImpl.instance;
   }
 
   List<DartType> _checkTypeArguments(
     TypeArgumentList typeArgumentList,
-    String name,
+    String? name,
     List<TypeParameterElement> typeParameters,
     CompileTimeErrorCode errorCode,
   ) {
     if (typeArgumentList.arguments.length != typeParameters.length) {
-      _errorReporter.reportErrorForNode(
-        errorCode,
-        typeArgumentList,
-        [name, typeParameters.length, typeArgumentList.arguments.length],
-      );
+      if (name == null &&
+          errorCode ==
+              CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION) {
+        errorCode = CompileTimeErrorCode
+            .WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION;
+        _errorReporter.reportErrorForNode(
+          errorCode,
+          typeArgumentList,
+          [typeParameters.length, typeArgumentList.arguments.length],
+        );
+      } else {
+        assert(name != null);
+        _errorReporter.reportErrorForNode(
+          errorCode,
+          typeArgumentList,
+          [name, typeParameters.length, typeArgumentList.arguments.length],
+        );
+      }
       return List.filled(typeParameters.length, DynamicTypeImpl.instance);
     } else {
       return typeArgumentList.arguments
@@ -237,22 +94,68 @@
     }
   }
 
+  void _reportInvalidAccessToStaticMember(
+    SimpleIdentifier nameNode,
+    ExecutableElement element, {
+    required bool implicitReceiver,
+  }) {
+    if (_resolver.enclosingExtension != null) {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode
+            .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
+        nameNode,
+        [element.enclosingElement.displayName],
+      );
+    } else if (implicitReceiver) {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
+        nameNode,
+        [element.enclosingElement.displayName],
+      );
+    } else {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
+        nameNode,
+        [
+          nameNode.name,
+          element.kind.displayName,
+          element.enclosingElement.displayName,
+        ],
+      );
+    }
+  }
+
   /// Resolves [node]'s static type, as an instantiated function type, and type
   /// argument types, using [rawType] as the uninstantiated function type.
   void _resolve({
     required FunctionReferenceImpl node,
-    required String name,
-    required FunctionType rawType,
+    required DartType? rawType,
+    String? name,
   }) {
-    var typeArguments = _checkTypeArguments(
-      // `node.typeArguments`, coming from the parser, is never null.
-      node.typeArguments!, name, rawType.typeFormals,
-      CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
-    );
+    if (rawType == null) {
+      node.staticType = DynamicTypeImpl.instance;
+    }
 
-    var invokeType = rawType.instantiate(typeArguments);
-    node.typeArgumentTypes = typeArguments;
-    node.staticType = invokeType;
+    if (rawType is TypeParameterTypeImpl) {
+      // If the type of the function is a type parameter, the tearoff is
+      // disallowed, reported in [_resolveDisallowedExpression]. Use the type
+      // parameter's bound here in an attempt to assign the intended types.
+      rawType = rawType.element.bound;
+    }
+
+    if (rawType is FunctionType) {
+      var typeArguments = _checkTypeArguments(
+        // `node.typeArguments`, coming from the parser, is never null.
+        node.typeArguments!, name, rawType.typeFormals,
+        CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
+      );
+
+      var invokeType = rawType.instantiate(typeArguments);
+      node.typeArgumentTypes = typeArguments;
+      node.staticType = invokeType;
+    } else {
+      node.staticType = DynamicTypeImpl.instance;
+    }
   }
 
   void _resolveConstructorReference(FunctionReferenceImpl node) {
@@ -277,14 +180,220 @@
     _resolveTypeLiteral(node: node, instantiatedType: type, name: name);
   }
 
+  /// Resolves [node] as a type instantiation on an illegal expression.
+  ///
+  /// This function attempts to give [node] a static type, to continue working
+  /// with what the user may be intending.
+  void _resolveDisallowedExpression(
+      FunctionReferenceImpl node, DartType? rawType) {
+    _errorReporter.reportErrorForNode(
+      CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION,
+      node.function,
+      [],
+    );
+    _resolve(node: node, rawType: rawType);
+  }
+
+  void _resolveExtensionOverride(
+    FunctionReferenceImpl node,
+    PropertyAccessImpl function,
+    ExtensionOverride override,
+  ) {
+    var propertyName = function.propertyName;
+    var result =
+        _extensionResolver.getOverrideMember(override, propertyName.name);
+    var member = _resolver.toLegacyElement(result.getter);
+
+    if (member == null) {
+      node.staticType = DynamicTypeImpl.instance;
+      return;
+    }
+
+    if (member.isStatic) {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
+        function.propertyName,
+      );
+      // Continue to resolve type.
+    }
+
+    if (function.isCascaded) {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE,
+        override.extensionName,
+      );
+      // Continue to resolve type.
+    }
+
+    if (member is PropertyAccessorElement) {
+      function.accept(_resolver);
+      _resolveDisallowedExpression(node, member.returnType);
+      return;
+    }
+
+    _resolve(node: node, rawType: member.type, name: propertyName.name);
+  }
+
+  void _resolvePrefixedIdentifierFunction(
+      FunctionReferenceImpl node, PrefixedIdentifierImpl function) {
+    var prefixElement = _resolver.nameScope.lookup(function.prefix.name).getter;
+
+    if (prefixElement == null) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+        function.prefix,
+        [function.name],
+      );
+      function.staticType = DynamicTypeImpl.instance;
+      node.staticType = DynamicTypeImpl.instance;
+      return;
+    }
+
+    function.prefix.staticElement = prefixElement;
+    if (prefixElement is PrefixElement) {
+      var functionName = function.identifier.name;
+      var functionElement = prefixElement.scope.lookup(functionName).getter;
+      if (functionElement == null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
+          function.identifier,
+          [function.identifier.name, function.prefix.name],
+        );
+        function.staticType = DynamicTypeImpl.instance;
+        node.staticType = DynamicTypeImpl.instance;
+        return;
+      } else {
+        functionElement = _resolver.toLegacyElement(functionElement);
+        _resolveReceiverPrefix(node, prefixElement, function, functionElement);
+        return;
+      }
+    }
+
+    DartType? prefixType;
+    if (prefixElement is VariableElement) {
+      prefixType = prefixElement.type;
+    } else if (prefixElement is PropertyAccessorElement) {
+      prefixType = prefixElement.returnType;
+    }
+
+    function.prefix.staticType = prefixType;
+    if (prefixType != null && prefixType.isDynamic) {
+      // TODO(srawlins): Report error. See spec text: "We do not allow dynamic
+      // explicit instantiation."
+      node.staticType = DynamicTypeImpl.instance;
+      return;
+    }
+
+    var methodElement = _resolveTypeProperty(
+      receiver: function.prefix,
+      receiverElement: prefixElement,
+      name: function.identifier,
+      nameErrorEntity: function,
+    );
+
+    if (methodElement is MethodElement) {
+      function.identifier.staticElement = methodElement;
+      function.staticType = methodElement.type;
+      _resolve(
+        node: node,
+        rawType: methodElement.type,
+        name: function.identifier.name,
+      );
+      return;
+    }
+
+    if (methodElement is PropertyAccessorElement) {
+      function.accept(_resolver);
+      _resolveDisallowedExpression(node, methodElement.returnType);
+      return;
+    }
+
+    function.accept(_resolver);
+    node.staticType = DynamicTypeImpl.instance;
+  }
+
+  void _resolvePropertyAccessFunction(
+      FunctionReferenceImpl node, PropertyAccessImpl function) {
+    function.accept(_resolver);
+    var target = function.realTarget;
+
+    DartType targetType;
+    if (target is SuperExpressionImpl) {
+      targetType = target.typeOrThrow;
+    } else if (target is ThisExpressionImpl) {
+      targetType = target.typeOrThrow;
+    } else if (target is SimpleIdentifierImpl) {
+      var targetElement = _resolver.nameScope.lookup(target.name).getter;
+      if (targetElement is VariableElement) {
+        targetType = targetElement.type;
+      } else if (targetElement is PropertyAccessorElement) {
+        targetType = targetElement.returnType;
+      } else {
+        // TODO(srawlins): Can we get here?
+        node.staticType = DynamicTypeImpl.instance;
+        return;
+      }
+    } else if (target is PrefixedIdentifierImpl) {
+      var prefixElement = _resolver.nameScope.lookup(target.prefix.name).getter;
+      if (prefixElement is PrefixElement) {
+        var prefixName = target.identifier.name;
+        var targetElement = prefixElement.scope.lookup(prefixName).getter;
+
+        var methodElement = _resolveTypeProperty(
+          receiver: target,
+          receiverElement: targetElement,
+          name: function.propertyName,
+          nameErrorEntity: function,
+        );
+
+        if (methodElement == null) {
+          // TODO(srawlins): Can we get here?
+          node.staticType = DynamicTypeImpl.instance;
+          return;
+        } else {
+          _resolveReceiverPrefix(node, prefixElement, target, methodElement);
+          return;
+        }
+      } else {
+        // TODO(srawlins): Can we get here?
+        node.staticType = DynamicTypeImpl.instance;
+        return;
+      }
+    } else if (target is ExtensionOverrideImpl) {
+      _resolveExtensionOverride(node, function, target);
+      return;
+    } else {
+      targetType = target.typeOrThrow;
+    }
+
+    var propertyElement = _resolver.typePropertyResolver
+        .resolve(
+          receiver: function.realTarget,
+          receiverType: targetType,
+          name: function.propertyName.name,
+          propertyErrorEntity: function.propertyName,
+          nameErrorEntity: function,
+        )
+        .getter;
+
+    if (propertyElement is TypeParameterElement) {
+      _resolveDisallowedExpression(node, propertyElement!.type);
+      return;
+    }
+
+    _resolve(
+      node: node,
+      rawType: function.staticType,
+      name: propertyElement?.name,
+    );
+  }
+
   void _resolveReceiverPrefix(
     FunctionReferenceImpl node,
     PrefixElement prefixElement,
     PrefixedIdentifier prefix,
     Element element,
   ) {
-    // TODO(srawlins): Handle `loadLibrary`, as in `p.loadLibrary<int>;`.
-
     if (element is MultiplyDefinedElement) {
       MultiplyDefinedElement multiply = element;
       element = multiply.conflictingElements[0];
@@ -315,8 +424,8 @@
       node.function.accept(_resolver);
       _resolve(
         node: node,
-        name: element.name,
         rawType: node.function.typeOrThrow as FunctionType,
+        name: element.name,
       );
       return;
     }
@@ -326,6 +435,118 @@
     node.staticType = DynamicTypeImpl.instance;
   }
 
+  void _resolveSimpleIdentifierFunction(
+      FunctionReferenceImpl node, SimpleIdentifierImpl function) {
+    var element = _resolver.nameScope.lookup(function.name).getter;
+
+    if (element == null) {
+      DartType receiverType;
+      var enclosingClass = _resolver.enclosingClass;
+      if (enclosingClass != null) {
+        receiverType = enclosingClass.thisType;
+      } else {
+        var enclosingExtension = _resolver.enclosingExtension;
+        if (enclosingExtension != null) {
+          receiverType = enclosingExtension.extendedType;
+        } else {
+          _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+            function,
+            [function.name],
+          );
+          function.staticType = DynamicTypeImpl.instance;
+          node.staticType = DynamicTypeImpl.instance;
+          return;
+        }
+      }
+
+      var result = _resolver.typePropertyResolver.resolve(
+        receiver: null,
+        receiverType: receiverType,
+        name: function.name,
+        propertyErrorEntity: function,
+        nameErrorEntity: function,
+      );
+
+      var method = result.getter;
+      if (method != null) {
+        if (method.isStatic) {
+          _reportInvalidAccessToStaticMember(function, method,
+              implicitReceiver: true);
+          // Continue to assign types.
+        }
+
+        if (method is PropertyAccessorElement) {
+          _resolveDisallowedExpression(node, method.returnType);
+          return;
+        }
+
+        function.staticElement = method;
+        function.staticType = method.type;
+        _resolve(node: node, rawType: method.type, name: function.name);
+        return;
+      } else {
+        _resolver.errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_METHOD,
+          function,
+          [function.name, enclosingClass],
+        );
+        function.staticType = DynamicTypeImpl.instance;
+        node.staticType = DynamicTypeImpl.instance;
+        return;
+      }
+    }
+
+    // Classes and type aliases are checked first so as to include a
+    // PropertyAccess parent check, which does not need to be done for
+    // functions.
+    if (element is ClassElement || element is TypeAliasElement) {
+      // A type-instantiated constructor tearoff like `C<int>.name` or
+      // `prefix.C<int>.name` is initially represented as a [PropertyAccess]
+      // with a [FunctionReference] target.
+      if (node.parent is PropertyAccess) {
+        _resolveConstructorReference(node);
+        return;
+      } else if (element is ClassElement) {
+        function.staticElement = element;
+        _resolveDirectTypeLiteral(node, function, element);
+        return;
+      } else if (element is TypeAliasElement) {
+        function.staticElement = element;
+        _resolveTypeAlias(node: node, element: element, typeAlias: function);
+        return;
+      }
+    } else if (element is MethodElement) {
+      function.staticElement = element;
+      function.staticType = element.type;
+      _resolve(node: node, rawType: element.type, name: element.name);
+      return;
+    } else if (element is FunctionElement) {
+      function.staticElement = element;
+      function.staticType = element.type;
+      _resolve(node: node, rawType: element.type, name: element.name);
+      return;
+    } else if (element is PropertyAccessorElement) {
+      function.staticElement = element;
+      function.staticType = element.returnType;
+      _resolveDisallowedExpression(node, element.returnType);
+      return;
+    } else if (element is ExecutableElement) {
+      function.staticElement = element;
+      function.staticType = element.type;
+      _resolveDisallowedExpression(node, element.type);
+      return;
+    } else if (element is VariableElement) {
+      function.staticElement = element;
+      function.staticType = element.type;
+      _resolveDisallowedExpression(node, element.type);
+      return;
+    } else {
+      _resolveDisallowedExpression(node, DynamicTypeImpl.instance);
+      return;
+    }
+  }
+
   /// Returns the element that represents the property named [propertyName] on
   /// [classElement].
   ExecutableElement? _resolveStaticElement(
@@ -410,7 +631,7 @@
           'Unexpected receiverElement type: ${receiverElement.runtimeType}');
       return null;
     }
-    return _resolver.typePropertyResolver
+    var methodElement = _resolver.typePropertyResolver
         .resolve(
           receiver: receiver,
           receiverType: receiverType,
@@ -419,5 +640,10 @@
           nameErrorEntity: nameErrorEntity,
         )
         .getter;
+    if (methodElement != null && methodElement.isStatic) {
+      _reportInvalidAccessToStaticMember(name, methodElement,
+          implicitReceiver: false);
+    }
+    return methodElement;
   }
 }
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
new file mode 100644
index 0000000..cf4574c
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
@@ -0,0 +1,152 @@
+// 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/element/type.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// A resolver for [InstanceCreationExpression] nodes.
+///
+/// This resolver is responsible for rewriting a given
+/// [InstanceCreationExpression] as a [MethodInvocation] if the parsed
+/// [ConstructorName]'s `type` resolves to a [FunctionReference] or
+/// [ConstructorReference], instead of a [TypeName].
+class InstanceCreationExpressionResolver {
+  /// The resolver driving this participant.
+  final ResolverVisitor _resolver;
+
+  InstanceCreationExpressionResolver(this._resolver);
+
+  void resolve(InstanceCreationExpressionImpl node) {
+    // The parser can parse certain code as [InstanceCreationExpression] when it
+    // might be an invocation of a method on a [FunctionReference] or
+    // [ConstructorReference]. In such a case, it is this resolver's
+    // responsibility to rewrite. For example, given:
+    //
+    //     a.m<int>.apply();
+    //
+    // the parser will give an InstanceCreationExpression (`a.m<int>.apply()`)
+    // with a name of `a.m<int>.apply` (ConstructorName) with a type of
+    // `a.m<int>` (TypeName with a name of `a.m` (PrefixedIdentifier) and
+    // typeArguments of `<int>`) and a name of `apply` (SimpleIdentifier). If
+    // `a.m<int>` is actually a function reference, then the
+    // InstanceCreationExpression needs to be rewritten as a MethodInvocation
+    // with a target of `a.m<int>` (a FunctionReference) and a name of `apply`.
+    if (node.keyword == null) {
+      var typeNameTypeArguments = node.constructorName.type.typeArguments;
+      if (typeNameTypeArguments != null) {
+        // This could be a method call on a function reference or a constructor
+        // reference.
+        _resolveWithTypeNameWithTypeArguments(node, typeNameTypeArguments);
+        return;
+      }
+    }
+
+    _resolveInstanceCreationExpression(node);
+  }
+
+  void _inferArgumentTypes(covariant InstanceCreationExpressionImpl node) {
+    var constructorName = node.constructorName;
+    var typeName = constructorName.type;
+    var typeArguments = typeName.typeArguments;
+    var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
+      constructorName: constructorName,
+      definingLibrary: _resolver.definingLibrary,
+    );
+    FunctionType? inferred;
+
+    // If the constructor is generic, we'll have a ConstructorMember that
+    // substitutes in type arguments (possibly `dynamic`) from earlier in
+    // resolution.
+    //
+    // Otherwise we'll have a ConstructorElement, and we can skip inference
+    // because there's nothing to infer in a non-generic type.
+    if (elementToInfer != null) {
+      // TODO(leafp): Currently, we may re-infer types here, since we
+      // sometimes resolve multiple times.  We should really check that we
+      // have not already inferred something.  However, the obvious ways to
+      // check this don't work, since we may have been instantiated
+      // to bounds in an earlier phase, and we *do* want to do inference
+      // in that case.
+
+      // Get back to the uninstantiated generic constructor.
+      // TODO(jmesserly): should we store this earlier in resolution?
+      // Or look it up, instead of jumping backwards through the Member?
+      var rawElement = elementToInfer.element;
+      var constructorType = elementToInfer.asType;
+
+      inferred = _resolver.inferenceHelper.inferArgumentTypesForGeneric(
+          node, constructorType, typeArguments,
+          isConst: node.isConst, errorNode: node.constructorName);
+
+      if (inferred != null) {
+        var arguments = node.argumentList;
+        InferenceContext.setType(arguments, inferred);
+        // Fix up the parameter elements based on inferred method.
+        arguments.correspondingStaticParameters =
+            ResolverVisitor.resolveArgumentsToParameters(
+                arguments, inferred.parameters, null);
+
+        constructorName.type.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.
+        var constructorElement = ConstructorMember.from(
+          rawElement,
+          inferred.returnType as InterfaceType,
+        );
+        constructorName.staticElement = constructorElement;
+      }
+    }
+
+    if (inferred == null) {
+      var constructorElement = constructorName.staticElement;
+      if (constructorElement != null) {
+        var type = constructorElement.type;
+        type = _resolver.toLegacyTypeIfOptOut(type) as FunctionType;
+        InferenceContext.setType(node.argumentList, type);
+      }
+    }
+  }
+
+  void _resolveInstanceCreationExpression(InstanceCreationExpressionImpl node) {
+    var whyNotPromotedList = <WhyNotPromotedGetter>[];
+    node.constructorName.accept(_resolver);
+    _inferArgumentTypes(node);
+    _resolver.visitArgumentList(node.argumentList,
+        whyNotPromotedList: whyNotPromotedList);
+    node.accept(_resolver.elementResolver);
+    node.accept(_resolver.typeAnalyzer);
+    _resolver.checkForArgumentTypesNotAssignableInList(
+        node.argumentList, whyNotPromotedList);
+  }
+
+  /// Resolve [node] which has a [TypeName] with type arguments (given as
+  /// [typeNameTypeArguments]).
+  ///
+  /// The instance creation expression may actually be a method call on a
+  /// type-instantiated function reference or constructor reference.
+  void _resolveWithTypeNameWithTypeArguments(
+    InstanceCreationExpressionImpl node,
+    TypeArgumentListImpl typeNameTypeArguments,
+  ) {
+    var typeNameName = node.constructorName.type.name;
+    if (typeNameName is SimpleIdentifierImpl) {
+      // TODO(srawlins): Lookup the name and potentially rewrite `node` as a
+      // [MethodInvocation].
+      _resolveInstanceCreationExpression(node);
+      return;
+    } else if (typeNameName is PrefixedIdentifierImpl) {
+      // TODO(srawlins): Lookup the name and potentially rewrite `node` as a
+      // [MethodInvocation].
+      _resolveInstanceCreationExpression(node);
+    } else {
+      assert(
+          false, 'Unexpected typeNameName type: ${typeNameName.runtimeType}');
+      _resolveInstanceCreationExpression(node);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
index 94c39d7..7be20ef 100644
--- a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
@@ -144,7 +144,7 @@
       return;
     }
 
-    type.aliasArguments?.forEach(_assertLegacyType);
+    type.alias?.typeArguments.forEach(_assertLegacyType);
 
     if (type is TypeParameterType) {
       _assertLegacyType(type.bound);
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 7485e6e..5c7a513 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -10,12 +10,12 @@
 import 'package:analyzer/src/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/ast/utilities.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/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/migratable_ast_info_provider.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -42,7 +42,7 @@
   final InheritanceManager3 _inheritance;
 
   /// The element for the library containing the compilation unit being visited.
-  final LibraryElement _definingLibrary;
+  final LibraryElementImpl _definingLibrary;
 
   /// The URI of [_definingLibrary].
   final Uri _definingLibraryUri;
@@ -271,7 +271,7 @@
   }) {
     _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
 
-    if (nameScope.shouldIgnoreUndefined2(prefix: prefix, name: name)) {
+    if (_definingLibrary.shouldIgnoreUndefined(prefix: prefix, name: name)) {
       return;
     }
 
@@ -282,19 +282,6 @@
     );
   }
 
-  void _reportUndefinedMethod(
-      MethodInvocationImpl node,
-      String name,
-      ClassElement typeReference,
-      List<WhyNotPromotedGetter> whyNotPromotedList) {
-    _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
-    _resolver.errorReporter.reportErrorForNode(
-      CompileTimeErrorCode.UNDEFINED_METHOD,
-      node.methodName,
-      [name, typeReference.displayName],
-    );
-  }
-
   void _reportUseOfVoidType(MethodInvocationImpl node, AstNode errorNode,
       List<WhyNotPromotedGetter> whyNotPromotedList) {
     _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
@@ -779,7 +766,26 @@
       return;
     }
 
-    _reportUndefinedMethod(node, name, receiver, whyNotPromotedList);
+    _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+    if (nameNode.name == 'new') {
+      // Attempting to invoke the unnamed constructor via `C.new(`.
+      if (_resolver.isConstructorTearoffsEnabled) {
+        _resolver.errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT,
+          nameNode,
+          [receiver.displayName],
+        );
+      } else {
+        // [ParserErrorCode.EXPERIMENT_NOT_ENABLED] is reported by the parser.
+        // Do not report extra errors.
+      }
+    } else {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.UNDEFINED_METHOD,
+        node.methodName,
+        [name, receiver.displayName],
+      );
+    }
   }
 
   /// If the given [type] is a type parameter, replace with its bound.
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
index e2d5336..10c9f96 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -13,7 +13,6 @@
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/resolution_result.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/assignment_verifier.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -590,7 +589,7 @@
 
     if (hasRead && readElement == null || hasWrite && writeElement == null) {
       if (!forAnnotation &&
-          !_resolver.nameScope.shouldIgnoreUndefined2(
+          !_resolver.definingLibrary.shouldIgnoreUndefined(
             prefix: target.name,
             name: identifier.name,
           )) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 6a03d38..f08fb8d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -56,6 +56,7 @@
 /// 3. Resolve all [TypeName]s - set elements and types.
 /// 4. Resolve all [GenericFunctionType]s - set their types.
 class ResolutionVisitor extends RecursiveAstVisitor<void> {
+  LibraryElementImpl _libraryElement;
   final TypeProvider _typeProvider;
   final CompilationUnitElementImpl _unitElement;
   final bool _isNonNullableByDefault;
@@ -102,13 +103,14 @@
     );
 
     var typeNameResolver = TypeNameResolver(
-      libraryElement.typeSystem,
+      libraryElement,
       typeProvider,
       isNonNullableByDefault,
       errorReporter,
     );
 
     return ResolutionVisitor._(
+      libraryElement,
       typeProvider,
       unitElement,
       isNonNullableByDefault,
@@ -122,6 +124,7 @@
   }
 
   ResolutionVisitor._(
+    this._libraryElement,
     this._typeProvider,
     this._unitElement,
     this._isNonNullableByDefault,
@@ -1211,7 +1214,7 @@
     // If the type is not an InterfaceType, then visitTypeName() sets the type
     // to be a DynamicTypeImpl
     Identifier name = typeName.name;
-    if (!_nameScope.shouldIgnoreUndefined(name)) {
+    if (!_libraryElement.shouldIgnoreUndefinedIdentifier(name)) {
       _errorReporter.reportErrorForNode(errorCode, name, [name.name]);
     }
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 95850f3..845c8e1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -352,35 +352,6 @@
 }
 
 extension ScopeExtension on Scope {
-  /// Return `true` if the fact that the given [node] is not defined should be
-  /// ignored (from the perspective of error reporting).
-  bool shouldIgnoreUndefined(Identifier node) {
-    if (node is PrefixedIdentifier) {
-      return shouldIgnoreUndefined2(
-        prefix: node.prefix.name,
-        name: node.identifier.name,
-      );
-    }
-
-    return shouldIgnoreUndefined2(
-      prefix: null,
-      name: (node as SimpleIdentifier).name,
-    );
-  }
-
-  /// Return `true` if the fact that the identifier with the given [prefix]
-  /// (might be `null`) and [name] is not defined should be ignored (from the
-  /// perspective of error reporting).
-  bool shouldIgnoreUndefined2({
-    required String? prefix,
-    required String name,
-  }) {
-    return _enclosingLibraryScope.shouldIgnoreUndefined(
-      prefix: prefix,
-      name: name,
-    );
-  }
-
   List<ExtensionElement> get extensions {
     return _enclosingLibraryScope.extensions;
   }
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 a3e5943..4c872f9 100644
--- a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
@@ -14,7 +14,6 @@
 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/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
@@ -203,7 +202,8 @@
           CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT,
           node,
         );
-      } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) {
+      } else if (!_resolver.definingLibrary
+          .shouldIgnoreUndefinedIdentifier(node)) {
         _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
           node,
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
index 4acea06..3f3c167 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
@@ -16,7 +16,6 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
 import 'package:analyzer/src/error/codes.dart';
 
@@ -24,6 +23,7 @@
 ///
 /// The client must set [nameScope] before calling [resolveTypeName].
 class TypeNameResolver {
+  final LibraryElementImpl _libraryElement;
   final TypeSystemImpl typeSystem;
   final DartType dynamicType;
   final bool isNonNullableByDefault;
@@ -56,9 +56,10 @@
   /// If [resolveTypeName] reported an error, this flag is set to `true`.
   bool hasErrorReported = false;
 
-  TypeNameResolver(this.typeSystem, TypeProvider typeProvider,
+  TypeNameResolver(this._libraryElement, TypeProvider typeProvider,
       this.isNonNullableByDefault, this.errorReporter)
-      : dynamicType = typeProvider.dynamicType;
+      : typeSystem = _libraryElement.typeSystem,
+        dynamicType = typeProvider.dynamicType;
 
   bool get _genericMetadataIsEnabled =>
       enclosingClass!.library.featureSet.isEnabled(Feature.generic_metadata);
@@ -285,7 +286,7 @@
   void _resolveToElement(TypeNameImpl node, Element? element) {
     if (element == null) {
       node.type = dynamicType;
-      if (!nameScope.shouldIgnoreUndefined(node.name)) {
+      if (!_libraryElement.shouldIgnoreUndefinedIdentifier(node.name)) {
         _ErrorHelper(errorReporter).reportNullOrNonTypeElement(node, null);
       }
       return;
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 ee009b4..e781de9 100644
--- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
@@ -37,7 +37,7 @@
       TypeSystemImpl typeSystem, TypeProviderImpl typeProvider,
       {MigratableAstInfoProvider migratableAstInfoProvider =
           const MigratableAstInfoProvider()}) {
-    var library = resolver.definingLibrary as LibraryElementImpl;
+    var library = resolver.definingLibrary;
     var analysisOptions = library.context.analysisOptions;
     var analysisOptionsImpl = analysisOptions as AnalysisOptionsImpl;
     return TypedLiteralResolver._(
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index a1d8739..bfa745d 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -755,7 +755,7 @@
       // not report synthetic `dynamic` in place of an unresolved type.
       if ((type.element == _nullType.element ||
               (type.isDynamic && name == 'dynamic')) &&
-          type.aliasElement == null) {
+          type.alias == null) {
         _errorReporter.reportErrorForNode(
             HintCode.UNNECESSARY_QUESTION_MARK, node, [name]);
       }
@@ -1048,7 +1048,7 @@
           ...element.typeParameters.map((tp) => tp.bound),
         ];
         for (var type in signatureTypes) {
-          var aliasElement = type?.aliasElement;
+          var aliasElement = type?.alias?.element;
           if (aliasElement != null && aliasElement.hasInternal) {
             _errorReporter.reportErrorForNode(
                 HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY,
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index a5fdaf2..fb2881f 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -10505,6 +10505,18 @@
   /**
    * No parameters.
    */
+  static const CompileTimeErrorCode DISALLOWED_TYPE_INSTANTIATION_EXPRESSION =
+      CompileTimeErrorCode(
+          'DISALLOWED_TYPE_INSTANTIATION_EXPRESSION',
+          'Only a generic type, generic function, generic instance method, or '
+              'generic constructor can be type instantiated.',
+          correction:
+              'Try instantiating the type(s) of a generic type, generic '
+              'function, generic instance method, or generic constructor.');
+
+  /**
+   * No parameters.
+   */
   // #### Description
   //
   // The analyzer produces this diagnostic when the static type of the
@@ -14632,6 +14644,22 @@
 
   /**
    * Parameters:
+   * 0: the number of type parameters that were declared
+   * 1: the number of type arguments provided
+   */
+  static const CompileTimeErrorCode
+      WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION = CompileTimeErrorCode(
+          'WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION',
+          "This function is declared with {0} type parameters, "
+              "but {1} type arguments were given.",
+          correction:
+              "Try adjusting the number of type arguments to match the number "
+              "of type parameters.",
+          hasPublishedDocs: true,
+          uniqueName: 'WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION');
+
+  /**
+   * Parameters:
    * 0: the name of the class being instantiated
    * 1: the name of the constructor being invoked
    */
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index e4a6930..55d66ce 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -210,10 +210,10 @@
 
     List<TypeParameterElement> typeParameters;
     List<DartType> typeArguments;
-    var aliasElement = type.aliasElement;
-    if (aliasElement != null) {
-      typeParameters = aliasElement.typeParameters;
-      typeArguments = type.aliasArguments!;
+    var alias = type.alias;
+    if (alias != null) {
+      typeParameters = alias.element.typeParameters;
+      typeArguments = alias.typeArguments;
     } else if (type is InterfaceType) {
       typeParameters = type.element.typeParameters;
       typeArguments = type.typeArguments;
@@ -277,8 +277,9 @@
 
     // Prepare type arguments for checking for super-bounded.
     type = _typeSystem.replaceTopAndBottom(type);
-    if (type.aliasElement != null) {
-      typeArguments = type.aliasArguments!;
+    alias = type.alias;
+    if (alias != null) {
+      typeArguments = alias.typeArguments;
     } else if (type is InterfaceType) {
       typeArguments = type.typeArguments;
     } else {
@@ -422,9 +423,9 @@
   bool _isMissingTypeArguments(AstNode node, DartType type, Element? element,
       Expression? inferenceContextNode) {
     List<DartType> typeArguments;
-    var aliasElement = type.aliasElement;
-    if (aliasElement != null) {
-      typeArguments = type.aliasArguments!;
+    var alias = type.alias;
+    if (alias != null) {
+      typeArguments = alias.typeArguments;
     } else if (type is InterfaceType) {
       typeArguments = type.typeArguments;
     } else {
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index cc5fc13..2a378e11 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -498,7 +498,8 @@
     var declaration = node.thisOrAncestorOfType<ClassDeclaration>();
     var superclassName = declaration?.extendsClause?.superclass.name;
     if (superclassName != null &&
-        _resolver.nameScope.shouldIgnoreUndefined(superclassName)) {
+        _resolver.definingLibrary
+            .shouldIgnoreUndefinedIdentifier(superclassName)) {
       return;
     }
     var argumentList = node.argumentList;
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 7f04b64..c678842 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -281,6 +281,10 @@
   /// This option is experimental and subject to change.
   bool implicitDynamic = true;
 
+  /// Indicates whether linter exceptions should be propagated to the caller (by
+  /// re-throwing them)
+  bool propagateLinterExceptions = false;
+
   /// A flag indicating whether inference failures are allowed, off by default.
   ///
   /// This option is experimental and subject to change.
@@ -319,6 +323,7 @@
     if (options is AnalysisOptionsImpl) {
       implicitCasts = options.implicitCasts;
       implicitDynamic = options.implicitDynamic;
+      propagateLinterExceptions = options.propagateLinterExceptions;
       strictInference = options.strictInference;
       strictRawTypes = options.strictRawTypes;
     }
@@ -382,6 +387,7 @@
       // Append boolean flags.
       buffer.addBool(implicitCasts);
       buffer.addBool(implicitDynamic);
+      buffer.addBool(propagateLinterExceptions);
       buffer.addBool(strictInference);
       buffer.addBool(strictRawTypes);
       buffer.addBool(useFastaParser);
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index b4880fb..3ad6c31 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -518,8 +518,9 @@
     _withEnclosingExecutable(element, () {
       _checkForInvalidModifierOnBody(
           node.body, CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR);
-      _checkForConstConstructorWithNonFinalField(node, element);
-      _checkForConstConstructorWithNonConstSuper(node);
+      if (!_checkForConstConstructorWithNonConstSuper(node)) {
+        _checkForConstConstructorWithNonFinalField(node, element);
+      }
       _constructorFieldsVerifier.verify(node);
       _checkForRedirectingConstructorErrorCodes(node);
       _checkForMultipleSuperInitializers(node);
@@ -1851,23 +1852,40 @@
   /// are no invocations of non-'const' super constructors, and that there are
   /// no instance variables mixed in.
   ///
+  /// Return `true` if an error is reported here, and the caller should stop
+  /// checking the constructor for constant-related errors.
+  ///
   /// See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER], and
   /// [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD].
-  void _checkForConstConstructorWithNonConstSuper(
+  bool _checkForConstConstructorWithNonConstSuper(
       ConstructorDeclaration constructor) {
     if (!_enclosingExecutable.isConstConstructor) {
-      return;
+      return false;
     }
     // OK, const factory, checked elsewhere
     if (constructor.factoryKeyword != null) {
-      return;
+      return false;
     }
 
     // check for mixins
     var instanceFields = <FieldElement>[];
     for (var mixin in _enclosingClass!.mixins) {
-      instanceFields.addAll(mixin.element.fields
-          .where((field) => !field.isStatic && !field.isSynthetic));
+      instanceFields.addAll(mixin.element.fields.where((field) {
+        if (field.isStatic) {
+          return false;
+        }
+        if (field.isSynthetic) {
+          return false;
+        }
+        // From the abstract and external fields specification:
+        // > An abstract instance variable declaration D is treated as an
+        // > abstract getter declaration and possibly an abstract setter
+        // > declaration. The setter is included if and only if D is non-final.
+        if (field.isAbstract && field.isFinal) {
+          return false;
+        }
+        return true;
+      }));
     }
     if (instanceFields.length == 1) {
       var field = instanceFields.single;
@@ -1875,7 +1893,7 @@
           CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
           constructor.returnType,
           ["'${field.enclosingElement.name}.${field.name}'"]);
-      return;
+      return true;
     } else if (instanceFields.length > 1) {
       var fieldNames = instanceFields
           .map((field) => "'${field.enclosingElement.name}.${field.name}'")
@@ -1884,7 +1902,7 @@
           CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELDS,
           constructor.returnType,
           [fieldNames]);
-      return;
+      return true;
     }
 
     // try to find and check super constructor invocation
@@ -1892,26 +1910,26 @@
       if (initializer is SuperConstructorInvocation) {
         var element = initializer.staticElement;
         if (element == null || element.isConst) {
-          return;
+          return false;
         }
         errorReporter.reportErrorForNode(
             CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
             initializer,
             [element.enclosingElement.displayName]);
-        return;
+        return true;
       }
     }
     // no explicit super constructor invocation, check default constructor
     var supertype = _enclosingClass!.supertype;
     if (supertype == null) {
-      return;
+      return false;
     }
     if (supertype.isDartCoreObject) {
-      return;
+      return false;
     }
     var unnamedConstructor = supertype.element.unnamedConstructor;
     if (unnamedConstructor == null || unnamedConstructor.isConst) {
-      return;
+      return false;
     }
 
     // default constructor is not 'const', report problem
@@ -1919,6 +1937,7 @@
         CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
         constructor.returnType,
         [supertype]);
+    return true;
   }
 
   /// Verify that if the given [constructor] declaration is 'const' then there
@@ -1935,10 +1954,6 @@
     if (!classElement.hasNonFinalField) {
       return;
     }
-    // TODO(brianwilkerson) Stop generating
-    //  CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD when either
-    //  CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER or
-    //  CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD is also generated.
     errorReporter.reportErrorForName(
         CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
         constructor);
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index 8382b13..576627a 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -23,6 +23,7 @@
   static const _dartFfiLibraryName = 'dart.ffi';
   static const _isLeafParamName = 'isLeaf';
   static const _opaqueClassName = 'Opaque';
+  static const _ffiNativeName = 'FfiNative';
 
   static const List<String> _primitiveIntegerNativeTypes = [
     'Int8',
@@ -76,8 +77,8 @@
           inCompound = true;
           compound = node;
           if (node.declaredElement!.isEmptyStruct) {
-            _errorReporter
-                .reportErrorForNode(FfiCode.EMPTY_STRUCT, node, [node.name]);
+            _errorReporter.reportErrorForNode(
+                FfiCode.EMPTY_STRUCT, node.name, [node.name.name]);
           }
           if (className == _structClassName) {
             _validatePackedAnnotation(node.metadata);
@@ -155,6 +156,12 @@
   }
 
   @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    _checkFfiNative(node);
+    super.visitFunctionDeclaration(node);
+  }
+
+  @override
   void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     var element = node.staticElement;
     if (element is MethodElement) {
@@ -196,6 +203,12 @@
   }
 
   @override
+  void visitMethodDeclaration(MethodDeclaration node) {
+    _checkFfiNative(node);
+    super.visitMethodDeclaration(node);
+  }
+
+  @override
   void visitMethodInvocation(MethodInvocation node) {
     var element = node.methodName.staticElement;
     if (element is MethodElement) {
@@ -256,6 +269,38 @@
     super.visitPropertyAccess(node);
   }
 
+  void _checkFfiNative(Declaration node) {
+    NodeList<Annotation> annotations = node.metadata;
+    if (annotations.isEmpty) {
+      return;
+    }
+
+    for (Annotation annotation in annotations) {
+      if (annotation.name.name == _ffiNativeName) {
+        // All FFI Natives must be static.
+        final isStatic = (node is FunctionDeclaration) ||
+            ((node is MethodDeclaration) && node.isStatic);
+        if (!isStatic) {
+          _errorReporter.reportErrorForNode(
+              FfiCode.FFI_NATIVE_ONLY_STATIC, node);
+        }
+        // Leaf call FFI Natives can't use Handles.
+        ArgumentList? argumentList = annotation.arguments;
+        if (argumentList != null) {
+          NodeList<Expression> arguments = argumentList.arguments;
+          TypeArgumentList? typeArgumentList = annotation.typeArguments;
+          if (typeArgumentList != null) {
+            NodeList<TypeAnnotation> typeArguments = typeArgumentList.arguments;
+            if (typeArguments.isNotEmpty && typeArguments[0].type != null) {
+              _validateFfiLeafCallUsesNoHandles(
+                  arguments, typeArguments[0].type!, node);
+            }
+          }
+        }
+      }
+    }
+  }
+
   /// Returns `true` if [nativeType] is a C type that has a size.
   bool _isSized(DartType nativeType) {
     switch (_primitiveNativeType(nativeType)) {
@@ -499,7 +544,8 @@
         _errorReporter.reportErrorForNode(
             FfiCode.MUST_BE_A_SUBTYPE, node, [TPrime, F, 'asFunction']);
       }
-      _validateFfiLeafCallUsesNoHandles(node, TPrime, node);
+      _validateFfiLeafCallUsesNoHandles(
+          node.argumentList.arguments, TPrime, node);
     }
     _validateIsLeafIsConst(node);
   }
@@ -592,8 +638,7 @@
   }
 
   void _validateFfiLeafCallUsesNoHandles(
-      MethodInvocation node, DartType nativeType, AstNode errorNode) {
-    final args = node.argumentList.arguments;
+      NodeList<Expression> args, DartType nativeType, AstNode errorNode) {
     if (args.isNotEmpty) {
       for (final arg in args) {
         if (arg is NamedExpression) {
@@ -670,6 +715,8 @@
       } else if (declaredType.isCompoundSubtype) {
         final clazz = (declaredType as InterfaceType).element;
         if (clazz.isEmptyStruct) {
+          // TODO(brianwilkerson) There are no tests for this branch. Ensure
+          //  that the diagnostic is correct and add tests.
           _errorReporter
               .reportErrorForNode(FfiCode.EMPTY_STRUCT, node, [clazz.name]);
         }
@@ -705,8 +752,13 @@
 
     final DartType T = node.typeArgumentTypes![0];
     if (!_isValidFfiNativeFunctionType(T)) {
-      _errorReporter.reportErrorForNode(
-          FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, node, [T, 'fromFunction']);
+      AstNode errorNode = node.methodName;
+      var typeArgument = node.typeArguments?.arguments[0];
+      if (typeArgument != null) {
+        errorNode = typeArgument;
+      }
+      _errorReporter.reportErrorForNode(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE,
+          errorNode, [T, 'fromFunction']);
       return;
     }
 
@@ -765,7 +817,7 @@
   /// `DynamicLibrary.lookupFunction<S, F>()`.
   void _validateLookupFunction(MethodInvocation node) {
     final typeArguments = node.typeArguments?.arguments;
-    if (typeArguments?.length != 2) {
+    if (typeArguments == null || typeArguments.length != 2) {
       // There are other diagnostics reported against the invocation and the
       // diagnostics generated below might be inaccurate, so don't report them.
       return;
@@ -775,18 +827,19 @@
     final DartType S = argTypes[0];
     final DartType F = argTypes[1];
     if (!_isValidFfiNativeFunctionType(S)) {
-      final AstNode errorNode = typeArguments![0];
+      final AstNode errorNode = typeArguments[0];
       _errorReporter.reportErrorForNode(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE,
           errorNode, [S, 'lookupFunction']);
       return;
     }
     if (!_validateCompatibleFunctionTypes(F, S)) {
-      final AstNode errorNode = typeArguments![1];
+      final AstNode errorNode = typeArguments[1];
       _errorReporter.reportErrorForNode(
           FfiCode.MUST_BE_A_SUBTYPE, errorNode, [S, F, 'lookupFunction']);
     }
     _validateIsLeafIsConst(node);
-    _validateFfiLeafCallUsesNoHandles(node, S, typeArguments![0]);
+    _validateFfiLeafCallUsesNoHandles(
+        node.argumentList.arguments, S, typeArguments[0]);
   }
 
   /// Validate that none of the [annotations] are from `dart:ffi`.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 112f2e7..6a09580 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -21,8 +21,7 @@
 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/member.dart'
-    show ConstructorMember, Member;
+import 'package:analyzer/src/dart/element/member.dart' show Member;
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
 import 'package:analyzer/src/dart/element/scope.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -38,6 +37,7 @@
 import 'package:analyzer/src/dart/resolver/function_expression_invocation_resolver.dart';
 import 'package:analyzer/src/dart/resolver/function_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/function_reference_resolver.dart';
+import 'package:analyzer/src/dart/resolver/instance_creation_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
 import 'package:analyzer/src/dart/resolver/lexical_lookup.dart';
 import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
@@ -210,10 +210,6 @@
   @override
   final TypeSystemImpl typeSystem;
 
-  /// The element representing the function containing the current node, or
-  /// `null` if the current node is not contained in a function.
-  ExecutableElement? _enclosingFunction;
-
   /// The helper for tracking if the current location has access to `this`.
   final ThisAccessTracker _thisAccessTracker = ThisAccessTracker.unit();
 
@@ -253,6 +249,9 @@
 
   late final FunctionReferenceResolver _functionReferenceResolver;
 
+  late final InstanceCreationExpressionResolver
+      _instanceCreationExpressionResolver;
+
   /// Initialize a newly created visitor to resolve the nodes in an AST node.
   ///
   /// The [definingLibrary] is the element for the library containing the node
@@ -269,7 +268,7 @@
   /// breaking change).
   ResolverVisitor(
       InheritanceManager3 inheritanceManager,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       Source source,
       TypeProvider typeProvider,
       AnalysisErrorListener errorListener,
@@ -280,7 +279,7 @@
             inheritanceManager,
             definingLibrary,
             source,
-            definingLibrary.typeSystem as TypeSystemImpl,
+            definingLibrary.typeSystem,
             typeProvider,
             errorListener,
             featureSet ??
@@ -292,7 +291,7 @@
 
   ResolverVisitor._(
       this.inheritance,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       Source source,
       this.typeSystem,
       TypeProvider typeProvider,
@@ -373,13 +372,12 @@
     typeAnalyzer = StaticTypeAnalyzer(this, migrationResolutionHooks);
     _functionReferenceResolver =
         FunctionReferenceResolver(this, _isNonNullableByDefault);
+    _instanceCreationExpressionResolver =
+        InstanceCreationExpressionResolver(this);
   }
 
-  /// Return the element representing the function containing the current node,
-  /// or `null` if the current node is not contained in a function.
-  ///
-  /// @return the element representing the function containing the current node
-  ExecutableElement? get enclosingFunction => _enclosingFunction;
+  bool get isConstructorTearoffsEnabled =>
+      _featureSet.isEnabled(Feature.constructor_tearoffs);
 
   /// Return the object providing promoted or declared types of variables.
   LocalVariableTypeProvider get localVariableTypeProvider {
@@ -1218,13 +1216,10 @@
 
   @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    _enclosingFunction = node.declaredElement;
-
     flowAnalysis!.topLevelDeclaration_enter(node, node.parameters);
     flowAnalysis!.executableDeclaration_enter(node, node.parameters, false);
 
-    var returnType = _enclosingFunction!.type.returnType;
+    var returnType = node.declaredElement!.type.returnType;
     InferenceContext.setType(node.body, returnType);
 
     super.visitConstructorDeclaration(node);
@@ -1240,8 +1235,6 @@
     flowAnalysis!.executableDeclaration_exit(node.body, false);
     flowAnalysis!.topLevelDeclaration_exit();
     nullSafetyDeadCodeVerifier.flowEnd(node);
-
-    _enclosingFunction = outerFunction;
   }
 
   @override
@@ -1442,9 +1435,6 @@
 
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    _enclosingFunction = node.declaredElement;
-
     bool isLocal = node.parent is FunctionDeclarationStatement;
 
     if (isLocal) {
@@ -1459,7 +1449,7 @@
       isLocal,
     );
 
-    var functionType = _enclosingFunction!.type;
+    var functionType = node.declaredElement!.type;
     InferenceContext.setType(node.functionExpression, functionType);
 
     super.visitFunctionDeclaration(node);
@@ -1484,7 +1474,6 @@
     }
     nullSafetyDeadCodeVerifier.flowEnd(node);
 
-    _enclosingFunction = outerFunction;
     node.accept(elementResolver);
     // Note: no need to call the typeAnalyzer since it does not override
     // visitFunctionDeclaration
@@ -1498,6 +1487,8 @@
 
   @override
   void visitFunctionExpression(covariant FunctionExpressionImpl node) {
+    // Note: we have to update _enclosingFunction because we don't make use of
+    // super.visitFunctionExpression.
     var outerFunction = _enclosingFunction;
     _enclosingFunction = node.declaredElement;
 
@@ -1677,15 +1668,7 @@
   @override
   void visitInstanceCreationExpression(
       covariant InstanceCreationExpressionImpl node) {
-    var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
-    node.constructorName.accept(this);
-    _inferArgumentTypesForInstanceCreate(node);
-    visitArgumentList(node.argumentList,
-        whyNotPromotedList: whyNotPromotedList);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
-    checkForArgumentTypesNotAssignableInList(
-        node.argumentList, whyNotPromotedList);
+    _instanceCreationExpressionResolver.resolve(node);
   }
 
   @override
@@ -1715,13 +1698,10 @@
 
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    _enclosingFunction = node.declaredElement;
-
     flowAnalysis!.topLevelDeclaration_enter(node, node.parameters);
     flowAnalysis!.executableDeclaration_enter(node, node.parameters, false);
 
-    DartType returnType = _enclosingFunction!.returnType;
+    DartType returnType = node.declaredElement!.returnType;
     InferenceContext.setType(node.body, returnType);
 
     super.visitMethodDeclaration(node);
@@ -1737,7 +1717,6 @@
     flowAnalysis!.topLevelDeclaration_exit();
     nullSafetyDeadCodeVerifier.flowEnd(node);
 
-    _enclosingFunction = outerFunction;
     node.accept(elementResolver);
     // Note: no need to call the typeAnalyzer since it does not override
     // visitMethodDeclaration.
@@ -2176,72 +2155,6 @@
     return typeProvider.futureOrType(type);
   }
 
-  void _inferArgumentTypesForInstanceCreate(
-      covariant InstanceCreationExpressionImpl node) {
-    var constructorName = node.constructorName;
-
-    var typeName = constructorName.type;
-    var typeArguments = typeName.typeArguments;
-
-    var elementToInfer = inferenceHelper.constructorElementToInfer(
-      constructorName: constructorName,
-      definingLibrary: definingLibrary,
-    );
-
-    FunctionType? inferred;
-    // If the constructor is generic, we'll have a ConstructorMember that
-    // substitutes in type arguments (possibly `dynamic`) from earlier in
-    // resolution.
-    //
-    // Otherwise we'll have a ConstructorElement, and we can skip inference
-    // because there's nothing to infer in a non-generic type.
-    if (elementToInfer != null) {
-      // TODO(leafp): Currently, we may re-infer types here, since we
-      // sometimes resolve multiple times.  We should really check that we
-      // have not already inferred something.  However, the obvious ways to
-      // check this don't work, since we may have been instantiated
-      // to bounds in an earlier phase, and we *do* want to do inference
-      // in that case.
-
-      // Get back to the uninstantiated generic constructor.
-      // TODO(jmesserly): should we store this earlier in resolution?
-      // Or look it up, instead of jumping backwards through the Member?
-      var rawElement = elementToInfer.element;
-      var constructorType = elementToInfer.asType;
-
-      inferred = inferenceHelper.inferArgumentTypesForGeneric(
-          node, constructorType, typeArguments,
-          isConst: node.isConst, errorNode: node.constructorName);
-
-      if (inferred != null) {
-        var arguments = node.argumentList;
-        InferenceContext.setType(arguments, inferred);
-        // Fix up the parameter elements based on inferred method.
-        arguments.correspondingStaticParameters =
-            resolveArgumentsToParameters(arguments, inferred.parameters, null);
-
-        constructorName.type.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.
-        var constructorElement = ConstructorMember.from(
-          rawElement,
-          inferred.returnType as InterfaceType,
-        );
-        constructorName.staticElement = constructorElement;
-      }
-    }
-
-    if (inferred == null) {
-      var constructorElement = constructorName.staticElement;
-      if (constructorElement != null) {
-        var type = constructorElement.type;
-        type = toLegacyTypeIfOptOut(type) as FunctionType;
-        InferenceContext.setType(node.argumentList, type);
-      }
-    }
-  }
-
   /// Continues resolution of a [FunctionExpressionInvocation] that was created
   /// from a rewritten [MethodInvocation]. The target function is already
   /// resolved.
@@ -2387,7 +2300,7 @@
 
   ResolverVisitorForMigration(
       InheritanceManager3 inheritanceManager,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       Source source,
       TypeProvider typeProvider,
       AnalysisErrorListener errorListener,
@@ -2457,7 +2370,7 @@
   static const _nameScopeProperty = 'nameScope';
 
   /// The element for the library containing the compilation unit being visited.
-  final LibraryElement definingLibrary;
+  final LibraryElementImpl definingLibrary;
 
   /// The source representing the compilation unit being visited.
   final Source source;
@@ -2487,6 +2400,10 @@
   /// visited, or `null` if we are not in the scope of an extension.
   ExtensionElement? enclosingExtension;
 
+  /// The element representing the function containing the current node, or
+  /// `null` if the current node is not contained in a function.
+  ExecutableElement? _enclosingFunction;
+
   /// Initialize a newly created visitor to resolve the nodes in a compilation
   /// unit.
   ///
@@ -2511,6 +2428,12 @@
         ),
         nameScope = nameScope ?? LibraryScope(definingLibrary);
 
+  /// Return the element representing the function containing the current node,
+  /// or `null` if the current node is not contained in a function.
+  ///
+  /// @return the element representing the function containing the current node
+  ExecutableElement? get enclosingFunction => _enclosingFunction;
+
   /// Return the implicit label scope in which the current node is being
   /// resolved.
   ImplicitLabelScope get implicitLabelScope => _implicitLabelScope;
@@ -2644,6 +2567,8 @@
 
   @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
+    var outerFunction = _enclosingFunction;
+    _enclosingFunction = node.declaredElement;
     Scope outerScope = nameScope;
     try {
       ConstructorElement element = node.declaredElement!;
@@ -2673,6 +2598,7 @@
       visitConstructorDeclarationInScope(node);
     } finally {
       nameScope = outerScope;
+      _enclosingFunction = outerFunction;
     }
   }
 
@@ -2851,6 +2777,9 @@
 
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
+    var outerFunction = _enclosingFunction;
+    _enclosingFunction = node.declaredElement;
+
     node.metadata.accept(this);
     Scope outerScope = nameScope;
     try {
@@ -2862,6 +2791,7 @@
       visitFunctionDeclarationInScope(node);
     } finally {
       nameScope = outerScope;
+      _enclosingFunction = outerFunction;
     }
   }
 
@@ -2882,6 +2812,8 @@
       return;
     }
 
+    var outerFunction = _enclosingFunction;
+    _enclosingFunction = node.declaredElement;
     Scope outerScope = nameScope;
     try {
       ExecutableElement element = node.declaredElement!;
@@ -2892,6 +2824,7 @@
       super.visitFunctionExpression(node);
     } finally {
       nameScope = outerScope;
+      _enclosingFunction = outerFunction;
     }
   }
 
@@ -3018,6 +2951,9 @@
 
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
+    var outerFunction = _enclosingFunction;
+    _enclosingFunction = node.declaredElement;
+
     node.metadata.accept(this);
     Scope outerScope = nameScope;
     try {
@@ -3029,6 +2965,7 @@
       visitMethodDeclarationInScope(node);
     } finally {
       nameScope = outerScope;
+      _enclosingFunction = outerFunction;
     }
   }
 
@@ -3214,10 +3151,6 @@
 /// Instances of the class `VariableResolverVisitor` are used to resolve
 /// [SimpleIdentifier]s to local variables and formal parameters.
 class VariableResolverVisitor extends ScopedVisitor {
-  /// The method or function that we are currently visiting, or `null` if we are
-  /// not inside a method or function.
-  ExecutableElement? _enclosingFunction;
-
   /// The container with information about local variables.
   final LocalVariableInfo _localVariableInfo = LocalVariableInfo();
 
@@ -3234,7 +3167,7 @@
   /// [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].
-  VariableResolverVisitor(LibraryElement definingLibrary, Source source,
+  VariableResolverVisitor(LibraryElementImpl definingLibrary, Source source,
       TypeProvider typeProvider, AnalysisErrorListener errorListener,
       {Scope? nameScope})
       : super(definingLibrary, source, typeProvider as TypeProviderImpl,
@@ -3243,14 +3176,8 @@
 
   @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    try {
-      (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
-      _enclosingFunction = node.declaredElement;
-      super.visitConstructorDeclaration(node);
-    } finally {
-      _enclosingFunction = outerFunction;
-    }
+    (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+    super.visitConstructorDeclaration(node);
   }
 
   @override
@@ -3258,28 +3185,16 @@
 
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    try {
-      (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
-          _localVariableInfo;
-      _enclosingFunction = node.declaredElement;
-      super.visitFunctionDeclaration(node);
-    } finally {
-      _enclosingFunction = outerFunction;
-    }
+    (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
+        _localVariableInfo;
+    super.visitFunctionDeclaration(node);
   }
 
   @override
   void visitFunctionExpression(FunctionExpression node) {
     if (node.parent is! FunctionDeclaration) {
-      var outerFunction = _enclosingFunction;
-      try {
-        (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
-        _enclosingFunction = node.declaredElement;
-        super.visitFunctionExpression(node);
-      } finally {
-        _enclosingFunction = outerFunction;
-      }
+      (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+      super.visitFunctionExpression(node);
     } else {
       super.visitFunctionExpression(node);
     }
@@ -3290,14 +3205,8 @@
 
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    try {
-      (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
-      _enclosingFunction = node.declaredElement;
-      super.visitMethodDeclaration(node);
-    } finally {
-      _enclosingFunction = outerFunction;
-    }
+    (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+    super.visitMethodDeclaration(node);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 6045950..ed9b4f8 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -106,9 +106,11 @@
   static ConstructorElementImpl constructorElement(
       ClassElement definingClass, String? name, bool isConst,
       [List<DartType> argumentTypes = const []]) {
-    ConstructorElementImpl constructor = name == null
-        ? ConstructorElementImpl("", -1)
-        : ConstructorElementImpl(name, 0);
+    var offset = name == null ? -1 : 0;
+    // An unnamed constructor declared with `C.new(` is modeled as unnamed.
+    var constructor = name == null || name == 'new'
+        ? ConstructorElementImpl('', offset)
+        : ConstructorElementImpl(name, offset);
     if (name != null) {
       if (name.isEmpty) {
         constructor.nameEnd = definingClass.name.length;
diff --git a/pkg/analyzer/lib/src/lint/linter_visitor.dart b/pkg/analyzer/lib/src/lint/linter_visitor.dart
index df3f994..0794a4c 100644
--- a/pkg/analyzer/lib/src/lint/linter_visitor.dart
+++ b/pkg/analyzer/lib/src/lint/linter_visitor.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:analyzer/src/services/lint.dart';
 
@@ -16,7 +17,9 @@
   final NodeLintRegistry registry;
   final LintRuleExceptionHandler exceptionHandler;
 
-  LinterVisitor(this.registry, this.exceptionHandler);
+  LinterVisitor(this.registry, [LintRuleExceptionHandler? exceptionHandler])
+      : exceptionHandler =
+            exceptionHandler ?? LinterExceptionHandler(true).logException;
 
   @override
   void visitAdjacentStrings(AdjacentStrings node) {
diff --git a/pkg/analyzer/lib/src/macro/api/code.dart b/pkg/analyzer/lib/src/macro/api/code.dart
new file mode 100644
index 0000000..a3fed07
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/api/code.dart
@@ -0,0 +1,62 @@
+// 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.
+
+/// Combines [parts] into a [String].
+/// Must only contain [Code] or [String] instances.
+String _combineParts(List<Object> parts) {
+  var buffer = StringBuffer();
+
+  void write(Object part) {
+    if (part is String) {
+      buffer.write(part);
+    } else if (part is Code) {
+      buffer.write(part.code);
+    } else if (part is Iterable<Object>) {
+      part.forEach(write);
+    } else {
+      throw UnsupportedError(
+        'Only String, Code, and List(s) of them are '
+        'allowed but got ${part.runtimeType}',
+      );
+    }
+  }
+
+  write(parts);
+  return buffer.toString();
+}
+
+/// The representation of a piece of code.
+abstract class Code {
+  String get code;
+
+  @override
+  String toString() => code;
+}
+
+/// A piece of code representing a syntactically valid declaration.
+class Declaration extends Code {
+  @override
+  final String code;
+
+  Declaration(this.code);
+
+  /// Creates a [Declaration] from [parts], which must be of type [Code],
+  /// [String], or [Iterable]s of them.
+  factory Declaration.fromParts(List<Object> parts) =>
+      Declaration(_combineParts(parts));
+}
+
+/// A piece of code that can't be parsed into a valid language construct in its
+/// current form. No validation or parsing is performed.
+class Fragment extends Code {
+  @override
+  final String code;
+
+  Fragment(this.code);
+
+  /// Creates a [Fragment] from [parts], which must be of type [Code],
+  /// [String], or [Iterable]s of them.
+  factory Fragment.fromParts(List<Object> parts) =>
+      Fragment(_combineParts(parts));
+}
diff --git a/pkg/analyzer/lib/src/macro/api/macro.dart b/pkg/analyzer/lib/src/macro/api/macro.dart
new file mode 100644
index 0000000..78eb6c0
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/api/macro.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/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/macro/api/code.dart';
+
+/// The api used by [DeclarationMacro]s to contribute new declarations to the
+/// current class.
+///
+/// Note that this is available to macros that run directly on classes, as well
+/// as macros that run on any members of a class.
+abstract class ClassDeclarationBuilder implements DeclarationBuilder {
+  /// Adds a new declaration to the surrounding class.
+  void addToClass(Declaration declaration);
+}
+
+/// The interface for [DeclarationMacro]s that can be applied to classes.
+abstract class ClassDeclarationMacro implements DeclarationMacro {
+  void visitClassDeclaration(
+      ast.ClassDeclaration declaration, ClassDeclarationBuilder builder);
+}
+
+/// The api used by [DeclarationMacro]s to contribute new declarations to the
+/// current library.
+abstract class DeclarationBuilder {
+  /// Adds a new regular declaration to the surrounding library.
+  ///
+  /// Note that type declarations are not supported.
+  void addToLibrary(Declaration declaration);
+
+  /// Return the [Code] of the [node].
+  Code typeAnnotationCode(ast.TypeAnnotation node);
+}
+
+/// The marker interface for macros that are allowed to contribute new
+/// declarations to the program, including both top level and class level
+/// declarations.
+///
+/// These macros run after [TypeMacro] macros, but before [DefinitionMacro]
+/// macros.
+///
+/// These macros can resolve type annotations to specific declarations, and
+/// inspect type hierarchies, but they cannot inspect the declarations on those
+/// type annotations, since new declarations could still be added in this phase.
+abstract class DeclarationMacro implements Macro {}
+
+/// The marker interface for macros that are only allowed to implement or wrap
+/// existing declarations in the program. They cannot introduce any new
+/// declarations that are visible to the program, but are allowed to add
+/// declarations that only they can see.
+///
+/// These macros run after all other types of macros.
+///
+/// These macros can fully reflect on the program since the static shape is
+/// fully defined by the time they run.
+abstract class DefinitionMacro implements Macro {}
+
+/// The interface for [DeclarationMacro]s that can be applied to fields.
+abstract class FieldDeclarationMacro implements DeclarationMacro {
+  void visitFieldDeclaration(
+    ast.FieldDeclaration declaration,
+    ClassDeclarationBuilder builder,
+  );
+}
+
+/// The marker interface for all types of macros.
+abstract class Macro {}
+
+/// The marker interface for macros that are allowed to contribute new type
+/// declarations into the program.
+///
+/// These macros run before all other types of macros.
+///
+/// In exchange for the power to add new type declarations, these macros have
+/// limited introspections capabilities, since new types can be added in this
+/// phase you cannot follow type references back to their declarations.
+abstract class TypeMacro implements Macro {}
diff --git a/pkg/analyzer/lib/src/macro/builders/data_class.dart b/pkg/analyzer/lib/src/macro/builders/data_class.dart
new file mode 100644
index 0000000..664f5d8
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/builders/data_class.dart
@@ -0,0 +1,89 @@
+// 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' as ast;
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/macro/api/code.dart';
+import 'package:analyzer/src/macro/api/macro.dart';
+
+class AutoConstructorMacro implements ClassDeclarationMacro {
+  const AutoConstructorMacro();
+
+  @override
+  void visitClassDeclaration(
+    ast.ClassDeclaration node,
+    ClassDeclarationBuilder builder,
+  ) {
+    // TODO(scheglov) Should we provide the element as a parameter?
+    var classElement = node.declaredElement!;
+    var typeSystem = classElement.library.typeSystem;
+
+    if (classElement.unnamedConstructor != null) {
+      throw ArgumentError(
+        'Cannot generate a constructor because one already exists',
+      );
+    }
+
+    var fieldsCode = classElement.fields.map((field) {
+      var isNullable = typeSystem.isNullable(field.type);
+      var requiredKeyword = isNullable ? '' : 'required ';
+      return '${requiredKeyword}this.${field.name}';
+    }).join(', ');
+
+    // TODO(scheglov) super constructor
+
+    builder.addToClass(
+      Declaration('${classElement.name}({$fieldsCode});'),
+    );
+  }
+}
+
+class HashCodeMacro implements ClassDeclarationMacro {
+  const HashCodeMacro();
+
+  @override
+  void visitClassDeclaration(
+    ast.ClassDeclaration node,
+    ClassDeclarationBuilder builder,
+  ) {
+    var expression = node.declaredElement!.allFields
+        .map((e) => '${e.name}.hashCode')
+        .join(' ^ ');
+    builder.addToClass(
+      Declaration('''
+@override
+int get hashCode => $expression;'''),
+    );
+  }
+}
+
+class ToStringMacro implements ClassDeclarationMacro {
+  const ToStringMacro();
+
+  @override
+  void visitClassDeclaration(
+    ast.ClassDeclaration node,
+    ClassDeclarationBuilder builder,
+  ) {
+    var classElement = node.declaredElement!;
+    var fieldsCode = classElement.allFields.map((field) {
+      var name = field.name;
+      return '$name: \$$name';
+    }).join(', ');
+    builder.addToClass(
+      Declaration('''
+@override
+String toString() => '${classElement.name}($fieldsCode)';'''),
+    );
+  }
+}
+
+extension on ClassElement {
+  Iterable<FieldElement> get allFields sync* {
+    for (ClassElement? class_ = this; class_ != null;) {
+      yield* class_.fields.where((e) => !e.isSynthetic);
+      class_ = class_.supertype?.element;
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/macro/builders/observable.dart b/pkg/analyzer/lib/src/macro/builders/observable.dart
new file mode 100644
index 0000000..6857d34
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/builders/observable.dart
@@ -0,0 +1,48 @@
+// 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' as ast;
+import 'package:analyzer/src/macro/api/code.dart';
+import 'package:analyzer/src/macro/api/macro.dart';
+
+class ObservableMacro implements FieldDeclarationMacro {
+  const ObservableMacro();
+
+  @override
+  void visitFieldDeclaration(
+    ast.FieldDeclaration node,
+    ClassDeclarationBuilder builder,
+  ) {
+    var typeNode = node.fields.type;
+    if (typeNode == null) {
+      throw ArgumentError('@observable can only annotate typed fields.');
+    }
+    var typeCode = builder.typeAnnotationCode(typeNode);
+
+    var fields = node.fields.variables;
+    for (var field in fields) {
+      var name = field.name.name;
+      if (!name.startsWith('_')) {
+        throw ArgumentError(
+          '@observable can only annotate private fields, and it will create '
+          'public getters and setters for them, but the public field '
+          '$name was annotated.',
+        );
+      }
+      var publicName = name.substring(1);
+
+      var getter = Declaration(
+        '$typeCode get $publicName => $name;',
+      );
+      builder.addToClass(getter);
+
+      var setter = Declaration('''
+set $publicName($typeCode val) {
+  print('Setting $publicName to \${val}');
+  $name = val;
+}''');
+      builder.addToClass(setter);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/macro/impl/macro.dart b/pkg/analyzer/lib/src/macro/impl/macro.dart
new file mode 100644
index 0000000..73e10f7
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/impl/macro.dart
@@ -0,0 +1,108 @@
+// 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:analyzer/dart/analysis/utilities.dart';
+import 'package:analyzer/dart/ast/ast.dart' as ast;
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/macro/api/code.dart';
+import 'package:analyzer/src/macro/api/macro.dart';
+import 'package:analyzer/src/summary2/informative_data.dart';
+
+class ClassDeclarationBuilderImpl extends DeclarationBuilderImpl
+    implements ClassDeclarationBuilder {
+  final DeclarationCollector _collector;
+  final ast.ClassDeclarationImpl node;
+
+  ClassDeclarationBuilderImpl(this._collector, this.node);
+
+  @override
+  void addToClass(Declaration declaration) {
+    var declarationCode = declaration.code.trim();
+
+    // TODO(scheglov) feature set
+    // TODO(scheglov) throw if errors?
+    var parseResult = parseString(
+      content: 'class ${node.name.name} { $declarationCode }',
+    );
+    var parsedDeclarations = parseResult.unit.declarations;
+    var parsedClass = parsedDeclarations.single as ast.ClassDeclaration;
+    var parsedMember = parsedClass.members.single;
+    _rebaseOffsets(parsedMember);
+
+    node.members.add(parsedMember);
+    _collector._add(parsedMember, declaration);
+  }
+
+  /// We parsed [node] in the context of some synthetic code string, its
+  /// current offsets only have meaning relative to the begin offset of the
+  /// [node]. So, we update offsets accordingly.
+  static void _rebaseOffsets(ast.AstNode node) {
+    var baseOffset = node.offset;
+    for (Token? t = node.beginToken;
+        t != null && t != node.endToken;
+        t = t.next) {
+      t.offset -= baseOffset;
+    }
+  }
+}
+
+class DeclarationBuilderImpl implements DeclarationBuilder {
+  @override
+  void addToLibrary(Declaration declaration) {
+    // TODO: implement addToLibrary
+  }
+
+  @override
+  Code typeAnnotationCode(ast.TypeAnnotation node) {
+    return Fragment(node.toSource());
+  }
+}
+
+class DeclarationCollector {
+  final Map<ast.AstNode, _CollectedDeclaration> _declarations = {};
+  int _nextId = 0;
+
+  /// Elements for nodes in [_declarations] were built.
+  /// Move information from [_CollectedDeclaration] into elements.
+  void updateElements() {
+    for (var entry in _declarations.entries) {
+      var node = entry.key;
+      if (node is ast.Declaration) {
+        var element = node.declaredElement;
+        if (element is HasMacroGenerationData) {
+          var collectedDeclaration = entry.value;
+          (element as HasMacroGenerationData).macro = MacroGenerationData(
+            collectedDeclaration.id,
+            collectedDeclaration.declaration.code,
+            collectedDeclaration.informative,
+          );
+        }
+      }
+    }
+  }
+
+  void _add(ast.AstNode node, Declaration declaration) {
+    _declarations[node] = _CollectedDeclaration(
+      _nextId++,
+      declaration,
+      writeDeclarationInformative(node),
+    );
+  }
+}
+
+class _CollectedDeclaration {
+  final int id;
+  final Declaration declaration;
+  final Uint8List informative;
+
+  _CollectedDeclaration(
+    this.id,
+    this.declaration,
+    this.informative,
+  );
+}
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index cccbbb3..51a33b6 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -493,12 +493,24 @@
       offset: resolutionOffset,
     );
 
-    InformativeDataApplier(_elementFactory, _unitsInformativeBytes)
-        .applyTo(libraryElement);
+    _declareDartCoreDynamicNever();
+
+    InformativeDataApplier(_elementFactory).applyTo(
+      _unitsInformativeBytes,
+      libraryElement,
+    );
 
     return libraryElement;
   }
 
+  /// These elements are implicitly declared in `dart:core`.
+  void _declareDartCoreDynamicNever() {
+    if (_reference.name == 'dart:core') {
+      _reference.getChild('dynamic').element = DynamicElementImpl.instance;
+      _reference.getChild('Never').element = NeverElementImpl.instance;
+    }
+  }
+
   ClassElementImpl _readClassElement(
     CompilationUnitElementImpl unitElement,
     Reference unitReference,
@@ -580,6 +592,7 @@
       element.setLinkedData(reference, linkedData);
       ConstructorElementFlags.read(_reader, element);
       element.parameters = _readParameters(element, reference);
+      _readMacro(element, element);
       return element;
     });
   }
@@ -840,6 +853,20 @@
     return LibraryLanguageVersion(package: package, override: override);
   }
 
+  void _readMacro(Element element, HasMacroGenerationData hasMacro) {
+    if (_reader.readBool()) {
+      hasMacro.macro = MacroGenerationData(
+        _reader.readUInt30(),
+        _reader.readStringUtf8(),
+        Uint8List(0),
+      );
+      InformativeDataApplier(_elementFactory).applyToDeclaration(
+        element,
+        _reader.readUint8List(),
+      );
+    }
+  }
+
   List<MethodElementImpl> _readMethods(
     CompilationUnitElementImpl unitElement,
     ElementImpl enclosingElement,
@@ -863,6 +890,7 @@
       element.typeParameters = _readTypeParameters();
       element.parameters = _readParameters(element, reference);
       element.typeInferenceError = _readTopLevelInferenceError();
+      _readMacro(element, element);
       return element;
     });
   }
@@ -989,6 +1017,7 @@
     element.setLinkedData(reference, linkedData);
 
     element.parameters = _readParameters(element, reference);
+    _readMacro(element, element);
     return element;
   }
 
@@ -1525,23 +1554,29 @@
           parameters: type.parameters,
           returnType: type.returnType,
           nullabilitySuffix: type.nullabilitySuffix,
-          aliasElement: aliasElement,
-          aliasArguments: aliasArguments,
+          alias: InstantiatedTypeAliasElementImpl(
+            element: aliasElement,
+            typeArguments: aliasArguments,
+          ),
         );
       } else if (type is InterfaceType) {
         return InterfaceTypeImpl(
           element: type.element,
           typeArguments: type.typeArguments,
           nullabilitySuffix: type.nullabilitySuffix,
-          aliasElement: aliasElement,
-          aliasArguments: aliasArguments,
+          alias: InstantiatedTypeAliasElementImpl(
+            element: aliasElement,
+            typeArguments: aliasArguments,
+          ),
         );
       } else if (type is TypeParameterType) {
         return TypeParameterTypeImpl(
           element: type.element,
           nullabilitySuffix: type.nullabilitySuffix,
-          aliasElement: aliasElement,
-          aliasArguments: aliasArguments,
+          alias: InstantiatedTypeAliasElementImpl(
+            element: aliasElement,
+            typeArguments: aliasArguments,
+          ),
         );
       } else if (type is VoidType) {
         // TODO(scheglov) add support for `void` aliasing
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index 528b9d2..5fd0bf8 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -164,6 +164,7 @@
     _resolutionSink.localElements.declareAll(element.parameters);
     try {
       _writeList(element.parameters, _writeParameterElement);
+      _writeMacro(element.macro);
       if (element.isConst || element.isFactory) {
         _resolutionSink.writeElement(element.redirectedConstructor);
         _resolutionSink._writeNodeList(element.constantInitializers);
@@ -280,6 +281,15 @@
     }
   }
 
+  void _writeMacro(MacroGenerationData? macro) {
+    _sink.writeBool(macro != null);
+    if (macro != null) {
+      _sink.writeUInt30(macro.id);
+      _sink.writeStringUtf8(macro.code);
+      _sink.writeUint8List(macro.informative);
+    }
+  }
+
   void _writeMethodElement(MethodElement element) {
     element as MethodElementImpl;
     _sink.writeUInt30(_resolutionSink.offset);
@@ -293,6 +303,8 @@
       _sink._writeTopLevelInferenceError(element.typeInferenceError);
       _resolutionSink.writeType(element.returnType);
     });
+
+    _writeMacro(element.macro);
   }
 
   void _writeMixinElement(ClassElement element) {
@@ -367,7 +379,9 @@
 
     _resolutionSink._writeAnnotationList(element.metadata);
     _resolutionSink.writeType(element.returnType);
+
     _writeList(element.parameters, _writeParameterElement);
+    _writeMacro(element.macro);
   }
 
   void _writeReferences(List<Reference> references) {
@@ -706,10 +720,10 @@
   }
 
   void _writeTypeAliasElementArguments(DartType type) {
-    var aliasElement = type.aliasElement;
-    _writeElement(aliasElement);
-    if (aliasElement != null) {
-      _writeTypeList(type.aliasArguments!);
+    var alias = type.alias;
+    _writeElement(alias?.element);
+    if (alias != null) {
+      _writeTypeList(alias.typeArguments);
     }
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index 3737f6e..b5b366b 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -89,6 +89,19 @@
     }
   }
 
+  /// Build elements for [members] and add into the [element].
+  void buildMacroClassMembers(
+    ClassElementImpl element,
+    List<ClassMember> members,
+  ) {
+    var holder = _buildClassMembers(element, members);
+
+    element.accessors.addAll(holder.propertyAccessors);
+    element.constructors.addAll(holder.constructors);
+    element.fields.addAll(holder.properties.whereType<FieldElementImpl>());
+    element.methods.addAll(holder.methods);
+  }
+
   @override
   void visitClassDeclaration(covariant ClassDeclarationImpl node) {
     var nameNode = node.name;
@@ -159,6 +172,10 @@
   ) {
     var nameNode = node.name ?? node.returnType;
     var name = node.name?.name ?? '';
+    if (name == 'new') {
+      // An unnamed constructor declared with `C.new(` is modeled as unnamed.
+      name = '';
+    }
     var nameOffset = nameNode.offset;
 
     var element = ConstructorElementImpl(name, nameOffset);
@@ -868,7 +885,7 @@
   }
 
   _EnclosingContext _buildClassMembers(
-      ElementImpl element, NodeList<ClassMember> members) {
+      ElementImpl element, List<ClassMember> members) {
     var hasConstConstructor = members.any((e) {
       return e is ConstructorDeclaration && e.constKeyword != null;
     });
@@ -884,29 +901,9 @@
     var element = node.declaredElement as ClassElementImpl;
     var holder = _buildClassMembers(element, node.members);
     element.accessors = holder.propertyAccessors;
+    element.constructors = holder.constructors;
     element.fields = holder.properties.whereType<FieldElement>().toList();
     element.methods = holder.methods;
-
-    var constructors = holder.constructors;
-    if (constructors.isEmpty) {
-      var containerRef = element.reference!.getChild('@constructor');
-      constructors = [
-        ConstructorElementImpl('', -1)
-          ..isSynthetic = true
-          ..reference = containerRef.getChild(''),
-      ];
-    }
-    element.constructors = constructors;
-
-    // We have all fields and constructors.
-    // Now we can resolve field formal parameters.
-    for (var constructor in constructors) {
-      for (var parameter in constructor.parameters) {
-        if (parameter is FieldFormalParameterElementImpl) {
-          parameter.field = element.getField(parameter.name);
-        }
-      }
-    }
   }
 
   void _buildExecutableElementChildren({
diff --git a/pkg/analyzer/lib/src/summary2/element_flags.dart b/pkg/analyzer/lib/src/summary2/element_flags.dart
index e808000..529a06f 100644
--- a/pkg/analyzer/lib/src/summary2/element_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/element_flags.dart
@@ -8,8 +8,8 @@
 
 class ClassElementFlags {
   static const int _isAbstract = 1 << 0;
-  static const int _isMixinApplication = 1 << 1;
-  static const int _isSimplyBounded = 1 << 2;
+  static const int _isMixinApplication = 1 << 2;
+  static const int _isSimplyBounded = 1 << 3;
 
   static void read(SummaryDataReader reader, ClassElementImpl element) {
     var byte = reader.readByte();
@@ -60,8 +60,8 @@
   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 _isLate = 1 << 9;
+  static const int _isStatic = 1 << 10;
 
   static void read(SummaryDataReader reader, FieldElementImpl element) {
     var byte = reader.readUInt30();
@@ -161,8 +161,8 @@
   static const int _isAbstract = 1 << 1;
   static const int _isAsynchronous = 1 << 2;
   static const int _isExternal = 1 << 3;
-  static const int _isGenerator = 1 << 4;
-  static const int _isStatic = 1 << 5;
+  static const int _isGenerator = 1 << 5;
+  static const int _isStatic = 1 << 6;
 
   static void read(SummaryDataReader reader, MethodElementImpl element) {
     var byte = reader.readByte();
@@ -217,8 +217,8 @@
   static const int _isAbstract = 1 << 3;
   static const int _isAsynchronous = 1 << 4;
   static const int _isExternal = 1 << 5;
-  static const int _isGenerator = 1 << 6;
-  static const int _isStatic = 1 << 7;
+  static const int _isGenerator = 1 << 7;
+  static const int _isStatic = 1 << 8;
 
   static void read(
     SummaryDataReader reader,
diff --git a/pkg/analyzer/lib/src/summary2/function_type_builder.dart b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
index f59a117..4ab0f6a 100644
--- a/pkg/analyzer/lib/src/summary2/function_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
@@ -190,7 +190,7 @@
       } else if (isNNBD) {
         nullabilitySuffix = NullabilitySuffix.none;
       } else {
-        nullabilitySuffix = NullabilitySuffix.question;
+        nullabilitySuffix = NullabilitySuffix.star;
       }
 
       return FunctionTypeBuilder(
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index 1dd1e5f..f14a0f2 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -19,6 +19,15 @@
 import 'package:analyzer/src/util/comment.dart';
 import 'package:collection/collection.dart';
 
+/// Write the informative data (mostly offsets) of the given [node].
+/// Throw [UnimplementedError] if [node] is not supported.
+Uint8List writeDeclarationInformative(AstNode node) {
+  var byteSink = ByteSink();
+  var sink = BufferedSink(byteSink);
+  _InformativeDataWriter(sink).writeDeclaration(node);
+  return sink.flushAndTake();
+}
+
 Uint8List writeUnitInformative(CompilationUnit unit) {
   var byteSink = ByteSink();
   var sink = BufferedSink(byteSink);
@@ -55,14 +64,13 @@
 
 class InformativeDataApplier {
   final LinkedElementFactory _elementFactory;
-  final Map<Uri, Uint8List> _unitsInformativeBytes2;
 
-  InformativeDataApplier(
-    this._elementFactory,
-    this._unitsInformativeBytes2,
-  );
+  InformativeDataApplier(this._elementFactory);
 
-  void applyTo(LibraryElementImpl libraryElement) {
+  void applyTo(
+    Map<Uri, Uint8List> unitsInformativeBytes,
+    LibraryElementImpl libraryElement,
+  ) {
     if (_elementFactory.isApplyingInformativeData) {
       throw StateError('Unexpected recursion.');
     }
@@ -72,7 +80,7 @@
     for (var i = 0; i < unitElements.length; i++) {
       var unitElement = unitElements[i] as CompilationUnitElementImpl;
       var unitUri = unitElement.source.uri;
-      var unitInfoBytes = _unitsInformativeBytes2[unitUri];
+      var unitInfoBytes = unitsInformativeBytes[unitUri];
       if (unitInfoBytes != null) {
         var unitReader = SummaryDataReader(unitInfoBytes);
         var unitInfo = _InfoUnit(unitReader);
@@ -140,35 +148,49 @@
     _elementFactory.isApplyingInformativeData = false;
   }
 
+  /// Read informative data from [bytes], and apply it to [element].
+  /// The data and the [element] must correspond to each other.
+  void applyToDeclaration(Element element, Uint8List bytes) {
+    if (_elementFactory.isApplyingInformativeData) {
+      throw StateError('Unexpected recursion.');
+    }
+    _elementFactory.isApplyingInformativeData = true;
+
+    var reader = SummaryDataReader(bytes);
+
+    var kindIndex = reader.readByte();
+    var kind = _DeclarationKind.values[kindIndex];
+
+    if (kind == _DeclarationKind.constructorDeclaration &&
+        element is ConstructorElement) {
+      var info = _InfoConstructorDeclaration(reader);
+      _applyToConstructor(element, info);
+    } else if (kind == _DeclarationKind.methodDeclaration &&
+        element is MethodElement) {
+      var info = _InfoMethodDeclaration(reader);
+      _applyToMethod(element, info);
+    } else if (kind == _DeclarationKind.methodDeclaration &&
+        element is PropertyAccessorElement) {
+      var info = _InfoMethodDeclaration(reader);
+      _applyToPropertyAccessor(element, info);
+    } else {
+      throw UnimplementedError(
+        'Unsupported kind: $kind, '
+        'or element: ${element.runtimeType}',
+      );
+    }
+
+    _elementFactory.isApplyingInformativeData = false;
+  }
+
   void _applyToAccessors(
     List<PropertyAccessorElement> elementList,
     List<_InfoMethodDeclaration> infoList,
   ) {
-    forCorrespondingPairs<PropertyAccessorElement, _InfoMethodDeclaration>(
+    forCorrespondingPairs(
       elementList.notSynthetic,
       infoList,
-      (element, info) {
-        element as PropertyAccessorElementImpl;
-        element.setCodeRange(info.codeOffset, info.codeLength);
-        element.nameOffset = info.nameOffset;
-        element.documentationComment = info.documentationComment;
-        _applyToFormalParameters(
-          element.parameters_unresolved,
-          info.parameters,
-        );
-
-        var linkedData = element.linkedData;
-        if (linkedData is PropertyAccessorElementLinkedData) {
-          linkedData.applyConstantOffsets = ApplyConstantOffsets(
-            info.constantOffsets,
-            (applier) {
-              applier.applyToMetadata(element);
-              applier.applyToTypeParameters(element.typeParameters);
-              applier.applyToFormalParameters(element.parameters);
-            },
-          );
-        }
-      },
+      _applyToPropertyAccessor,
     );
   }
 
@@ -240,6 +262,32 @@
     );
   }
 
+  void _applyToConstructor(
+    ConstructorElement element,
+    _InfoConstructorDeclaration info,
+  ) {
+    element as ConstructorElementImpl;
+    element.setCodeRange(info.codeOffset, info.codeLength);
+    element.periodOffset = info.periodOffset;
+    element.nameOffset = info.nameOffset;
+    element.nameEnd = info.nameEnd;
+    element.documentationComment = info.documentationComment;
+    _applyToFormalParameters(
+      element.parameters_unresolved,
+      info.parameters,
+    );
+
+    var linkedData = element.linkedData as ConstructorElementLinkedData;
+    linkedData.applyConstantOffsets = ApplyConstantOffsets(
+      info.constantOffsets,
+      (applier) {
+        applier.applyToMetadata(element);
+        applier.applyToFormalParameters(element.parameters);
+        applier.applyToConstructorInitializers(element);
+      },
+    );
+  }
+
   void _applyToConstructors(
     List<ConstructorElement> elementList,
     List<_InfoConstructorDeclaration> infoList,
@@ -247,28 +295,7 @@
     forCorrespondingPairs<ConstructorElement, _InfoConstructorDeclaration>(
       elementList,
       infoList,
-      (element, info) {
-        element as ConstructorElementImpl;
-        element.setCodeRange(info.codeOffset, info.codeLength);
-        element.periodOffset = info.periodOffset;
-        element.nameOffset = info.nameOffset;
-        element.nameEnd = info.nameEnd;
-        element.documentationComment = info.documentationComment;
-        _applyToFormalParameters(
-          element.parameters_unresolved,
-          info.parameters,
-        );
-
-        var linkedData = element.linkedData as ConstructorElementLinkedData;
-        linkedData.applyConstantOffsets = ApplyConstantOffsets(
-          info.constantOffsets,
-          (applier) {
-            applier.applyToMetadata(element);
-            applier.applyToFormalParameters(element.parameters);
-            applier.applyToConstructorInitializers(element);
-          },
-        );
-      },
+      _applyToConstructor,
     );
   }
 
@@ -499,6 +526,31 @@
     );
   }
 
+  void _applyToMethod(MethodElement element, _InfoMethodDeclaration info) {
+    element as MethodElementImpl;
+    element.setCodeRange(info.codeOffset, info.codeLength);
+    element.nameOffset = info.nameOffset;
+    element.documentationComment = info.documentationComment;
+    _applyToTypeParameters(
+      element.typeParameters_unresolved,
+      info.typeParameters,
+    );
+    _applyToFormalParameters(
+      element.parameters_unresolved,
+      info.parameters,
+    );
+
+    var linkedData = element.linkedData as MethodElementLinkedData;
+    linkedData.applyConstantOffsets = ApplyConstantOffsets(
+      info.constantOffsets,
+      (applier) {
+        applier.applyToMetadata(element);
+        applier.applyToTypeParameters(element.typeParameters);
+        applier.applyToFormalParameters(element.parameters);
+      },
+    );
+  }
+
   void _applyToMethods(
     List<MethodElement> elementList,
     List<_InfoMethodDeclaration> infoList,
@@ -506,30 +558,7 @@
     forCorrespondingPairs<MethodElement, _InfoMethodDeclaration>(
       elementList,
       infoList,
-      (element, info) {
-        element as MethodElementImpl;
-        element.setCodeRange(info.codeOffset, info.codeLength);
-        element.nameOffset = info.nameOffset;
-        element.documentationComment = info.documentationComment;
-        _applyToTypeParameters(
-          element.typeParameters_unresolved,
-          info.typeParameters,
-        );
-        _applyToFormalParameters(
-          element.parameters_unresolved,
-          info.parameters,
-        );
-
-        var linkedData = element.linkedData as MethodElementLinkedData;
-        linkedData.applyConstantOffsets = ApplyConstantOffsets(
-          info.constantOffsets,
-          (applier) {
-            applier.applyToMetadata(element);
-            applier.applyToTypeParameters(element.typeParameters);
-            applier.applyToFormalParameters(element.parameters);
-          },
-        );
-      },
+      _applyToMethod,
     );
   }
 
@@ -560,6 +589,32 @@
     );
   }
 
+  void _applyToPropertyAccessor(
+    PropertyAccessorElement element,
+    _InfoMethodDeclaration info,
+  ) {
+    element as PropertyAccessorElementImpl;
+    element.setCodeRange(info.codeOffset, info.codeLength);
+    element.nameOffset = info.nameOffset;
+    element.documentationComment = info.documentationComment;
+    _applyToFormalParameters(
+      element.parameters_unresolved,
+      info.parameters,
+    );
+
+    var linkedData = element.linkedData;
+    if (linkedData is PropertyAccessorElementLinkedData) {
+      linkedData.applyConstantOffsets = ApplyConstantOffsets(
+        info.constantOffsets,
+        (applier) {
+          applier.applyToMetadata(element);
+          applier.applyToTypeParameters(element.typeParameters);
+          applier.applyToFormalParameters(element.parameters);
+        },
+      );
+    }
+  }
+
   void _applyToTopLevelVariable(
     TopLevelVariableElement element,
     _InfoTopLevelVariable info,
@@ -629,6 +684,11 @@
   }
 }
 
+enum _DeclarationKind {
+  constructorDeclaration,
+  methodDeclaration,
+}
+
 class _InfoClassDeclaration {
   final int codeOffset;
   final int codeLength;
@@ -1289,6 +1349,18 @@
     );
   }
 
+  void writeDeclaration(AstNode node) {
+    if (node is ConstructorDeclaration) {
+      sink.addByte(_DeclarationKind.constructorDeclaration.index);
+      _writeConstructor(node);
+    } else if (node is MethodDeclaration) {
+      sink.addByte(_DeclarationKind.methodDeclaration.index);
+      _writeMethod(node);
+    } else {
+      throw UnimplementedError('(${node.runtimeType}) $node');
+    }
+  }
+
   int _codeOffsetForVariable(VariableDeclaration node) {
     var codeOffset = node.offset;
     var variableList = node.parent as VariableDeclarationList;
@@ -1305,22 +1377,24 @@
     });
   }
 
+  void _writeConstructor(ConstructorDeclaration node) {
+    sink.writeUInt30(node.offset);
+    sink.writeUInt30(node.length);
+    sink.writeOptionalUInt30(node.period?.offset);
+    var nameNode = node.name ?? node.returnType;
+    sink.writeUInt30(nameNode.offset);
+    sink.writeUInt30(nameNode.end);
+    _writeDocumentationComment(node);
+    _writeFormalParameters(node.parameters);
+    _writeOffsets(
+      metadata: node.metadata,
+      formalParameters: node.parameters,
+      constructorInitializers: node.initializers,
+    );
+  }
+
   void _writeConstructors(List<ClassMember> members) {
-    sink.writeList2<ConstructorDeclaration>(members, (node) {
-      sink.writeUInt30(node.offset);
-      sink.writeUInt30(node.length);
-      sink.writeOptionalUInt30(node.period?.offset);
-      var nameNode = node.name ?? node.returnType;
-      sink.writeUInt30(nameNode.offset);
-      sink.writeUInt30(nameNode.end);
-      _writeDocumentationComment(node);
-      _writeFormalParameters(node.parameters);
-      _writeOffsets(
-        metadata: node.metadata,
-        formalParameters: node.parameters,
-        constructorInitializers: node.initializers,
-      );
-    });
+    sink.writeList2<ConstructorDeclaration>(members, _writeConstructor);
   }
 
   void _writeDocumentationComment(AnnotatedNode node) {
@@ -1383,19 +1457,7 @@
           .whereType<MethodDeclaration>()
           .where((e) => e.isGetter || e.isSetter)
           .toList(),
-      (node) {
-        sink.writeUInt30(node.offset);
-        sink.writeUInt30(node.length);
-        sink.writeUInt30(node.name.offset);
-        _writeDocumentationComment(node);
-        _writeTypeParameters(node.typeParameters);
-        _writeFormalParameters(node.parameters);
-        _writeOffsets(
-          metadata: node.metadata,
-          typeParameters: node.typeParameters,
-          formalParameters: node.parameters,
-        );
-      },
+      _writeMethod,
     );
   }
 
@@ -1420,25 +1482,27 @@
     );
   }
 
+  void _writeMethod(MethodDeclaration node) {
+    sink.writeUInt30(node.offset);
+    sink.writeUInt30(node.length);
+    sink.writeUInt30(node.name.offset);
+    _writeDocumentationComment(node);
+    _writeTypeParameters(node.typeParameters);
+    _writeFormalParameters(node.parameters);
+    _writeOffsets(
+      metadata: node.metadata,
+      typeParameters: node.typeParameters,
+      formalParameters: node.parameters,
+    );
+  }
+
   void _writeMethods(List<ClassMember> members) {
     sink.writeList<MethodDeclaration>(
       members
           .whereType<MethodDeclaration>()
           .where((e) => !(e.isGetter || e.isSetter))
           .toList(),
-      (node) {
-        sink.writeUInt30(node.offset);
-        sink.writeUInt30(node.length);
-        sink.writeUInt30(node.name.offset);
-        _writeDocumentationComment(node);
-        _writeTypeParameters(node.typeParameters);
-        _writeFormalParameters(node.parameters);
-        _writeOffsets(
-          metadata: node.metadata,
-          typeParameters: node.typeParameters,
-          formalParameters: node.parameters,
-        );
-      },
+      _writeMethod,
     );
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 2c1a0b3..c1eb205 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -2,13 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart' as ast;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/ast/ast.dart' as ast;
 import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/macro/builders/data_class.dart' as macro;
+import 'package:analyzer/src/macro/builders/observable.dart' as macro;
+import 'package:analyzer/src/macro/impl/macro.dart' as macro;
 import 'package:analyzer/src/summary2/combinator.dart';
 import 'package:analyzer/src/summary2/constructor_initializer_resolver.dart';
 import 'package:analyzer/src/summary2/default_value_resolver.dart';
@@ -111,10 +113,7 @@
       }
       elementBuilder.buildDeclarationElements(linkingUnit.node);
     }
-    if ('$uri' == 'dart:core') {
-      localScope.declare('dynamic', reference.getChild('dynamic'));
-      localScope.declare('Never', reference.getChild('Never'));
-    }
+    _declareDartCoreDynamicNever();
   }
 
   void buildEnumChildren() {
@@ -145,6 +144,38 @@
     }
   }
 
+  /// We don't create default constructors during building elements from AST,
+  /// there might be macros that will add one later. So, this method is
+  /// invoked after all macros that affect element models.
+  void processClassConstructors() {
+    // TODO(scheglov) We probably don't need constructors for mixins.
+    var classes = element.topLevelElements
+        .whereType<ClassElementImpl>()
+        .where((e) => !e.isMixinApplication)
+        .toList();
+
+    for (var element in classes) {
+      if (element.constructors.isEmpty) {
+        var containerRef = element.reference!.getChild('@constructor');
+        element.constructors = [
+          ConstructorElementImpl('', -1)
+            ..isSynthetic = true
+            ..reference = containerRef.getChild(''),
+        ];
+      }
+
+      // We have all fields and constructors.
+      // Now we can resolve field formal parameters.
+      for (var constructor in element.constructors) {
+        for (var parameter in constructor.parameters) {
+          if (parameter is FieldFormalParameterElementImpl) {
+            parameter.field = element.getField(parameter.name);
+          }
+        }
+      }
+    }
+  }
+
   void resolveConstructors() {
     ConstructorInitializerResolver(linker, element).resolve();
   }
@@ -162,18 +193,99 @@
 
   void resolveTypes(NodesToBuildType nodesToBuildType) {
     for (var linkingUnit in units) {
-      var resolver = ReferenceResolver(
-        linker,
-        nodesToBuildType,
-        linker.elementFactory,
-        element,
-        linkingUnit.reference,
-        linkingUnit.node.featureSet.isEnabled(Feature.non_nullable),
-      );
+      var resolver = ReferenceResolver(linker, nodesToBuildType, element);
       linkingUnit.node.accept(resolver);
     }
   }
 
+  /// Run built-in declaration macros.
+  void runDeclarationMacros() {
+    bool hasMacroAnnotation(ast.AnnotatedNode node, String name) {
+      for (var annotation in node.metadata) {
+        var nameNode = annotation.name;
+        if (nameNode is ast.SimpleIdentifier &&
+            annotation.arguments == null &&
+            annotation.constructorName == null &&
+            nameNode.name == name) {
+          var nameElement = element.scope.lookup(name).getter;
+          return nameElement != null &&
+              nameElement.library?.name == 'analyzer.macro.annotations';
+        }
+      }
+      return false;
+    }
+
+    /// Build types for type annotations in new [nodes].
+    void resolveTypeAnnotations(
+      List<ast.AstNode> nodes, {
+      ClassElementImpl? classElement,
+    }) {
+      var nodesToBuildType = NodesToBuildType();
+      var resolver = ReferenceResolver(linker, nodesToBuildType, element);
+      if (classElement != null) {
+        resolver.enterScopeClassElement(classElement);
+      }
+      for (var node in nodes) {
+        node.accept(resolver);
+      }
+      TypesBuilder(linker).build(nodesToBuildType);
+    }
+
+    var collector = macro.DeclarationCollector();
+    for (var linkingUnit in units) {
+      for (var declaration in linkingUnit.node.declarations) {
+        if (declaration is ast.ClassDeclarationImpl) {
+          var members = declaration.members.toList();
+          var classBuilder = macro.ClassDeclarationBuilderImpl(
+            collector,
+            declaration,
+          );
+          if (hasMacroAnnotation(declaration, 'autoConstructor')) {
+            macro.AutoConstructorMacro().visitClassDeclaration(
+              declaration,
+              classBuilder,
+            );
+          }
+          if (hasMacroAnnotation(declaration, 'hashCode')) {
+            macro.HashCodeMacro().visitClassDeclaration(
+              declaration,
+              classBuilder,
+            );
+          }
+          if (hasMacroAnnotation(declaration, 'toString')) {
+            macro.ToStringMacro().visitClassDeclaration(
+              declaration,
+              classBuilder,
+            );
+          }
+          for (var member in members) {
+            if (member is ast.FieldDeclarationImpl) {
+              if (hasMacroAnnotation(member, 'observable')) {
+                macro.ObservableMacro().visitFieldDeclaration(
+                  member,
+                  classBuilder,
+                );
+              }
+            }
+          }
+
+          var newMembers = declaration.members.sublist(members.length);
+          if (newMembers.isNotEmpty) {
+            var elementBuilder = ElementBuilder(
+              libraryBuilder: this,
+              unitReference: linkingUnit.reference,
+              unitElement: linkingUnit.element,
+            );
+            var classElement = declaration.declaredElement as ClassElementImpl;
+            elementBuilder.buildMacroClassMembers(classElement, newMembers);
+            resolveTypeAnnotations(newMembers, classElement: classElement);
+          }
+        }
+      }
+    }
+    collector.updateElements();
+  }
+
   void storeExportScope() {
     exports = exportScope.map.values.toList();
     linker.elementFactory.setExportsOfLibrary('$uri', exports);
@@ -195,6 +307,19 @@
     }
   }
 
+  /// These elements are implicitly declared in `dart:core`.
+  void _declareDartCoreDynamicNever() {
+    if (reference.name == 'dart:core') {
+      var dynamicRef = reference.getChild('dynamic');
+      dynamicRef.element = DynamicElementImpl.instance;
+      localScope.declare('dynamic', dynamicRef);
+
+      var neverRef = reference.getChild('Never');
+      neverRef.element = NeverElementImpl.instance;
+      localScope.declare('Never', neverRef);
+    }
+  }
+
   static void build(Linker linker, LinkInputLibrary inputLibrary) {
     var elementFactory = linker.elementFactory;
 
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index f0b0174..7a33308 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -93,6 +93,7 @@
     _createTypeSystem();
     _buildEnumChildren();
     _resolveTypes();
+    _runDeclarationMacros();
     _performTopLevelInference();
     _resolveConstructors();
     _resolveConstantInitializers();
@@ -213,6 +214,13 @@
     TypesBuilder(this).build(nodesToBuildType);
   }
 
+  void _runDeclarationMacros() {
+    for (var library in builders.values) {
+      library.runDeclarationMacros();
+      library.processClassConstructors();
+    }
+  }
+
   void _writeLibraries() {
     var bundleWriter = BundleWriter(
       elementFactory.dynamicRef,
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index a449b97..e83e492 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -27,7 +27,6 @@
   ) {
     ArgumentError.checkNotNull(analysisContext, 'analysisContext');
     ArgumentError.checkNotNull(analysisSession, 'analysisSession');
-    _declareDartCoreDynamicNever();
   }
 
   Reference get dynamicRef {
@@ -182,10 +181,22 @@
   /// that the client can re-add the bundle, this time read from bytes.
   void removeBundle(Set<String> uriStrSet) {
     removeLibraries(uriStrSet);
+  }
 
-    // This is the bundle with dart:core and dart:async, based on full ASTs.
-    // To link them, the linker set the type provider. We are removing these
-    // libraries, and we should also remove the type provider.
+  /// Remove libraries with the specified URIs from the reference tree, and
+  /// any session level caches.
+  void removeLibraries(Set<String> uriStrSet) {
+    for (var uriStr in uriStrSet) {
+      _exportsOfLibrary.remove(uriStr);
+      libraryReaders.remove(uriStr);
+      rootReference.removeChild(uriStr);
+    }
+
+    analysisSession.classHierarchy.removeOfLibraries(uriStrSet);
+    analysisSession.inheritanceManager.removeOfLibraries(uriStrSet);
+
+    // If we discard `dart:core` and `dart:async`, we should also discard
+    // the type provider.
     if (uriStrSet.contains('dart:core')) {
       if (!uriStrSet.contains('dart:async')) {
         throw StateError(
@@ -200,23 +211,9 @@
         );
       }
       analysisContext.clearTypeProvider();
-      _declareDartCoreDynamicNever();
     }
   }
 
-  /// Remove libraries with the specified URIs from the reference tree, and
-  /// any session level caches.
-  void removeLibraries(Set<String> uriStrSet) {
-    for (var uriStr in uriStrSet) {
-      _exportsOfLibrary.remove(uriStr);
-      libraryReaders.remove(uriStr);
-      rootReference.removeChild(uriStr);
-    }
-
-    analysisSession.classHierarchy.removeOfLibraries(uriStrSet);
-    analysisSession.inheritanceManager.removeOfLibraries(uriStrSet);
-  }
-
   /// 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) {
@@ -242,10 +239,4 @@
 
     libraryElement.createLoadLibraryFunction();
   }
-
-  void _declareDartCoreDynamicNever() {
-    var dartCoreRef = rootReference.getChild('dart:core');
-    dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
-    dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
-  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart
index a2cf17b..23c3836 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/summary2/scope.dart';
 
@@ -32,14 +31,6 @@
   /// The simple name of the reference in its [parent].
   final String name;
 
-  /// The node accessor, used to read nodes lazily.
-  /// Or `null` if a named container.
-  ReferenceNodeAccessor? nodeAccessor;
-
-  /// The corresponding [AstNode], or `null` if a named container.
-  /// TODO(scheglov) remove it
-  AstNode? node;
-
   /// The corresponding [Element], or `null` if a named container.
   Element? element;
 
@@ -62,30 +53,14 @@
     return const [];
   }
 
-  bool get isClass => parent != null && parent!.name == '@class';
-
-  bool get isConstructor => parent != null && parent!.name == '@constructor';
-
-  bool get isDynamic => name == 'dynamic' && parent?.name == 'dart:core';
-
-  bool get isEnum => parent != null && parent!.name == '@enum';
-
-  bool get isGetter => parent != null && parent!.name == '@getter';
-
   bool get isLibrary => parent != null && parent!.isRoot;
 
-  bool get isParameter => parent != null && parent!.name == '@parameter';
-
   bool get isPrefix => parent != null && parent!.name == '@prefix';
 
   bool get isRoot => parent == null;
 
   bool get isSetter => parent != null && parent!.name == '@setter';
 
-  bool get isTypeAlias => parent != null && parent!.name == '@typeAlias';
-
-  bool get isUnit => parent != null && parent!.name == '@unit';
-
   /// Return the child with the given name, or `null` if does not exist.
   Reference? operator [](String name) {
     return _children != null ? _children![name] : null;
@@ -97,21 +72,6 @@
     return map[name] ??= Reference._(this, name);
   }
 
-  /// If the reference has element, and it is for the [node], return `true`.
-  ///
-  /// The element might be not `null`, but the node is different in case of
-  /// duplicate declarations.
-  bool hasElementFor(AstNode node) {
-    if (element != null && this.node == node) {
-      return true;
-    } else {
-      if (this.node == null) {
-        this.node = node;
-      }
-      return false;
-    }
-  }
-
   void removeChild(String name) {
     _children!.remove(name);
   }
@@ -119,13 +79,3 @@
   @override
   String toString() => parent == null ? 'root' : '$parent::$name';
 }
-
-abstract class ReferenceNodeAccessor {
-  /// Return the node that corresponds to this [Reference], read it if not yet.
-  AstNode get node;
-
-  /// Fill [Reference.nodeAccessor] for children.
-  ///
-  /// TODO(scheglov) only class reader has a meaningful implementation.
-  void readIndex();
-}
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index ea3f216..1cba245 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -14,10 +14,8 @@
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/summary2/function_type_builder.dart';
 import 'package:analyzer/src/summary2/link.dart';
-import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/linking_node_scope.dart';
 import 'package:analyzer/src/summary2/named_type_builder.dart';
-import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/summary2/types_builder.dart';
 
 /// Recursive visitor of [LinkedNode]s that resolves explicit type annotations
@@ -33,8 +31,6 @@
   final Linker linker;
   final TypeSystemImpl _typeSystem;
   final NodesToBuildType nodesToBuildType;
-  final LinkedElementFactory elementFactory;
-  final Reference unitReference;
 
   /// Indicates whether the library is opted into NNBD.
   final bool isNNBD;
@@ -44,12 +40,14 @@
   ReferenceResolver(
     this.linker,
     this.nodesToBuildType,
-    this.elementFactory,
     LibraryElementImpl libraryElement,
-    this.unitReference,
-    this.isNNBD,
   )   : _typeSystem = libraryElement.typeSystem,
-        scope = libraryElement.scope;
+        scope = libraryElement.scope,
+        isNNBD = libraryElement.isNonNullableByDefault;
+
+  void enterScopeClassElement(ClassElementImpl element) {
+    scope = TypeParameterScope(scope, element.typeParameters);
+  }
 
   @override
   void visitBlockFunctionBody(BlockFunctionBody node) {}
@@ -59,9 +57,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as ClassElementImpl;
-    element.accessors; // create elements
-    element.constructors; // create elements
-    element.methods; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
 
@@ -108,7 +103,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as ConstructorElementImpl;
-    element.parameters; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
     LinkingNodeContext(node, scope);
@@ -164,7 +158,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as FieldFormalParameterElementImpl;
-    element.parameters; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
 
@@ -186,7 +179,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as ExecutableElementImpl;
-    element.parameters; // create elements
 
     scope = TypeParameterScope(outerScope, element.typeParameters);
     LinkingNodeContext(node, scope);
@@ -214,9 +206,6 @@
 
     node.returnType?.accept(this);
     node.typeParameters?.accept(this);
-
-    var function = element.aliasedElement as GenericFunctionTypeElementImpl;
-    function.parameters; // create elements
     node.parameters.accept(this);
 
     nodesToBuildType.addDeclaration(node);
@@ -229,7 +218,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as ParameterElementImpl;
-    element.parameters; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
 
@@ -293,7 +281,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as ExecutableElementImpl;
-    element.parameters; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
     LinkingNodeContext(node, scope);
@@ -311,9 +298,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as MixinElementImpl;
-    element.accessors; // create elements
-    element.constructors; // create elements
-    element.methods; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
 
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 28b4452..2efaaa1 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -151,6 +151,8 @@
   /// Ways to say `include`.
   static const List<String> includeSynonyms = ['include', 'true'];
 
+  static const String propagateLinterExceptions = 'propagate-linter-exceptions';
+
   /// Ways to say `true` or `false`.
   static const List<String> trueOrFalse = ['true', 'false'];
 
@@ -163,6 +165,7 @@
     language,
     optionalChecks,
     plugins,
+    propagateLinterExceptions,
     strong_mode,
   ];
 
@@ -805,6 +808,9 @@
       if (feature == AnalyzerOptions.implicitDynamic) {
         options.implicitDynamic = boolValue;
       }
+      if (feature == AnalyzerOptions.propagateLinterExceptions) {
+        options.propagateLinterExceptions = boolValue;
+      }
     }
   }
 
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 3aa1807..b20ece0 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -748,6 +748,12 @@
 
   external T operator [](int index);
 }
+
+class FfiNative<T> {
+  final String nativeName;
+  final bool isLeaf;
+  const FfiNative(this.nativeName, {this.isLeaf: false});
+}
 ''',
   )
 ]);
diff --git a/pkg/analyzer/lib/src/workspace/simple.dart b/pkg/analyzer/lib/src/workspace/simple.dart
index 51d96d2..02413ce 100644
--- a/pkg/analyzer/lib/src/workspace/simple.dart
+++ b/pkg/analyzer/lib/src/workspace/simple.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
@@ -12,9 +11,6 @@
 
 /// An abstract class for simple workspaces which do not feature any build
 /// artifacts or generated files.
-///
-/// The [packageMap] and [packageUrlResolver] are simple derivations from the
-/// [ContextBuilder] and [ResourceProvider] required for the class.
 abstract class SimpleWorkspace extends Workspace {
   /// The [ResourceProvider] by which paths are converted into [Resource]s.
   final ResourceProvider provider;
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index d52b622..4afb0cc 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 2.0.0
+version: 2.1.0-dev
 description: This package provides a library that performs static analysis of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
 
diff --git a/pkg/analyzer/test/error/error_reporter_test.dart b/pkg/analyzer/test/error/error_reporter_test.dart
index dba624a..7b32e98 100644
--- a/pkg/analyzer/test/error/error_reporter_test.dart
+++ b/pkg/analyzer/test/error/error_reporter_test.dart
@@ -166,7 +166,7 @@
     var fa = findNode.topLevelVariableDeclaration('fa');
     var fb = findNode.topLevelVariableDeclaration('fb');
 
-    var source = result.unit!.declaredElement!.source;
+    var source = result.unit.declaredElement!.source;
     var reporter = ErrorReporter(
       listener,
       source,
@@ -201,7 +201,7 @@
     var ba = findNode.topLevelVariableDeclaration('ba');
     var bb = findNode.topLevelVariableDeclaration('bb');
 
-    var source = result.unit!.declaredElement!.source;
+    var source = result.unit.declaredElement!.source;
     var reporter = ErrorReporter(
       listener,
       source,
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index f4a4079..f97d66a 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -497,7 +497,7 @@
 
     var expression = findNode.variableDeclaration('x =').initializer!;
 
-    var file = getFile(result.path!);
+    var file = getFile(result.path);
     var evaluator = ConstantEvaluator(
       file.createSource(result.uri),
       result.libraryElement as LibraryElementImpl,
diff --git a/pkg/analyzer/test/generated/function_reference_parser_test.dart b/pkg/analyzer/test/generated/function_reference_parser_test.dart
index 13d0d82..c7cc214 100644
--- a/pkg/analyzer/test/generated/function_reference_parser_test.dart
+++ b/pkg/analyzer/test/generated/function_reference_parser_test.dart
@@ -300,6 +300,59 @@
             as MethodInvocation);
   }
 
+  void test_functionReference_after_indexExpression() {
+    // Note: this is not legal Dart, but it's important that we do error
+    // recovery and don't crash the parser.
+    var functionReference =
+        parseExpression('x[0]<a, b>', featureSet: constructorTearoffs)
+            as FunctionReference;
+    expect(functionReference.function, TypeMatcher<IndexExpression>());
+    var typeArgs = functionReference.typeArguments!.arguments;
+    expect(typeArgs, hasLength(2));
+    expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+    expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+  }
+
+  void test_functionReference_after_indexExpression_bang() {
+    // Note: this is not legal Dart, but it's important that we do error
+    // recovery and don't crash the parser.
+    var functionReference =
+        parseExpression('x[0]!<a, b>', featureSet: constructorTearoffs)
+            as FunctionReference;
+    expect(functionReference.function, TypeMatcher<PostfixExpression>());
+    var typeArgs = functionReference.typeArguments!.arguments;
+    expect(typeArgs, hasLength(2));
+    expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+    expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+  }
+
+  void test_functionReference_after_indexExpression_functionCall() {
+    // Note: this is not legal Dart, but it's important that we do error
+    // recovery and don't crash the parser.
+    var functionReference =
+        parseExpression('x[0]()<a, b>', featureSet: constructorTearoffs)
+            as FunctionReference;
+    expect(functionReference.function,
+        TypeMatcher<FunctionExpressionInvocation>());
+    var typeArgs = functionReference.typeArguments!.arguments;
+    expect(typeArgs, hasLength(2));
+    expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+    expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+  }
+
+  void test_functionReference_after_indexExpression_nullAware() {
+    // Note: this is not legal Dart, but it's important that we do error
+    // recovery and don't crash the parser.
+    var functionReference =
+        parseExpression('x?[0]<a, b>', featureSet: constructorTearoffs)
+            as FunctionReference;
+    expect(functionReference.function, TypeMatcher<IndexExpression>());
+    var typeArgs = functionReference.typeArguments!.arguments;
+    expect(typeArgs, hasLength(2));
+    expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+    expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+  }
+
   void test_methodTearoff() {
     var functionReference =
         parseExpression('f().m<a, b>', featureSet: constructorTearoffs)
@@ -314,6 +367,21 @@
     expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
   }
 
+  void test_methodTearoff_cascaded() {
+    var cascadeExpression =
+        parseExpression('f()..m<a, b>', featureSet: constructorTearoffs)
+            as CascadeExpression;
+    var functionReference =
+        cascadeExpression.cascadeSections[0] as FunctionReference;
+    var function = functionReference.function as PropertyAccess;
+    expect(function.target, isNull);
+    expect(function.propertyName.name, 'm');
+    var typeArgs = functionReference.typeArguments!.arguments;
+    expect(typeArgs, hasLength(2));
+    expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+    expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+  }
+
   void test_prefixedIdentifier() {
     var functionReference =
         parseExpression('prefix.f<a, b>', featureSet: constructorTearoffs)
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 33fc9a1..91e4e01 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -761,7 +761,7 @@
 class D {}
 class E {}
 ''');
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     ClassElement classC = unit.declaredElement!.getType('C')!;
     expect(classC.documentationComment, isNotNull);
   }
@@ -1610,7 +1610,7 @@
 
 class C extends A<B> with M {}
 ''');
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     ClassElement classC = unit.declaredElement!.getType('C')!;
     expect(classC.mixins, hasLength(1));
     assertType(classC.mixins[0], 'M<B>');
@@ -1632,7 +1632,7 @@
         1,
       ),
     ]);
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     ClassElement classC = unit.declaredElement!.getType('C')!;
     expect(classC.mixins, hasLength(1));
     assertType(classC.mixins[0], 'M<int, String>');
@@ -1648,7 +1648,7 @@
 
 class C extends A<List<B>> with M {}
 ''');
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     ClassElement classC = unit.declaredElement!.getType('C')!;
     expect(classC.mixins, hasLength(1));
     assertType(classC.mixins[0], 'M<B>');
@@ -2095,7 +2095,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 93, 1),
       error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 97, 1),
     ]);
-    var z = result.unit!.declaredElement!.topLevelVariables
+    var z = result.unit.declaredElement!.topLevelVariables
         .where((e) => e.name == 'z')
         .single;
     assertType(z.type, 'List<String>');
@@ -2275,7 +2275,7 @@
 class B<T> = Object with A<T>;
 class C = Object with B;
 ''');
-    var bReference = result.unit!.declaredElement!.getType('C')!.mixins[0];
+    var bReference = result.unit.declaredElement!.getType('C')!.mixins[0];
     assertTypeDynamic(bReference.typeArguments[0]);
   }
 
@@ -2294,7 +2294,7 @@
 ''', [
       error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 122, 1),
     ]);
-    var bReference = result.unit!.declaredElement!.getType('C')!.mixins[0];
+    var bReference = result.unit.declaredElement!.getType('C')!.mixins[0];
     assertType(bReference.typeArguments[0], 'int');
   }
 
@@ -2333,7 +2333,7 @@
   x;
 }
 ''');
-    var main = result.unit!.declarations.last as FunctionDeclaration;
+    var main = result.unit.declarations.last as FunctionDeclaration;
     var mainBody = main.functionExpression.body as BlockFunctionBody;
     var xDecl = mainBody.block.statements[0] as VariableDeclarationStatement;
     var xElem = xDecl.variables.variables[0].declaredElement!;
@@ -2804,8 +2804,8 @@
 @B.named8()
 main() {}
 ''');
-    expect(result.unit!.declarations, hasLength(1));
-    final mainDecl = result.unit!.declarations[0];
+    expect(result.unit.declarations, hasLength(1));
+    final mainDecl = result.unit.declarations[0];
     expect(mainDecl.metadata, hasLength(8));
     mainDecl.metadata.forEach((metadata) {
       final value = metadata.elementAnnotation!.computeConstantValue()!;
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index b0a30a2..254dea0 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -1264,7 +1264,7 @@
   /// Verify that all of the identifiers in the [result] have been resolved.
   void verifyTestResolved() {
     var verifier = ResolutionVerifier();
-    result.unit!.accept(verifier);
+    result.unit.accept(verifier);
     verifier.assertResolved();
   }
 
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index aa67fe2..e724509 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -59,7 +59,7 @@
 
   late final AsserterBuilder<Element, DartType> _hasElement;
 
-  CompilationUnit get unit => result.unit!;
+  CompilationUnit get unit => result.unit;
 
   @override
   Future<void> resolveTestFile() async {
@@ -2404,7 +2404,7 @@
 }
 ''');
 
-    var b = result.unit!.declarations[1] as ClassDeclaration;
+    var b = result.unit.declarations[1] as ClassDeclaration;
     var bConstructor = b.members[0] as ConstructorDeclaration;
     var redirected = bConstructor.redirectedConstructor as ConstructorName;
 
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index 589c79a..b6d2157 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -5,13 +5,11 @@
 import 'package:analyzer/dart/analysis/utilities.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/src/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -19,7 +17,6 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(BooleanArrayTest);
-    defineReflectiveTests(ExceptionHandlingDelegatingAstVisitorTest);
     defineReflectiveTests(LineInfoTest);
     defineReflectiveTests(NodeReplacerTest);
     defineReflectiveTests(SourceRangeTest);
@@ -116,23 +113,6 @@
   }
 }
 
-@reflectiveTest
-class ExceptionHandlingDelegatingAstVisitorTest {
-  void test_handlerIsCalled() {
-    AstVisitor exceptionThrowingVisitor = _ExceptionThrowingVisitor();
-    bool handlerInvoked = false;
-    AstVisitor visitor = ExceptionHandlingDelegatingAstVisitor(
-        [exceptionThrowingVisitor], (AstNode node, AstVisitor visitor,
-            dynamic exception, StackTrace stackTrace) {
-      handlerInvoked = true;
-    });
-    astFactory
-        .nullLiteral(TokenFactory.tokenFromKeyword(Keyword.NULL))
-        .accept(visitor);
-    expect(handlerInvoked, isTrue);
-  }
-}
-
 class Getter_NodeReplacerTest_test_annotation
     implements NodeReplacerTest_Getter<Annotation, ArgumentList> {
   @override
@@ -2740,10 +2720,3 @@
     expect(StringUtilities.substringBeforeChar("abc", 0x64), "abc");
   }
 }
-
-class _ExceptionThrowingVisitor extends SimpleAstVisitor {
-  @override
-  visitNullLiteral(NullLiteral node) {
-    throw ArgumentError('');
-  }
-}
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index e439283..66c9590 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -4,22 +4,6 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/builder.dart';
-import 'package:analyzer/src/context/context_root.dart';
-import 'package:analyzer/src/context/packages.dart';
-import 'package:analyzer/src/context/source.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/source/package_map_resolver.dart';
-import 'package:analyzer/src/test_utilities/mock_sdk.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-import 'package:analyzer/src/workspace/basic.dart';
-import 'package:analyzer/src/workspace/bazel.dart';
-import 'package:analyzer/src/workspace/gn.dart';
-import 'package:analyzer/src/workspace/package_build.dart';
-import 'package:analyzer/src/workspace/pub.dart';
-import 'package:analyzer/src/workspace/workspace.dart';
-import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -27,461 +11,11 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ContextBuilderTest);
     defineReflectiveTests(EmbedderYamlLocatorTest);
   });
 }
 
 @reflectiveTest
-class ContextBuilderTest with ResourceProviderMixin {
-  /// The SDK manager used by the tests;
-  late final DartSdkManager sdkManager;
-
-  /// The options passed to the context builder.
-  ContextBuilderOptions builderOptions = ContextBuilderOptions();
-
-  /// The context builder to be used in the test.
-  late ContextBuilder builder;
-
-  /// The path to the default SDK, or `null` if the test has not explicitly
-  /// invoked [createDefaultSdk].
-  late final String defaultSdkPath;
-
-  Uri convertedDirectoryUri(String directoryPath) {
-    return Uri.directory(convertPath(directoryPath),
-        windows: resourceProvider.pathContext.style == path.windows.style);
-  }
-
-  void createDefaultSdk() {
-    defaultSdkPath = convertPath(sdkRoot);
-    MockSdk(resourceProvider: resourceProvider);
-  }
-
-  void setUp() {
-    MockSdk(resourceProvider: resourceProvider);
-    sdkManager = DartSdkManager(convertPath('/sdk'));
-    builder = ContextBuilder(
-      resourceProvider,
-      sdkManager,
-      options: builderOptions,
-    );
-  }
-
-  @failingTest
-  void test_buildContext() {
-    fail('Incomplete test');
-  }
-
-  @failingTest
-  void test_cmdline_options_override_options_file() {
-    fail('No clear choice of option to override.');
-//    ArgParser argParser = new ArgParser();
-//    defineAnalysisArguments(argParser);
-//    ArgResults argResults = argParser.parse(['--$enableSuperMixinFlag']);
-//    var builder = new ContextBuilder(resourceProvider, sdkManager, contentCache,
-//        options: createContextBuilderOptions(argResults));
-//
-//    AnalysisOptionsImpl expected = new AnalysisOptionsImpl();
-//    expected.option = true;
-//
-//    String path = resourceProvider.convertPath('/some/directory/path');
-//    String filePath =
-//        join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
-//    resourceProvider.newFile(filePath, '''
-//analyzer:
-//  language:
-//    option: true
-//''');
-//
-//    AnalysisOptions options = builder.getAnalysisOptions(path);
-//    _expectEqualOptions(options, expected);
-  }
-
-  void test_createPackageMap_fromPackageFile_explicit() {
-    // Use a package file that is outside the project directory's hierarchy.
-    String rootPath = convertPath('/root');
-    String projectPath = join(rootPath, 'project');
-    String packageFilePath = join(rootPath, 'child', '.packages');
-    newFolder(projectPath);
-    newFile(packageFilePath, content: '''
-foo:${toUriStr('/pkg/foo')}
-bar:${toUriStr('/pkg/bar')}
-''');
-
-    builderOptions.defaultPackageFilePath = packageFilePath;
-    Packages packages = _createPackageMap(projectPath);
-    _assertPackages(
-      packages,
-      {
-        'foo': convertPath('/pkg/foo'),
-        'bar': convertPath('/pkg/bar'),
-      },
-    );
-  }
-
-  void test_createPackageMap_fromPackageFile_inParentOfRoot() {
-    // Use a package file that is inside the parent of the project directory.
-    String rootPath = convertPath('/root');
-    String projectPath = join(rootPath, 'project');
-    String packageFilePath = join(rootPath, '.packages');
-    newFolder(projectPath);
-    newFile(packageFilePath, content: '''
-foo:${toUriStr('/pkg/foo')}
-bar:${toUriStr('/pkg/bar')}
-''');
-
-    Packages packages = _createPackageMap(projectPath);
-    _assertPackages(
-      packages,
-      {
-        'foo': convertPath('/pkg/foo'),
-        'bar': convertPath('/pkg/bar'),
-      },
-    );
-  }
-
-  void test_createPackageMap_fromPackageFile_inRoot() {
-    // Use a package file that is inside the project directory.
-    String rootPath = convertPath('/root');
-    String projectPath = join(rootPath, 'project');
-    String packageFilePath = join(projectPath, '.packages');
-    newFolder(projectPath);
-    newFile(packageFilePath, content: '''
-foo:${toUriStr('/pkg/foo')}
-bar:${toUriStr('/pkg/bar')}
-''');
-
-    Packages packages = _createPackageMap(projectPath);
-    _assertPackages(
-      packages,
-      {
-        'foo': convertPath('/pkg/foo'),
-        'bar': convertPath('/pkg/bar'),
-      },
-    );
-  }
-
-  void test_createPackageMap_none() {
-    String rootPath = convertPath('/root');
-    newFolder(rootPath);
-    Packages packages = _createPackageMap(rootPath);
-    expect(packages.packages, isEmpty);
-  }
-
-  void test_createPackageMap_rootDoesNotExist() {
-    String rootPath = convertPath('/root');
-    Packages packages = _createPackageMap(rootPath);
-    expect(packages.packages, isEmpty);
-  }
-
-  void test_createSourceFactory_bazelWorkspace_fileProvider() {
-    String projectPath = convertPath('/workspace/my/module');
-    newFile('/workspace/WORKSPACE');
-    newFolder('/workspace/bazel-bin');
-    newFolder('/workspace/bazel-genfiles');
-    newFolder(projectPath);
-
-    var factory = _createSourceFactory(projectPath);
-    expect(factory.resolvers,
-        contains(predicate((r) => r is BazelFileUriResolver)));
-    expect(factory.resolvers,
-        contains(predicate((r) => r is BazelPackageUriResolver)));
-  }
-
-  void test_createSourceFactory_bazelWorkspace_withPackagesFile() {
-    String projectPath = convertPath('/workspace/my/module');
-    newFile('/workspace/WORKSPACE');
-    newFolder('/workspace/bazel-bin');
-    newFolder('/workspace/bazel-genfiles');
-    newFolder(projectPath);
-    newFile(join(projectPath, '.packages'));
-
-    var factory = _createSourceFactory(projectPath);
-    expect(factory.resolvers,
-        contains(predicate((r) => r is ResourceUriResolver)));
-    expect(factory.resolvers,
-        contains(predicate((r) => r is PackageMapUriResolver)));
-  }
-
-  void test_createSourceFactory_noProvider_packages_embedder_noExtensions() {
-    String rootPath = convertPath('/root');
-    createDefaultSdk();
-    String projectPath = join(rootPath, 'project');
-    String packageFilePath = join(projectPath, '.packages');
-
-    String skyEnginePath = join(rootPath, 'pkgs', 'sky_engine');
-    String embedderPath = join(skyEnginePath, '_embedder.yaml');
-    String asyncPath = join(skyEnginePath, 'sdk', 'async.dart');
-    String corePath = join(skyEnginePath, 'sdk', 'core.dart');
-    newFile(embedderPath, content: '''
-embedded_libs:
-  "dart:async": ${_relativeUri(asyncPath, from: skyEnginePath)}
-  "dart:core": ${_relativeUri(corePath, from: skyEnginePath)}
-''');
-
-    String packageB = join(rootPath, 'pkgs', 'b');
-    newFile(packageFilePath, content: '''
-sky_engine:${resourceProvider.pathContext.toUri(skyEnginePath)}
-b:${resourceProvider.pathContext.toUri(packageB)}
-''');
-
-    SourceFactory factory = _createSourceFactory(projectPath);
-
-    var dartSource = factory.forUri('dart:async')!;
-    expect(dartSource, isNotNull);
-    expect(dartSource.fullName, asyncPath);
-
-    var packageSource = factory.forUri('package:b/b.dart')!;
-    expect(packageSource, isNotNull);
-    expect(packageSource.fullName, join(packageB, 'b.dart'));
-  }
-
-  @failingTest
-  void test_createSourceFactory_noProvider_packages_noEmbedder_extensions() {
-    fail('Incomplete test');
-  }
-
-  void test_createSourceFactory_noProvider_packages_noEmbedder_noExtensions() {
-    String rootPath = convertPath('/root');
-    createDefaultSdk();
-    String projectPath = join(rootPath, 'project');
-    String packageFilePath = join(projectPath, '.packages');
-    String packageA = join(rootPath, 'pkgs', 'a');
-    String packageB = join(rootPath, 'pkgs', 'b');
-    newFile(packageFilePath, content: '''
-a:${resourceProvider.pathContext.toUri(packageA)}
-b:${resourceProvider.pathContext.toUri(packageB)}
-''');
-
-    SourceFactory factory = _createSourceFactory(projectPath);
-
-    var dartSource = factory.forUri('dart:core')!;
-    expect(dartSource, isNotNull);
-    expect(
-        dartSource.fullName, join(defaultSdkPath, 'lib', 'core', 'core.dart'));
-
-    var packageSource = factory.forUri('package:a/a.dart')!;
-    expect(packageSource, isNotNull);
-    expect(packageSource.fullName, join(packageA, 'a.dart'));
-  }
-
-  void test_createWorkspace_hasPackagesFile_hasDartToolAndPubspec() {
-    newDotPackagesFile('/workspace');
-    newFolder('/workspace/.dart_tool/build/generated/project/lib');
-    newPubspecYamlFile('/workspace', 'name: project');
-    Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
-    expect(workspace, TypeMatcher<PackageBuildWorkspace>());
-  }
-
-  void test_createWorkspace_hasPackagesFile_hasPubspec() {
-    newDotPackagesFile('/workspace');
-    newPubspecYamlFile('/workspace', 'name: project');
-    Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
-    expect(workspace, TypeMatcher<PubWorkspace>());
-  }
-
-  void test_createWorkspace_hasPackagesFile_noMarkerFiles() {
-    newDotPackagesFile('/workspace');
-    Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
-    expect(workspace, TypeMatcher<BasicWorkspace>());
-  }
-
-  void test_createWorkspace_noPackagesFile_hasBazelMarkerFiles() {
-    newFile('/workspace/WORKSPACE');
-    newFolder('/workspace/bazel-genfiles');
-    Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
-    expect(workspace, TypeMatcher<BazelWorkspace>());
-  }
-
-  void test_createWorkspace_noPackagesFile_hasDartToolAndPubspec() {
-    newFolder('/workspace/.dart_tool/build/generated/project/lib');
-    newPubspecYamlFile('/workspace', 'name: project');
-    Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
-    expect(workspace, TypeMatcher<PackageBuildWorkspace>());
-  }
-
-  void test_createWorkspace_noPackagesFile_hasGnMarkerFiles() {
-    newFolder('/workspace/.jiri_root');
-    newFile(
-        '/workspace/out/debug-x87_128/dartlang/gen/project/lib/lib_package_config.json',
-        content: '''{
-  "configVersion": 2,
-  "packages": []
-}''');
-    Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
-    expect(workspace, TypeMatcher<GnWorkspace>());
-  }
-
-  void test_createWorkspace_noPackagesFile_hasPubspec() {
-    newPubspecYamlFile('/workspace', 'name: project');
-    Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
-    expect(workspace, TypeMatcher<PubWorkspace>());
-  }
-
-  void test_createWorkspace_noPackagesFile_noMarkerFiles() {
-    Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
-    expect(workspace, TypeMatcher<BasicWorkspace>());
-  }
-
-  @failingTest
-  void test_findSdk_embedder_extensions() {
-    // See test_createSourceFactory_noProvider_packages_embedder_extensions
-    fail('Incomplete test');
-  }
-
-  @failingTest
-  void test_findSdk_embedder_noExtensions() {
-    // See test_createSourceFactory_noProvider_packages_embedder_noExtensions
-    fail('Incomplete test');
-  }
-
-  @failingTest
-  void test_findSdk_noEmbedder_extensions() {
-    // See test_createSourceFactory_noProvider_packages_noEmbedder_extensions
-    fail('Incomplete test');
-  }
-
-  @failingTest
-  void test_findSdk_noEmbedder_noExtensions() {
-    // See test_createSourceFactory_noProvider_packages_noEmbedder_noExtensions
-    fail('Incomplete test');
-  }
-
-  void test_findSdk_noPackageMap() {
-    DartSdk sdk = builder.findSdk(null);
-    expect(sdk, isNotNull);
-  }
-
-  void test_findSdk_noPackageMap_html_strong() {
-    DartSdk sdk = builder.findSdk(null);
-    expect(sdk, isNotNull);
-    Source htmlSource = sdk.mapDartUri('dart:html')!;
-    expect(htmlSource.fullName,
-        convertPath('/sdk/lib/html/dart2js/html_dart2js.dart'));
-    expect(htmlSource.exists(), isTrue);
-  }
-
-  void test_getAnalysisOptions_gnWorkspace() {
-    String projectPath = convertPath('/workspace/some/path');
-    newFolder('/workspace/.jiri_root');
-    newFile('/workspace/out/debug/gen/dart.sources/foo_pkg',
-        content: convertPath('/workspace/foo_pkg/lib'));
-    newFolder(projectPath);
-    builder =
-        ContextBuilder(resourceProvider, sdkManager, options: builderOptions);
-    AnalysisOptionsImpl expected = AnalysisOptionsImpl();
-    var options = _getAnalysisOptions(builder, projectPath);
-    _expectEqualOptions(options, expected);
-  }
-
-  void test_getAnalysisOptions_invalid() {
-    String path = convertPath('/some/directory/path');
-    newAnalysisOptionsYamlFile(path, content: ';');
-
-    AnalysisOptions options = _getAnalysisOptions(builder, path);
-    expect(options, isNotNull);
-  }
-
-  void test_getAnalysisOptions_noDefault_noOverrides() {
-    String path = convertPath('/some/directory/path');
-    newAnalysisOptionsYamlFile(path, content: '''
-linter:
-  rules:
-    - non_existent_lint_rule
-''');
-
-    var options = _getAnalysisOptions(builder, path);
-    _expectEqualOptions(options, AnalysisOptionsImpl());
-  }
-
-  void test_getAnalysisOptions_sdkVersionConstraint() {
-    var projectPath = convertPath('/test');
-    newPubspecYamlFile(projectPath, '''
-environment:
-  sdk: ^2.1.0
-''');
-
-    var options = _getAnalysisOptions(builder, projectPath);
-    expect(options.sdkVersionConstraint.toString(), '^2.1.0');
-  }
-
-  void test_getAnalysisOptions_sdkVersionConstraint_any_noOptionsFile() {
-    var projectPath = convertPath('/test');
-    var options = _getAnalysisOptions(builder, projectPath);
-    expect(options.sdkVersionConstraint, isNull);
-  }
-
-  void _assertPackages(Packages packages, Map<String, String> nameToPath) {
-    expect(packages, isNotNull);
-    expect(packages.packages, hasLength(nameToPath.length));
-    for (var name in nameToPath.keys) {
-      var expectedPath = nameToPath[name];
-      var path = packages[name]!.libFolder.path;
-      expect(path, expectedPath, reason: 'package $name');
-    }
-  }
-
-  Packages _createPackageMap(String rootPath) {
-    return ContextBuilder.createPackageMap(
-      resourceProvider: resourceProvider,
-      options: builderOptions,
-      rootPath: rootPath,
-    );
-  }
-
-  SourceFactoryImpl _createSourceFactory(String projectPath) {
-    Workspace workspace = ContextBuilder.createWorkspace(
-      resourceProvider: resourceProvider,
-      options: builderOptions,
-      rootPath: projectPath,
-    );
-    return builder.createSourceFactory(projectPath, workspace)
-        as SourceFactoryImpl;
-  }
-
-  Workspace _createWorkspace(String posixPath) {
-    return ContextBuilder.createWorkspace(
-      resourceProvider: resourceProvider,
-      options: ContextBuilderOptions(),
-      rootPath: convertPath(posixPath),
-    );
-  }
-
-  void _expectEqualOptions(
-      AnalysisOptionsImpl actual, AnalysisOptionsImpl expected) {
-    // TODO(brianwilkerson) Consider moving this to AnalysisOptionsImpl.==.
-    expect(actual.enableTiming, expected.enableTiming);
-    expect(actual.hint, expected.hint);
-    expect(actual.lint, expected.lint);
-    expect(
-      actual.lintRules.map((l) => l.name),
-      unorderedEquals(expected.lintRules.map((l) => l.name)),
-    );
-    expect(actual.implicitCasts, expected.implicitCasts);
-    expect(actual.implicitDynamic, expected.implicitDynamic);
-    expect(actual.strictInference, expected.strictInference);
-    expect(actual.strictRawTypes, expected.strictRawTypes);
-  }
-
-  AnalysisOptionsImpl _getAnalysisOptions(ContextBuilder builder, String path,
-      {ContextRoot? contextRoot}) {
-    Workspace workspace = ContextBuilder.createWorkspace(
-      resourceProvider: resourceProvider,
-      options: builder.builderOptions,
-      rootPath: path,
-    );
-    return builder.getAnalysisOptions(path, workspace,
-        contextRoot: contextRoot);
-  }
-
-  Uri _relativeUri(String path, {String? from}) {
-    var pathContext = resourceProvider.pathContext;
-    String relativePath = pathContext.relative(path, from: from);
-    return pathContext.toUri(relativePath);
-  }
-}
-
-@reflectiveTest
 class EmbedderYamlLocatorTest extends EmbedderRelatedTest {
   void test_empty() {
     EmbedderYamlLocator locator = EmbedderYamlLocator({
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index 542e7f8..1bb79b1 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -33,7 +33,7 @@
   late final AnalysisDriverScheduler scheduler;
   late final AnalysisDriver driver;
   final List<AnalysisStatus> allStatuses = <AnalysisStatus>[];
-  final List<ResolvedUnitResult> allResults = <ResolvedUnitResult>[];
+  final List<AnalysisResultWithErrors> allResults = [];
   final List<ExceptionResult> allExceptions = <ExceptionResult>[];
 
   late final String testProject;
@@ -141,7 +141,11 @@
     driver = createAnalysisDriver();
     scheduler.start();
     scheduler.status.listen(allStatuses.add);
-    driver.results.listen(allResults.add);
+    driver.results.listen((result) {
+      if (result is AnalysisResultWithErrors) {
+        allResults.add(result);
+      }
+    });
     driver.exceptions.listen(allExceptions.add);
   }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
index af27464..44a7634 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
@@ -5,14 +5,25 @@
 import 'package:analyzer/dart/analysis/analysis_context.dart';
 import 'package:analyzer/dart/analysis/context_root.dart';
 import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/dart/analysis/context_builder.dart';
+import 'package:analyzer/src/dart/analysis/context_locator.dart';
 import 'package:analyzer/src/dart/analysis/context_root.dart';
+import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer/src/workspace/basic.dart';
+import 'package:analyzer/src/workspace/bazel.dart';
+import 'package:analyzer/src/workspace/pub.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../resolution/context_collection_resolution.dart';
+
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ContextBuilderImplTest);
@@ -40,6 +51,61 @@
     contextRoot = ContextRootImpl(resourceProvider, folder, workspace);
   }
 
+  void test_analysisOptions_invalid() {
+    MockSdk(resourceProvider: resourceProvider);
+
+    var projectPath = convertPath('/home/test');
+    newAnalysisOptionsYamlFile(projectPath, content: ';');
+
+    var analysisContext = _createSingleAnalysisContext(projectPath);
+    var analysisOptions = analysisContext.analysisOptionsImpl;
+    _expectEqualOptions(analysisOptions, AnalysisOptionsImpl());
+  }
+
+  void test_analysisOptions_languageOptions() {
+    MockSdk(resourceProvider: resourceProvider);
+
+    var projectPath = convertPath('/home/test');
+    newAnalysisOptionsYamlFile(
+      projectPath,
+      content: AnalysisOptionsFileConfig(
+        strictRawTypes: true,
+      ).toContent(),
+    );
+
+    var analysisContext = _createSingleAnalysisContext(projectPath);
+    var analysisOptions = analysisContext.analysisOptionsImpl;
+    _expectEqualOptions(
+      analysisOptions,
+      AnalysisOptionsImpl()..strictRawTypes = true,
+    );
+  }
+
+  void test_analysisOptions_sdkVersionConstraint_hasPubspec_hasSdk() {
+    MockSdk(resourceProvider: resourceProvider);
+
+    var projectPath = convertPath('/home/test');
+    newPubspecYamlFile(projectPath, '''
+environment:
+  sdk: ^2.1.0
+''');
+
+    var analysisContext = _createSingleAnalysisContext(projectPath);
+    var analysisOptions = analysisContext.analysisOptionsImpl;
+    expect(analysisOptions.sdkVersionConstraint.toString(), '^2.1.0');
+  }
+
+  void test_analysisOptions_sdkVersionConstraint_noPubspec() {
+    MockSdk(resourceProvider: resourceProvider);
+
+    var projectPath = convertPath('/home/test');
+    newFile('$projectPath/lib/a.dart');
+
+    var analysisContext = _createSingleAnalysisContext(projectPath);
+    var analysisOptions = analysisContext.driver.analysisOptions;
+    expect(analysisOptions.sdkVersionConstraint, isNull);
+  }
+
   test_createContext_declaredVariables() {
     MockSdk(resourceProvider: resourceProvider);
     DeclaredVariables declaredVariables =
@@ -101,4 +167,88 @@
     expect(context.contextRoot, contextRoot);
     expect(context.sdkRoot?.path, resourceProvider.convertPath(sdkRoot));
   }
+
+  void test_sourceFactory_bazelWorkspace() {
+    MockSdk(resourceProvider: resourceProvider);
+
+    var projectPath = convertPath('/workspace/my/module');
+    newFile('/workspace/WORKSPACE');
+    newFolder('/workspace/bazel-bin');
+    newFolder('/workspace/bazel-genfiles');
+
+    var analysisContext = _createSingleAnalysisContext(projectPath);
+    expect(analysisContext.contextRoot.workspace, isA<BazelWorkspace>());
+
+    expect(
+      analysisContext.uriResolvers,
+      unorderedEquals([
+        isA<DartUriResolver>(),
+        isA<BazelPackageUriResolver>(),
+        isA<BazelFileUriResolver>(),
+      ]),
+    );
+  }
+
+  void test_sourceFactory_pubWorkspace() {
+    MockSdk(resourceProvider: resourceProvider);
+
+    var projectPath = convertPath('/home/my');
+    newFile('/home/my/pubspec.yaml');
+
+    var analysisContext = _createSingleAnalysisContext(projectPath);
+    expect(analysisContext.contextRoot.workspace, isA<PubWorkspace>());
+
+    expect(
+      analysisContext.uriResolvers,
+      unorderedEquals([
+        isA<DartUriResolver>(),
+        isA<PackageMapUriResolver>(),
+        isA<ResourceUriResolver>(),
+      ]),
+    );
+  }
+
+  /// Return a single expected analysis context at the [path].
+  DriverBasedAnalysisContext _createSingleAnalysisContext(String path) {
+    var roots = ContextLocatorImpl(
+      resourceProvider: resourceProvider,
+    ).locateRoots(includedPaths: [path]);
+
+    return ContextBuilderImpl(
+      resourceProvider: resourceProvider,
+    ).createContext(
+      contextRoot: roots.single,
+      sdkPath: convertPath(sdkRoot),
+    );
+  }
+
+  static void _expectEqualOptions(
+    AnalysisOptionsImpl actual,
+    AnalysisOptionsImpl expected,
+  ) {
+    // TODO(brianwilkerson) Consider moving this to AnalysisOptionsImpl.==.
+    expect(actual.enableTiming, expected.enableTiming);
+    expect(actual.hint, expected.hint);
+    expect(actual.lint, expected.lint);
+    expect(
+      actual.lintRules.map((l) => l.name),
+      unorderedEquals(expected.lintRules.map((l) => l.name)),
+    );
+    expect(actual.implicitCasts, expected.implicitCasts);
+    expect(actual.implicitDynamic, expected.implicitDynamic);
+    expect(
+        actual.propagateLinterExceptions, expected.propagateLinterExceptions);
+    expect(actual.strictInference, expected.strictInference);
+    expect(actual.strictRawTypes, expected.strictRawTypes);
+  }
+}
+
+extension on DriverBasedAnalysisContext {
+  AnalysisOptionsImpl get analysisOptionsImpl {
+    return driver.analysisOptions as AnalysisOptionsImpl;
+  }
+
+  List<UriResolver> get uriResolvers {
+    return (driver.sourceFactory as SourceFactoryImpl).resolvers;
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/analysis/dependency/base.dart b/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
index 6570844..0c2aefa 100644
--- a/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
@@ -138,9 +138,9 @@
 
   Future<List<CompilationUnit>> _resolveLibrary(String libraryPath) async {
     var session = contextFor(libraryPath).currentSession;
-    var resolvedLibrary = await session.getResolvedLibrary2(libraryPath);
+    var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
     resolvedLibrary as ResolvedLibraryResult;
-    return resolvedLibrary.units!.map((ru) => ru.unit!).toList();
+    return resolvedLibrary.units.map((ru) => ru.unit).toList();
   }
 }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
index 300536e..230b7cd 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
@@ -276,7 +276,7 @@
     var testFilePathConverted = convertPath(testFilePath);
     var errorsResult = await contextFor(testFilePathConverted)
         .currentSession
-        .getErrors2(testFilePathConverted) as ErrorsResult;
+        .getErrors(testFilePathConverted) as ErrorsResult;
     return errorsResult.errors;
   }
 }
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 5853f91..9fe7223 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -143,7 +143,7 @@
     await resolveTestFile();
 
     var myDeclaration =
-        result.unit!.declarations[0] as TopLevelVariableDeclaration;
+        result.unit.declarations[0] as TopLevelVariableDeclaration;
     var myVariable = myDeclaration.variables.variables[0];
     var myElement = myVariable.declaredElement as TopLevelVariableElement;
 
@@ -157,7 +157,7 @@
     }
 
     {
-      var classNode = result.unit!.declarations[1] as ClassDeclaration;
+      var classNode = result.unit.declarations[1] as ClassDeclaration;
       assertMyAnnotation(classNode);
 
       {
@@ -177,12 +177,12 @@
     }
 
     {
-      var node = result.unit!.declarations[2] as TopLevelVariableDeclaration;
+      var node = result.unit.declarations[2] as TopLevelVariableDeclaration;
       assertMyAnnotation(node);
     }
 
     {
-      var node = result.unit!.declarations[3] as FunctionDeclaration;
+      var node = result.unit.declarations[3] as FunctionDeclaration;
       assertMyAnnotation(node);
     }
   }
@@ -346,11 +346,11 @@
 
     await resolveTestFile();
 
-    var c = result.unit!.declarations[0] as ClassDeclaration;
+    var c = result.unit.declarations[0] as ClassDeclaration;
     var constructor = c.members[1] as ConstructorDeclaration;
     ConstructorElement element = constructor.declaredElement!;
 
-    var main = result.unit!.declarations[1] as FunctionDeclaration;
+    var main = result.unit.declarations[1] as FunctionDeclaration;
     var statement = (main.functionExpression.body as BlockFunctionBody)
         .block
         .statements[0] as VariableDeclarationStatement;
@@ -377,11 +377,11 @@
     await resolveTestFile();
 
     var myDeclaration =
-        result.unit!.declarations[0] as TopLevelVariableDeclaration;
+        result.unit.declarations[0] as TopLevelVariableDeclaration;
     VariableDeclaration myVariable = myDeclaration.variables.variables[0];
     var myElement = myVariable.declaredElement as TopLevelVariableElement;
 
-    var classNode = result.unit!.declarations[1] as ClassDeclaration;
+    var classNode = result.unit.declarations[1] as ClassDeclaration;
     var node = classNode.members[0] as MethodDeclaration;
     var statement = (node.body as BlockFunctionBody).block.statements[0]
         as VariableDeclarationStatement;
@@ -406,7 +406,7 @@
 main() {}
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     ImportElement aImport = unit.declaredElement!.library.imports[0];
     PrefixElement aPrefix = aImport.prefix!;
@@ -445,7 +445,7 @@
 main() {}
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     ImportElement aImport = unit.declaredElement!.library.imports[0];
     PrefixElement aPrefix = aImport.prefix!;
@@ -486,7 +486,7 @@
 main() {}
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     ImportElement aImport = unit.declaredElement!.library.imports[0];
     PrefixElement aPrefix = aImport.prefix!;
@@ -527,7 +527,7 @@
 main() {}
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     ImportElement aImport = unit.declaredElement!.library.imports[0];
     PrefixElement aPrefix = aImport.prefix!;
@@ -560,7 +560,7 @@
 }
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     CompilationUnitElement unitElement = unit.declaredElement!;
 
     ClassElement aClass = unitElement.getType('A')!;
@@ -590,7 +590,7 @@
 }
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     CompilationUnitElement unitElement = unit.declaredElement!;
 
     ClassElement aClass = unitElement.getType('A')!;
@@ -620,7 +620,7 @@
 }
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     CompilationUnitElement unitElement = unit.declaredElement!;
 
     ClassElement aClass = unitElement.getType('A')!;
@@ -657,11 +657,11 @@
 f() {}
 ''');
     await resolveTestFile();
-    var elementC = AstFinder.getClass(result.unit!, 'C').declaredElement!;
+    var elementC = AstFinder.getClass(result.unit, 'C').declaredElement!;
     var constructorC = elementC.constructors[0];
-    var elementD = AstFinder.getClass(result.unit!, 'D').declaredElement!;
+    var elementD = AstFinder.getClass(result.unit, 'D').declaredElement!;
     var constructorD = elementD.constructors[0];
-    var atD = AstFinder.getTopLevelFunction(result.unit!, 'f').metadata[0];
+    var atD = AstFinder.getTopLevelFunction(result.unit, 'f').metadata[0];
     var constC = atD.arguments!.arguments[0] as InstanceCreationExpression;
 
     expect(atD.name.staticElement, elementD);
@@ -689,16 +689,16 @@
     await resolveTestFile();
 
     var declaration_1 =
-        result.unit!.declarations[0] as TopLevelVariableDeclaration;
+        result.unit.declarations[0] as TopLevelVariableDeclaration;
     VariableDeclaration variable_1 = declaration_1.variables.variables[0];
     var element_1 = variable_1.declaredElement as TopLevelVariableElement;
 
     var declaration_2 =
-        result.unit!.declarations[1] as TopLevelVariableDeclaration;
+        result.unit.declarations[1] as TopLevelVariableDeclaration;
     VariableDeclaration variable_2 = declaration_2.variables.variables[0];
     var element_2 = variable_2.declaredElement as TopLevelVariableElement;
 
-    var main = result.unit!.declarations[2] as FunctionDeclaration;
+    var main = result.unit.declarations[2] as FunctionDeclaration;
 
     Annotation annotation_1 = main.metadata[0];
     expect(annotation_1.element, same(element_1.getter));
@@ -959,7 +959,7 @@
 ''');
     await resolveTestFile();
 
-    var mainDeclaration = result.unit!.declarations[0] as FunctionDeclaration;
+    var mainDeclaration = result.unit.declarations[0] as FunctionDeclaration;
     var mainElement = mainDeclaration.declaredElement as FunctionElement;
     var mainBody = mainDeclaration.functionExpression.body as BlockFunctionBody;
     List<Statement> mainStatements = mainBody.block.statements;
@@ -1090,7 +1090,7 @@
 }
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var c = unit.declarations[0] as ClassDeclaration;
     var declaration = c.members[0] as FieldDeclaration;
@@ -1107,7 +1107,7 @@
 var v = (() => 42)();
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
     VariableDeclaration variable = declaration.variables.variables[0];
@@ -1164,7 +1164,7 @@
 ''');
     await resolveTestFile();
 
-    var cNode = result.unit!.declarations[0] as ClassDeclaration;
+    var cNode = result.unit.declarations[0] as ClassDeclaration;
 
     var constructorNode = cNode.members[0] as ConstructorDeclaration;
     ParameterElement pElement = constructorNode.declaredElement!.parameters[0];
@@ -1188,7 +1188,7 @@
 ''');
     await resolveTestFile();
 
-    var cNode = result.unit!.declarations[0] as ClassDeclaration;
+    var cNode = result.unit.declarations[0] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
     FieldElement fElement = cElement.getField('f')!;
 
@@ -1219,10 +1219,10 @@
 ''');
     await resolveTestFile();
 
-    var aNode = result.unit!.declarations[0] as ClassDeclaration;
+    var aNode = result.unit.declarations[0] as ClassDeclaration;
     ClassElement aElement = aNode.declaredElement!;
 
-    var bNode = result.unit!.declarations[1] as ClassDeclaration;
+    var bNode = result.unit.declarations[1] as ClassDeclaration;
 
     {
       var constructor = bNode.members[0] as ConstructorDeclaration;
@@ -1261,7 +1261,7 @@
 ''');
     await resolveTestFile();
 
-    var cNode = result.unit!.declarations[0] as ClassDeclaration;
+    var cNode = result.unit.declarations[0] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
 
     {
@@ -1312,10 +1312,10 @@
     await resolveTestFile();
     expect(result.errors, isEmpty);
 
-    var aNode = result.unit!.declarations[0] as ClassDeclaration;
+    var aNode = result.unit.declarations[0] as ClassDeclaration;
     ClassElement aElement = aNode.declaredElement!;
 
-    var bNode = result.unit!.declarations[1] as ClassDeclaration;
+    var bNode = result.unit.declarations[1] as ClassDeclaration;
 
     {
       ConstructorElement aUnnamed = aElement.constructors[0];
@@ -1373,10 +1373,10 @@
     await resolveTestFile();
     expect(result.errors, isEmpty);
 
-    var aNode = result.unit!.declarations[0] as ClassDeclaration;
+    var aNode = result.unit.declarations[0] as ClassDeclaration;
     ClassElement aElement = aNode.declaredElement!;
 
-    var bNode = result.unit!.declarations[1] as ClassDeclaration;
+    var bNode = result.unit.declarations[1] as ClassDeclaration;
     TypeParameterType uType =
         typeParameterTypeNone(bNode.declaredElement!.typeParameters[0]);
     InterfaceType auType = aElement.instantiate(
@@ -1714,7 +1714,7 @@
 ''');
     await resolveTestFile();
 
-    var enumNode = result.unit!.declarations[0] as EnumDeclaration;
+    var enumNode = result.unit.declarations[0] as EnumDeclaration;
     ClassElement enumElement = enumNode.declaredElement!;
 
     List<Statement> mainStatements = _getMainStatements(result);
@@ -1758,7 +1758,7 @@
 ''');
     await resolveTestFile();
 
-    var cNode = result.unit!.declarations[0] as ClassDeclaration;
+    var cNode = result.unit.declarations[0] as ClassDeclaration;
     var tElement = cNode.declaredElement!.typeParameters[0];
 
     var fDeclaration = cNode.members[0] as FieldDeclaration;
@@ -1806,7 +1806,7 @@
 ''');
     await resolveTestFile();
 
-    var clazz = result.unit!.declarations[0] as ClassDeclaration;
+    var clazz = result.unit.declarations[0] as ClassDeclaration;
     var constructor = clazz.members[0] as ConstructorDeclaration;
     List<FormalParameter> parameters = constructor.parameters.parameters;
 
@@ -1841,7 +1841,7 @@
 ''');
     await resolveTestFile();
 
-    var clazz = result.unit!.declarations[0] as ClassDeclaration;
+    var clazz = result.unit.declarations[0] as ClassDeclaration;
 
     var fDeclaration = clazz.members[0] as FieldDeclaration;
     VariableDeclaration fNode = fDeclaration.fields.variables[0];
@@ -1886,7 +1886,7 @@
 ''');
     await resolveTestFile();
 
-    var clazz = result.unit!.declarations[0] as ClassDeclaration;
+    var clazz = result.unit.declarations[0] as ClassDeclaration;
 
     var fDeclaration = clazz.members[0] as FieldDeclaration;
     VariableDeclaration fNode = fDeclaration.fields.variables[0];
@@ -1916,7 +1916,7 @@
 ''');
     await resolveTestFile();
 
-    var clazz = result.unit!.declarations[0] as ClassDeclaration;
+    var clazz = result.unit.declarations[0] as ClassDeclaration;
 
     var fDeclaration = clazz.members[0] as FieldDeclaration;
     VariableDeclaration fNode = fDeclaration.fields.variables[0];
@@ -2078,7 +2078,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var cNode = unit.declarations[0] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
@@ -2131,7 +2131,7 @@
 ''');
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var xNode = unit.declarations[0] as ClassDeclaration;
     ClassElement xElement = xNode.declaredElement!;
@@ -2172,7 +2172,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var cNode = unit.declarations[0] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
@@ -2239,7 +2239,7 @@
 }
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     ImportElement aImport = unit.declaredElement!.library.imports[0];
     LibraryElement aLibrary = aImport.importedLibrary!;
@@ -2356,7 +2356,7 @@
 }
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     CompilationUnitElement unitElement = unit.declaredElement!;
 
     ClassElement cElement = unitElement.getType('C')!;
@@ -4342,7 +4342,7 @@
 }
 ''');
 
-    var main = result.unit!.declarations[0] as FunctionDeclaration;
+    var main = result.unit.declarations[0] as FunctionDeclaration;
     List<Statement> statements = _getMainStatements(result);
 
     // (int p)
@@ -4735,7 +4735,7 @@
 
     InterfaceType intType = typeProvider.intType;
 
-    var main = result.unit!.declarations[0] as FunctionDeclaration;
+    var main = result.unit.declarations[0] as FunctionDeclaration;
     expect(main.declaredElement, isNotNull);
     expect(main.name.staticElement, isNotNull);
     expect(main.name.staticType, isNull);
@@ -4778,7 +4778,7 @@
 }
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var cDeclaration = unit.declarations[0] as ClassDeclaration;
 
@@ -4849,7 +4849,7 @@
 num v;
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     List<Statement> statements = _getMainStatements(result);
 
@@ -5089,7 +5089,7 @@
     String fTypeString = 'double Function(int, {String b, bool c})';
 
     await resolveTestFile();
-    var classDeclaration = result.unit!.declarations[0] as ClassDeclaration;
+    var classDeclaration = result.unit.declarations[0] as ClassDeclaration;
     var methodDeclaration = classDeclaration.members[0] as MethodDeclaration;
     var methodElement = methodDeclaration.declaredElement as MethodElement;
 
@@ -5134,7 +5134,7 @@
     // Validate the arguments at the call site.
     //
     var functionDeclaration =
-        result.unit!.declarations[1] as FunctionDeclaration;
+        result.unit.declarations[1] as FunctionDeclaration;
     var body = functionDeclaration.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
     var invocation = statement.expression as MethodInvocation;
@@ -5157,7 +5157,7 @@
     await resolveTestFile();
     expect(result.errors, isEmpty);
 
-    var cNode = result.unit!.declarations[0] as ClassDeclaration;
+    var cNode = result.unit.declarations[0] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
     MethodElement callElement = cElement.methods[0];
 
@@ -5183,7 +5183,7 @@
     await resolveTestFile();
     expect(result.errors, isEmpty);
 
-    var main = result.unit!.declarations[0] as FunctionDeclaration;
+    var main = result.unit.declarations[0] as FunctionDeclaration;
     var mainElement = main.declaredElement as FunctionElement;
     ParameterElement parameter = mainElement.parameters[0];
 
@@ -5220,7 +5220,7 @@
 ''');
     await resolveTestFile();
 
-    var aNode = result.unit!.declarations[0] as ClassDeclaration;
+    var aNode = result.unit.declarations[0] as ClassDeclaration;
     var fooNode = aNode.members[0] as MethodDeclaration;
     var fooElement = fooNode.declaredElement as MethodElement;
 
@@ -5305,7 +5305,7 @@
     await resolveTestFile();
     List<Statement> mainStatements = _getMainStatements(result);
 
-    var foo = result.unit!.declarations[1] as FunctionDeclaration;
+    var foo = result.unit.declarations[1] as FunctionDeclaration;
     ExecutableElement fooElement = foo.declaredElement!;
 
     var statement = mainStatements[0] as ExpressionStatement;
@@ -5452,7 +5452,7 @@
     await resolveTestFile();
     List<Statement> mainStatements = _getMainStatements(result);
 
-    var cNode = result.unit!.declarations[1] as ClassDeclaration;
+    var cNode = result.unit.declarations[1] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
     var mNode = cNode.members[0] as MethodDeclaration;
     var mElement = mNode.declaredElement as MethodElement;
@@ -5509,7 +5509,7 @@
 ''');
     await resolveTestFile();
 
-    var cNode = result.unit!.declarations[0] as ClassDeclaration;
+    var cNode = result.unit.declarations[0] as ClassDeclaration;
     TypeParameterElement tElement = cNode.declaredElement!.typeParameters[0];
 
     var barNode = cNode.members[1] as MethodDeclaration;
@@ -5535,7 +5535,7 @@
 
     InterfaceType doubleType = typeProvider.doubleType;
 
-    var fNode = result.unit!.declarations[1] as FunctionDeclaration;
+    var fNode = result.unit.declarations[1] as FunctionDeclaration;
     var fElement = fNode.declaredElement as FunctionElement;
 
     var statement = mainStatements[0] as ExpressionStatement;
@@ -5564,7 +5564,7 @@
 
     List<Statement> mainStatements = _getMainStatements(result);
 
-    var fNode = result.unit!.declarations[1] as FunctionDeclaration;
+    var fNode = result.unit.declarations[1] as FunctionDeclaration;
     var fElement = fNode.declaredElement as FunctionElement;
 
     // f<bool, String>(true, 'str');
@@ -6030,7 +6030,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var cClassDeclaration = unit.declarations[1] as ClassDeclaration;
     ClassElement cClassElement = cClassDeclaration.declaredElement!;
@@ -6129,7 +6129,7 @@
 
     List<Statement> statements = _getMainStatements(result);
 
-    var cDeclaration = result.unit!.declarations[1] as ClassDeclaration;
+    var cDeclaration = result.unit.declarations[1] as ClassDeclaration;
     ClassElement cElement = cDeclaration.declaredElement!;
     FieldElement fElement = cElement.fields[0];
 
@@ -6164,7 +6164,7 @@
 
     List<Statement> statements = _getMainStatements(result);
 
-    var cDeclaration = result.unit!.declarations[1] as ClassDeclaration;
+    var cDeclaration = result.unit.declarations[1] as ClassDeclaration;
     ClassElement cElement = cDeclaration.declaredElement!;
     FieldElement fElement = cElement.fields[0];
 
@@ -6189,7 +6189,7 @@
     await resolveTestFile();
     expect(result.errors, isEmpty);
 
-    var main = result.unit!.declarations[0] as FunctionDeclaration;
+    var main = result.unit.declarations[0] as FunctionDeclaration;
     var mainElement = main.declaredElement as FunctionElement;
     ParameterElement parameter = mainElement.parameters[0];
 
@@ -6232,7 +6232,7 @@
     // TODO(scheglov) Uncomment and fix "unused imports" hint.
 //    expect(result.errors, isEmpty);
 
-    var unitElement = result.unit!.declaredElement!;
+    var unitElement = result.unit.declaredElement!;
     ImportElement myImport = unitElement.library.imports[0];
     PrefixElement myPrefix = myImport.prefix!;
 
@@ -6405,7 +6405,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var cClassDeclaration = unit.declarations[1] as ClassDeclaration;
     ClassElement cClassElement = cClassDeclaration.declaredElement!;
@@ -6467,7 +6467,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var cClassDeclaration = unit.declarations[1] as ClassDeclaration;
     ClassElement cClassElement = cClassDeclaration.declaredElement!;
@@ -6504,7 +6504,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var cClassDeclaration = unit.declarations[1] as ClassDeclaration;
     ClassElement cClassElement = cClassDeclaration.declaredElement!;
@@ -6571,7 +6571,7 @@
 }
 ''');
 
-    var main = result.unit!.declarations[0] as FunctionDeclaration;
+    var main = result.unit.declarations[0] as FunctionDeclaration;
     expect(main.declaredElement, isNotNull);
     expect(main.name.staticElement, isNotNull);
     expect(main.name.staticType, isNull);
@@ -6655,8 +6655,8 @@
     addTestFile(content);
     await resolveTestFile();
 
-    var aNode = result.unit!.declarations[0] as ClassDeclaration;
-    var bNode = result.unit!.declarations[1] as ClassDeclaration;
+    var aNode = result.unit.declarations[0] as ClassDeclaration;
+    var bNode = result.unit.declarations[1] as ClassDeclaration;
 
     var methodElement = aNode.members[0].declaredElement as MethodElement;
     var getterElement =
@@ -6784,7 +6784,7 @@
     addTestFile(content);
     await resolveTestFile();
 
-    var aNode = result.unit!.declarations[0] as ClassDeclaration;
+    var aNode = result.unit.declarations[0] as ClassDeclaration;
 
     var methodElement = aNode.members[0].declaredElement as MethodElement;
     var getterElement =
@@ -6900,7 +6900,7 @@
     addTestFile(content);
     await resolveTestFile();
 
-    var cNode = result.unit!.declarations[0] as ClassDeclaration;
+    var cNode = result.unit.declarations[0] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
 
     var constructorNode = cNode.members[1] as ConstructorDeclaration;
@@ -6945,16 +6945,16 @@
     addTestFile(content);
     await resolveTestFile();
 
-    var aNode = result.unit!.declarations[0] as ClassDeclaration;
+    var aNode = result.unit.declarations[0] as ClassDeclaration;
     ClassElement aElement = aNode.declaredElement!;
 
-    var bNode = result.unit!.declarations[1] as ClassDeclaration;
+    var bNode = result.unit.declarations[1] as ClassDeclaration;
     ClassElement bElement = bNode.declaredElement!;
 
-    var cNode = result.unit!.declarations[2] as ClassDeclaration;
+    var cNode = result.unit.declarations[2] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
 
-    var dNode = result.unit!.declarations[3] as ClassDeclaration;
+    var dNode = result.unit.declarations[3] as ClassDeclaration;
     Element dElement = dNode.declaredElement!;
 
     SimpleIdentifier dName = dNode.name;
@@ -7014,16 +7014,16 @@
     addTestFile(content);
     await resolveTestFile();
 
-    var aNode = result.unit!.declarations[0] as ClassDeclaration;
+    var aNode = result.unit.declarations[0] as ClassDeclaration;
     ClassElement aElement = aNode.declaredElement!;
 
-    var bNode = result.unit!.declarations[1] as ClassDeclaration;
+    var bNode = result.unit.declarations[1] as ClassDeclaration;
     ClassElement bElement = bNode.declaredElement!;
 
-    var cNode = result.unit!.declarations[2] as ClassDeclaration;
+    var cNode = result.unit.declarations[2] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
 
-    var dNode = result.unit!.declarations[3] as ClassTypeAlias;
+    var dNode = result.unit.declarations[3] as ClassTypeAlias;
     Element dElement = dNode.declaredElement!;
 
     SimpleIdentifier dName = dNode.name;
@@ -7082,7 +7082,7 @@
     addTestFile(content);
     await resolveTestFile();
 
-    var enumNode = result.unit!.declarations[0] as EnumDeclaration;
+    var enumNode = result.unit.declarations[0] as EnumDeclaration;
     ClassElement enumElement = enumNode.declaredElement!;
 
     SimpleIdentifier dName = enumNode.name;
@@ -7123,7 +7123,7 @@
     ClassElement doubleElement = doubleType.element;
     ClassElement intElement = intType.element;
 
-    var cNode = result.unit!.declarations[0] as ClassDeclaration;
+    var cNode = result.unit.declarations[0] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
 
     // The class name identifier.
@@ -7248,7 +7248,7 @@
 
     // topFunction()
     {
-      var node = result.unit!.declarations[0] as FunctionDeclaration;
+      var node = result.unit.declarations[0] as FunctionDeclaration;
       expect(node.declaredElement, isNotNull);
       assertType(node.declaredElement!.type, 'int Function(double)');
 
@@ -7281,7 +7281,7 @@
 
     // topGetter()
     {
-      var node = result.unit!.declarations[1] as FunctionDeclaration;
+      var node = result.unit.declarations[1] as FunctionDeclaration;
       expect(node.declaredElement, isNotNull);
       assertType(node.declaredElement!.type, 'int Function()');
 
@@ -7299,7 +7299,7 @@
 
     // topSetter()
     {
-      var node = result.unit!.declarations[2] as FunctionDeclaration;
+      var node = result.unit.declarations[2] as FunctionDeclaration;
       expect(node.declaredElement, isNotNull);
       assertType(node.declaredElement!.type, 'void Function(double)');
 
@@ -7341,7 +7341,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     CompilationUnitElement unitElement = unit.declaredElement!;
 
     var cNode = unit.declarations[0] as ClassDeclaration;
@@ -7388,7 +7388,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var cNode = unit.declarations[0] as ClassDeclaration;
     ClassElement cElement = cNode.declaredElement!;
@@ -7432,7 +7432,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     CompilationUnitElement unitElement = unit.declaredElement!;
 
     {
@@ -7474,7 +7474,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     CompilationUnitElement unitElement = unit.declaredElement!;
 
     var variableDeclaration =
@@ -7518,7 +7518,7 @@
     String fTypeString = 'double Function(int, {String b, bool c})';
 
     await resolveTestFile();
-    var fDeclaration = result.unit!.declarations[0] as FunctionDeclaration;
+    var fDeclaration = result.unit.declarations[0] as FunctionDeclaration;
     var fElement = fDeclaration.declaredElement as FunctionElement;
 
     InterfaceType doubleType = typeProvider.doubleType;
@@ -7571,7 +7571,7 @@
     //
     // Validate the arguments at the call site.
     //
-    var mainDeclaration = result.unit!.declarations[1] as FunctionDeclaration;
+    var mainDeclaration = result.unit.declarations[1] as FunctionDeclaration;
     var body = mainDeclaration.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
     var invocation = statement.expression as MethodInvocation;
@@ -7589,7 +7589,7 @@
     addTestFile(content);
 
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var alias = unit.declarations[0] as FunctionTypeAlias;
     TypeAliasElement aliasElement = alias.declaredElement!;
@@ -7623,7 +7623,7 @@
 ''';
     addTestFile(content);
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
     CompilationUnitElement unitElement = unit.declaredElement!;
 
     var aNode = unit.declarations[0] as ClassDeclaration;
@@ -7870,7 +7870,7 @@
 c.A a2;
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     ImportElement bImport = unit.declaredElement!.library.imports[0];
     ImportElement cImport = unit.declaredElement!.library.imports[1];
@@ -7915,7 +7915,7 @@
 typedef void F(int p);
 ''');
     await resolveTestFile();
-    CompilationUnit unit = result.unit!;
+    CompilationUnit unit = result.unit;
 
     var fNode = unit.declarations[1] as FunctionTypeAlias;
     TypeAliasElement fElement = fNode.declaredElement!;
@@ -8033,7 +8033,7 @@
     await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
-    var unitElement = result.unit!.declaredElement!;
+    var unitElement = result.unit.declaredElement!;
     var foo = unitElement.library.imports[0].prefix;
 
     List<Statement> statements = _getMainStatements(result);
@@ -8117,7 +8117,7 @@
     await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
-    var unitElement = result.unit!.declaredElement!;
+    var unitElement = result.unit.declaredElement!;
     var mathImport = unitElement.library.imports[0];
     var foo = mathImport.prefix;
 
@@ -8163,7 +8163,7 @@
     await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
-    var unitElement = result.unit!.declaredElement!;
+    var unitElement = result.unit.declaredElement!;
     var mathImport = unitElement.library.imports[0];
     var foo = mathImport.prefix;
     var randomElement = mathImport.importedLibrary!.getType('Random')!;
@@ -8716,7 +8716,7 @@
   }
 
   List<Statement> _getMainStatements(ResolvedUnitResult result) {
-    for (var declaration in result.unit!.declarations) {
+    for (var declaration in result.unit.declarations) {
       if (declaration is FunctionDeclaration &&
           declaration.name.name == 'main') {
         var body = declaration.functionExpression.body as BlockFunctionBody;
@@ -8728,7 +8728,7 @@
 
   TopLevelVariableElement _getTopLevelVariable(
       ResolvedUnitResult result, String name) {
-    for (var variable in result.unit!.declaredElement!.topLevelVariables) {
+    for (var variable in result.unit.declaredElement!.topLevelVariables) {
       if (variable.name == name) {
         return variable;
       }
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index dee0e8e..29a974a 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -59,7 +59,7 @@
 
   late final AnalysisDriverScheduler scheduler;
 
-  List<ResolvedUnitResult> allResults = [];
+  final List<AnalysisResultWithErrors> allResults = [];
 
   AnalysisDriver newDriver() {
     sdk = MockSdk(resourceProvider: resourceProvider);
@@ -74,7 +74,11 @@
       analysisOptions: AnalysisOptionsImpl(),
       packages: Packages.empty,
     );
-    driver.results.forEach(allResults.add);
+    driver.results.listen((result) {
+      if (result is AnalysisResultWithErrors) {
+        allResults.add(result);
+      }
+    });
     return driver;
   }
 
@@ -444,9 +448,9 @@
     ResolvedUnitResult partResult1 = await driver.getResultValid(part1);
     ResolvedUnitResult partResult2 = await driver.getResultValid(part2);
 
-    CompilationUnit libUnit = libResult.unit!;
-    CompilationUnit partUnit1 = partResult1.unit!;
-    CompilationUnit partUnit2 = partResult2.unit!;
+    CompilationUnit libUnit = libResult.unit;
+    CompilationUnit partUnit1 = partResult1.unit;
+    CompilationUnit partUnit2 = partResult2.unit;
 
     CompilationUnitElement unitElement = libUnit.declaredElement!;
     CompilationUnitElement partElement1 = partUnit1.declaredElement!;
@@ -669,8 +673,10 @@
     await waitForIdleWithoutExceptions();
     expect(allResults, hasLength(1));
     {
-      ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
-      _assertTopLevelVarType(ar.unit!, 'A', 'int');
+      ResolvedUnitResult ar = allResults
+          .whereType<ResolvedUnitResult>()
+          .firstWhere((r) => r.path == a);
+      _assertTopLevelVarType(ar.unit, 'A', 'int');
     }
     allResults.clear();
 
@@ -686,8 +692,10 @@
     await waitForIdleWithoutExceptions();
     expect(allResults, hasLength(1));
     {
-      ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
-      _assertTopLevelVarType(ar.unit!, 'A', 'double');
+      ResolvedUnitResult ar = allResults
+          .whereType<ResolvedUnitResult>()
+          .firstWhere((r) => r.path == a);
+      _assertTopLevelVarType(ar.unit, 'A', 'double');
     }
   }
 
@@ -740,13 +748,17 @@
     // We have results for both "a" and "b".
     expect(allResults, hasLength(2));
     {
-      ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
-      _assertTopLevelVarType(ar.unit!, 'A1', 'int');
-      _assertTopLevelVarType(ar.unit!, 'A2', 'int');
+      ResolvedUnitResult ar = allResults
+          .whereType<ResolvedUnitResult>()
+          .firstWhere((r) => r.path == a);
+      _assertTopLevelVarType(ar.unit, 'A1', 'int');
+      _assertTopLevelVarType(ar.unit, 'A2', 'int');
     }
     {
-      ResolvedUnitResult br = allResults.firstWhere((r) => r.path == b);
-      _assertTopLevelVarType(br.unit!, 'B1', 'int');
+      ResolvedUnitResult br = allResults
+          .whereType<ResolvedUnitResult>()
+          .firstWhere((r) => r.path == b);
+      _assertTopLevelVarType(br.unit, 'B1', 'int');
     }
 
     // Clear the results and update "a".
@@ -763,13 +775,17 @@
     await waitForIdleWithoutExceptions();
     expect(allResults, hasLength(2));
     {
-      ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
-      _assertTopLevelVarType(ar.unit!, 'A1', 'double');
-      _assertTopLevelVarType(ar.unit!, 'A2', 'double');
+      ResolvedUnitResult ar = allResults
+          .whereType<ResolvedUnitResult>()
+          .firstWhere((r) => r.path == a);
+      _assertTopLevelVarType(ar.unit, 'A1', 'double');
+      _assertTopLevelVarType(ar.unit, 'A2', 'double');
     }
     {
-      ResolvedUnitResult br = allResults.firstWhere((r) => r.path == b);
-      _assertTopLevelVarType(br.unit!, 'B1', 'double');
+      ResolvedUnitResult br = allResults
+          .whereType<ResolvedUnitResult>()
+          .firstWhere((r) => r.path == b);
+      _assertTopLevelVarType(br.unit, 'B1', 'double');
     }
   }
 
@@ -780,9 +796,9 @@
     {
       await waitForIdleWithoutExceptions();
       expect(allResults, hasLength(1));
-      ResolvedUnitResult result = allResults[0];
+      var result = allResults[0] as ResolvedUnitResult;
       expect(result.path, testFile);
-      _assertTopLevelVarType(result.unit!, 'V', 'int');
+      _assertTopLevelVarType(result.unit, 'V', 'int');
     }
 
     // Update the file, but don't notify the driver.
@@ -803,9 +819,9 @@
     {
       await waitForIdleWithoutExceptions();
       expect(allResults, hasLength(1));
-      ResolvedUnitResult result = allResults[0];
+      var result = allResults[0] as ResolvedUnitResult;
       expect(result.path, testFile);
-      _assertTopLevelVarType(result.unit!, 'V', 'double');
+      _assertTopLevelVarType(result.unit, 'V', 'double');
     }
   }
 
@@ -820,7 +836,7 @@
 class C {}
 ''');
     var result = await driver.getResultValid(testFile);
-    var atD = AstFinder.getClass(result.unit!, 'C').metadata[0];
+    var atD = AstFinder.getClass(result.unit, 'C').metadata[0];
     var atDI = atD.elementAnnotation as ElementAnnotationImpl;
     var value = atDI.evaluationResult!.value;
     // That is illegal.
@@ -837,7 +853,7 @@
 }
 ''');
     var result = await driver.getResultValid(testFile);
-    var atD = AstFinder.getClass(result.unit!, 'C').metadata[0];
+    var atD = AstFinder.getClass(result.unit, 'C').metadata[0];
     var atDI = atD.elementAnnotation as ElementAnnotationImpl;
     var value = atDI.evaluationResult!.value!;
     expect(value.type, isNotNull);
@@ -853,7 +869,7 @@
 @x class C {}
 ''');
     var result = await driver.getResultValid(testFile);
-    Annotation at_x = AstFinder.getClass(result.unit!, 'C').metadata[0];
+    Annotation at_x = AstFinder.getClass(result.unit, 'C').metadata[0];
     expect(at_x.elementAnnotation!.computeConstantValue()!.toIntValue(), 1);
   }
 
@@ -863,7 +879,7 @@
 const y = x + 1;
 ''');
     var result = await driver.getResultValid(testFile);
-    var x = AstFinder.getTopLevelVariableElement(result.unit!, 'x')
+    var x = AstFinder.getTopLevelVariableElement(result.unit, 'x')
         as TopLevelVariableElementImpl;
     _expectCircularityError(x.evaluationResult!);
   }
@@ -874,8 +890,8 @@
 const y = 1;
 ''');
     var result = await driver.getResultValid(testFile);
-    var x = AstFinder.getTopLevelVariableElement(result.unit!, 'x');
-    var y = AstFinder.getTopLevelVariableElement(result.unit!, 'y');
+    var x = AstFinder.getTopLevelVariableElement(result.unit, 'x');
+    var y = AstFinder.getTopLevelVariableElement(result.unit, 'y');
     expect(x.computeConstantValue()!.toIntValue(), 2);
     expect(y.computeConstantValue()!.toIntValue(), 1);
   }
@@ -891,7 +907,7 @@
 class B {}
 ''');
     var result = await driver.getResultValid(testFile);
-    var x = AstFinder.getTopLevelVariableElement(result.unit!, 'x');
+    var x = AstFinder.getTopLevelVariableElement(result.unit, 'x');
     expect(x.computeConstantValue(), isNotNull);
   }
 
@@ -957,7 +973,7 @@
 const x = const Derived();
 ''');
     var result = await driver.getResultValid(testFile);
-    var x = AstFinder.getTopLevelVariableElement(result.unit!, 'x');
+    var x = AstFinder.getTopLevelVariableElement(result.unit, 'x');
     expect(x.computeConstantValue(), isNotNull);
   }
 
@@ -966,7 +982,7 @@
 const x = 1;
 ''');
     var result = await driver.getResultValid(testFile);
-    var x = AstFinder.getTopLevelVariableElement(result.unit!, 'x');
+    var x = AstFinder.getTopLevelVariableElement(result.unit, 'x');
     expect(x.computeConstantValue()!.toIntValue(), 1);
   }
 
@@ -1403,10 +1419,10 @@
     var result = driver.getParsedLibrary2(testFile);
     result as ParsedLibraryResult;
     expect(result.units, hasLength(1));
-    expect(result.units![0].path, testFile);
-    expect(result.units![0].content, content);
-    expect(result.units![0].unit, isNotNull);
-    expect(result.units![0].errors, isEmpty);
+    expect(result.units[0].path, testFile);
+    expect(result.units[0].content, content);
+    expect(result.units[0].unit, isNotNull);
+    expect(result.units[0].errors, isEmpty);
   }
 
   test_getParsedLibrary2_invalidPath_notAbsolute() async {
@@ -1429,9 +1445,9 @@
     result as ParsedLibraryResult;
     expect(result.uri, uri);
     expect(result.units, hasLength(1));
-    expect(result.units![0].uri, uri);
-    expect(result.units![0].path, testFile);
-    expect(result.units![0].content, content);
+    expect(result.units[0].uri, uri);
+    expect(result.units[0].path, testFile);
+    expect(result.units[0].content, content);
   }
 
   test_getParsedLibraryByUri2_notLibrary() async {
@@ -1454,10 +1470,10 @@
     var result = await driver.getResolvedLibrary2(testFile);
     result as ResolvedLibraryResult;
     expect(result.units, hasLength(1));
-    expect(result.units![0].path, testFile);
-    expect(result.units![0].content, content);
-    expect(result.units![0].unit, isNotNull);
-    expect(result.units![0].errors, isEmpty);
+    expect(result.units[0].path, testFile);
+    expect(result.units[0].content, content);
+    expect(result.units[0].unit, isNotNull);
+    expect(result.units[0].errors, isEmpty);
   }
 
   test_getResolvedLibrary2_invalidPath_notAbsolute() async {
@@ -1479,11 +1495,11 @@
     var result = await driver.getResolvedLibraryByUri2(uri);
     result as ResolvedLibraryResult;
     expect(result.uri, uri);
-    expect(result.element!.source.fullName, testFile);
+    expect(result.element.source.fullName, testFile);
     expect(result.units, hasLength(1));
-    expect(result.units![0].uri, uri);
-    expect(result.units![0].path, testFile);
-    expect(result.units![0].content, content);
+    expect(result.units[0].uri, uri);
+    expect(result.units[0].path, testFile);
+    expect(result.units[0].content, content);
   }
 
   test_getResolvedLibraryByUri2_notLibrary() async {
@@ -1512,7 +1528,7 @@
     expect(result.unit, isNotNull);
     expect(result.errors, hasLength(0));
 
-    var f = result.unit!.declarations[0] as FunctionDeclaration;
+    var f = result.unit.declarations[0] as FunctionDeclaration;
     assertType(f.declaredElement!.type, 'int Function()');
     assertType(f.returnType!.typeOrThrow, 'int');
 
@@ -1657,7 +1673,7 @@
     await waitForIdleWithoutExceptions();
 
     ResolvedUnitResult result = await driver.getResultValid(testFile);
-    _assertClassFieldType(result.unit!, 'C', 'f', 'int');
+    _assertClassFieldType(result.unit, 'C', 'f', 'int');
   }
 
   test_getResult_inferTypes_instanceMethod() async {
@@ -1672,8 +1688,8 @@
     await waitForIdleWithoutExceptions();
 
     ResolvedUnitResult result = await driver.getResultValid(testFile);
-    _assertClassMethodReturnType(result.unit!, 'A', 'm', 'int');
-    _assertClassMethodReturnType(result.unit!, 'B', 'm', 'int');
+    _assertClassMethodReturnType(result.unit, 'A', 'm', 'int');
+    _assertClassMethodReturnType(result.unit, 'B', 'm', 'int');
   }
 
   test_getResult_invalid_annotation_functionAsConstructor() async {
@@ -1685,7 +1701,7 @@
 ''', priority: true);
 
     ResolvedUnitResult result = await driver.getResultValid(testFile);
-    ClassDeclaration c = result.unit!.declarations[1] as ClassDeclaration;
+    ClassDeclaration c = result.unit.declarations[1] as ClassDeclaration;
     Annotation a = c.metadata[0];
     expect(a.name.name, 'fff');
     expect(a.name.staticElement, isFunctionElement);
@@ -1772,7 +1788,7 @@
 ''');
 
     var result = await driver.getResultValid(path);
-    var languageVersion = result.unit!.languageVersionToken!;
+    var languageVersion = result.unit.languageVersionToken!;
     expect(languageVersion.major, 2);
     expect(languageVersion.minor, 7);
   }
@@ -1855,7 +1871,7 @@
 
     ResolvedUnitResult result = await driver.getResultValid(path);
     expect(result, isNotNull);
-    expect(result.unit!.declaredElement!.classes.map((e) => e.name), ['A']);
+    expect(result.unit.declaredElement!.classes.map((e) => e.name), ['A']);
   }
 
   test_getResult_recursiveFlatten() async {
@@ -1888,18 +1904,18 @@
 
     {
       ResolvedUnitResult result = await driver.getResultValid(b);
-      expect(_getImportSource(result.unit!, 0).uri.toString(),
+      expect(_getImportSource(result.unit, 0).uri.toString(),
           'package:test/a.dart');
-      _assertTopLevelVarType(result.unit!, 'VB', 'A<int>');
+      _assertTopLevelVarType(result.unit, 'VB', 'A<int>');
     }
 
     {
       ResolvedUnitResult result = await driver.getResultValid(c);
       expect(
-        _getImportSource(result.unit!, 0).uri,
+        _getImportSource(result.unit, 0).uri,
         toUri('/test/lib/a.dart'),
       );
-      _assertTopLevelVarType(result.unit!, 'VC', 'A<double>');
+      _assertTopLevelVarType(result.unit, 'VC', 'A<double>');
     }
   }
 
@@ -1922,8 +1938,8 @@
 
     {
       ResolvedUnitResult result = await driver.getResultValid(a);
-      _assertTopLevelVarType(result.unit!, 'A1', 'int');
-      _assertTopLevelVarType(result.unit!, 'A2', 'int');
+      _assertTopLevelVarType(result.unit, 'A1', 'int');
+      _assertTopLevelVarType(result.unit, 'A2', 'int');
     }
 
     // Update "a" so that "A1" is now "double".
@@ -1942,8 +1958,8 @@
 
     {
       ResolvedUnitResult result = await driver.getResultValid(a);
-      _assertTopLevelVarType(result.unit!, 'A1', 'double');
-      _assertTopLevelVarType(result.unit!, 'A2', 'double');
+      _assertTopLevelVarType(result.unit, 'A1', 'double');
+      _assertTopLevelVarType(result.unit, 'A2', 'double');
     }
   }
 
@@ -2078,7 +2094,7 @@
 ''');
 
     var result = await driver.getResultValid(b);
-    var c = _getTopLevelVar(result.unit!, 'c');
+    var c = _getTopLevelVar(result.unit, 'c');
     var typeC = c.declaredElement!.type as InterfaceType;
     // The class C has an old field 'foo', not the new 'bar'.
     expect(typeC.element.getField('foo'), isNotNull);
@@ -2517,15 +2533,15 @@
     {
       ResolvedUnitResult result = await driver.getResultValid(a);
       expect(result.errors, isEmpty);
-      _assertTopLevelVarType(result.unit!, 'c', 'C');
+      _assertTopLevelVarType(result.unit, 'c', 'C');
     }
 
     // Now c.dart can be resolved without errors in the context of a.dart
     {
       ResolvedUnitResult result = await driver.getResultValid(c);
       expect(result.errors, isEmpty);
-      _assertTopLevelVarType(result.unit!, 'a', 'A');
-      _assertTopLevelVarType(result.unit!, 'b', 'B');
+      _assertTopLevelVarType(result.unit, 'a', 'A');
+      _assertTopLevelVarType(result.unit, 'b', 'B');
     }
   }
 
@@ -2556,8 +2572,8 @@
     // So, A and B references are resolved.
     ResolvedUnitResult result = await driver.getResultValid(c);
     expect(result.errors, isEmpty);
-    _assertTopLevelVarType(result.unit!, 'a', 'A');
-    _assertTopLevelVarType(result.unit!, 'b', 'B');
+    _assertTopLevelVarType(result.unit, 'a', 'A');
+    _assertTopLevelVarType(result.unit, 'b', 'B');
   }
 
   test_part_getResult_changePart_invalidatesLibraryCycle() async {
@@ -2735,9 +2751,9 @@
 
       // c.dart was added after a.dart, so it is analyzed after a.dart,
       // so we know that a.dart is the library of c.dart, so no errors.
-      ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c);
+      var result =
+          allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
       expect(result.errors, isEmpty);
-      expect(result.unit, isNull);
     }
 
     // Update a.dart so that c.dart is not a part.
@@ -2748,9 +2764,9 @@
 
       // Now c.dart does not have a library context, so A and B cannot be
       // resolved, so there are errors.
-      ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c);
+      var result =
+          allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
       expect(result.errors, isNotEmpty);
-      expect(result.unit, isNull);
     }
   }
 
@@ -2784,9 +2800,9 @@
     // a.dart, but we cannot find the library for it, so we delay analysis
     // until all other files are analyzed, including a.dart, after which we
     // analyze the delayed parts.
-    ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c);
+    var result =
+        allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
     expect(result.errors, isEmpty);
-    expect(result.unit, isNull);
   }
 
   test_part_results_noLibrary() async {
@@ -2804,9 +2820,9 @@
 
     // There is no library which c.dart is a part of, so it has unresolved
     // A and B references.
-    ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c);
+    var result =
+        allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
     expect(result.errors, isNotEmpty);
-    expect(result.unit, isNull);
   }
 
   test_part_results_priority_beforeLibrary() async {
@@ -2840,7 +2856,9 @@
     // a.dart, but we cannot find the library for it, so we delay analysis
     // until all other files are analyzed, including a.dart, after which we
     // analyze the delayed parts.
-    ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c);
+    ResolvedUnitResult result = allResults
+        .whereType<ResolvedUnitResult>()
+        .lastWhere((r) => r.path == c);
     expect(result.errors, isEmpty);
     expect(result.unit, isNotNull);
   }
@@ -2862,12 +2880,16 @@
     await waitForIdleWithoutExceptions();
     expect(allResults, hasLength(2));
     {
-      ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
-      _assertTopLevelVarType(ar.unit!, 'A', 'int');
+      ResolvedUnitResult ar = allResults
+          .whereType<ResolvedUnitResult>()
+          .firstWhere((r) => r.path == a);
+      _assertTopLevelVarType(ar.unit, 'A', 'int');
     }
     {
-      ResolvedUnitResult br = allResults.firstWhere((r) => r.path == b);
-      _assertTopLevelVarType(br.unit!, 'B', 'int');
+      ResolvedUnitResult br = allResults
+          .whereType<ResolvedUnitResult>()
+          .firstWhere((r) => r.path == b);
+      _assertTopLevelVarType(br.unit, 'B', 'int');
     }
     allResults.clear();
 
@@ -2882,8 +2904,10 @@
     await waitForIdleWithoutExceptions();
     expect(allResults, hasLength(1));
     {
-      ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
-      _assertTopLevelVarType(ar.unit!, 'A', 'double');
+      ResolvedUnitResult ar = allResults
+          .whereType<ResolvedUnitResult>()
+          .firstWhere((r) => r.path == a);
+      _assertTopLevelVarType(ar.unit, 'A', 'double');
     }
   }
 
@@ -3028,7 +3052,7 @@
     driver.changeFile(b);
     await waitForIdleWithoutExceptions();
 
-    List<String> analyzedPaths = allResults.map((r) => r.path!).toList();
+    List<String> analyzedPaths = allResults.map((r) => r.path).toList();
 
     // The changed file must be the first.
     expect(analyzedPaths[0], b);
@@ -3070,7 +3094,7 @@
     driver.changeFile(a);
     await waitForIdleWithoutExceptions();
 
-    List<String> analyzedPaths = allResults.map((r) => r.path!).toList();
+    List<String> analyzedPaths = allResults.map((r) => r.path).toList();
 
     // The changed files must be the first.
     expect(analyzedPaths[0], a);
@@ -3088,14 +3112,14 @@
     await waitForIdleWithoutExceptions();
 
     expect(allResults, hasLength(1));
-    ResolvedUnitResult result = allResults.single;
+    var result = allResults.single as ResolvedUnitResult;
     expect(result.path, testFile);
     expect(result.uri.toString(), 'package:test/test.dart');
     expect(result.content, content);
     expect(result.unit, isNotNull);
     expect(result.errors, hasLength(0));
 
-    var f = result.unit!.declarations[0] as FunctionDeclaration;
+    var f = result.unit.declarations[0] as FunctionDeclaration;
     assertType(f.declaredElement!.type, 'int Function()');
     assertType(f.returnType!.typeOrThrow, 'int');
   }
@@ -3115,7 +3139,7 @@
     await waitForIdleWithoutExceptions();
 
     expect(allResults, hasLength(3));
-    ResolvedUnitResult result = allResults[0];
+    var result = allResults[0] as ResolvedUnitResult;
     expect(result.path, b);
     expect(result.unit, isNotNull);
     expect(result.errors, hasLength(0));
@@ -3127,11 +3151,9 @@
     await waitForIdleWithoutExceptions();
 
     expect(allResults, hasLength(1));
-    ResolvedUnitResult result = allResults.single;
+    var result = allResults.single as ErrorsResult;
     expect(result.path, testFile);
     expect(result.uri.toString(), 'package:test/test.dart');
-    expect(result.content, isNull);
-    expect(result.unit, isNull);
     expect(result.errors, hasLength(0));
   }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index 63c5831..c61fa44 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -1734,7 +1734,7 @@
   Future<void> _indexTestUnit(String code) async {
     await resolveTestCode(code);
 
-    var indexBuilder = indexUnit(result.unit!);
+    var indexBuilder = indexUnit(result.unit);
     var indexBytes = indexBuilder.toBuffer();
     index = AnalysisDriverUnitIndex.fromBuffer(indexBytes);
   }
diff --git a/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart b/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart
index 89fdeda..983d7bb 100644
--- a/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart
@@ -42,7 +42,7 @@
       expect(node.name.name, 'A');
       expect(
         node.name.offset,
-        this.result.content!.indexOf('A {} // 1'),
+        this.result.content.indexOf('A {} // 1'),
       );
     }
 
@@ -53,7 +53,7 @@
       expect(node.name.name, 'A');
       expect(
         node.name.offset,
-        this.result.content!.indexOf('A {} // 2'),
+        this.result.content.indexOf('A {} // 2'),
       );
     }
   }
@@ -66,7 +66,7 @@
     await resolveTestCode(r'''
 part 'a.dart';
 ''');
-    var library = this.result.unit!.declaredElement!.library;
+    var library = this.result.unit.declaredElement!.library;
     var element = library.getType('A')!;
     var result = await getElementDeclaration(element);
     var node = result!.node as ClassDeclaration;
@@ -139,7 +139,7 @@
       expect(node.name!.name, 'named');
       expect(
         node.name!.offset,
-        this.result.content!.indexOf('named(); // 1'),
+        this.result.content.indexOf('named(); // 1'),
       );
     }
 
@@ -150,7 +150,7 @@
       expect(node.name!.name, 'named');
       expect(
         node.name!.offset,
-        this.result.content!.indexOf('named(); // 2'),
+        this.result.content.indexOf('named(); // 2'),
       );
     }
   }
@@ -169,7 +169,7 @@
       expect(node.name, isNull);
       expect(
         node.returnType.offset,
-        this.result.content!.indexOf('A(); // 1'),
+        this.result.content.indexOf('A(); // 1'),
       );
     }
 
@@ -180,7 +180,7 @@
       expect(node.name, isNull);
       expect(
         node.returnType.offset,
-        this.result.content!.indexOf('A(); // 2'),
+        this.result.content.indexOf('A(); // 2'),
       );
     }
   }
@@ -439,7 +439,7 @@
 
   ParsedLibraryResult _getParsedLibrary(String path) {
     var session = contextFor(path).currentSession;
-    return session.getParsedLibrary2(path) as ParsedLibraryResult;
+    return session.getParsedLibrary(path) as ParsedLibraryResult;
   }
 }
 
@@ -456,6 +456,6 @@
 
   Future<ResolvedLibraryResult> _getResolvedLibrary(String path) async {
     var session = contextFor(path).currentSession;
-    return await session.getResolvedLibrary2(path) as ResolvedLibraryResult;
+    return await session.getResolvedLibrary(path) as ResolvedLibraryResult;
   }
 }
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 5b33cdf..dab758b 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -64,7 +64,7 @@
 class SearchTest extends PubPackageResolutionTest {
   AnalysisDriver get driver => driverFor(testFilePath);
 
-  CompilationUnitElement get resultUnitElement => result.unit!.declaredElement!;
+  CompilationUnitElement get resultUnitElement => result.unit.declaredElement!;
 
   String get testUriStr => 'package:test/test.dart';
 
@@ -378,7 +378,7 @@
     var element = findElement.unnamedConstructor('A');
 
     var otherUnitResult = await driver.getResult2(other) as ResolvedUnitResult;
-    CompilationUnit otherUnit = otherUnitResult.unit!;
+    CompilationUnit otherUnit = otherUnitResult.unit;
     Element main = otherUnit.declaredElement!.functions[0];
     var expected = [
       ExpectedResult(main, SearchResultKind.REFERENCE,
diff --git a/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
index 6e96379..6beca53 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
@@ -91,7 +91,7 @@
 ''');
     var element = findNode.classDeclaration('A').declaredElement!;
     var resolvedUnit = (await helper.getResolvedUnitByElement(element))!;
-    expect(resolvedUnit.unit!.declarations, hasLength(2));
+    expect(resolvedUnit.unit.declarations, hasLength(2));
   }
 
   test_getTopLevelPropertyAccessor_defined_getter() async {
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index 1d2f2b0..6a9d493 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -33,7 +33,7 @@
 
     var path = convertPath('$workspaceRootPath/$relPath');
     var session = contextFor(path).currentSession;
-    var result = await session.getErrors2(path);
+    var result = await session.getErrors(path);
     expect(result, isA<NotPathOfUriResult>());
   }
 
@@ -57,7 +57,7 @@
 
     var path = convertPath('$workspaceRootPath/$relPath');
     var session = contextFor(path).currentSession;
-    var result = session.getParsedLibrary2(path);
+    var result = session.getParsedLibrary(path);
     expect(result, isA<NotPathOfUriResult>());
   }
 
@@ -67,7 +67,7 @@
 
     var path = convertPath('$workspaceRootPath/$relPath');
     var session = contextFor(path).currentSession;
-    var result = await session.getResolvedLibrary2(path);
+    var result = await session.getResolvedLibrary(path);
     expect(result, isA<NotPathOfUriResult>());
   }
 
@@ -77,7 +77,7 @@
 
     var path = convertPath('$workspaceRootPath/$relPath');
     var session = contextFor(path).currentSession;
-    var result = await session.getResolvedUnit2(path);
+    var result = await session.getResolvedUnit(path);
     expect(result, isA<NotPathOfUriResult>());
   }
 
@@ -88,8 +88,7 @@
     );
 
     var session = contextFor(file.path).currentSession;
-    var result =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+    var result = await session.getResolvedUnit(file.path) as ResolvedUnitResult;
     expect(result.state, ResultState.VALID);
     expect(result.path, file.path);
     expect(result.errors, isEmpty);
@@ -103,7 +102,7 @@
     );
 
     var session = contextFor(file.path).currentSession;
-    var result = await session.getUnitElement2('not_absolute.dart');
+    var result = await session.getUnitElement('not_absolute.dart');
     expect(result, isA<InvalidPathResult>());
   }
 
@@ -113,7 +112,7 @@
 
     var path = convertPath('$workspaceRootPath/$relPath');
     var session = contextFor(path).currentSession;
-    var result = await session.getUnitElement2(path);
+    var result = await session.getUnitElement(path);
     expect(result, isA<NotPathOfUriResult>());
   }
 
@@ -175,12 +174,12 @@
   }
 
   test_getErrors2_invalidPath_notAbsolute() async {
-    var errorsResult = await session.getErrors2('not_absolute.dart');
+    var errorsResult = await session.getErrors('not_absolute.dart');
     expect(errorsResult, isA<InvalidPathResult>());
   }
 
   test_getFile2_invalidPath_notAbsolute() async {
-    var errorsResult = session.getFile2('not_absolute.dart');
+    var errorsResult = session.getFile('not_absolute.dart');
     expect(errorsResult, isA<InvalidPathResult>());
   }
 
@@ -216,7 +215,7 @@
   }
 
   test_getLibraryByUri2_unresolvedUri() async {
-    var result = await session.getLibraryByUri2('package:foo/foo.dart');
+    var result = await session.getLibraryByUri('package:foo/foo.dart');
     expect(result, isA<CannotResolveUriResult>());
   }
 
@@ -233,7 +232,7 @@
 
     expect(parsedLibrary.units, hasLength(1));
     {
-      var parsedUnit = parsedLibrary.units![0];
+      var parsedUnit = parsedLibrary.units[0];
       expect(parsedUnit.session, session);
       expect(parsedUnit.path, testPath);
       expect(parsedUnit.uri, Uri.parse('package:test/test.dart'));
@@ -242,13 +241,13 @@
   }
 
   test_getParsedLibrary2_invalidPath_notAbsolute() async {
-    var result = session.getParsedLibrary2('not_absolute.dart');
+    var result = session.getParsedLibrary('not_absolute.dart');
     expect(result, isA<InvalidPathResult>());
   }
 
   test_getParsedLibrary2_notLibrary() async {
     newFile(testPath, content: 'part of "a.dart";');
-    expect(session.getParsedLibrary2(testPath), isA<NotLibraryButPartResult>());
+    expect(session.getParsedLibrary(testPath), isA<NotLibraryButPartResult>());
   }
 
   test_getParsedLibrary2_parts() async {
@@ -288,21 +287,21 @@
     expect(parsedLibrary.units, hasLength(3));
 
     {
-      var aUnit = parsedLibrary.units![0];
+      var aUnit = parsedLibrary.units[0];
       expect(aUnit.path, a);
       expect(aUnit.uri, Uri.parse('package:test/a.dart'));
       expect(aUnit.unit.declarations, hasLength(1));
     }
 
     {
-      var bUnit = parsedLibrary.units![1];
+      var bUnit = parsedLibrary.units[1];
       expect(bUnit.path, b);
       expect(bUnit.uri, Uri.parse('package:test/b.dart'));
       expect(bUnit.unit.declarations, hasLength(2));
     }
 
     {
-      var cUnit = parsedLibrary.units![2];
+      var cUnit = parsedLibrary.units[2];
       expect(cUnit.path, c);
       expect(cUnit.uri, Uri.parse('package:test/c.dart'));
       expect(cUnit.unit.declarations, hasLength(3));
@@ -332,7 +331,7 @@
     newFile(testPath, content: '');
 
     var resolvedUnit =
-        await session.getResolvedUnit2(testPath) as ResolvedUnitResult;
+        await session.getResolvedUnit(testPath) as ResolvedUnitResult;
     var typeProvider = resolvedUnit.typeProvider;
     var intClass = typeProvider.intType.element;
 
@@ -378,15 +377,15 @@
 
     expect(parsedLibrary.units, hasLength(3));
     expect(
-      parsedLibrary.units![0].path,
+      parsedLibrary.units[0].path,
       convertPath('/home/test/lib/test.dart'),
     );
     expect(
-      parsedLibrary.units![1].path,
+      parsedLibrary.units[1].path,
       convertPath('/home/test/lib/a.dart'),
     );
     expect(
-      parsedLibrary.units![2].path,
+      parsedLibrary.units[2].path,
       convertPath('/home/test/lib/c.dart'),
     );
   }
@@ -417,7 +416,7 @@
     var aaaSession =
         contextCollection.contextFor(aaaContextPath).currentSession;
 
-    var result = aaaSession.getParsedLibraryByElement2(element);
+    var result = aaaSession.getParsedLibraryByElement(element);
     expect(result, isA<NotElementOfThisSessionResult>());
   }
 
@@ -435,7 +434,7 @@
   }
 
   test_getParsedUnit2_invalidPath_notAbsolute() async {
-    var result = session.getParsedUnit2('not_absolute.dart');
+    var result = session.getParsedUnit('not_absolute.dart');
     expect(result, isA<InvalidPathResult>());
   }
 
@@ -466,28 +465,28 @@
     var typeProvider = resolvedLibrary.typeProvider;
     expect(typeProvider.intType.element.name, 'int');
 
-    var libraryElement = resolvedLibrary.element!;
+    var libraryElement = resolvedLibrary.element;
 
     var aClass = libraryElement.getType('A')!;
 
     var bClass = libraryElement.getType('B')!;
 
-    var aUnitResult = resolvedLibrary.units![0];
+    var aUnitResult = resolvedLibrary.units[0];
     expect(aUnitResult.path, a);
     expect(aUnitResult.uri, Uri.parse('package:test/a.dart'));
     expect(aUnitResult.content, aContent);
     expect(aUnitResult.unit, isNotNull);
-    expect(aUnitResult.unit!.directives, hasLength(1));
-    expect(aUnitResult.unit!.declarations, hasLength(1));
+    expect(aUnitResult.unit.directives, hasLength(1));
+    expect(aUnitResult.unit.declarations, hasLength(1));
     expect(aUnitResult.errors, isEmpty);
 
-    var bUnitResult = resolvedLibrary.units![1];
+    var bUnitResult = resolvedLibrary.units[1];
     expect(bUnitResult.path, b);
     expect(bUnitResult.uri, Uri.parse('package:test/b.dart'));
     expect(bUnitResult.content, bContent);
     expect(bUnitResult.unit, isNotNull);
-    expect(bUnitResult.unit!.directives, hasLength(1));
-    expect(bUnitResult.unit!.declarations, hasLength(2));
+    expect(bUnitResult.unit.directives, hasLength(1));
+    expect(bUnitResult.unit.declarations, hasLength(2));
     expect(bUnitResult.errors, isNotEmpty);
 
     var aDeclaration = resolvedLibrary.getElementDeclaration(aClass)!;
@@ -506,14 +505,14 @@
   }
 
   test_getResolvedLibrary2_invalidPath_notAbsolute() async {
-    var result = await session.getResolvedLibrary2('not_absolute.dart');
+    var result = await session.getResolvedLibrary('not_absolute.dart');
     expect(result, isA<InvalidPathResult>());
   }
 
   test_getResolvedLibrary2_notLibrary() async {
     newFile(testPath, content: 'part of "a.dart";');
 
-    var result = await session.getResolvedLibrary2(testPath);
+    var result = await session.getResolvedLibrary(testPath);
     expect(result, isA<NotLibraryButPartResult>());
   }
 
@@ -534,7 +533,7 @@
 ''');
 
     var resolvedLibrary = await session.getResolvedLibraryValid(testPath);
-    var unitElement = resolvedLibrary.element!.definingCompilationUnit;
+    var unitElement = resolvedLibrary.element.definingCompilationUnit;
 
     var fooElement = unitElement.topLevelVariables[0];
     expect(fooElement.name, 'foo');
@@ -563,15 +562,15 @@
 
     expect(resolvedLibrary.units, hasLength(3));
     expect(
-      resolvedLibrary.units![0].path,
+      resolvedLibrary.units[0].path,
       convertPath('/home/test/lib/test.dart'),
     );
     expect(
-      resolvedLibrary.units![1].path,
+      resolvedLibrary.units[1].path,
       convertPath('/home/test/lib/a.dart'),
     );
     expect(
-      resolvedLibrary.units![2].path,
+      resolvedLibrary.units[2].path,
       convertPath('/home/test/lib/c.dart'),
     );
   }
@@ -589,7 +588,7 @@
     expect(result.path, testPath);
     expect(result.uri, Uri.parse('package:test/test.dart'));
     expect(result.units, hasLength(1));
-    expect(result.units![0].unit!.declaredElement, isNotNull);
+    expect(result.units[0].unit.declaredElement, isNotNull);
   }
 
   test_getResolvedLibraryByElement2_differentSession() async {
@@ -603,7 +602,7 @@
     var aaaSession =
         contextCollection.contextFor(aaaContextPath).currentSession;
 
-    var result = await aaaSession.getResolvedLibraryByElement2(element);
+    var result = await aaaSession.getResolvedLibraryByElement(element);
     expect(result, isA<NotElementOfThisSessionResult>());
   }
 
@@ -614,11 +613,11 @@
 ''');
 
     var unitResult =
-        await session.getResolvedUnit2(testPath) as ResolvedUnitResult;
+        await session.getResolvedUnit(testPath) as ResolvedUnitResult;
     expect(unitResult.session, session);
     expect(unitResult.path, testPath);
     expect(unitResult.uri, Uri.parse('package:test/test.dart'));
-    expect(unitResult.unit!.declarations, hasLength(2));
+    expect(unitResult.unit.declarations, hasLength(2));
     expect(unitResult.typeProvider, isNotNull);
     expect(unitResult.libraryElement, isNotNull);
   }
@@ -643,39 +642,39 @@
 
 extension on AnalysisSession {
   Future<UnitElementResult> getUnitElementValid(String path) async {
-    return await getUnitElement2(path) as UnitElementResult;
+    return await getUnitElement(path) as UnitElementResult;
   }
 
   ParsedLibraryResult getParsedLibraryValid(String path) {
-    return getParsedLibrary2(path) as ParsedLibraryResult;
+    return getParsedLibrary(path) as ParsedLibraryResult;
   }
 
   FileResult getFileValid(String path) {
-    return getFile2(path) as FileResult;
+    return getFile(path) as FileResult;
   }
 
   ParsedUnitResult getParsedUnitValid(String path) {
-    return getParsedUnit2(path) as ParsedUnitResult;
+    return getParsedUnit(path) as ParsedUnitResult;
   }
 
   Future<ResolvedLibraryResult> getResolvedLibraryValid(String path) async {
-    return await getResolvedLibrary2(path) as ResolvedLibraryResult;
+    return await getResolvedLibrary(path) as ResolvedLibraryResult;
   }
 
   Future<LibraryElementResult> getLibraryByUriValid(String path) async {
-    return await getLibraryByUri2(path) as LibraryElementResult;
+    return await getLibraryByUri(path) as LibraryElementResult;
   }
 
   Future<ResolvedLibraryResult> getResolvedLibraryByElementValid(
       LibraryElement element) async {
-    return await getResolvedLibraryByElement2(element) as ResolvedLibraryResult;
+    return await getResolvedLibraryByElement(element) as ResolvedLibraryResult;
   }
 
   ParsedLibraryResult getParsedLibraryByElementValid(LibraryElement element) {
-    return getParsedLibraryByElement2(element) as ParsedLibraryResult;
+    return getParsedLibraryByElement(element) as ParsedLibraryResult;
   }
 
   Future<ErrorsResult> getErrorsValid(String path) async {
-    return await getErrors2(path) as ErrorsResult;
+    return await getErrors(path) as ErrorsResult;
   }
 }
diff --git a/pkg/analyzer/test/src/dart/ast/element_locator_test.dart b/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
index b6f51e2..c594940 100644
--- a/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
@@ -46,7 +46,7 @@
   test_locate_CompilationUnit() async {
     await resolveTestCode('// only comment');
 
-    var unitElement = result.unit!.declaredElement!;
+    var unitElement = result.unit.declaredElement!;
 
     var element = ElementLocator.locate(result.unit);
     expect(element, same(unitElement));
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 40ba0f8..1db519f 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -1218,9 +1218,6 @@
     var expression = findNode.topVariableDeclarationByName(name).initializer!;
 
     var unit = this.result.unit;
-    if (unit == null) {
-      throw StateError('analysis result unit is null');
-    }
     var source = unit.declaredElement!.source;
     var errorListener = GatheringErrorListener();
     var errorReporter = ErrorReporter(
diff --git a/pkg/analyzer/test/src/dart/element/class_element_test.dart b/pkg/analyzer/test/src/dart/element/class_element_test.dart
index dbe96a2..c6ed690 100644
--- a/pkg/analyzer/test/src/dart/element/class_element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/class_element_test.dart
@@ -3,7 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../resolution/context_collection_resolution.dart';
@@ -16,6 +18,132 @@
 
 @reflectiveTest
 class ClassElementTest extends PubPackageResolutionTest {
+  test_isEnumLike_false_constructors_hasFactory() async {
+    await assertNoErrorsInCode('''
+class A {
+  factory A._foo() => A._bar();
+  A._bar();
+}
+
+void f() {
+  A._foo();
+}
+''');
+    _assertIsEnumLike(findElement.class_('A'), false);
+  }
+
+  test_isEnumLike_false_constructors_hasPublic() async {
+    await assertNoErrorsInCode('''
+class A {}
+''');
+    _assertIsEnumLike(findElement.class_('A'), false);
+  }
+
+  test_isEnumLike_false_fields_empty() async {
+    await assertNoErrorsInCode('''
+class A {
+  const A._();
+}
+
+void f() {
+  A._();
+}
+''');
+    _assertIsEnumLike(findElement.class_('A'), false);
+  }
+
+  test_isEnumLike_false_isAbstract() async {
+    await assertNoErrorsInCode('''
+abstract class A {}
+''');
+    _assertIsEnumLike(findElement.class_('A'), false);
+  }
+
+  test_isEnumLike_false_isExtended() async {
+    await assertNoErrorsInCode('''
+class A {
+  static const one = A._();
+  static const two = A._();
+  const A._();
+}
+
+class B extends A {
+  B() : super._();
+}
+''');
+    _assertIsEnumLike(findElement.class_('A'), false);
+  }
+
+  test_isEnumLike_false_isMixin() async {
+    await assertNoErrorsInCode('''
+mixin M {}
+''');
+    _assertIsEnumLike(findElement.mixin('M'), false);
+  }
+
+  test_isEnumLike_true() async {
+    await assertNoErrorsInCode('''
+class A {
+  static const one = A._();
+  static const two = A._();
+  const A._();
+}
+''');
+    _assertIsEnumLike(findElement.class_('A'), true);
+  }
+
+  test_isEnumLike_true_hasInstanceField() async {
+    await assertNoErrorsInCode('''
+class A {
+  static const one = A._(1);
+  static const two = A._(2);
+  final int f;
+  const A._(this.f);
+}
+''');
+    _assertIsEnumLike(findElement.class_('A'), true);
+  }
+
+  test_isEnumLike_true_hasSuperclass() async {
+    await assertNoErrorsInCode('''
+class A {
+  const A();
+}
+
+class B extends A {
+  static const one = B._();
+  static const two = B._();
+  const B._();
+}
+''');
+    _assertIsEnumLike(findElement.class_('B'), true);
+  }
+
+  test_isEnumLike_true_hasSyntheticField() async {
+    await assertNoErrorsInCode('''
+class A {
+  static const one = A._();
+  static const two = A._();
+  const A._();
+  int get foo => 0;
+}
+''');
+    _assertIsEnumLike(findElement.class_('A'), true);
+  }
+
+  test_isEnumLike_true_isImplemented() async {
+    await assertNoErrorsInCode('''
+class A {
+  static const one = A._();
+  static const two = A._();
+  const A._();
+}
+
+class B implements A {}
+''');
+    _assertIsEnumLike(findElement.class_('A'), true);
+  }
+
   test_lookUpInheritedConcreteGetter_declared() async {
     await assertNoErrorsInCode('''
 class A {
@@ -1196,6 +1324,10 @@
       A._lookUpInheritedMethod('foo'),
     );
   }
+
+  static void _assertIsEnumLike(ClassElement element, bool expected) {
+    expect((element as ClassElementImpl).isEnumLike, expected);
+  }
 }
 
 extension on ClassElement {
diff --git a/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
index 632677a..ff5c8f9 100644
--- a/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
+++ b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
@@ -155,13 +156,11 @@
       nullabilitySuffix: NullabilitySuffix.none,
     );
     expect(_typeToString(input), 'int Function()');
-    expect(input.aliasElement, same(A));
-    expect(input.aliasArguments!.map(_typeToString).join(', '), 'int');
+    _assertInstantiatedAlias(input, A, 'int');
 
     var result = NullabilityEliminator.perform(typeProvider, input);
     expect(_typeToString(result), 'int* Function()*');
-    expect(result.aliasElement, same(A));
-    expect(result.aliasArguments!.map(_typeToString).join(', '), 'int*');
+    _assertInstantiatedAlias(result, A, 'int*');
   }
 
   test_functionType_typeParameters() {
@@ -278,8 +277,7 @@
 
     var result = NullabilityEliminator.perform(typeProvider, input);
     expect(_typeToString(result), 'List<int*>*');
-    expect(result.aliasElement, same(A));
-    expect(result.aliasArguments!.map(_typeToString).join(', '), 'int*');
+    _assertInstantiatedAlias(result, A, 'int*');
   }
 
   test_interfaceType_int() {
@@ -333,6 +331,13 @@
     _verifySame(typeProvider.voidType);
   }
 
+  void _assertInstantiatedAlias(
+      DartType type, Element aliasElement, String aliasArguments) {
+    var alias = type.alias!;
+    expect(alias.element, same(aliasElement));
+    expect(alias.typeArguments.map(_typeToString).join(', '), aliasArguments);
+  }
+
   String _typeToString(DartType type) {
     return type.getDisplayString(withNullability: true);
   }
diff --git a/pkg/analyzer/test/src/dart/micro/file_resolution.dart b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
index ca6326b..3c85527 100644
--- a/pkg/analyzer/test/src/dart/micro/file_resolution.dart
+++ b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
@@ -74,8 +74,8 @@
   Future<void> resolveTestFile() async {
     var path = convertPath(_testFile);
     result = await resolveFile(path);
-    findNode = FindNode(result.content!, result.unit!);
-    findElement = FindElement(result.unit!);
+    findNode = FindNode(result.content, result.unit);
+    findElement = FindElement(result.unit);
   }
 
   void setUp() {
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 03dd0ff..6e07a14 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -346,6 +346,29 @@
         (fileResolver.byteStore as CiderCachedByteStore).testView!.length);
   }
 
+  test_elements_export_dartCoreDynamic() async {
+    var a_path = convertPath('/workspace/dart/test/lib/a.dart');
+    newFile(a_path, content: r'''
+export 'dart:core' show dynamic;
+''');
+
+    // Analyze so that `dart:core` is linked.
+    var a_result = await resolveFile(a_path);
+
+    // Touch `dart:core` so that its element model is discarded.
+    var dartCorePath = a_result.session.uriConverter.uriToPath(
+      Uri.parse('dart:core'),
+    )!;
+    fileResolver.changeFile(dartCorePath);
+
+    // Analyze, this will read the element model for `dart:core`.
+    // There was a bug that `root::dart:core::dynamic` had no element set.
+    await assertNoErrorsInCode(r'''
+import 'a.dart' as p;
+p.dynamic f() {}
+''');
+  }
+
   test_findReferences_class() async {
     var aPath = convertPath('/workspace/dart/test/lib/a.dart');
     newFile(aPath, content: r'''
@@ -650,34 +673,34 @@
     var path = convertPath('/workspace/dart/test/lib/test.dart');
 
     // No resolved files yet.
-    expect(fileResolver.testView!.resolvedFiles, isEmpty);
+    expect(fileResolver.testView!.resolvedLibraries, isEmpty);
 
     // No cached, will resolve once.
     expect(getTestErrors().errors, hasLength(1));
-    expect(fileResolver.testView!.resolvedFiles, [path]);
+    expect(fileResolver.testView!.resolvedLibraries, [path]);
 
     // Has cached, will be not resolved again.
     expect(getTestErrors().errors, hasLength(1));
-    expect(fileResolver.testView!.resolvedFiles, [path]);
+    expect(fileResolver.testView!.resolvedLibraries, [path]);
 
     // New resolver.
     // Still has cached, will be not resolved.
     createFileResolver();
     expect(getTestErrors().errors, hasLength(1));
-    expect(fileResolver.testView!.resolvedFiles, <Object>[]);
+    expect(fileResolver.testView!.resolvedLibraries, <Object>[]);
 
     // Change the file, new resolver.
     // With changed file the previously cached result cannot be used.
     addTestFile('var a = c;');
     createFileResolver();
     expect(getTestErrors().errors, hasLength(1));
-    expect(fileResolver.testView!.resolvedFiles, [path]);
+    expect(fileResolver.testView!.resolvedLibraries, [path]);
 
     // New resolver.
     // Still has cached, will be not resolved.
     createFileResolver();
     expect(getTestErrors().errors, hasLength(1));
-    expect(fileResolver.testView!.resolvedFiles, <Object>[]);
+    expect(fileResolver.testView!.resolvedLibraries, <Object>[]);
   }
 
   test_getErrors_reuse_changeDependency() {
@@ -693,15 +716,15 @@
     var path = convertPath('/workspace/dart/test/lib/test.dart');
 
     // No resolved files yet.
-    expect(fileResolver.testView!.resolvedFiles, isEmpty);
+    expect(fileResolver.testView!.resolvedLibraries, isEmpty);
 
     // No cached, will resolve once.
     expect(getTestErrors().errors, hasLength(1));
-    expect(fileResolver.testView!.resolvedFiles, [path]);
+    expect(fileResolver.testView!.resolvedLibraries, [path]);
 
     // Has cached, will be not resolved again.
     expect(getTestErrors().errors, hasLength(1));
-    expect(fileResolver.testView!.resolvedFiles, [path]);
+    expect(fileResolver.testView!.resolvedLibraries, [path]);
 
     // Change the dependency, new resolver.
     // The signature of the result is different.
@@ -711,13 +734,13 @@
 ''');
     createFileResolver();
     expect(getTestErrors().errors, hasLength(1));
-    expect(fileResolver.testView!.resolvedFiles, [path]);
+    expect(fileResolver.testView!.resolvedLibraries, [path]);
 
     // New resolver.
     // Still has cached, will be not resolved.
     createFileResolver();
     expect(getTestErrors().errors, hasLength(1));
-    expect(fileResolver.testView!.resolvedFiles, <Object>[]);
+    expect(fileResolver.testView!.resolvedLibraries, <Object>[]);
   }
 
   test_getLibraryByUri() {
@@ -1007,7 +1030,7 @@
 }
 ''');
 
-    _assertDiscoveredLibraryForParts([result.path!]);
+    _assertDiscoveredLibraryForParts([result.path]);
   }
 
   test_resolve_part_of_uri() async {
@@ -1028,7 +1051,7 @@
 }
 ''');
 
-    _assertDiscoveredLibraryForParts([result.path!]);
+    _assertDiscoveredLibraryForParts([result.path]);
   }
 
   test_resolveFile_cache() async {
@@ -1036,17 +1059,21 @@
     newFile(path, content: 'var a = 0;');
 
     // No resolved files yet.
-    expect(fileResolver.testView!.resolvedFiles, isEmpty);
+    var testView = fileResolver.testView!;
+    expect(testView.resolvedLibraries, isEmpty);
 
     await resolveFile2(path);
     var result1 = result;
 
     // The file was resolved.
-    expect(fileResolver.testView!.resolvedFiles, [path]);
+    expect(testView.resolvedLibraries, [path]);
+
+    // The result is cached.
+    expect(fileResolver.cachedResults, contains(path));
 
     // Ask again, no changes, not resolved.
     await resolveFile2(path);
-    expect(fileResolver.testView!.resolvedFiles, [path]);
+    expect(testView.resolvedLibraries, [path]);
 
     // The same result was returned.
     expect(result, same(result1));
@@ -1057,12 +1084,41 @@
 
     // The was a change to a file, no matter which, resolve again.
     await resolveFile2(path);
-    expect(fileResolver.testView!.resolvedFiles, [path, path]);
+    expect(testView.resolvedLibraries, [path, path]);
 
     // Get should get a new result.
     expect(result, isNot(same(result1)));
   }
 
+  test_resolveFile_dontCache_whenForCompletion() async {
+    var a_path = convertPath('/workspace/dart/test/lib/a.dart');
+    newFile(a_path, content: r'''
+part 'b.dart';
+''');
+
+    var b_path = convertPath('/workspace/dart/test/lib/b.dart');
+    newFile(b_path, content: r'''
+part of 'a.dart';
+''');
+
+    // No resolved files yet.
+    var testView = fileResolver.testView!;
+    expect(testView.resolvedLibraries, isEmpty);
+
+    fileResolver.resolve(
+      path: b_path,
+      completionLine: 0,
+      completionColumn: 0,
+    );
+
+    // The file was resolved.
+    expect(testView.resolvedLibraries, [a_path]);
+
+    // The completion location was set, so not units are resolved.
+    // So, the result should not be cached.
+    expect(fileResolver.cachedResults, isEmpty);
+  }
+
   test_resolveLibrary() async {
     var aPath = convertPath('/workspace/dart/test/lib/a.dart');
     newFile(aPath, content: r'''
@@ -1084,7 +1140,7 @@
 
     var result = fileResolver.resolveLibrary(path: aPath);
     expect(result.path, aPath);
-    expect(result.units?.length, 2);
+    expect(result.units.length, 2);
   }
 
   test_reuse_compatibleOptions() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
index 2fb3462..b2bceea 100644
--- a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
@@ -351,7 +351,7 @@
     List<String> expectedArguments,
   ) {
     var argumentStrings = argumentList.arguments
-        .map((e) => result.content!.substring(e.offset, e.end))
+        .map((e) => result.content.substring(e.offset, e.end))
         .toList();
     expect(argumentStrings, expectedArguments);
   }
@@ -383,7 +383,7 @@
     }
 
     var argumentStrings = argumentList.arguments
-        .map((e) => result.content!.substring(e.offset, e.end))
+        .map((e) => result.content.substring(e.offset, e.end))
         .toList();
     expect(argumentStrings, expectedArguments);
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
index 7d71d57..2e49834 100644
--- a/pkg/analyzer/test/src/dart/resolution/constant_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -214,7 +214,7 @@
     result = await resolveFile(convertPath('$testPackageLibPath/a.dart'));
     assertErrorsInResolvedUnit(result, []);
 
-    var bElement = FindElement(result.unit!).field('b') as ConstVariableElement;
+    var bElement = FindElement(result.unit).field('b') as ConstVariableElement;
     var bValue = bElement.evaluationResult!.value!;
     var superFields = bValue.getField(GenericState.SUPERCLASS_FIELD);
     expect(superFields!.getField('f1')!.toBoolValue(), false);
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 27ec665..afc3556 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -190,7 +190,7 @@
   Future<ResolvedUnitResult> resolveFile(String path) async {
     var analysisContext = contextFor(pathForContextSelection ?? path);
     var session = analysisContext.currentSession;
-    return await session.getResolvedUnit2(path) as ResolvedUnitResult;
+    return await session.getResolvedUnit(path) as ResolvedUnitResult;
   }
 
   @mustCallSuper
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index 9922d73..3675f92 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -28,23 +28,210 @@
     assertType(reference, 'dynamic');
   }
 
-  test_instanceGetter_explicitReceiver() async {
-    // This test is here to assert that the resolver does not throw, but in the
-    // future, an error should be reported here as well.
+  test_explicitReceiver_unknown_multipleProperties() async {
+    await assertErrorsInCode('''
+bar() {
+  a.b.foo<int>;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 1),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'dynamic');
+  }
+
+  test_extensionGetter_extensionOverride() async {
+    await assertErrorsInCode('''
+class A {}
+
+extension E on A {
+  int get foo => 0;
+}
+
+bar(A a) {
+  E(a).foo<int>;
+}
+''', [
+      error(
+          CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 67, 8),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'dynamic');
+  }
+
+  test_extensionMethod() async {
+    await assertNoErrorsInCode('''
+class A {}
+
+extension E on A {
+  void foo<T>(T a) {}
+
+  bar() {
+    foo<int>;
+  }
+}
+''');
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertFunctionReference(
+        reference, findElement.method('foo'), 'void Function(int)');
+  }
+
+  test_extensionMethod_explicitReceiver_this() async {
+    await assertNoErrorsInCode('''
+class A {}
+
+extension E on A {
+  void foo<T>(T a) {}
+
+  bar() {
+    this.foo<int>;
+  }
+}
+''');
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertFunctionReference(
+        reference, findElement.method('foo'), 'void Function(int)');
+  }
+
+  test_extensionMethod_extensionOverride() async {
     await assertNoErrorsInCode('''
 class A {
   int foo = 0;
 }
 
+extension E on A {
+  void foo<T>(T a) {}
+}
+
 bar(A a) {
-  a.foo<int>;
+  E(a).foo<int>;
 }
 ''');
 
     var reference = findNode.functionReference('foo<int>;');
+    assertFunctionReference(
+        reference, findElement.method('foo'), 'void Function(int)');
+  }
+
+  test_extensionMethod_extensionOverride_cascade() async {
+    await assertErrorsInCode('''
+class A {
+  int foo = 0;
+}
+
+extension E on A {
+  void foo<T>(T a) {}
+}
+
+bar(A a) {
+  E(a)..foo<int>;
+}
+''', [
+      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 85, 1),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertFunctionReference(
+        reference, findElement.method('foo'), 'void Function(int)');
+  }
+
+  test_extensionMethod_extensionOverride_static() async {
+    await assertErrorsInCode('''
+class A {}
+
+extension E on A {
+  static void foo<T>(T a) {}
+}
+
+bar(A a) {
+  E(a).foo<int>;
+}
+''', [
+      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER, 81,
+          3),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertFunctionReference(
+        reference, findElement.method('foo'), 'void Function(int)');
+  }
+
+  test_extensionMethod_extensionOverride_unknown() async {
+    await assertErrorsInCode('''
+class A {}
+
+extension E on A {}
+
+bar(A a) {
+  E(a).foo<int>;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER, 51, 3),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
     assertType(reference, 'dynamic');
   }
 
+  test_extensionMethod_fromClassDeclaration() async {
+    await assertNoErrorsInCode('''
+class A {
+  bar() {
+    foo<int>;
+  }
+}
+
+extension E on A {
+  void foo<T>(T a) {}
+}
+''');
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertFunctionReference(
+        reference, findElement.method('foo'), 'void Function(int)');
+  }
+
+  test_instanceGetter() async {
+    await assertErrorsInCode('''
+abstract class A {
+  late void Function<T>(T) foo;
+
+  bar() {
+    foo<int>;
+  }
+}
+
+''', [
+      error(
+          CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 66, 3),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'void Function(int)');
+  }
+
+  test_instanceGetter_explicitReceiver() async {
+    await assertErrorsInCode('''
+class A {
+  late void Function<T>(T) foo;
+}
+
+bar(A a) {
+  a.foo<int>;
+}
+''', [
+      error(
+          CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 58, 5),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'void Function(int)');
+  }
+
   test_instanceMethod() async {
     await assertNoErrorsInCode('''
 class A {
@@ -81,6 +268,21 @@
         reference, findElement.method('foo'), 'void Function(int)');
   }
 
+  test_instanceMethod_explicitReceiver_otherExpression() async {
+    await assertNoErrorsInCode('''
+class A {
+  void foo<T>(T a) {}
+}
+
+void f(A? a, A b) {
+  (a ?? b).foo<int>;
+}
+''');
+
+    var reference = findNode.functionReference('(a ?? b).foo<int>;');
+    assertType(reference, 'void Function(int)');
+  }
+
   test_instanceMethod_explicitReceiver_super() async {
     await assertNoErrorsInCode('''
 class A {
@@ -184,6 +386,27 @@
         'void Function(int)');
   }
 
+  test_instanceMethod_explicitReceiver_topLevelVariable_prefix_unknown() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+class A {}
+var a = A();
+''');
+    await assertErrorsInCode('''
+import 'a.dart' as prefix;
+
+bar() {
+  prefix.a.foo<int>;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_GETTER, 47, 3),
+    ]);
+
+    assertImportPrefix(
+        findNode.simple('prefix.'), findElement.prefix('prefix'));
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'dynamic');
+  }
+
   test_instanceMethod_explicitReceiver_typeParameter() async {
     await assertErrorsInCode('''
 bar<T>() {
@@ -213,6 +436,55 @@
         reference, findElement.method('foo'), 'void Function(int)');
   }
 
+  test_instanceMethod_explicitReceiver_variable_cascade() async {
+    await assertNoErrorsInCode('''
+class A {
+  void foo<T>(T a) {}
+}
+
+bar(A a) {
+  a..foo<int>;
+}
+''');
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertFunctionReference(
+        reference, findElement.method('foo'), 'void Function(int)');
+  }
+
+  test_instanceMethod_inherited() async {
+    await assertNoErrorsInCode('''
+class A {
+  void foo<T>(T a) {}
+}
+
+class B extends A {
+  bar() {
+    foo<int>;
+  }
+}
+''');
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertFunctionReference(
+        reference, findElement.method('foo'), 'void Function(int)');
+  }
+
+  test_instanceMethod_unknown() async {
+    await assertErrorsInCode('''
+class A {
+  bar() {
+    foo<int>;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_METHOD, 24, 3),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'dynamic');
+  }
+
   test_localFunction() async {
     await assertNoErrorsInCode('''
 void bar() {
@@ -228,11 +500,29 @@
   }
 
   test_localVariable() async {
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode('''
 void bar(void Function<T>(T a) foo) {
   foo<int>;
 }
-''');
+''', [
+      error(
+          CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 40, 3),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertFunctionReference(
+        reference, findElement.parameter('foo'), 'void Function(int)');
+  }
+
+  test_localVariable_typeVariable() async {
+    await assertErrorsInCode('''
+void bar<T extends void Function<U>(U)>(T foo) {
+  foo<int>;
+}
+''', [
+      error(
+          CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 51, 3),
+    ]);
 
     var reference = findNode.functionReference('foo<int>;');
     assertFunctionReference(
@@ -258,6 +548,40 @@
         reference, findElement.method('foo'), 'void Function()');
   }
 
+  test_otherExpression() async {
+    await assertErrorsInCode('''
+void f(void Function<T>(T a) foo, void Function<T>(T a) bar) {
+  (1 == 2 ? foo : bar)<int>;
+}
+''', [
+      error(CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 65,
+          20),
+    ]);
+
+    var reference = findNode.functionReference('(1 == 2 ? foo : bar)<int>;');
+    assertType(reference, 'void Function(int)');
+  }
+
+  test_otherExpression_wrongNumberOfTypeArguments() async {
+    await assertErrorsInCode('''
+void f(void Function<T>(T a) foo, void Function<T>(T a) bar) {
+  (1 == 2 ? foo : bar)<int, String>;
+}
+''', [
+      error(CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 65,
+          20),
+      error(
+          CompileTimeErrorCode
+              .WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
+          85,
+          13),
+    ]);
+
+    var reference =
+        findNode.functionReference('(1 == 2 ? foo : bar)<int, String>;');
+    assertType(reference, 'void Function(dynamic)');
+  }
+
   test_staticMethod() async {
     await assertNoErrorsInCode('''
 class A {
@@ -453,6 +777,37 @@
     );
   }
 
+  test_topLevelFunction_prefix_unknownPrefix() async {
+    await assertErrorsInCode('''
+bar() {
+  prefix.foo<int>;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 6),
+    ]);
+
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'dynamic');
+  }
+
+  test_topLevelVariable_prefix_unknownIdentifier() async {
+    newFile('$testPackageLibPath/a.dart', content: '');
+    await assertErrorsInCode('''
+import 'a.dart' as prefix;
+
+bar() {
+  prefix.a.foo<int>;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME, 45, 1),
+    ]);
+
+    assertImportPrefix(
+        findNode.simple('prefix.'), findElement.prefix('prefix'));
+    var reference = findNode.functionReference('foo<int>;');
+    assertType(reference, 'dynamic');
+  }
+
   test_typeAlias_function_unknownProperty() async {
     await assertErrorsInCode('''
 typedef Cb = void Function();
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
index 206f003..4d27277 100644
--- a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/instance_creation_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/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -10,6 +11,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(InstanceCreationTest);
+    defineReflectiveTests(InstanceCreationWithoutConstructorTearoffsTest);
   });
 }
 
@@ -426,4 +428,75 @@
       expectedSubstitution: {'T': 'String'},
     );
   }
+
+  test_unnamed_declaredNew() async {
+    await assertNoErrorsInCode('''
+class A {
+  A.new(int a);
+}
+
+void f() {
+  A(0);
+}
+
+''');
+
+    var creation = findNode.instanceCreation('A(0)');
+    assertInstanceCreation(creation, findElement.class_('A'), 'A');
+  }
+
+  test_unnamedViaNew_declaredNew() async {
+    await assertNoErrorsInCode('''
+class A {
+  A.new(int a);
+}
+
+void f() {
+  A.new(0);
+}
+
+''');
+
+    var creation = findNode.instanceCreation('A.new(0)');
+    assertInstanceCreation(creation, findElement.class_('A'), 'A');
+  }
+
+  test_unnamedViaNew_declaredUnnamed() async {
+    await assertNoErrorsInCode('''
+class A {
+  A(int a);
+}
+
+void f() {
+  A.new(0);
+}
+
+''');
+
+    var creation = findNode.instanceCreation('A.new(0)');
+    assertInstanceCreation(creation, findElement.class_('A'), 'A');
+  }
+}
+
+@reflectiveTest
+class InstanceCreationWithoutConstructorTearoffsTest
+    extends PubPackageResolutionTest with WithoutConstructorTearoffsMixin {
+  test_unnamedViaNew() async {
+    await assertErrorsInCode('''
+class A {
+  A(int a);
+}
+
+void f() {
+  A.new(0);
+}
+
+''', [
+      error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 40, 3),
+    ]);
+
+    // Resolution should continue even though the experiment is not enabled.
+    var creation = findNode.instanceCreation('A.new(0)');
+    assertInstanceCreation(creation, findElement.class_('A'), 'A');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart b/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
index 213fbbb..ddad876 100644
--- a/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
@@ -11,7 +11,6 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(LocalVariableResolutionTest);
-    defineReflectiveTests(LocalVariableResolutionWithNullSafetyTest);
   });
 }
 
@@ -95,11 +94,7 @@
     expect(x.isLate, isFalse);
     expect(x.isStatic, isFalse);
   }
-}
 
-@reflectiveTest
-class LocalVariableResolutionWithNullSafetyTest
-    extends LocalVariableResolutionTest with WithNullSafetyMixin {
   test_element_late() async {
     await assertErrorsInCode(r'''
 void f() {
diff --git a/pkg/analyzer/test/src/dart/resolution/macro_test.dart b/pkg/analyzer/test/src/dart/resolution/macro_test.dart
new file mode 100644
index 0000000..4dd8ebc
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/macro_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.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/elements_types_mixin.dart';
+import 'context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MacroResolutionTest);
+  });
+}
+
+@reflectiveTest
+class MacroResolutionTest extends PubPackageResolutionTest
+    with ElementsTypesMixin {
+  @override
+  void setUp() {
+    super.setUp();
+
+    newFile('$testPackageLibPath/macro_annotations.dart', content: r'''
+library analyzer.macro.annotations;
+const observable = 0;
+''');
+  }
+
+  test_observable() async {
+    await assertErrorsInCode(r'''
+import 'macro_annotations.dart';
+
+class A {
+  @observable
+  int _foo = 0;
+}
+
+void f(A a) {
+  a.foo;
+  a.foo = 2;
+}
+''', [
+      error(HintCode.UNUSED_FIELD, 64, 4),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
index e32e7e8..daa949c 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -152,7 +152,7 @@
   }
 
   void _fillLibraries([LibraryElement? library]) {
-    library ??= result.unit!.declaredElement!.library;
+    library ??= result.unit.declaredElement!.library;
     var uriStr = library.source.uri.toString();
     if (!libraries.containsKey(uriStr)) {
       libraries[uriStr] = library;
diff --git a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
index 094323e..2c5f443 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -12,13 +12,298 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PostfixExpressionResolutionTest);
-    defineReflectiveTests(PostfixExpressionResolutionWithNullSafetyTest);
+    defineReflectiveTests(PostfixExpressionResolutionWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class PostfixExpressionResolutionTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with PostfixExpressionResolutionTestCases {
+  test_inc_propertyAccess_nullShorting() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int foo = 0;
+}
+
+void f(A? a) {
+  a?.foo++;
+}
+''');
+
+    assertPostfixExpression(
+      findNode.postfix('foo++'),
+      readElement: findElement.getter('foo'),
+      readType: 'int',
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      element: numElement.getMethod('+'),
+      type: 'int?',
+    );
+  }
+
+  test_inc_simpleIdentifier_parameter_depromote() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  Object operator +(int _) => this;
+}
+
+void f(Object x) {
+  if (x is A) {
+    x++;
+    x; // ref
+  }
+}
+''');
+
+    if (hasAssignmentLeftResolution) {
+      assertType(findNode.simple('x++;'), 'A');
+    }
+
+    assertPostfixExpression(
+      findNode.postfix('x++'),
+      readElement: findElement.parameter('x'),
+      readType: 'A',
+      writeElement: findElement.parameter('x'),
+      writeType: 'Object',
+      element: findElement.method('+'),
+      type: 'A',
+    );
+
+    assertType(findNode.simple('x; // ref'), 'Object');
+  }
+
+  test_nullCheck() async {
+    await assertNoErrorsInCode(r'''
+void f(int? x) {
+  x!;
+}
+''');
+
+    assertPostfixExpression(
+      findNode.postfix('x!'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'int',
+    );
+  }
+
+  test_nullCheck_functionExpressionInvocation_rewrite() async {
+    await assertNoErrorsInCode(r'''
+void f(Function f2) {
+  f2(42)!;
+}
+''');
+  }
+
+  test_nullCheck_indexExpression() async {
+    await assertNoErrorsInCode(r'''
+void f(Map<String, int> a) {
+  int v = a['foo']!;
+  v;
+}
+''');
+
+    assertIndexExpression(
+      findNode.index('a['),
+      readElement: elementMatcher(
+        mapElement.getMethod('[]'),
+        substitution: {'K': 'String', 'V': 'int'},
+      ),
+      writeElement: null,
+      type: 'int?',
+    );
+
+    assertPostfixExpression(
+      findNode.postfix(']!'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'int',
+    );
+  }
+
+  test_nullCheck_null() async {
+    await assertErrorsInCode('''
+void f(Null x) {
+  x!;
+}
+''', [
+      error(HintCode.NULL_CHECK_ALWAYS_FAILS, 19, 2),
+    ]);
+
+    assertType(findNode.postfix('x!'), 'Never');
+  }
+
+  test_nullCheck_nullableContext() async {
+    await assertNoErrorsInCode(r'''
+T f<T>(T t) => t;
+
+int g() => f(null)!;
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('f(null)'),
+      element: findElement.topFunction('f'),
+      typeArgumentTypes: ['int?'],
+      invokeType: 'int? Function(int?)',
+      type: 'int?',
+    );
+
+    assertPostfixExpression(
+      findNode.postfix('f(null)!'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'int',
+    );
+  }
+
+  /// See https://github.com/dart-lang/language/issues/1163
+  test_nullCheck_participatesNullShorting() async {
+    await assertErrorsInCode('''
+class A {
+  int zero;
+  int? zeroOrNull;
+
+  A(this.zero, [this.zeroOrNull]);
+}
+
+void test1(A? a) => a?.zero!;
+void test2(A? a) => a?.zeroOrNull!;
+void test3(A? a) => a?.zero!.isEven;
+void test4(A? a) => a?.zeroOrNull!.isEven;
+
+class Foo {
+  Bar? bar;
+
+  Foo(this.bar);
+
+  Bar? operator [](int? index) => null;
+}
+
+class Bar {
+  int baz;
+
+  Bar(this.baz);
+
+  int operator [](int index) => index;
+}
+
+void test5(Foo? foo) => foo?.bar!;
+void test6(Foo? foo) => foo?.bar!.baz;
+void test7(Foo? foo, int a) => foo?.bar![a];
+void test8(Foo? foo, int? a) => foo?[a]!;
+void test9(Foo? foo, int? a) => foo?[a]!.baz;
+void test10(Foo? foo, int? a, int b) => foo?[a]![b];
+''', [
+      error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 107, 1),
+      error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 173, 1),
+    ]);
+
+    void assertTestType(int index, String expected) {
+      var function = findNode.functionDeclaration('test$index(');
+      var body = function.functionExpression.body as ExpressionFunctionBody;
+      assertType(body.expression, expected);
+    }
+
+    assertTestType(1, 'int?');
+    assertTestType(2, 'int?');
+    assertTestType(3, 'bool?');
+    assertTestType(4, 'bool?');
+
+    assertTestType(5, 'Bar?');
+    assertTestType(6, 'int?');
+    assertTestType(7, 'int?');
+    assertTestType(8, 'Bar?');
+    assertTestType(9, 'int?');
+    assertTestType(10, 'int?');
+  }
+
+  test_nullCheck_superExpression() async {
+    await assertErrorsInCode(r'''
+class A {
+  int foo() => 0;
+}
+
+class B extends A {
+  void bar() {
+    super!.foo();
+  }
+}
+''', [
+      error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 70, 6),
+    ]);
+
+    assertTypeDynamic(findNode.super_('super!'));
+
+    assertPostfixExpression(
+      findNode.postfix('super!'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'dynamic',
+    );
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('foo();'),
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
+    );
+  }
+
+  test_nullCheck_typeParameter() async {
+    await assertNoErrorsInCode(r'''
+void f<T>(T? x) {
+  x!;
+}
+''');
+
+    var postfixExpression = findNode.postfix('x!');
+    assertPostfixExpression(
+      postfixExpression,
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'T & Object',
+    );
+  }
+
+  test_nullCheck_typeParameter_already_promoted() async {
+    await assertNoErrorsInCode('''
+void f<T>(T? x) {
+  if (x is num?) {
+    x!;
+  }
+}
+''');
+
+    var postfixExpression = findNode.postfix('x!');
+    assertPostfixExpression(
+      postfixExpression,
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'T & num',
+    );
+  }
+}
+
+mixin PostfixExpressionResolutionTestCases on PubPackageResolutionTest {
   test_dec_simpleIdentifier_parameter_int() async {
     await assertNoErrorsInCode(r'''
 void f(int x) {
@@ -484,288 +769,6 @@
 }
 
 @reflectiveTest
-class PostfixExpressionResolutionWithNullSafetyTest
-    extends PostfixExpressionResolutionTest with WithNullSafetyMixin {
-  test_inc_propertyAccess_nullShorting() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int foo = 0;
-}
-
-void f(A? a) {
-  a?.foo++;
-}
-''');
-
-    assertPostfixExpression(
-      findNode.postfix('foo++'),
-      readElement: findElement.getter('foo'),
-      readType: 'int',
-      writeElement: findElement.setter('foo'),
-      writeType: 'int',
-      element: numElement.getMethod('+'),
-      type: 'int?',
-    );
-  }
-
-  test_inc_simpleIdentifier_parameter_depromote() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  Object operator +(int _) => this;
-}
-
-void f(Object x) {
-  if (x is A) {
-    x++;
-    x; // ref
-  }
-}
-''');
-
-    if (hasAssignmentLeftResolution) {
-      assertType(findNode.simple('x++;'), 'A');
-    }
-
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.parameter('x'),
-      readType: 'A',
-      writeElement: findElement.parameter('x'),
-      writeType: 'Object',
-      element: findElement.method('+'),
-      type: 'A',
-    );
-
-    assertType(findNode.simple('x; // ref'), 'Object');
-  }
-
-  test_nullCheck() async {
-    await assertNoErrorsInCode(r'''
-void f(int? x) {
-  x!;
-}
-''');
-
-    assertPostfixExpression(
-      findNode.postfix('x!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'int',
-    );
-  }
-
-  test_nullCheck_functionExpressionInvocation_rewrite() async {
-    await assertNoErrorsInCode(r'''
-void f(Function f2) {
-  f2(42)!;
-}
-''');
-  }
-
-  test_nullCheck_indexExpression() async {
-    await assertNoErrorsInCode(r'''
-void f(Map<String, int> a) {
-  int v = a['foo']!;
-  v;
-}
-''');
-
-    assertIndexExpression(
-      findNode.index('a['),
-      readElement: elementMatcher(
-        mapElement.getMethod('[]'),
-        substitution: {'K': 'String', 'V': 'int'},
-      ),
-      writeElement: null,
-      type: 'int?',
-    );
-
-    assertPostfixExpression(
-      findNode.postfix(']!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'int',
-    );
-  }
-
-  test_nullCheck_null() async {
-    await assertErrorsInCode('''
-void f(Null x) {
-  x!;
-}
-''', [
-      error(HintCode.NULL_CHECK_ALWAYS_FAILS, 19, 2),
-    ]);
-
-    assertType(findNode.postfix('x!'), 'Never');
-  }
-
-  test_nullCheck_nullableContext() async {
-    await assertNoErrorsInCode(r'''
-T f<T>(T t) => t;
-
-int g() => f(null)!;
-''');
-
-    assertMethodInvocation2(
-      findNode.methodInvocation('f(null)'),
-      element: findElement.topFunction('f'),
-      typeArgumentTypes: ['int?'],
-      invokeType: 'int? Function(int?)',
-      type: 'int?',
-    );
-
-    assertPostfixExpression(
-      findNode.postfix('f(null)!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'int',
-    );
-  }
-
-  /// See https://github.com/dart-lang/language/issues/1163
-  test_nullCheck_participatesNullShorting() async {
-    await assertErrorsInCode('''
-class A {
-  int zero;
-  int? zeroOrNull;
-
-  A(this.zero, [this.zeroOrNull]);
-}
-
-void test1(A? a) => a?.zero!;
-void test2(A? a) => a?.zeroOrNull!;
-void test3(A? a) => a?.zero!.isEven;
-void test4(A? a) => a?.zeroOrNull!.isEven;
-
-class Foo {
-  Bar? bar;
-
-  Foo(this.bar);
-
-  Bar? operator [](int? index) => null;
-}
-
-class Bar {
-  int baz;
-
-  Bar(this.baz);
-
-  int operator [](int index) => index;
-}
-
-void test5(Foo? foo) => foo?.bar!;
-void test6(Foo? foo) => foo?.bar!.baz;
-void test7(Foo? foo, int a) => foo?.bar![a];
-void test8(Foo? foo, int? a) => foo?[a]!;
-void test9(Foo? foo, int? a) => foo?[a]!.baz;
-void test10(Foo? foo, int? a, int b) => foo?[a]![b];
-''', [
-      error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 107, 1),
-      error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 173, 1),
-    ]);
-
-    void assertTestType(int index, String expected) {
-      var function = findNode.functionDeclaration('test$index(');
-      var body = function.functionExpression.body as ExpressionFunctionBody;
-      assertType(body.expression, expected);
-    }
-
-    assertTestType(1, 'int?');
-    assertTestType(2, 'int?');
-    assertTestType(3, 'bool?');
-    assertTestType(4, 'bool?');
-
-    assertTestType(5, 'Bar?');
-    assertTestType(6, 'int?');
-    assertTestType(7, 'int?');
-    assertTestType(8, 'Bar?');
-    assertTestType(9, 'int?');
-    assertTestType(10, 'int?');
-  }
-
-  test_nullCheck_superExpression() async {
-    await assertErrorsInCode(r'''
-class A {
-  int foo() => 0;
-}
-
-class B extends A {
-  void bar() {
-    super!.foo();
-  }
-}
-''', [
-      error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 70, 6),
-    ]);
-
-    assertTypeDynamic(findNode.super_('super!'));
-
-    assertPostfixExpression(
-      findNode.postfix('super!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'dynamic',
-    );
-
-    assertMethodInvocation2(
-      findNode.methodInvocation('foo();'),
-      element: null,
-      typeArgumentTypes: [],
-      invokeType: 'dynamic',
-      type: 'dynamic',
-    );
-  }
-
-  test_nullCheck_typeParameter() async {
-    await assertNoErrorsInCode(r'''
-void f<T>(T? x) {
-  x!;
-}
-''');
-
-    var postfixExpression = findNode.postfix('x!');
-    assertPostfixExpression(
-      postfixExpression,
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'T & Object',
-    );
-  }
-
-  test_nullCheck_typeParameter_already_promoted() async {
-    await assertNoErrorsInCode('''
-void f<T>(T? x) {
-  if (x is num?) {
-    x!;
-  }
-}
-''');
-
-    var postfixExpression = findNode.postfix('x!');
-    assertPostfixExpression(
-      postfixExpression,
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'T & num',
-    );
-  }
-}
+class PostfixExpressionResolutionWithoutNullSafetyTest
+    extends PubPackageResolutionTest
+    with PostfixExpressionResolutionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
index 06fd33d..1fa6d56 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
@@ -12,13 +12,140 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PrefixExpressionResolutionTest);
-    defineReflectiveTests(PrefixExpressionResolutionWithNullSafetyTest);
+    defineReflectiveTests(PrefixExpressionResolutionWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class PrefixExpressionResolutionTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with PrefixExpressionResolutionTestCases {
+  test_bang_no_nullShorting() async {
+    await assertErrorsInCode(r'''
+class A {
+  bool get foo => true;
+}
+
+void f(A? a) {
+  !a?.foo;
+}
+''', [
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+          55, 6),
+    ]);
+
+    assertPrefixExpression(
+      findNode.prefix('!a'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: boolElement.getMethod('!'),
+      type: 'bool',
+    );
+  }
+
+  test_minus_no_nullShorting() async {
+    await assertErrorsInCode(r'''
+class A {
+  int get foo => 0;
+}
+
+void f(A? a) {
+  -a?.foo;
+}
+''', [
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          50, 1),
+    ]);
+
+    assertPrefixExpression(
+      findNode.prefix('-a'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: intElement.getMethod('unary-'),
+      type: 'int',
+    );
+  }
+
+  test_plusPlus_depromote() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  Object operator +(int _) => this;
+}
+
+void f(Object x) {
+  if (x is A) {
+    ++x;
+  }
+}
+''');
+
+    assertPrefixExpression(
+      findNode.prefix('++x'),
+      readElement: findElement.parameter('x'),
+      readType: 'A',
+      writeElement: findElement.parameter('x'),
+      writeType: 'Object',
+      element: findElement.method('+'),
+      type: 'Object',
+    );
+
+    if (hasAssignmentLeftResolution) {
+      assertType(findNode.simple('x;'), 'A');
+    }
+  }
+
+  test_plusPlus_nullShorting() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int foo = 0;
+}
+
+void f(A? a) {
+  ++a?.foo;
+}
+''');
+
+    assertPrefixExpression(
+      findNode.prefix('++a'),
+      readElement: findElement.getter('foo'),
+      readType: 'int',
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      element: numElement.getMethod('+'),
+      type: 'int?',
+    );
+  }
+
+  test_tilde_no_nullShorting() async {
+    await assertErrorsInCode(r'''
+class A {
+  int get foo => 0;
+}
+
+void f(A? a) {
+  ~a?.foo;
+}
+''', [
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          50, 1),
+    ]);
+
+    assertPrefixExpression(
+      findNode.prefix('~a'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: intElement.getMethod('~'),
+      type: 'int',
+    );
+  }
+}
+
+mixin PrefixExpressionResolutionTestCases on PubPackageResolutionTest {
   test_bang_bool_context() async {
     await assertNoErrorsInCode(r'''
 T f<T>() {
@@ -637,130 +764,6 @@
 }
 
 @reflectiveTest
-class PrefixExpressionResolutionWithNullSafetyTest
-    extends PrefixExpressionResolutionTest with WithNullSafetyMixin {
-  test_bang_no_nullShorting() async {
-    await assertErrorsInCode(r'''
-class A {
-  bool get foo => true;
-}
-
-void f(A? a) {
-  !a?.foo;
-}
-''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
-          55, 6),
-    ]);
-
-    assertPrefixExpression(
-      findNode.prefix('!a'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: boolElement.getMethod('!'),
-      type: 'bool',
-    );
-  }
-
-  test_minus_no_nullShorting() async {
-    await assertErrorsInCode(r'''
-class A {
-  int get foo => 0;
-}
-
-void f(A? a) {
-  -a?.foo;
-}
-''', [
-      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
-          50, 1),
-    ]);
-
-    assertPrefixExpression(
-      findNode.prefix('-a'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: intElement.getMethod('unary-'),
-      type: 'int',
-    );
-  }
-
-  test_plusPlus_depromote() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  Object operator +(int _) => this;
-}
-
-void f(Object x) {
-  if (x is A) {
-    ++x;
-  }
-}
-''');
-
-    assertPrefixExpression(
-      findNode.prefix('++x'),
-      readElement: findElement.parameter('x'),
-      readType: 'A',
-      writeElement: findElement.parameter('x'),
-      writeType: 'Object',
-      element: findElement.method('+'),
-      type: 'Object',
-    );
-
-    if (hasAssignmentLeftResolution) {
-      assertType(findNode.simple('x;'), 'A');
-    }
-  }
-
-  test_plusPlus_nullShorting() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int foo = 0;
-}
-
-void f(A? a) {
-  ++a?.foo;
-}
-''');
-
-    assertPrefixExpression(
-      findNode.prefix('++a'),
-      readElement: findElement.getter('foo'),
-      readType: 'int',
-      writeElement: findElement.setter('foo'),
-      writeType: 'int',
-      element: numElement.getMethod('+'),
-      type: 'int?',
-    );
-  }
-
-  test_tilde_no_nullShorting() async {
-    await assertErrorsInCode(r'''
-class A {
-  int get foo => 0;
-}
-
-void f(A? a) {
-  ~a?.foo;
-}
-''', [
-      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
-          50, 1),
-    ]);
-
-    assertPrefixExpression(
-      findNode.prefix('~a'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: intElement.getMethod('~'),
-      type: 'int',
-    );
-  }
-}
+class PrefixExpressionResolutionWithoutNullSafetyTest
+    extends PubPackageResolutionTest
+    with PrefixExpressionResolutionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
index b95d627..e3ef89b 100644
--- a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -11,13 +11,168 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PropertyAccessResolutionTest);
-    defineReflectiveTests(PropertyAccessResolutionWithNullSafetyTest);
+    defineReflectiveTests(PropertyAccessResolutionWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class PropertyAccessResolutionTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with PropertyAccessResolutionTestCases {
+  test_implicitCall_tearOff_nullable() async {
+    await assertErrorsInCode('''
+class A {
+  int call() => 0;
+}
+
+class B {
+  A? a;
+}
+
+int Function() foo() {
+  return B().a; // ref
+}
+''', [
+      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 85, 5),
+    ]);
+
+    var identifier = findNode.simple('a; // ref');
+    assertElement(identifier, findElement.getter('a'));
+    assertType(identifier, 'A?');
+  }
+
+  test_nullShorting_cascade() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int get foo => 0;
+  int get bar => 0;
+}
+
+void f(A? a) {
+  a?..foo..bar;
+}
+''');
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('..foo'),
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('..bar'),
+      element: findElement.getter('bar'),
+      type: 'int',
+    );
+
+    assertType(findNode.cascade('a?'), 'A?');
+  }
+
+  test_nullShorting_cascade2() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int? get foo => 0;
+}
+
+main() {
+  A a = A()..foo?.isEven;
+  a;
+}
+''');
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('..foo?'),
+      element: findElement.getter('foo'),
+      type: 'int?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.isEven'),
+      element: intElement.getGetter('isEven'),
+      type: 'bool',
+    );
+
+    assertType(findNode.cascade('A()'), 'A');
+  }
+
+  test_nullShorting_cascade3() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A? get foo => this;
+  A? get bar => this;
+  A? get baz => this;
+}
+
+main() {
+  A a = A()..foo?.bar?.baz;
+  a;
+}
+''');
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.foo'),
+      element: findElement.getter('foo'),
+      type: 'A?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.bar'),
+      element: findElement.getter('bar'),
+      type: 'A?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.baz'),
+      element: findElement.getter('baz'),
+      type: 'A?',
+    );
+
+    assertType(findNode.cascade('A()'), 'A');
+  }
+
+  test_nullShorting_cascade4() async {
+    await assertNoErrorsInCode(r'''
+A? get foo => A();
+
+class A {
+  A get bar => this;
+  A? get baz => this;
+  A get baq => this;
+}
+
+main() {
+  foo?.bar?..baz?.baq;
+}
+''');
+
+    assertSimpleIdentifier(
+      findNode.simple('foo?'),
+      element: findElement.topGet('foo'),
+      type: 'A?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.bar'),
+      element: findElement.getter('bar'),
+      type: 'A?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.baz'),
+      element: findElement.getter('baz'),
+      type: 'A?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.baq'),
+      element: findElement.getter('baq'),
+      type: 'A',
+    );
+
+    assertType(findNode.cascade('foo?'), 'A?');
+  }
+}
+
+mixin PropertyAccessResolutionTestCases on PubPackageResolutionTest {
   test_extensionOverride_read() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -561,158 +716,6 @@
 }
 
 @reflectiveTest
-class PropertyAccessResolutionWithNullSafetyTest
-    extends PropertyAccessResolutionTest with WithNullSafetyMixin {
-  test_implicitCall_tearOff_nullable() async {
-    await assertErrorsInCode('''
-class A {
-  int call() => 0;
-}
-
-class B {
-  A? a;
-}
-
-int Function() foo() {
-  return B().a; // ref
-}
-''', [
-      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 85, 5),
-    ]);
-
-    var identifier = findNode.simple('a; // ref');
-    assertElement(identifier, findElement.getter('a'));
-    assertType(identifier, 'A?');
-  }
-
-  test_nullShorting_cascade() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int get foo => 0;
-  int get bar => 0;
-}
-
-void f(A? a) {
-  a?..foo..bar;
-}
-''');
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('..foo'),
-      element: findElement.getter('foo'),
-      type: 'int',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('..bar'),
-      element: findElement.getter('bar'),
-      type: 'int',
-    );
-
-    assertType(findNode.cascade('a?'), 'A?');
-  }
-
-  test_nullShorting_cascade2() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int? get foo => 0;
-}
-
-main() {
-  A a = A()..foo?.isEven;
-  a;
-}
-''');
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('..foo?'),
-      element: findElement.getter('foo'),
-      type: 'int?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.isEven'),
-      element: intElement.getGetter('isEven'),
-      type: 'bool',
-    );
-
-    assertType(findNode.cascade('A()'), 'A');
-  }
-
-  test_nullShorting_cascade3() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  A? get foo => this;
-  A? get bar => this;
-  A? get baz => this;
-}
-
-main() {
-  A a = A()..foo?.bar?.baz;
-  a;
-}
-''');
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.foo'),
-      element: findElement.getter('foo'),
-      type: 'A?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.bar'),
-      element: findElement.getter('bar'),
-      type: 'A?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.baz'),
-      element: findElement.getter('baz'),
-      type: 'A?',
-    );
-
-    assertType(findNode.cascade('A()'), 'A');
-  }
-
-  test_nullShorting_cascade4() async {
-    await assertNoErrorsInCode(r'''
-A? get foo => A();
-
-class A {
-  A get bar => this;
-  A? get baz => this;
-  A get baq => this;
-}
-
-main() {
-  foo?.bar?..baz?.baq;
-}
-''');
-
-    assertSimpleIdentifier(
-      findNode.simple('foo?'),
-      element: findElement.topGet('foo'),
-      type: 'A?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.bar'),
-      element: findElement.getter('bar'),
-      type: 'A?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.baz'),
-      element: findElement.getter('baz'),
-      type: 'A?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.baq'),
-      element: findElement.getter('baq'),
-      type: 'A',
-    );
-
-    assertType(findNode.cascade('foo?'), 'A?');
-  }
-}
+class PropertyAccessResolutionWithoutNullSafetyTest
+    extends PubPackageResolutionTest
+    with PropertyAccessResolutionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 2080ec9..63a93db 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -754,8 +754,8 @@
     required TypeAliasElement element,
     required List<String> typeArguments,
   }) {
-    assertElement2(type.aliasElement, declaration: element);
-    assertElementTypeStrings(type.aliasArguments, typeArguments);
+    assertElement2(type.alias?.element, declaration: element);
+    assertElementTypeStrings(type.alias?.typeArguments, typeArguments);
   }
 
   /// Assert that the given [identifier] is a reference to a type alias, in the
@@ -924,8 +924,8 @@
     result = await resolveFile(path);
     expect(result.state, ResultState.VALID);
 
-    findNode = FindNode(result.content!, result.unit!);
-    findElement = FindElement(result.unit!);
+    findNode = FindNode(result.content, result.unit);
+    findElement = FindElement(result.unit);
   }
 
   /// Create a new file with the [path] and [content], resolve it into [result].
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 5f1c71d..08c23ad 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -42,6 +42,7 @@
 import 'library_element_test.dart' as library_element;
 import 'local_function_test.dart' as local_function;
 import 'local_variable_test.dart' as local_variable;
+import 'macro_test.dart' as macro;
 import 'metadata_test.dart' as metadata;
 import 'method_declaration_test.dart' as method_declaration;
 import 'method_invocation_test.dart' as method_invocation;
@@ -101,6 +102,7 @@
     library_element.main();
     local_function.main();
     local_variable.main();
+    macro.main();
     metadata.main();
     method_declaration.main();
     method_invocation.main();
diff --git a/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart b/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart
index 1349f39..444c894 100644
--- a/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart
@@ -11,13 +11,32 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(TopLevelVariableTest);
-    defineReflectiveTests(TopLevelVariableWithNullSafetyTest);
+    defineReflectiveTests(TopLevelVariableWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class TopLevelVariableTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with TopLevelVariableTestCases {
+  test_type_inferred_nonNullify() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+var a = 0;
+''');
+
+    await assertErrorsInCode('''
+import 'a.dart';
+
+var v = a;
+''', [
+      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+    ]);
+
+    assertType(findElement.topVar('v').type, 'int');
+  }
+}
+
+mixin TopLevelVariableTestCases on PubPackageResolutionTest {
   test_session_getterSetter() async {
     await resolveTestCode('''
 var v = 0;
@@ -65,22 +84,5 @@
 }
 
 @reflectiveTest
-class TopLevelVariableWithNullSafetyTest extends TopLevelVariableTest
-    with WithNullSafetyMixin {
-  test_type_inferred_nonNullify() async {
-    newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-var a = 0;
-''');
-
-    await assertErrorsInCode('''
-import 'a.dart';
-
-var v = a;
-''', [
-      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
-    ]);
-
-    assertType(findElement.topVar('v').type, 'int');
-  }
-}
+class TopLevelVariableWithoutNullSafetyTest extends PubPackageResolutionTest
+    with TopLevelVariableTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
index 71d74e19..a1531fb 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
@@ -9,27 +9,13 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ConditionalExpressionTest);
-    defineReflectiveTests(ConditionalExpressionWithNullSafetyTest);
+    defineReflectiveTests(ConditionalExpressionWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class ConditionalExpressionTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
-  test_upward() async {
-    await resolveTestCode('''
-void f(bool a, int b, int c) {
-  var d = a ? b : c;
-  print(d);
-}
-''');
-    assertType(findNode.simple('d)'), 'int');
-  }
-}
-
-@reflectiveTest
-class ConditionalExpressionWithNullSafetyTest extends ConditionalExpressionTest
-    with WithNullSafetyMixin {
+    with ConditionalExpressionTestCases {
   @failingTest
   test_downward() async {
     await resolveTestCode('''
@@ -51,3 +37,20 @@
     assertType(findNode.conditionalExpression('b ?'), 'int?');
   }
 }
+
+mixin ConditionalExpressionTestCases on PubPackageResolutionTest {
+  test_upward() async {
+    await resolveTestCode('''
+void f(bool a, int b, int c) {
+  var d = a ? b : c;
+  print(d);
+}
+''');
+    assertType(findNode.simple('d)'), 'int');
+  }
+}
+
+@reflectiveTest
+class ConditionalExpressionWithoutNullSafetyTest
+    extends PubPackageResolutionTest
+    with ConditionalExpressionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
index bcde92b..11676d2 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
@@ -10,13 +10,129 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(FunctionExpressionTest);
-    defineReflectiveTests(FunctionExpressionWithNullSafetyTest);
+    defineReflectiveTests(FunctionExpressionWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class FunctionExpressionTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with FunctionExpressionTestCases {
+  test_contextFunctionType_nonNullify() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+
+int Function(int a) v;
+''');
+
+    await assertErrorsInCode('''
+import 'a.dart';
+
+T foo<T>() => throw 0;
+
+void f() {
+  v = (a) {
+    return foo();
+  };
+}
+''', [
+      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+    ]);
+    assertType(findElement.parameter('a').type, 'int');
+    _assertReturnType('(a) {', 'int');
+  }
+
+  test_contextFunctionType_nonNullify_returnType_takeActual() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+
+void foo(int Function() x) {}
+''');
+    await assertErrorsInCode('''
+import 'a.dart';
+
+void test(int? a) {
+  foo(() => a);
+}
+''', [
+      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+    ]);
+    _assertReturnType('() => a', 'int?');
+  }
+
+  test_contextFunctionType_nonNullify_returnType_takeContext() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+
+void foo(int Function() x) {}
+''');
+    await assertErrorsInCode('''
+import 'a.dart';
+
+void test(dynamic a) {
+  foo(() => a);
+}
+''', [
+      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+    ]);
+    _assertReturnType('() => a', 'int');
+  }
+
+  test_contextFunctionType_returnType_async_blockBody_objectQ() async {
+    await assertNoErrorsInCode('''
+T foo<T>() => throw 0;
+
+Object? Function() v = () async {
+  return foo();
+};
+''');
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo();'),
+      ['FutureOr<Object?>'],
+    );
+    _assertReturnType('() async', 'Future<Object?>');
+  }
+
+  test_contextFunctionType_returnType_async_blockBody_objectQ2() async {
+    await assertNoErrorsInCode('''
+T foo<T>() => throw 0;
+
+Object? Function() v = () async {
+  return;
+};
+''');
+    _assertReturnType('() async', 'Future<Null>');
+  }
+
+  test_contextFunctionType_returnType_async_expressionBody_objectQ() async {
+    await assertNoErrorsInCode('''
+T foo<T>() => throw 0;
+
+Object? Function() v = () async => foo();
+''');
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo();'),
+      ['FutureOr<Object?>'],
+    );
+    _assertReturnType('() async => foo', 'Future<Object?>');
+  }
+
+  test_optOut_downward_returnType_expressionBody_Null() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+void foo(Map<String, String> Function() f) {}
+''');
+    await resolveTestCode('''
+// @dart = 2.5
+import 'a.dart';
+
+void main() {
+  foo(() => null);
+}
+''');
+    _assertReturnType('() =>', 'Null*');
+  }
+}
+
+mixin FunctionExpressionTestCases on PubPackageResolutionTest {
   test_contextFunctionType_returnType_async_blockBody_futureOrVoid() async {
     var expectedErrors = expectedErrorsByNullability(
       nullable: [
@@ -460,119 +576,5 @@
 }
 
 @reflectiveTest
-class FunctionExpressionWithNullSafetyTest extends FunctionExpressionTest
-    with WithNullSafetyMixin {
-  test_contextFunctionType_nonNullify() async {
-    newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-
-int Function(int a) v;
-''');
-
-    await assertErrorsInCode('''
-import 'a.dart';
-
-T foo<T>() => throw 0;
-
-void f() {
-  v = (a) {
-    return foo();
-  };
-}
-''', [
-      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
-    ]);
-    assertType(findElement.parameter('a').type, 'int');
-    _assertReturnType('(a) {', 'int');
-  }
-
-  test_contextFunctionType_nonNullify_returnType_takeActual() async {
-    newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-
-void foo(int Function() x) {}
-''');
-    await assertErrorsInCode('''
-import 'a.dart';
-
-void test(int? a) {
-  foo(() => a);
-}
-''', [
-      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
-    ]);
-    _assertReturnType('() => a', 'int?');
-  }
-
-  test_contextFunctionType_nonNullify_returnType_takeContext() async {
-    newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-
-void foo(int Function() x) {}
-''');
-    await assertErrorsInCode('''
-import 'a.dart';
-
-void test(dynamic a) {
-  foo(() => a);
-}
-''', [
-      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
-    ]);
-    _assertReturnType('() => a', 'int');
-  }
-
-  test_contextFunctionType_returnType_async_blockBody_objectQ() async {
-    await assertNoErrorsInCode('''
-T foo<T>() => throw 0;
-
-Object? Function() v = () async {
-  return foo();
-};
-''');
-    assertTypeArgumentTypes(
-      findNode.methodInvocation('foo();'),
-      ['FutureOr<Object?>'],
-    );
-    _assertReturnType('() async', 'Future<Object?>');
-  }
-
-  test_contextFunctionType_returnType_async_blockBody_objectQ2() async {
-    await assertNoErrorsInCode('''
-T foo<T>() => throw 0;
-
-Object? Function() v = () async {
-  return;
-};
-''');
-    _assertReturnType('() async', 'Future<Null>');
-  }
-
-  test_contextFunctionType_returnType_async_expressionBody_objectQ() async {
-    await assertNoErrorsInCode('''
-T foo<T>() => throw 0;
-
-Object? Function() v = () async => foo();
-''');
-    assertTypeArgumentTypes(
-      findNode.methodInvocation('foo();'),
-      ['FutureOr<Object?>'],
-    );
-    _assertReturnType('() async => foo', 'Future<Object?>');
-  }
-
-  test_optOut_downward_returnType_expressionBody_Null() async {
-    newFile('$testPackageLibPath/a.dart', content: r'''
-void foo(Map<String, String> Function() f) {}
-''');
-    await resolveTestCode('''
-// @dart = 2.5
-import 'a.dart';
-
-void main() {
-  foo(() => null);
-}
-''');
-    _assertReturnType('() =>', 'Null*');
-  }
-}
+class FunctionExpressionWithoutNullSafetyTest extends PubPackageResolutionTest
+    with FunctionExpressionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
index 80aeb15..39f7df5 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
@@ -10,13 +10,98 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ListLiteralTest);
-    defineReflectiveTests(ListLiteralWithNullSafetyTest);
+    defineReflectiveTests(ListLiteralWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class ListLiteralTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with ListLiteralTestCases {
+  test_context_spread_nullAware() async {
+    await assertNoErrorsInCode('''
+T f<T>(T t) => t;
+
+main() {
+  <int>[...?f(null)];
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('f(null)'),
+      element: findElement.topFunction('f'),
+      typeArgumentTypes: ['Iterable<int>?'],
+      invokeType: 'Iterable<int>? Function(Iterable<int>?)',
+      type: 'Iterable<int>?',
+    );
+  }
+
+  test_nested_hasNull_1() async {
+    await assertNoErrorsInCode('''
+main() {
+  [[0], null];
+}
+''');
+    assertType(findNode.listLiteral('[0'), 'List<int>');
+    assertType(findNode.listLiteral('[[0'), 'List<List<int>?>');
+  }
+
+  test_nested_hasNull_2() async {
+    await assertNoErrorsInCode('''
+main() {
+  [[0], [1, null]];
+}
+''');
+    assertType(findNode.listLiteral('[0'), 'List<int>');
+    assertType(findNode.listLiteral('[1,'), 'List<int?>');
+    assertType(findNode.listLiteral('[[0'), 'List<List<int?>>');
+  }
+
+  test_noContext_noTypeArgs_spread_never() async {
+    await assertNoErrorsInCode('''
+void f(Never a) async {
+  // ignore:unused_local_variable
+  var v = [...a];
+}
+''');
+    assertType(findNode.listLiteral('['), 'List<Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_never() async {
+    await assertErrorsInCode('''
+void f(Never a) async {
+  // ignore:unused_local_variable
+  var v = [...?a];
+}
+''', [
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 69, 4),
+    ]);
+    assertType(findNode.listLiteral('['), 'List<Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_typeParameter_implementsNever() async {
+    await assertErrorsInCode('''
+void f<T extends Never>(T a) async {
+  // ignore:unused_local_variable
+  var v = [...?a];
+}
+''', [
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 82, 4),
+    ]);
+    assertType(findNode.listLiteral('['), 'List<Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_typeParameter_implementsNever() async {
+    await assertNoErrorsInCode('''
+void f<T extends Never>(T a) async {
+  // ignore:unused_local_variable
+  var v = [...a];
+}
+''');
+    assertType(findNode.listLiteral('['), 'List<Never>');
+  }
+}
+
+mixin ListLiteralTestCases on PubPackageResolutionTest {
   test_context_noTypeArgs_expression_conflict() async {
     await assertErrorsInCode('''
 List<int> a = ['a'];
@@ -415,88 +500,5 @@
 }
 
 @reflectiveTest
-class ListLiteralWithNullSafetyTest extends ListLiteralTest
-    with WithNullSafetyMixin {
-  test_context_spread_nullAware() async {
-    await assertNoErrorsInCode('''
-T f<T>(T t) => t;
-
-main() {
-  <int>[...?f(null)];
-}
-''');
-
-    assertMethodInvocation2(
-      findNode.methodInvocation('f(null)'),
-      element: findElement.topFunction('f'),
-      typeArgumentTypes: ['Iterable<int>?'],
-      invokeType: 'Iterable<int>? Function(Iterable<int>?)',
-      type: 'Iterable<int>?',
-    );
-  }
-
-  test_nested_hasNull_1() async {
-    await assertNoErrorsInCode('''
-main() {
-  [[0], null];
-}
-''');
-    assertType(findNode.listLiteral('[0'), 'List<int>');
-    assertType(findNode.listLiteral('[[0'), 'List<List<int>?>');
-  }
-
-  test_nested_hasNull_2() async {
-    await assertNoErrorsInCode('''
-main() {
-  [[0], [1, null]];
-}
-''');
-    assertType(findNode.listLiteral('[0'), 'List<int>');
-    assertType(findNode.listLiteral('[1,'), 'List<int?>');
-    assertType(findNode.listLiteral('[[0'), 'List<List<int?>>');
-  }
-
-  test_noContext_noTypeArgs_spread_never() async {
-    await assertNoErrorsInCode('''
-void f(Never a) async {
-  // ignore:unused_local_variable
-  var v = [...a];
-}
-''');
-    assertType(findNode.listLiteral('['), 'List<Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_never() async {
-    await assertErrorsInCode('''
-void f(Never a) async {
-  // ignore:unused_local_variable
-  var v = [...?a];
-}
-''', [
-      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 69, 4),
-    ]);
-    assertType(findNode.listLiteral('['), 'List<Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_typeParameter_implementsNever() async {
-    await assertErrorsInCode('''
-void f<T extends Never>(T a) async {
-  // ignore:unused_local_variable
-  var v = [...?a];
-}
-''', [
-      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 82, 4),
-    ]);
-    assertType(findNode.listLiteral('['), 'List<Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_typeParameter_implementsNever() async {
-    await assertNoErrorsInCode('''
-void f<T extends Never>(T a) async {
-  // ignore:unused_local_variable
-  var v = [...a];
-}
-''');
-    assertType(findNode.listLiteral('['), 'List<Never>');
-  }
-}
+class ListLiteralWithoutNullSafetyTest extends PubPackageResolutionTest
+    with ListLiteralTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
index e4af4f6..894f8a9 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
@@ -11,13 +11,121 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapLiteralTest);
-    defineReflectiveTests(MapLiteralWithNullSafetyTest);
+    defineReflectiveTests(MapLiteralWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
-class MapLiteralTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+class MapLiteralTest extends PubPackageResolutionTest with MapLiteralTestCases {
+  test_context_noTypeArgs_noEntries_typeParameterNullable() async {
+    await assertNoErrorsInCode('''
+class C<T extends Object?> {
+  Map<String, T> a = {}; // 1
+  Map<String, T>? b = {}; // 2
+  Map<String, T?> c = {}; // 3
+  Map<String, T?>? d = {}; // 4
+}
+''');
+    assertType(setOrMapLiteral('{}; // 1'), 'Map<String, T>');
+    assertType(setOrMapLiteral('{}; // 2'), 'Map<String, T>');
+    assertType(setOrMapLiteral('{}; // 3'), 'Map<String, T?>');
+    assertType(setOrMapLiteral('{}; // 4'), 'Map<String, T?>');
+  }
+
+  test_context_spread_nullAware() async {
+    await assertNoErrorsInCode('''
+T f<T>(T t) => t;
+
+main() {
+  <int, double>{...?f(null)};
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('f(null)'),
+      element: findElement.topFunction('f'),
+      typeArgumentTypes: ['Map<int, double>?'],
+      invokeType: 'Map<int, double>? Function(Map<int, double>?)',
+      type: 'Map<int, double>?',
+    );
+  }
+
+  test_noContext_noTypeArgs_spread_never() async {
+    await assertErrorsInCode('''
+void f(Never a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...a, if (b) throw 0: throw 0};
+}
+''', [
+      error(HintCode.DEAD_CODE, 87, 21),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_never() async {
+    await assertErrorsInCode('''
+void f(Never a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 77, 4),
+      error(HintCode.DEAD_CODE, 88, 21),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_null() async {
+    await assertErrorsInCode('''
+void f(Null a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+      error(HintCode.DEAD_CODE, 99, 9),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_typeParameter_never() async {
+    await assertErrorsInCode('''
+void f<T extends Never>(T a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 90, 4),
+      error(HintCode.DEAD_CODE, 101, 21),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_typeParameter_null() async {
+    await assertErrorsInCode('''
+void f<T extends Null>(T a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+      error(HintCode.DEAD_CODE, 112, 9),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_typeParameter_never() async {
+    await assertErrorsInCode('''
+void f<T extends Never>(T a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...a, if (b) throw 0: throw 0};
+}
+''', [
+      error(HintCode.DEAD_CODE, 100, 21),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+}
+
+mixin MapLiteralTestCases on PubPackageResolutionTest {
   AstNode setOrMapLiteral(String search) => findNode.setOrMapLiteral(search);
 
   test_context_noTypeArgs_entry_conflictingKey() async {
@@ -439,112 +547,5 @@
 }
 
 @reflectiveTest
-class MapLiteralWithNullSafetyTest extends MapLiteralTest
-    with WithNullSafetyMixin {
-  test_context_noTypeArgs_noEntries_typeParameterNullable() async {
-    await assertNoErrorsInCode('''
-class C<T extends Object?> {
-  Map<String, T> a = {}; // 1
-  Map<String, T>? b = {}; // 2
-  Map<String, T?> c = {}; // 3
-  Map<String, T?>? d = {}; // 4
-}
-''');
-    assertType(setOrMapLiteral('{}; // 1'), 'Map<String, T>');
-    assertType(setOrMapLiteral('{}; // 2'), 'Map<String, T>');
-    assertType(setOrMapLiteral('{}; // 3'), 'Map<String, T?>');
-    assertType(setOrMapLiteral('{}; // 4'), 'Map<String, T?>');
-  }
-
-  test_context_spread_nullAware() async {
-    await assertNoErrorsInCode('''
-T f<T>(T t) => t;
-
-main() {
-  <int, double>{...?f(null)};
-}
-''');
-
-    assertMethodInvocation2(
-      findNode.methodInvocation('f(null)'),
-      element: findElement.topFunction('f'),
-      typeArgumentTypes: ['Map<int, double>?'],
-      invokeType: 'Map<int, double>? Function(Map<int, double>?)',
-      type: 'Map<int, double>?',
-    );
-  }
-
-  test_noContext_noTypeArgs_spread_never() async {
-    await assertErrorsInCode('''
-void f(Never a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...a, if (b) throw 0: throw 0};
-}
-''', [
-      error(HintCode.DEAD_CODE, 87, 21),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_never() async {
-    await assertErrorsInCode('''
-void f(Never a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
-      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 77, 4),
-      error(HintCode.DEAD_CODE, 88, 21),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_null() async {
-    await assertErrorsInCode('''
-void f(Null a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
-      error(HintCode.DEAD_CODE, 99, 9),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_typeParameter_never() async {
-    await assertErrorsInCode('''
-void f<T extends Never>(T a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
-      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 90, 4),
-      error(HintCode.DEAD_CODE, 101, 21),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_typeParameter_null() async {
-    await assertErrorsInCode('''
-void f<T extends Null>(T a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
-      error(HintCode.DEAD_CODE, 112, 9),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_typeParameter_never() async {
-    await assertErrorsInCode('''
-void f<T extends Never>(T a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...a, if (b) throw 0: throw 0};
-}
-''', [
-      error(HintCode.DEAD_CODE, 100, 21),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-}
+class MapLiteralWithoutNullSafetyTest extends PubPackageResolutionTest
+    with MapLiteralTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
index a24235f..690050e 100644
--- a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
+++ b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
@@ -1102,7 +1102,7 @@
   Future<void> _assertHasReturn(String code, int n, bool expected) async {
     await resolveTestCode(code);
 
-    var function = result.unit!.declarations.last as FunctionDeclaration;
+    var function = result.unit.declarations.last as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     Statement statement = body.block.statements[n];
     expect(ExitDetector.exits(statement), expected);
diff --git a/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart b/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart
index cba3c60..7879c8c 100644
--- a/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart
@@ -10,13 +10,15 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AbstractClassMemberTest);
-    defineReflectiveTests(AbstractClassMemberWithNullSafetyTest);
+    defineReflectiveTests(AbstractClassMemberWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class AbstractClassMemberTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with AbstractClassMemberTestCases {}
+
+mixin AbstractClassMemberTestCases on PubPackageResolutionTest {
   test_abstract_field_dynamic() async {
     await assertErrorsInCode(
         '''
@@ -55,5 +57,5 @@
 }
 
 @reflectiveTest
-class AbstractClassMemberWithNullSafetyTest extends AbstractClassMemberTest
-    with WithNullSafetyMixin {}
+class AbstractClassMemberWithoutNullSafetyTest extends PubPackageResolutionTest
+    with AbstractClassMemberTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart
index d45f72d..1ef0c33 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart
@@ -10,119 +10,13 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AssignmentToFinalTest);
-    defineReflectiveTests(AssignmentToFinalWithNullSafetyTest);
+    defineReflectiveTests(AssignmentToFinalWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class AssignmentToFinalTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
-  test_prefixedIdentifier_instanceField() async {
-    await assertNoErrorsInCode('''
-class A {
-  var x = 0;
-}
-
-void f(A a) {
-  a.x = 0;
-  a.x += 0;
-  ++a.x;
-  a.x++;
-}
-''');
-  }
-
-  test_prefixedIdentifier_instanceField_final() async {
-    await assertErrorsInCode('''
-class A {
-  final x = 0;
-}
-
-void f(A a) {
-  a.x = 0;
-  a.x += 0;
-  ++a.x;
-  a.x++;
-}
-''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 46, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 57, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 71, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 78, 1),
-    ]);
-  }
-
-  test_simpleIdentifier_inheritedSetter_shadowedBy_topLevelGetter() async {
-    await assertErrorsInCode('''
-class A {
-  void set foo(int _) {}
-}
-
-int get foo => 0;
-
-class B extends A {
-  void bar() {
-    foo = 0;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 96, 3),
-    ]);
-  }
-
-  test_simpleIdentifier_topLevelGetter() async {
-    await assertErrorsInCode('''
-int get x => 0;
-
-void f() {
-  x = 0;
-  x += 0;
-  ++x;
-  x++;
-}
-''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 30, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 39, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 51, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 56, 1),
-    ]);
-  }
-
-  test_simpleIdentifier_topLevelVariable() async {
-    await assertNoErrorsInCode('''
-var x = 0;
-
-void f() {
-  x = 0;
-  x += 0;
-  ++x;
-  x++;
-}
-''');
-  }
-
-  test_simpleIdentifier_topLevelVariable_final() async {
-    await assertErrorsInCode('''
-final x = 0;
-
-void f() {
-  x = 0;
-  x += 0;
-  ++x;
-  x++;
-}
-''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 27, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 36, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 48, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 53, 1),
-    ]);
-  }
-}
-
-@reflectiveTest
-class AssignmentToFinalWithNullSafetyTest extends AssignmentToFinalTest
-    with WithNullSafetyMixin {
+    with AssignmentToFinalTestCases {
   test_prefixedIdentifier_instanceField_abstract() async {
     await assertNoErrorsInCode('''
 abstract class A {
@@ -450,3 +344,111 @@
     ]);
   }
 }
+
+mixin AssignmentToFinalTestCases on PubPackageResolutionTest {
+  test_prefixedIdentifier_instanceField() async {
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+}
+
+void f(A a) {
+  a.x = 0;
+  a.x += 0;
+  ++a.x;
+  a.x++;
+}
+''');
+  }
+
+  test_prefixedIdentifier_instanceField_final() async {
+    await assertErrorsInCode('''
+class A {
+  final x = 0;
+}
+
+void f(A a) {
+  a.x = 0;
+  a.x += 0;
+  ++a.x;
+  a.x++;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 46, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 57, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 71, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 78, 1),
+    ]);
+  }
+
+  test_simpleIdentifier_inheritedSetter_shadowedBy_topLevelGetter() async {
+    await assertErrorsInCode('''
+class A {
+  void set foo(int _) {}
+}
+
+int get foo => 0;
+
+class B extends A {
+  void bar() {
+    foo = 0;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 96, 3),
+    ]);
+  }
+
+  test_simpleIdentifier_topLevelGetter() async {
+    await assertErrorsInCode('''
+int get x => 0;
+
+void f() {
+  x = 0;
+  x += 0;
+  ++x;
+  x++;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 30, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 39, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 51, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 56, 1),
+    ]);
+  }
+
+  test_simpleIdentifier_topLevelVariable() async {
+    await assertNoErrorsInCode('''
+var x = 0;
+
+void f() {
+  x = 0;
+  x += 0;
+  ++x;
+  x++;
+}
+''');
+  }
+
+  test_simpleIdentifier_topLevelVariable_final() async {
+    await assertErrorsInCode('''
+final x = 0;
+
+void f() {
+  x = 0;
+  x += 0;
+  ++x;
+  x++;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 27, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 36, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 48, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 53, 1),
+    ]);
+  }
+}
+
+@reflectiveTest
+class AssignmentToFinalWithoutNullSafetyTest extends PubPackageResolutionTest
+    with AssignmentToFinalTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart b/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
index 73e81a8..08b1904 100644
--- a/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
@@ -15,6 +15,37 @@
 
 @reflectiveTest
 class ConstConstructorWithMixinWithFieldTest extends PubPackageResolutionTest {
+  test_class_instance_abstract() async {
+    await assertErrorsInCode('''
+mixin A {
+  abstract int a;
+}
+
+class B with A {
+  @override
+  int a;
+  const B(this.a);
+}
+''', [
+      error(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 77, 1),
+    ]);
+  }
+
+  test_class_instance_abstract_final() async {
+    await assertNoErrorsInCode('''
+mixin A {
+  abstract final int a;
+}
+
+class B with A {
+  @override
+  final int a;
+  const B(this.a);
+}
+''');
+  }
+
   test_class_instance_final() async {
     await assertErrorsInCode('''
 class A {
@@ -64,7 +95,6 @@
   const B();
 }
 ''', [
-      error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 62, 1),
       error(
           CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 62, 1),
     ]);
@@ -81,7 +111,6 @@
   const B();
 }
 ''', [
-      error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 71, 1),
       error(
           CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELDS, 71, 1),
     ]);
@@ -119,7 +148,6 @@
   const X();
 }
 ''', [
-      error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 62, 1),
       error(
           CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 62, 1),
     ]);
diff --git a/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_final_field_test.dart b/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_final_field_test.dart
index 4d4f331..0b5cf6e 100644
--- a/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_final_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_final_field_test.dart
@@ -15,35 +15,6 @@
 
 @reflectiveTest
 class ConstConstructorWithNonFinalFieldTest extends PubPackageResolutionTest {
-  test_mixin() async {
-    await assertErrorsInCode(r'''
-class A {
-  var a;
-}
-class B extends Object with A {
-  const B();
-}
-''', [
-      error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 61, 1),
-      error(
-          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 61, 1),
-    ]);
-  }
-
-  test_super() async {
-    await assertErrorsInCode(r'''
-class A {
-  var a;
-}
-class B extends A {
-  const B();
-}
-''', [
-      error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 49, 1),
-      error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, 49, 1),
-    ]);
-  }
-
   test_this_named() async {
     await assertErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
index 1fc2927..92f1995 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
@@ -10,13 +10,139 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(DeadCodeTest);
-    defineReflectiveTests(DeadCodeWithNullSafetyTest);
+    defineReflectiveTests(DeadCodeWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
-class DeadCodeTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+class DeadCodeTest extends PubPackageResolutionTest with DeadCodeTestCases {
+  test_assert_dead_message() async {
+    // We don't warn if an assert statement is live but its message is dead,
+    // because this results in nuisance warnings for desirable assertions (e.g.
+    // a `!= null` assertion that is redundant with strong checking but still
+    // useful with weak checking).
+    await assertErrorsInCode('''
+void f(Object waldo) {
+  assert(waldo != null, "Where's Waldo?");
+}
+''', [
+      error(HintCode.UNNECESSARY_NULL_COMPARISON_TRUE, 38, 7),
+    ]);
+  }
+
+  test_flowEnd_tryStatement_body() async {
+    await assertErrorsInCode(r'''
+Never foo() => throw 0;
+
+main() {
+  try {
+    foo();
+    1;
+  } catch (_) {
+    2;
+  }
+  3;
+}
+''', [
+      error(HintCode.DEAD_CODE, 57, 2),
+    ]);
+  }
+
+  test_invokeNever_functionExpressionInvocation_getter_propertyAccess() async {
+    await assertErrorsInCode(r'''
+class A {
+  Never get f => throw 0;
+}
+void g(A a) {
+  a.f(0);
+  print(1);
+}
+''', [
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 54, 3),
+      error(HintCode.DEAD_CODE, 57, 16),
+    ]);
+  }
+
+  test_invokeNever_functionExpressionInvocation_parenthesizedExpression() async {
+    await assertErrorsInCode(r'''
+void g(Never f) {
+  (f)(0);
+  print(1);
+}
+''', [
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 3),
+      error(HintCode.DEAD_CODE, 23, 16),
+    ]);
+  }
+
+  test_invokeNever_functionExpressionInvocation_simpleIdentifier() async {
+    await assertErrorsInCode(r'''
+void g(Never f) {
+  f(0);
+  print(1);
+}
+''', [
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 21, 16),
+    ]);
+  }
+
+  test_returnTypeNever_function() async {
+    await assertErrorsInCode(r'''
+Never foo() => throw 0;
+
+main() {
+  foo();
+  1;
+}
+''', [
+      error(HintCode.DEAD_CODE, 45, 2),
+    ]);
+  }
+
+  test_returnTypeNever_getter() async {
+    await assertErrorsInCode(r'''
+Never get foo => throw 0;
+
+main() {
+  foo;
+  2;
+}
+''', [
+      error(HintCode.DEAD_CODE, 45, 2),
+    ]);
+  }
+
+  @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
+  @override
+  test_statementAfterAlwaysThrowsFunction() async {
+    return super.test_statementAfterAlwaysThrowsFunction();
+  }
+
+  @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
+  @override
+  test_statementAfterAlwaysThrowsMethod() async {
+    return super.test_statementAfterAlwaysThrowsMethod();
+  }
+
+  test_switchStatement_exhaustive() async {
+    await assertErrorsInCode(r'''
+enum Foo { a, b }
+
+int f(Foo foo) {
+  switch (foo) {
+    case Foo.a: return 0;
+    case Foo.b: return 1;
+  }
+  return -1;
+}
+''', [
+      error(HintCode.DEAD_CODE, 111, 10),
+    ]);
+  }
+}
+
+mixin DeadCodeTestCases on PubPackageResolutionTest {
   @override
   void setUp() {
     super.setUp();
@@ -846,129 +972,5 @@
 }
 
 @reflectiveTest
-class DeadCodeWithNullSafetyTest extends DeadCodeTest with WithNullSafetyMixin {
-  test_assert_dead_message() async {
-    // We don't warn if an assert statement is live but its message is dead,
-    // because this results in nuisance warnings for desirable assertions (e.g.
-    // a `!= null` assertion that is redundant with strong checking but still
-    // useful with weak checking).
-    await assertErrorsInCode('''
-void f(Object waldo) {
-  assert(waldo != null, "Where's Waldo?");
-}
-''', [
-      error(HintCode.UNNECESSARY_NULL_COMPARISON_TRUE, 38, 7),
-    ]);
-  }
-
-  test_flowEnd_tryStatement_body() async {
-    await assertErrorsInCode(r'''
-Never foo() => throw 0;
-
-main() {
-  try {
-    foo();
-    1;
-  } catch (_) {
-    2;
-  }
-  3;
-}
-''', [
-      error(HintCode.DEAD_CODE, 57, 2),
-    ]);
-  }
-
-  test_invokeNever_functionExpressionInvocation_getter_propertyAccess() async {
-    await assertErrorsInCode(r'''
-class A {
-  Never get f => throw 0;
-}
-void g(A a) {
-  a.f(0);
-  print(1);
-}
-''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 54, 3),
-      error(HintCode.DEAD_CODE, 57, 16),
-    ]);
-  }
-
-  test_invokeNever_functionExpressionInvocation_parenthesizedExpression() async {
-    await assertErrorsInCode(r'''
-void g(Never f) {
-  (f)(0);
-  print(1);
-}
-''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 3),
-      error(HintCode.DEAD_CODE, 23, 16),
-    ]);
-  }
-
-  test_invokeNever_functionExpressionInvocation_simpleIdentifier() async {
-    await assertErrorsInCode(r'''
-void g(Never f) {
-  f(0);
-  print(1);
-}
-''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
-      error(HintCode.DEAD_CODE, 21, 16),
-    ]);
-  }
-
-  test_returnTypeNever_function() async {
-    await assertErrorsInCode(r'''
-Never foo() => throw 0;
-
-main() {
-  foo();
-  1;
-}
-''', [
-      error(HintCode.DEAD_CODE, 45, 2),
-    ]);
-  }
-
-  test_returnTypeNever_getter() async {
-    await assertErrorsInCode(r'''
-Never get foo => throw 0;
-
-main() {
-  foo;
-  2;
-}
-''', [
-      error(HintCode.DEAD_CODE, 45, 2),
-    ]);
-  }
-
-  @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
-  @override
-  test_statementAfterAlwaysThrowsFunction() async {
-    return super.test_statementAfterAlwaysThrowsFunction();
-  }
-
-  @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
-  @override
-  test_statementAfterAlwaysThrowsMethod() async {
-    return super.test_statementAfterAlwaysThrowsMethod();
-  }
-
-  test_switchStatement_exhaustive() async {
-    await assertErrorsInCode(r'''
-enum Foo { a, b }
-
-int f(Foo foo) {
-  switch (foo) {
-    case Foo.a: return 0;
-    case Foo.b: return 1;
-  }
-  return -1;
-}
-''', [
-      error(HintCode.DEAD_CODE, 111, 10),
-    ]);
-  }
-}
+class DeadCodeWithoutNullSafetyTest extends PubPackageResolutionTest
+    with DeadCodeTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart b/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
new file mode 100644
index 0000000..a11172c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
@@ -0,0 +1,57 @@
+// 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/ffi_code.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FfiNativeTest);
+  });
+}
+
+@reflectiveTest
+class FfiNativeTest extends PubPackageResolutionTest {
+  test_FfiNativeAnnotationOnInstanceMethod() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+class K {
+  @FfiNative<Void Function()>('DoesntMatter')
+  external void doesntMatter();
+}
+''', [
+      error(FfiCode.FFI_NATIVE_ONLY_STATIC, 31, 75),
+    ]);
+  }
+
+  test_FfiNativeCanUseHandles() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Handle Function(Handle)>('DoesntMatter')
+external Object doesntMatter(Object);
+''', []);
+  }
+
+  test_FfiNativeLeafMustNotReturnHandle() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Handle Function()>('DoesntMatter', isLeaf:true)
+external Object doesntMatter();
+''', [
+      error(FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE, 19, 90),
+    ]);
+  }
+
+  test_FfiNativeLeafMustNotTakeHandles() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Void Function(Handle)>('DoesntMatter', isLeaf:true)
+external void doesntMatter(Object o);
+''', [
+      error(FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE, 19, 100),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart b/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart
index aeaec55..ee423c8 100644
--- a/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart
@@ -102,6 +102,19 @@
     ]);
   }
 
+  test_method_reference_typeInstantiation() async {
+    await assertErrorsInCode(r'''
+class A {
+  static m<T>() {}
+}
+f(A a) {
+  a.m<int>;
+}
+''', [
+      error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 44, 1),
+    ]);
+  }
+
   test_propertyAccess_field() async {
     await assertErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_application_not_implemented_interface_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_application_not_implemented_interface_test.dart
index 31546d9..0266782 100644
--- a/pkg/analyzer/test/src/diagnostics/mixin_application_not_implemented_interface_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/mixin_application_not_implemented_interface_test.dart
@@ -111,7 +111,7 @@
       error(HintCode.UNUSED_ELEMENT, 96, 15),
     ]);
     var mixins =
-        result.unit!.declaredElement!.getType('_LocalDirectory')!.mixins;
+        result.unit.declaredElement!.getType('_LocalDirectory')!.mixins;
     assertType(mixins[0], 'ForwardingDirectory<_LocalDirectory>');
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/must_be_a_native_function_type_test.dart b/pkg/analyzer/test/src/diagnostics/must_be_a_native_function_type_test.dart
index c46e611..ced28b0 100644
--- a/pkg/analyzer/test/src/diagnostics/must_be_a_native_function_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_be_a_native_function_type_test.dart
@@ -25,7 +25,7 @@
   }
 }
 ''', [
-      error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 89, 26),
+      error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 110, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/new_with_undefined_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/new_with_undefined_constructor_test.dart
index 602e5ff..4ebf06c 100644
--- a/pkg/analyzer/test/src/diagnostics/new_with_undefined_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/new_with_undefined_constructor_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/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -10,11 +11,16 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NewWithUndefinedConstructorTest);
+    defineReflectiveTests(
+        NewWithUndefinedConstructorWithoutConstructorTearoffsTest);
   });
 }
 
 @reflectiveTest
-class NewWithUndefinedConstructorTest extends PubPackageResolutionTest {
+class NewWithUndefinedConstructorTest extends PubPackageResolutionTest
+    with NewWithUndefinedConstructorTestCases {}
+
+mixin NewWithUndefinedConstructorTestCases on PubPackageResolutionTest {
   test_default() async {
     await assertErrorsInCode('''
 class A {
@@ -28,6 +34,43 @@
     ]);
   }
 
+  test_default_noKeyword() async {
+    await assertErrorsInCode('''
+class A {
+  A.name() {}
+}
+f() {
+  A();
+}
+''', [
+      error(CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, 34, 1),
+    ]);
+  }
+
+  test_default_unnamedViaNew() async {
+    await assertErrorsInCode('''
+class A {
+  A.name() {}
+}
+f() {
+  A.new();
+}
+''', [
+      error(CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, 36, 3),
+    ]);
+  }
+
+  test_defaultViaNew() async {
+    await assertNoErrorsInCode('''
+class A {
+  A.new() {}
+}
+f() {
+  A();
+}
+''');
+  }
+
   test_defined_named() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -111,3 +154,33 @@
     ]);
   }
 }
+
+@reflectiveTest
+class NewWithUndefinedConstructorWithoutConstructorTearoffsTest
+    extends PubPackageResolutionTest with WithoutConstructorTearoffsMixin {
+  test_defaultViaNew() async {
+    await assertErrorsInCode('''
+class A {
+  A.new() {}
+}
+f() {
+  A();
+}
+''', [
+      error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 14, 3),
+    ]);
+  }
+
+  test_unnamedViaNew() async {
+    await assertErrorsInCode('''
+class A {
+  A.named() {}
+}
+f() {
+  A.new();
+}
+''', [
+      error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 37, 3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/subtype_of_struct_class_test.dart b/pkg/analyzer/test/src/diagnostics/subtype_of_struct_class_test.dart
index ab9e982..026be64 100644
--- a/pkg/analyzer/test/src/diagnostics/subtype_of_struct_class_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/subtype_of_struct_class_test.dart
@@ -51,7 +51,7 @@
 class S extends Struct {}
 class C implements S {}
 ''', [
-      error(FfiCode.EMPTY_STRUCT, 19, 25),
+      error(FfiCode.EMPTY_STRUCT, 25, 1),
       error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS, 64, 1),
     ]);
   }
@@ -62,7 +62,7 @@
 class S extends Union {}
 class C implements S {}
 ''', [
-      error(FfiCode.EMPTY_STRUCT, 19, 24),
+      error(FfiCode.EMPTY_STRUCT, 25, 1),
       error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS, 63, 1),
     ]);
   }
@@ -76,7 +76,7 @@
 class S extends Struct {}
 class C with S {}
 ''', [
-      error(FfiCode.EMPTY_STRUCT, 19, 25),
+      error(FfiCode.EMPTY_STRUCT, 25, 1),
       error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 58, 1),
       error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH, 58, 1),
     ]);
@@ -88,7 +88,7 @@
 class S extends Union {}
 class C with S {}
 ''', [
-      error(FfiCode.EMPTY_STRUCT, 19, 24),
+      error(FfiCode.EMPTY_STRUCT, 25, 1),
       error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 57, 1),
       error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH, 57, 1),
     ]);
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index fd81c75..49fbffe 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -193,6 +193,7 @@
     as ffi_array_multi_non_positive_input_test;
 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;
 import 'field_in_struct_with_initializer_test.dart'
     as field_in_struct_with_initializer;
 import 'field_initialized_by_multiple_initializers_test.dart'
@@ -844,6 +845,7 @@
     extra_size_annotation_carray.main();
     ffi_array_multi_non_positive_input_test.main();
     ffi_leaf_call_must_not_use_handle.main();
+    ffi_native_test.main();
     field_in_struct_with_initializer.main();
     field_initialized_by_multiple_initializers.main();
     final_initialized_in_declaration_and_constructor.main();
diff --git a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
index 72f8042..79ab24a 100644
--- a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
@@ -300,7 +300,7 @@
       error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 65, 3),
     ]);
     // Instantiate-to-bounds should have instantiated "Bar" to "Bar<Foo>".
-    assertType(result.unit!.declaredElement!.getType('Baz')!.supertype,
+    assertType(result.unit.declaredElement!.getType('Baz')!.supertype,
         'Bar<Foo<dynamic>>');
   }
 
@@ -453,17 +453,19 @@
 
   test_functionReference() async {
     await assertErrorsInCode('''
-void bar(void Function<T extends num>(T a) foo) {
+void foo<T extends num>(T a) {}
+void bar() {
   foo<String>;
 }
 ''', [
-      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 56, 6),
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 51, 6),
     ]);
   }
 
   test_functionReference_matching() async {
     await assertNoErrorsInCode('''
-void bar(void Function<T extends num>(T a) foo) {
+void foo<T extends num>(T a) {}
+void bar() {
   foo<int>;
 }
 ''');
@@ -471,7 +473,8 @@
 
   test_functionReference_regularBounded() async {
     await assertNoErrorsInCode('''
-void bar(void Function<T>(T a) foo) {
+void foo<T>(T a) {}
+void bar() {
   foo<String>;
 }
 ''');
@@ -689,4 +692,32 @@
 A get foo => throw 0;
 ''');
   }
+
+  test_typeLiteral_class() async {
+    await assertErrorsInCode('''
+class C<T extends int> {}
+var t = C<String>;
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 36, 6),
+    ]);
+  }
+
+  test_typeLiteral_functionTypeAlias() async {
+    await assertErrorsInCode('''
+typedef Cb<T extends int> = void Function();
+var t = Cb<String>;
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 56, 6),
+    ]);
+  }
+
+  test_typeLiteral_typeAlias() async {
+    await assertErrorsInCode('''
+class C {}
+typedef D<T extends int> = C;
+var t = D<String>;
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 51, 6),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_non_local_static_member_test.dart b/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_non_local_static_member_test.dart
index 6551ffe..8e24064 100644
--- a/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_non_local_static_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_non_local_static_member_test.dart
@@ -50,6 +50,21 @@
     ]);
   }
 
+  test_methodTearoff() async {
+    await assertErrorsInCode('''
+class A {
+  static void a<T>() {}
+}
+class B extends A {
+  void b() {
+    a<int>;
+  }
+}
+''', [
+      error(_errorCode, 73, 1),
+    ]);
+  }
+
   test_readWrite() async {
     await assertErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.dart b/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.dart
index 8525aa2..1cf7168 100644
--- a/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.dart
@@ -51,6 +51,21 @@
     ]);
   }
 
+  test_methodTearoff() async {
+    await assertErrorsInCode('''
+class MyClass {
+  static void sm<T>() {}
+}
+extension MyExtension on MyClass {
+  void m() {
+    sm<int>;
+  }
+}
+''', [
+      error(_errorCode, 95, 2),
+    ]);
+  }
+
   test_readWrite() async {
     await assertErrorsInCode('''
 class MyClass {
diff --git a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
index ae55d6f..d743c6e 100644
--- a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
@@ -95,23 +95,52 @@
 
   test_functionReference_tooFew() async {
     await assertErrorsInCode('''
-f(void Function<T, U>() foo) {
+f() {
+  void foo<T, U>() {}
   foo<int>;
 }
 ''', [
       error(
-          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 36, 5),
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 33, 5),
     ]);
   }
 
   test_functionReference_tooMany() async {
     await assertErrorsInCode('''
-f(void Function<T>() foo) {
+f() {
+  void foo<T>() {}
   foo<int, int>;
 }
 ''', [
       error(
-          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 33, 10),
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 30, 10),
+    ]);
+  }
+
+  test_functionTypeExpression_tooFew() async {
+    await assertErrorsInCode('''
+f(void Function<T, U>() foo, void Function<T, U>() bar) {
+  (1 == 2 ? foo : bar)<int>;
+}
+''', [
+      error(CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 60,
+          20),
+      error(
+          CompileTimeErrorCode
+              .WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
+          80,
+          5),
+    ]);
+  }
+
+  test_functionTypeExpression_tooMany() async {
+    await assertErrorsInCode('''
+f(void Function<T>() foo, void Function<T, U>() bar) {
+  (1 == 2 ? foo : bar)<int, String>;
+}
+''', [
+      error(CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 57,
+          20),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
index 399d2e4..4212464 100644
--- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -28,7 +28,7 @@
 
   Future<void> resolve(String content) async {
     await resolveTestCode(content);
-    var contextUnit = LinterContextUnit(result.content!, result.unit!);
+    var contextUnit = LinterContextUnit(result.content, result.unit);
 
     final libraryElement = result.libraryElement;
     final analysisContext = libraryElement.session.analysisContext;
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index a2e41c6..a939f53 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -3496,9 +3496,9 @@
     newFile(a, content: 'class A {}');
     newFile(b, content: 'class B {}');
     newFile(c, content: 'class C {}');
-    testAnalysisContext.currentSession.getFile2(a);
-    testAnalysisContext.currentSession.getFile2(b);
-    testAnalysisContext.currentSession.getFile2(c);
+    testAnalysisContext.currentSession.getFile(a);
+    testAnalysisContext.currentSession.getFile(b);
+    testAnalysisContext.currentSession.getFile(c);
 
     var context = tracker.addContext(testAnalysisContext);
     await _doAllTrackerWork();
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 4243b45..f8366c5 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -361,6 +361,7 @@
     });
 
     _withIndent(() {
+      _writeMacro(e);
       _writeDocumentation(e);
       _writeMetadata(e);
       _writeCodeRange(e);
@@ -395,17 +396,14 @@
       expect(e.nameOffset, -1);
       expect(e.nonSynthetic, same(e.enclosingElement));
     } else {
-      expect(e.nameOffset, isPositive);
+      expect(e.nameOffset, isNonNegative);
     }
   }
 
   void _writeDocumentation(Element element) {
     var documentation = element.documentationComment;
     if (documentation != null) {
-      var str = documentation;
-      str = str.replaceAll('\n', r'\n');
-      str = str.replaceAll('\r', r'\r');
-      _writelnWithIndent('documentationComment: $str');
+      _writelnMultiLineWithIndent('documentationComment: $documentation');
     }
   }
 
@@ -521,11 +519,30 @@
     buffer.writeln();
   }
 
+  void _writelnMultiLineWithIndent(String str) {
+    str = str.replaceAll('\n', r'\n');
+    str = str.replaceAll('\r', r'\r');
+    _writelnWithIndent(str);
+  }
+
   void _writelnWithIndent(String line) {
     buffer.write(indent);
     buffer.writeln(line);
   }
 
+  void _writeMacro(Element e) {
+    if (e is HasMacroGenerationData) {
+      var macro = (e as HasMacroGenerationData).macro;
+      if (macro != null) {
+        _writelnWithIndent('macro');
+        _withIndent(() {
+          _writelnWithIndent('id: ${macro.id}');
+          _writelnMultiLineWithIndent('code: ${macro.code}');
+        });
+      }
+    }
+  }
+
   void _writeMetadata(Element element) {
     var annotations = element.metadata;
     if (annotations.isNotEmpty) {
@@ -551,6 +568,7 @@
     });
 
     _withIndent(() {
+      _writeMacro(e);
       _writeDocumentation(e);
       _writeMetadata(e);
       _writeCodeRange(e);
@@ -645,6 +663,8 @@
   }
 
   void _writePropertyAccessorElement(PropertyAccessorElement e) {
+    e as PropertyAccessorElementImpl;
+
     PropertyInducingElement variable = e.variable;
     expect(variable, isNotNull);
 
@@ -691,6 +711,7 @@
     });
 
     _withIndent(() {
+      _writeMacro(e);
       _writeDocumentation(e);
       _writeMetadata(e);
       _writeCodeRange(e);
@@ -752,15 +773,14 @@
       _writelnWithIndent('$typeStr');
     }
 
-    var aliasElement = type.aliasElement;
-    var aliasArguments = type.aliasArguments;
-    if (aliasElement is TypeAliasElementImpl && aliasArguments != null) {
+    var alias = type.alias;
+    if (alias != null) {
       _withIndent(() {
-        _createAstPrinter().writeElement('aliasElement', aliasElement);
+        _createAstPrinter().writeElement('aliasElement', alias.element);
 
         _writeElements<DartType>(
           'aliasArguments',
-          aliasArguments,
+          alias.typeArguments,
           _writeType,
         );
       });
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 3859042..8473b16 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -16762,8 +16762,8 @@
     var unit = library.definingCompilationUnit;
     var type = unit.topLevelVariables[0].type as FunctionType;
 
-    expect(type.aliasElement, same(unit.typeAliases[0]));
-    _assertTypeStrings(type.aliasArguments!, ['int']);
+    expect(type.alias!.element, same(unit.typeAliases[0]));
+    _assertTypeStrings(type.alias!.typeArguments, ['int']);
   }
 
   test_functionTypeAlias_typeParameters_variance_contravariant() async {
@@ -21246,6 +21246,359 @@
 ''');
   }
 
+  test_macro_autoConstructor() async {
+    addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const autoConstructor = 0;
+''');
+    var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+@autoConstructor
+class A {
+  final int a;
+  final int? b;
+}
+''');
+    checkElementText(library, r'''
+library
+  imports
+    macro_annotations.dart
+  definingUnit
+    classes
+      class A @56
+        metadata
+          Annotation
+            atSign: @ @33
+            element: macro_annotations.dart::@getter::autoConstructor
+            name: SimpleIdentifier
+              staticElement: macro_annotations.dart::@getter::autoConstructor
+              staticType: null
+              token: autoConstructor @34
+        fields
+          final a @72
+            type: int
+          final b @88
+            type: int?
+        constructors
+          @0
+            macro
+              id: 0
+              code: A({required this.a, this.b});
+            parameters
+              requiredName final this.a @17
+                type: int
+              optionalNamed final this.b @25
+                type: int?
+        accessors
+          synthetic get a @-1
+            returnType: int
+          synthetic get b @-1
+            returnType: int?
+''');
+  }
+
+  test_macro_hashCode() async {
+    addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const hashCode = 0;
+''');
+    var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+@hashCode
+class A {
+  final int a;
+  final int b;
+}
+''');
+    checkElementText(library, r'''
+library
+  imports
+    macro_annotations.dart
+  definingUnit
+    classes
+      class A @49
+        metadata
+          Annotation
+            atSign: @ @33
+            element: macro_annotations.dart::@getter::hashCode
+            name: SimpleIdentifier
+              staticElement: macro_annotations.dart::@getter::hashCode
+              staticType: null
+              token: hashCode @34
+        fields
+          final a @65
+            type: int
+          final b @80
+            type: int
+          synthetic hashCode @-1
+            type: int
+        constructors
+          synthetic @-1
+        accessors
+          synthetic get a @-1
+            returnType: int
+          synthetic get b @-1
+            returnType: int
+          get hashCode @18
+            macro
+              id: 0
+              code: @override\nint get hashCode => a.hashCode ^ b.hashCode;
+            metadata
+              Annotation
+                atSign: @ @0
+                element: dart:core::@getter::override
+                name: SimpleIdentifier
+                  staticElement: dart:core::@getter::override
+                  staticType: null
+                  token: override @1
+            returnType: int
+''');
+  }
+
+  test_macro_hashCode_withSuper() async {
+    addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const hashCode = 0;
+''');
+    var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+
+class A {
+  final int a;
+}
+
+@hashCode
+class B extends A {
+  final int b;
+}
+''');
+    checkElementText(library, r'''
+library
+  imports
+    macro_annotations.dart
+  definingUnit
+    classes
+      class A @40
+        fields
+          final a @56
+            type: int
+        constructors
+          synthetic @-1
+        accessors
+          synthetic get a @-1
+            returnType: int
+      class B @78
+        metadata
+          Annotation
+            atSign: @ @62
+            element: macro_annotations.dart::@getter::hashCode
+            name: SimpleIdentifier
+              staticElement: macro_annotations.dart::@getter::hashCode
+              staticType: null
+              token: hashCode @63
+        supertype: A
+        fields
+          final b @104
+            type: int
+          synthetic hashCode @-1
+            type: int
+        constructors
+          synthetic @-1
+        accessors
+          synthetic get b @-1
+            returnType: int
+          get hashCode @18
+            macro
+              id: 0
+              code: @override\nint get hashCode => b.hashCode ^ a.hashCode;
+            metadata
+              Annotation
+                atSign: @ @0
+                element: dart:core::@getter::override
+                name: SimpleIdentifier
+                  staticElement: dart:core::@getter::override
+                  staticType: null
+                  token: override @1
+            returnType: int
+''');
+  }
+
+  test_macro_observable() async {
+    addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const observable = 0;
+''');
+    var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+class A {
+  @observable
+  int _f = 0;
+}
+''');
+    checkElementText(library, r'''
+library
+  imports
+    macro_annotations.dart
+  definingUnit
+    classes
+      class A @39
+        fields
+          _f @63
+            metadata
+              Annotation
+                atSign: @ @45
+                element: macro_annotations.dart::@getter::observable
+                name: SimpleIdentifier
+                  staticElement: macro_annotations.dart::@getter::observable
+                  staticType: null
+                  token: observable @46
+            type: int
+          synthetic f @-1
+            type: int
+        constructors
+          synthetic @-1
+        accessors
+          synthetic get _f @-1
+            returnType: int
+          synthetic set _f @-1
+            parameters
+              requiredPositional __f @-1
+                type: int
+            returnType: void
+          get f @8
+            macro
+              id: 0
+              code: int get f => _f;
+            returnType: int
+          set f @4
+            macro
+              id: 1
+              code: set f(int val) {\n  print('Setting f to ${val}');\n  _f = val;\n}
+            parameters
+              requiredPositional val @10
+                type: int
+            returnType: void
+''');
+  }
+
+  test_macro_observable_generic() async {
+    addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const observable = 0;
+''');
+    var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+class A<T> {
+  @observable
+  T _f;
+}
+''');
+    checkElementText(library, r'''
+library
+  imports
+    macro_annotations.dart
+  definingUnit
+    classes
+      class A @39
+        typeParameters
+          covariant T @41
+            defaultType: dynamic
+        fields
+          _f @64
+            metadata
+              Annotation
+                atSign: @ @48
+                element: macro_annotations.dart::@getter::observable
+                name: SimpleIdentifier
+                  staticElement: macro_annotations.dart::@getter::observable
+                  staticType: null
+                  token: observable @49
+            type: T
+          synthetic f @-1
+            type: T
+        constructors
+          synthetic @-1
+        accessors
+          synthetic get _f @-1
+            returnType: T
+          synthetic set _f @-1
+            parameters
+              requiredPositional __f @-1
+                type: T
+            returnType: void
+          get f @6
+            macro
+              id: 0
+              code: T get f => _f;
+            returnType: T
+          set f @4
+            macro
+              id: 1
+              code: set f(T val) {\n  print('Setting f to ${val}');\n  _f = val;\n}
+            parameters
+              requiredPositional val @8
+                type: T
+            returnType: void
+''');
+  }
+
+  test_macro_toString() async {
+    addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const toString = 0;
+''');
+    var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+@toString
+class A {
+  final int a;
+  final int b;
+}
+''');
+    checkElementText(library, r'''
+library
+  imports
+    macro_annotations.dart
+  definingUnit
+    classes
+      class A @49
+        metadata
+          Annotation
+            atSign: @ @33
+            element: macro_annotations.dart::@getter::toString
+            name: SimpleIdentifier
+              staticElement: macro_annotations.dart::@getter::toString
+              staticType: null
+              token: toString @34
+        fields
+          final a @65
+            type: int
+          final b @80
+            type: int
+        constructors
+          synthetic @-1
+        accessors
+          synthetic get a @-1
+            returnType: int
+          synthetic get b @-1
+            returnType: int
+        methods
+          toString @17
+            macro
+              id: 0
+              code: @override\nString toString() => 'A(a: $a, b: $b)';
+            metadata
+              Annotation
+                atSign: @ @0
+                element: dart:core::@getter::override
+                name: SimpleIdentifier
+                  staticElement: dart:core::@getter::override
+                  staticType: null
+                  token: override @1
+            returnType: String
+''');
+  }
+
   test_main_class() async {
     var library = await checkLibrary('class main {}');
     checkElementText(library, r'''
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 b10c777..feb2509 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -6116,7 +6116,7 @@
 
     var path = convertPath(testFilePath);
     var analysisSession = contextFor(path).currentSession;
-    var result = await analysisSession.getUnitElement2(path);
+    var result = await analysisSession.getUnitElement(path);
     result as UnitElementResult;
     return result.element.library;
   }
diff --git a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
index e7b1ac5..87a1477 100644
--- a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
@@ -347,8 +347,8 @@
   }
 
   void _assertTypeAnnotations() {
-    var code = result.content!;
-    var unit = result.unit!;
+    var code = result.content;
+    var unit = result.unit;
 
     var types = <int, String>{};
     {
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 21fa9c9..4840db6 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -22,7 +22,7 @@
   // TODO(https://github.com/dart-lang/sdk/issues/44666): Use null safety in
   //  test cases.
   CompilationUnitElement get _resultUnitElement {
-    return result.unit!.declaredElement!;
+    return result.unit.declaredElement!;
   }
 
   test_asyncClosureReturnType_flatten() async {
diff --git a/pkg/analyzer/test/util/id_testing_helper.dart b/pkg/analyzer/test/util/id_testing_helper.dart
index 6d75b6f..f192694 100644
--- a/pkg/analyzer/test/util/id_testing_helper.dart
+++ b/pkg/analyzer/test/util/id_testing_helper.dart
@@ -196,7 +196,7 @@
         });
       } else {
         String _formatError(AnalysisError e) {
-          var locationInfo = result.unit!.lineInfo!.getLocation(e.offset);
+          var locationInfo = result.unit.lineInfo!.getLocation(e.offset);
           return '$locationInfo: ${e.errorCode}: ${e.message}';
         }
 
@@ -209,7 +209,7 @@
 
   results.forEach((testUri, result) {
     dataComputer.computeUnitData(
-        driver.testingData!, result.unit!, actualMapFor(testUri));
+        driver.testingData!, result.unit, actualMapFor(testUri));
   });
   var compiledData = AnalyzerCompiledData<T>(
       testData.code, testData.entryPoint, actualMaps, globalData);
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index 648fbf0..d8d7076 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -287,7 +287,7 @@
   /// [path] and return the result.
   ParsedUnitResult _parse(AnalysisContextCollection collection, String path) {
     AnalysisSession session = collection.contextFor(path).currentSession;
-    var result = session.getParsedUnit2(path);
+    var result = session.getParsedUnit(path);
     if (result is! ParsedUnitResult) {
       throw StateError('Unable to parse "$path"');
     }
@@ -321,7 +321,7 @@
   /// Extract documentation from the file that was parsed to produce the given
   /// [result].
   Future<void> _validateFile(ParsedUnitResult result) async {
-    filePath = result.path!;
+    filePath = result.path;
     hasWrittenFilePath = false;
     CompilationUnit unit = result.unit;
     for (CompilationUnitMember declaration in unit.declarations) {
@@ -420,6 +420,7 @@
 /// codes.
 @reflectiveTest
 class VerifyDiagnosticsTest {
+  @TestTimeout(Timeout.factor(4))
   test_diagnostics() async {
     Context pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
     List<CodePath> codePaths = computeCodePaths();
diff --git a/pkg/analyzer/test/verify_docs_test.dart b/pkg/analyzer/test/verify_docs_test.dart
index 8ffc750..b01d307 100644
--- a/pkg/analyzer/test/verify_docs_test.dart
+++ b/pkg/analyzer/test/verify_docs_test.dart
@@ -118,7 +118,7 @@
       if (contexts.length != 1) {
         fail('The snippets directory contains multiple analysis contexts.');
       }
-      var results = await contexts[0].currentSession.getErrors2(snippetPath);
+      var results = await contexts[0].currentSession.getErrors(snippetPath);
       if (results is ErrorsResult) {
         Iterable<AnalysisError> errors = results.errors.where((error) {
           ErrorCode errorCode = error.errorCode;
diff --git a/pkg/analyzer/tool/diagnostics/generate.dart b/pkg/analyzer/tool/diagnostics/generate.dart
index 927bbf2..e431fb0 100644
--- a/pkg/analyzer/tool/diagnostics/generate.dart
+++ b/pkg/analyzer/tool/diagnostics/generate.dart
@@ -363,7 +363,7 @@
   /// [path] and return the result.
   ParsedUnitResult _parse(AnalysisContextCollection collection, String path) {
     AnalysisSession session = collection.contextFor(path).currentSession;
-    var result = session.getParsedUnit2(path);
+    var result = session.getParsedUnit(path);
     if (result is! ParsedUnitResult) {
       throw StateError('Unable to parse "$path"');
     }
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 5b0948e..28e3590 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -382,7 +382,7 @@
   Iterable<io.File> _collectFiles(String filePath, AnalysisOptions options) {
     var files = <io.File>[];
     var file = io.File(filePath);
-    if (file.existsSync() && !pathFilter.ignored(filePath)) {
+    if (file.existsSync()) {
       files.add(file);
     } else {
       var directory = io.Directory(filePath);
@@ -431,7 +431,7 @@
   }
 
   void _verifyAnalysisOptionsFileExists(CommandLineOptions options) {
-    var path = options.analysisOptionsFile;
+    var path = options.defaultAnalysisOptionsPath;
     if (path != null) {
       if (!resourceProvider.getFile(path).exists) {
         printAndFail('Options file not found: $path',
@@ -449,8 +449,8 @@
       CommandLineOptions previous, CommandLineOptions newOptions) {
     return previous != null &&
         newOptions != null &&
-        newOptions.packageConfigPath == previous.packageConfigPath &&
-        _equalMaps(newOptions.definedVariables, previous.definedVariables) &&
+        newOptions.defaultPackagesPath == previous.defaultPackagesPath &&
+        _equalMaps(newOptions.declaredVariables, previous.declaredVariables) &&
         newOptions.log == previous.log &&
         newOptions.disableHints == previous.disableHints &&
         newOptions.showPackageWarnings == previous.showPackageWarnings &&
@@ -554,8 +554,8 @@
     _collection = AnalysisContextCollectionImpl(
       byteStore: Driver.analysisDriverMemoryByteStore,
       includedPaths: _pathList,
-      optionsFile: _commandLineOptions.analysisOptionsFile,
-      packagesFile: _commandLineOptions.packageConfigPath,
+      optionsFile: _commandLineOptions.defaultAnalysisOptionsPath,
+      packagesFile: _commandLineOptions.defaultPackagesPath,
       resourceProvider: _resourceProvider,
       sdkPath: _commandLineOptions.dartSdkPath,
       updateAnalysisOptions: _updateAnalysisOptions,
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index bb2da44..7ec27d6 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -6,7 +6,6 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
@@ -51,8 +50,18 @@
 class CommandLineOptions {
   final ArgResults _argResults;
 
-  /// The options defining the context in which analysis is performed.
-  final ContextBuilderOptions contextBuilderOptions;
+  /// The file path of the analysis options file that should be used in place of
+  /// any file in the root directory or a parent of the root directory,
+  /// or `null` if the normal lookup mechanism should be used.
+  String defaultAnalysisOptionsPath;
+
+  /// The file path of the .packages file that should be used in place of any
+  /// file found using the normal (Package Specification DEP) lookup mechanism,
+  /// or `null` if the normal lookup mechanism should be used.
+  String defaultPackagesPath;
+
+  /// A table mapping variable names to values for the declared variables.
+  final Map<String, String> declaredVariables = {};
 
   /// The path to the dart SDK.
   String dartSdkPath;
@@ -124,10 +133,6 @@
     ResourceProvider resourceProvider,
     ArgResults args,
   )   : _argResults = args,
-        contextBuilderOptions = _createContextBuilderOptions(
-          resourceProvider,
-          args,
-        ),
         dartSdkPath = cast(args[_sdkPathOption]),
         disableCacheFlushing = cast(args['disable-cache-flushing']),
         disableHints = cast(args['no-hints']),
@@ -149,11 +154,41 @@
         lintsAreFatal = cast(args['fatal-lints']),
         trainSnapshot = cast(args['train-snapshot']),
         verbose = cast(args['verbose']),
-        color = cast(args['color']);
+        color = cast(args['color']) {
+    //
+    // File locations.
+    //
+    defaultAnalysisOptionsPath = _absoluteNormalizedPath(
+      resourceProvider,
+      cast(args[_analysisOptionsFileOption]),
+    );
+    defaultPackagesPath = _absoluteNormalizedPath(
+      resourceProvider,
+      cast(args[_packagesOption]),
+    );
 
-  /// The path to an analysis options file
-  String get analysisOptionsFile =>
-      contextBuilderOptions.defaultAnalysisOptionsFilePath;
+    //
+    // Declared variables.
+    //
+    var variables = (args[_defineVariableOption] as List).cast<String>();
+    for (var variable in variables) {
+      var index = variable.indexOf('=');
+      if (index < 0) {
+        // TODO (brianwilkerson) Decide the semantics we want in this case.
+        // The VM prints "No value given to -D option", then tries to load '-Dfoo'
+        // as a file and dies. Unless there was nothing after the '-D', in which
+        // case it prints the warning and ignores the option.
+      } else {
+        var name = variable.substring(0, index);
+        if (name.isNotEmpty) {
+          // TODO (brianwilkerson) Decide the semantics we want in the case where
+          // there is no name. If there is no name, the VM tries to load a file
+          // named '-D' and dies.
+          declaredVariables[name] = variable.substring(index + 1);
+        }
+      }
+    }
+  }
 
   /// The default language version for files that are not in a package.
   /// (Or null if no default language version to force.)
@@ -161,10 +196,6 @@
     return cast(_argResults[_defaultLanguageVersionOption]);
   }
 
-  /// A table mapping the names of defined variables to their values.
-  Map<String, String> get definedVariables =>
-      contextBuilderOptions.declaredVariables;
-
   /// A list of the names of the experiments that are to be enabled.
   List<String> get enabledExperiments {
     return cast(_argResults[_enableExperimentOption]);
@@ -176,9 +207,6 @@
 
   bool get noImplicitDynamic => _argResults[_noImplicitDynamicFlag] as bool;
 
-  /// The path to a `.packages` configuration file
-  String get packageConfigPath => contextBuilderOptions.defaultPackageFilePath;
-
   /// Update the [analysisOptions] with flags that the user specified
   /// explicitly. The [analysisOptions] are usually loaded from one of
   /// `analysis_options.yaml` files, possibly with includes. We consider
@@ -307,57 +335,17 @@
     return options;
   }
 
-  /// Use the command-line [args] to create a context builder options.
-  static ContextBuilderOptions _createContextBuilderOptions(
+  static String _absoluteNormalizedPath(
     ResourceProvider resourceProvider,
-    ArgResults args,
+    String path,
   ) {
-    String absoluteNormalizedPath(String path) {
-      if (path == null) {
-        return null;
-      }
-      var pathContext = resourceProvider.pathContext;
-      return pathContext.normalize(
-        pathContext.absolute(path),
-      );
+    if (path == null) {
+      return null;
     }
-
-    var builderOptions = ContextBuilderOptions();
-
-    //
-    // File locations.
-    //
-    builderOptions.defaultAnalysisOptionsFilePath = absoluteNormalizedPath(
-      cast(args[_analysisOptionsFileOption]),
+    var pathContext = resourceProvider.pathContext;
+    return pathContext.normalize(
+      pathContext.absolute(path),
     );
-    builderOptions.defaultPackageFilePath = absoluteNormalizedPath(
-      cast(args[_packagesOption]),
-    );
-    //
-    // Declared variables.
-    //
-    var declaredVariables = <String, String>{};
-    var variables = (args[_defineVariableOption] as List).cast<String>();
-    for (var variable in variables) {
-      var index = variable.indexOf('=');
-      if (index < 0) {
-        // TODO (brianwilkerson) Decide the semantics we want in this case.
-        // The VM prints "No value given to -D option", then tries to load '-Dfoo'
-        // as a file and dies. Unless there was nothing after the '-D', in which
-        // case it prints the warning and ignores the option.
-      } else {
-        var name = variable.substring(0, index);
-        if (name.isNotEmpty) {
-          // TODO (brianwilkerson) Decide the semantics we want in the case where
-          // there is no name. If there is no name, the VM tries to load a file
-          // named '-D' and dies.
-          declaredVariables[name] = variable.substring(index + 1);
-        }
-      }
-    }
-    builderOptions.declaredVariables = declaredVariables;
-
-    return builderOptions;
   }
 
   /// Add the standard flags and options to the given [parser]. The standard flags
diff --git a/pkg/analyzer_cli/lib/src/perf_report.dart b/pkg/analyzer_cli/lib/src/perf_report.dart
index 25c21c5..04caa35 100644
--- a/pkg/analyzer_cli/lib/src/perf_report.dart
+++ b/pkg/analyzer_cli/lib/src/perf_report.dart
@@ -38,8 +38,8 @@
     'showPackageWarnings': options.showPackageWarnings,
     'showPackageWarningsPrefix': options.showPackageWarningsPrefix,
     'showSdkWarnings': options.showSdkWarnings,
-    'definedVariables': options.definedVariables,
-    'packageConfigPath': options.packageConfigPath,
+    'definedVariables': options.declaredVariables,
+    'packageConfigPath': options.defaultPackagesPath,
     'sourceFiles': options.sourceFiles,
   };
 
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index 419aceb..19d778d 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -73,7 +73,9 @@
         path.join(testDirectory, options),
       ];
     }
-    cmd..addAll(sources.map(_adjustFileSpec))..addAll(args);
+    cmd
+      ..addAll(sources.map(_adjustFileSpec))
+      ..addAll(args);
 
     await driver.start(cmd);
   }
@@ -390,6 +392,20 @@
   ErrorProcessor processorFor(AnalysisError error) =>
       processors.firstWhere((p) => p.appliesTo(error));
 
+  /// If a file is specified explicitly, it should be analyzed, even if
+  /// it is excluded. Excludes work when an including directory is specified.
+  Future<void> test_analysisOptions_excluded_requested() async {
+    await drive(
+      'data/exclude_test_project/lib/excluded_error.dart',
+      options: 'data/exclude_test_project/$analysisOptionsYaml',
+    );
+    expect(
+      bulletToDash(outSink),
+      contains("error - Undefined class 'ExcludedUndefinedClass'"),
+    );
+    expect(outSink.toString(), contains('1 error found.'));
+  }
+
   Future<void> test_analysisOptions_excludes() async {
     await drive('data/exclude_test_project',
         options: 'data/exclude_test_project/$analysisOptionsYaml');
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index 242c86d..4b7167b 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -84,8 +84,8 @@
 
       test('defined variables', () {
         var options = parse(['--dart-sdk', '.', '-Dfoo=bar', 'foo.dart']);
-        expect(options.definedVariables['foo'], equals('bar'));
-        expect(options.definedVariables['bar'], isNull);
+        expect(options.declaredVariables['foo'], equals('bar'));
+        expect(options.declaredVariables['bar'], isNull);
       });
 
       test('disable cache flushing', () {
@@ -210,7 +210,7 @@
       test('options', () {
         var options =
             parse(['--dart-sdk', '.', '--options', 'options.yaml', 'foo.dart']);
-        expect(options.analysisOptionsFile, endsWith('options.yaml'));
+        expect(options.defaultAnalysisOptionsPath, endsWith('options.yaml'));
       });
 
       test('lints', () {
@@ -284,8 +284,7 @@
   void test_declaredVariables() {
     _parse(['-Da=0', '-Db=', 'a.dart']);
 
-    var options = commandLineOptions.contextBuilderOptions;
-    var definedVariables = options.declaredVariables;
+    var definedVariables = commandLineOptions.declaredVariables;
 
     expect(definedVariables['a'], '0');
     expect(definedVariables['b'], '');
@@ -296,9 +295,8 @@
     var expected = 'my_options.yaml';
     _parse(['--options=$expected', 'a.dart']);
 
-    var builderOptions = commandLineOptions.contextBuilderOptions;
     expect(
-      builderOptions.defaultAnalysisOptionsFilePath,
+      commandLineOptions.defaultAnalysisOptionsPath,
       endsWith(expected),
     );
   }
@@ -307,21 +305,17 @@
     var expected = 'my_package_config.json';
     _parse(['--packages=$expected', 'a.dart']);
 
-    var builderOptions = commandLineOptions.contextBuilderOptions;
     expect(
-      builderOptions.defaultPackageFilePath,
+      commandLineOptions.defaultPackagesPath,
       endsWith(expected),
     );
   }
 
   void test_defaults() {
     _parse(['a.dart']);
-    var builderOptions = commandLineOptions.contextBuilderOptions;
-    expect(builderOptions, isNotNull);
-    expect(builderOptions.dartSdkSummaryPath, isNull);
-    expect(builderOptions.declaredVariables, isEmpty);
-    expect(builderOptions.defaultAnalysisOptionsFilePath, isNull);
-    expect(builderOptions.defaultPackageFilePath, isNull);
+    expect(commandLineOptions.declaredVariables, isEmpty);
+    expect(commandLineOptions.defaultAnalysisOptionsPath, isNull);
+    expect(commandLineOptions.defaultPackagesPath, isNull);
   }
 
   void test_filterUnknownArguments() {
diff --git a/pkg/analyzer_plugin/CHANGELOG.md b/pkg/analyzer_plugin/CHANGELOG.md
index a2d2707..3ee89a3 100644
--- a/pkg/analyzer_plugin/CHANGELOG.md
+++ b/pkg/analyzer_plugin/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.7.0
+
+- Support verison `2.x` of the `analyzer` package
+
 ## 0.6.0
 - Bug fixes to the protocol.
 
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index dbe9f26..96c8505 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1579,13 +1579,13 @@
           The one-based index of the column containing the first character of
           the range.
         </p>
-      </dd><dt class="field"><b>endLine: int</b></dt><dd>
+      </dd><dt class="field"><b>endLine: int<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
           The one-based index of the line containing the character immediately
           following the range.
         </p>
-      </dd><dt class="field"><b>endColumn: int</b></dt><dd>
+      </dd><dt class="field"><b>endColumn: int<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
           The one-based index of the column containing the character immediately
diff --git a/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart b/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
index de11deb..07dbddb 100644
--- a/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
@@ -27,7 +27,7 @@
     var length = parameters.length;
     if (offset < 0 && length < 0) {
       offset = 0;
-      length = result.content?.length ?? 0;
+      length = result.content.length;
     }
     return DartNavigationRequestImpl(resourceProvider, offset, length, result);
   }
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 691c48d..e437a89 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -2884,8 +2884,8 @@
 ///   "length": int
 ///   "startLine": int
 ///   "startColumn": int
-///   "endLine": int
-///   "endColumn": int
+///   "endLine": optional int
+///   "endColumn": optional int
 /// }
 ///
 /// Clients may not extend, implement or mix-in this class.
@@ -2909,14 +2909,15 @@
 
   /// The one-based index of the line containing the character immediately
   /// following the range.
-  int endLine;
+  int? endLine;
 
   /// The one-based index of the column containing the character immediately
   /// following the range.
-  int endColumn;
+  int? endColumn;
 
-  Location(this.file, this.offset, this.length, this.startLine,
-      this.startColumn, this.endLine, this.endColumn);
+  Location(
+      this.file, this.offset, this.length, this.startLine, this.startColumn,
+      {this.endLine, this.endColumn});
 
   factory Location.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -2954,21 +2955,17 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'startColumn');
       }
-      int endLine;
+      int? endLine;
       if (json.containsKey('endLine')) {
         endLine = jsonDecoder.decodeInt(jsonPath + '.endLine', json['endLine']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'endLine');
       }
-      int endColumn;
+      int? endColumn;
       if (json.containsKey('endColumn')) {
         endColumn =
             jsonDecoder.decodeInt(jsonPath + '.endColumn', json['endColumn']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'endColumn');
       }
-      return Location(
-          file, offset, length, startLine, startColumn, endLine, endColumn);
+      return Location(file, offset, length, startLine, startColumn,
+          endLine: endLine, endColumn: endColumn);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'Location', json);
     }
@@ -2982,8 +2979,14 @@
     result['length'] = length;
     result['startLine'] = startLine;
     result['startColumn'] = startColumn;
-    result['endLine'] = endLine;
-    result['endColumn'] = endColumn;
+    var endLine = this.endLine;
+    if (endLine != null) {
+      result['endLine'] = endLine;
+    }
+    var endColumn = this.endColumn;
+    if (endColumn != null) {
+      result['endColumn'] = endColumn;
+    }
     return result;
   }
 
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
index ab273d2..0e6ea1a 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
@@ -246,13 +246,13 @@
     }
 
     var session = workspace.getSession(path);
-    var result = await session?.getResolvedUnit2(path);
+    var result = await session?.getResolvedUnit(path);
     if (result is! ResolvedUnitResult) {
       throw AnalysisException('Cannot analyze "$path"');
     }
     var timeStamp = result.exists ? 0 : -1;
 
-    var declaredUnit = result.unit?.declaredElement;
+    var declaredUnit = result.unit.declaredElement;
     var libraryUnit = declaredUnit?.library.definingCompilationUnit;
 
     DartFileEditBuilderImpl? libraryEditBuilder;
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 12e92b5..7d86a7f 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
@@ -1155,12 +1155,11 @@
       return false;
     }
 
-    var aliasElement = type.aliasElement;
-    var aliasArguments = type.aliasArguments;
-    if (aliasElement != null && aliasArguments != null) {
+    var alias = type.alias;
+    if (alias != null) {
       _writeTypeElementArguments(
-        element: aliasElement,
-        typeArguments: aliasArguments,
+        element: alias.element,
+        typeArguments: alias.typeArguments,
         methodBeingCopied: methodBeingCopied,
       );
       _writeTypeNullability(type);
@@ -1281,7 +1280,7 @@
   /// the given [resolvedUnit] and [timeStamp].
   DartFileEditBuilderImpl(ChangeBuilderImpl changeBuilder, this.resolvedUnit,
       int timeStamp, this.libraryChangeBuilder)
-      : super(changeBuilder, resolvedUnit.path!, timeStamp);
+      : super(changeBuilder, resolvedUnit.path, timeStamp);
 
   @override
   bool get hasEdits =>
@@ -1353,7 +1352,7 @@
 
   @override
   void format(SourceRange range) {
-    var newContent = resolvedUnit.content!;
+    var newContent = resolvedUnit.content;
     var newRangeOffset = range.offset;
     var newRangeLength = range.length;
     for (var edit in fileEdit.edits) {
@@ -1437,7 +1436,7 @@
     LibraryDirective? libraryDirective;
     var importDirectives = <ImportDirective>[];
     PartDirective? partDirective;
-    var unit = resolvedUnit.unit!;
+    var unit = resolvedUnit.unit;
     for (var directive in unit.directives) {
       if (directive is LibraryDirective) {
         libraryDirective = directive;
diff --git a/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart b/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart
index a302a76..d424abf 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart
@@ -21,7 +21,7 @@
   DartFoldingRequestImpl(this.resourceProvider, this.result);
 
   @override
-  String get path => result.path!;
+  String get path => result.path;
 }
 
 /// A concrete implementation of [FoldingCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart b/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart
index 5e55b48..95bd889 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart
@@ -21,7 +21,7 @@
   DartHighlightsRequestImpl(this.resourceProvider, this.result);
 
   @override
-  String get path => result.path!;
+  String get path => result.path;
 }
 
 /// A concrete implementation of [HighlightsCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart b/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart
index 191101c..684e9e7 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart
@@ -19,7 +19,7 @@
   DartEntryRequestImpl(this.resourceProvider, this.result);
 
   @override
-  String get path => result.path!;
+  String get path => result.path;
 }
 
 /// A concrete implementation of [EntryCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart b/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart
index 4e1850c..23709a3 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart
@@ -28,7 +28,7 @@
       this.resourceProvider, this.offset, this.length, this.result);
 
   @override
-  String get path => result.path!;
+  String get path => result.path;
 }
 
 /// A concrete implementation of [NavigationCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart b/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart
index 6bd0592..f436774 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart
@@ -20,7 +20,7 @@
   DartOccurrencesRequestImpl(this.resourceProvider, this.result);
 
   @override
-  String get path => result.path!;
+  String get path => result.path;
 }
 
 /// A concrete implementation of [OccurrencesCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart b/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart
index 44d4dd9..284f140 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart
@@ -20,7 +20,7 @@
   DartOutlineRequestImpl(this.resourceProvider, this.result);
 
   @override
-  String get path => result.path!;
+  String get path => result.path;
 }
 
 /// A concrete implementation of [OutlineCollector].
diff --git a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
index 87af1a3..575cd5b 100644
--- a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
+++ b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
@@ -48,8 +48,9 @@
     return plugin.AnalysisError(
         convertErrorSeverity(severity),
         convertErrorType(errorCode.type),
-        plugin.Location(error.source.fullName, offset, error.length, startLine,
-            startColumn, endLine, endColumn),
+        plugin.Location(
+            error.source.fullName, offset, error.length, startLine, startColumn,
+            endLine: endLine, endColumn: endColumn),
         error.message,
         errorCode.name.toLowerCase(),
         contextMessages: contextMessages,
@@ -107,8 +108,8 @@
     }
     return plugin.DiagnosticMessage(
         message.messageText(includeUrl: true),
-        plugin.Location(
-            file, offset, length, startLine, startColumn, endLine, endColumn));
+        plugin.Location(file, offset, length, startLine, startColumn,
+            endLine: endLine, endColumn: endColumn));
   }
 
   /// Convert the given [element] from the 'analyzer' package to an element
@@ -407,6 +408,7 @@
       // Ignore exceptions
     }
     return plugin.Location(unitElement.source.fullName, range.offset,
-        range.length, startLine, startColumn, endLine, endColumn);
+        range.length, startLine, startColumn,
+        endLine: endLine, endColumn: endColumn);
   }
 }
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
index a605f4e..cf0a57b 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
@@ -35,7 +35,7 @@
   Future<void> computeSuggestions(
       DartCompletionRequest request, CompletionCollector collector) async {
     var target =
-        CompletionTarget.forOffset(request.result.unit!, request.offset);
+        CompletionTarget.forOffset(request.result.unit, request.offset);
     var optype = OpType.forCompletion(target, request.offset);
     if (!optype.includeIdentifiers) {
       return;
@@ -59,7 +59,7 @@
     CompletionTarget? target,
     OpType? optype,
   }) async {
-    target ??= CompletionTarget.forOffset(request.result.unit!, request.offset,
+    target ??= CompletionTarget.forOffset(request.result.unit, request.offset,
         entryPoint: entryPoint);
     optype ??= OpType.forCompletion(target, request.offset);
     if (!optype.includeIdentifiers) {
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
index 1009c12..d190e3d 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
@@ -53,7 +53,7 @@
   Expression? _computeDotTarget(
       DartCompletionRequest request, AstNode? entryPoint) {
     var target = CompletionTarget.forOffset(
-        request.result.unit!, request.offset,
+        request.result.unit, request.offset,
         entryPoint: entryPoint);
     var node = target.containingNode;
     if (node is MethodInvocation) {
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index e409097a..c161993 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -178,7 +178,7 @@
       return null;
     }
 
-    var parsedLibrary = session.getParsedLibrary2(libraryPath);
+    var parsedLibrary = session.getParsedLibrary(libraryPath);
     if (parsedLibrary is! ParsedLibraryResult) {
       return null;
     }
@@ -261,7 +261,8 @@
               uriNode.offset,
               uriNode.length,
               protocol.ElementKind.LIBRARY,
-              protocol.Location(source.fullName, 0, 0, 0, 0, 0, 0));
+              protocol.Location(source.fullName, 0, 0, 0, 0,
+                  endLine: 0, endColumn: 0));
         }
       }
     }
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 1ee70fe..7b0003e 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,13 +1,13 @@
 name: analyzer_plugin
 description: A framework and support code for building plugins for the analysis server.
-version: 0.6.0
+version: 0.7.0
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_plugin
 
 environment:
   sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
-  analyzer: ^1.5.0
+  analyzer: ^2.0.0
   collection: ^1.15.0
   dart_style: ^2.0.0
   pub_semver: ^2.0.0
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 5c52f19..4ed7683 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -591,15 +591,16 @@
 ///   "length": int
 ///   "startLine": int
 ///   "startColumn": int
-///   "endLine": int
-///   "endColumn": int
+///   "endLine": optional int
+///   "endColumn": optional int
 /// }
 final Matcher isLocation = LazyMatcher(() => MatchesJsonObject('Location', {
       'file': isFilePath,
       'offset': isInt,
       'length': isInt,
       'startLine': isInt,
-      'startColumn': isInt,
+      'startColumn': isInt
+    }, optionalFields: {
       'endLine': isInt,
       'endColumn': isInt
     }));
diff --git a/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
index 2c3dcfd..3c29dfb 100644
--- a/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
@@ -80,8 +80,8 @@
   void computeNavigation(
       NavigationRequest request, NavigationCollector collector) {
     for (var i = 0; i < regionCount; i++) {
-      collector.addRegion(
-          i, 5, ElementKind.METHOD, Location('a', 5, 5, 1, 5, 1, 10));
+      collector.addRegion(i, 5, ElementKind.METHOD,
+          Location('a', 5, 5, 1, 5, endLine: 1, endColumn: 10));
     }
   }
 }
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 7d3e886..fd398ed 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
@@ -790,7 +790,7 @@
     addSource(path, content);
     var unit = (await resolveFile(path)).unit;
 
-    var A = unit?.declarations[1] as ClassDeclaration;
+    var A = unit.declarations[1] as ClassDeclaration;
 
     var builder = newBuilder();
     await builder.addDartFileEdit(path, (builder) {
@@ -821,7 +821,7 @@
     addSource(path, content);
     var unit = (await resolveFile(path)).unit;
 
-    var A = unit?.declarations[1] as ClassDeclaration;
+    var A = unit.declarations[1] as ClassDeclaration;
 
     var builder = newBuilder();
     await builder.addDartFileEdit(path, (builder) {
@@ -857,7 +857,7 @@
     addSource(path, content);
     var unit = (await resolveFile(path)).unit;
 
-    var A = unit?.declarations[1] as ClassDeclaration;
+    var A = unit.declarations[1] as ClassDeclaration;
 
     var builder = newBuilder();
     await builder.addDartFileEdit(path, (builder) {
@@ -1026,7 +1026,7 @@
 ''';
     addSource(path, content);
     var unit = (await resolveFile(path)).unit;
-    var g = unit?.declarations[1] as FunctionDeclaration;
+    var g = unit.declarations[1] as FunctionDeclaration;
     var body = g.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
     var invocation = statement.expression as MethodInvocation;
@@ -1048,7 +1048,7 @@
     addSource(path, content);
 
     var unit = (await resolveFile(path)).unit;
-    var f = unit?.declarations[0] as FunctionDeclaration;
+    var f = unit.declarations[0] as FunctionDeclaration;
     var parameters = f.functionExpression.parameters;
     var elements = parameters?.parameters.map((p) => p.declaredElement!);
 
@@ -1068,7 +1068,7 @@
     var content = 'f(int a, [bool b = false, String c]) {}';
     addSource(path, content);
     var unit = (await resolveFile(path)).unit;
-    var f = unit?.declarations[0] as FunctionDeclaration;
+    var f = unit.declarations[0] as FunctionDeclaration;
     var parameters = f.functionExpression.parameters;
     var elements = parameters?.parameters.map((p) => p.declaredElement!);
 
@@ -1088,7 +1088,7 @@
     var content = 'f(int i, String s) {}';
     addSource(path, content);
     var unit = (await resolveFile(path)).unit;
-    var f = unit?.declarations[0] as FunctionDeclaration;
+    var f = unit.declarations[0] as FunctionDeclaration;
     var parameters = f.functionExpression.parameters;
     var elements = parameters?.parameters.map((p) => p.declaredElement!);
 
@@ -1110,7 +1110,7 @@
 }''';
     addSource(path, content);
     var unit = (await resolveFile(path)).unit;
-    var f = unit?.declarations[0] as FunctionDeclaration;
+    var f = unit.declarations[0] as FunctionDeclaration;
     var body = f.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
     var invocation = statement.expression as MethodInvocation;
@@ -1133,7 +1133,7 @@
 }''';
     addSource(path, content);
     var unit = (await resolveFile(path)).unit;
-    var f = unit?.declarations[0] as FunctionDeclaration;
+    var f = unit.declarations[0] as FunctionDeclaration;
     var body = f.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
     var invocation = statement.expression as MethodInvocation;
@@ -1330,7 +1330,7 @@
     var builder = newBuilder();
     await builder.addDartFileEdit(path, (builder) {
       builder.addInsertion(content.length - 1, (builder) {
-        var typeProvider = unit!.declaredElement!.library.typeProvider;
+        var typeProvider = unit.declaredElement!.library.typeProvider;
         builder.writeType(typeProvider.dynamicType);
       });
     });
@@ -1543,7 +1543,7 @@
     var builder = newBuilder();
     await builder.addDartFileEdit(path, (builder) {
       builder.addInsertion(content.length - 1, (builder) {
-        var typeProvider = unit!.declaredElement!.library.typeProvider;
+        var typeProvider = unit.declaredElement!.library.typeProvider;
         builder.writeType(typeProvider.dynamicType, required: true);
       });
     });
@@ -1690,13 +1690,13 @@
 
   Future<ClassElement> _getClassElement(String path, String name) async {
     var result = (await resolveFile(path)).unit;
-    return result!.declaredElement!.getType(name)!;
+    return result.declaredElement!.getType(name)!;
   }
 
   Future<PropertyAccessorElement> _getTopLevelAccessorElement(
       String path, String name) async {
     var result = (await resolveFile(path)).unit;
-    return result!.declaredElement!.accessors.firstWhere((v) => v.name == name);
+    return result.declaredElement!.accessors.firstWhere((v) => v.name == name);
   }
 
   Future<InterfaceType> _getType(
@@ -1720,7 +1720,7 @@
     addSource(path, '''var f = () {}''');
 
     var resolvedUnit = await resolveFile(path);
-    var findNode = FindNode(resolvedUnit.content!, resolvedUnit.unit!);
+    var findNode = FindNode(resolvedUnit.content, resolvedUnit.unit);
     var body = findNode.functionBody('{}');
 
     var builder = newBuilder();
@@ -1737,7 +1737,7 @@
     addSource(path, 'String f() {}');
 
     var resolvedUnit = await resolveFile(path);
-    var findNode = FindNode(resolvedUnit.content!, resolvedUnit.unit!);
+    var findNode = FindNode(resolvedUnit.content, resolvedUnit.unit);
     var body = findNode.functionBody('{}');
 
     var builder = newBuilder();
@@ -1850,7 +1850,7 @@
     addSource(path, 'String f() {}');
 
     var resolvedUnit = await resolveFile(path);
-    var findNode = FindNode(resolvedUnit.content!, resolvedUnit.unit!);
+    var findNode = FindNode(resolvedUnit.content, resolvedUnit.unit);
     var type = findNode.typeAnnotation('String');
 
     var builder = newBuilder();
@@ -1873,7 +1873,7 @@
 class C extends B {}
 ''');
     var unit = (await resolveFile(path)).unit;
-    var classC = unit?.declarations[2] as ClassDeclaration;
+    var classC = unit.declarations[2] as ClassDeclaration;
     var builder = DartLinkedEditBuilderImpl(MockEditBuilderImpl());
     builder.addSuperTypesAsSuggestions(
       classC.declaredElement?.instantiate(
@@ -2895,10 +2895,10 @@
     {
       var unitResult = (await resolveFile(path)).unit;
       if (targetMixinName != null) {
-        targetElement = unitResult!.declaredElement!.mixins
+        targetElement = unitResult.declaredElement!.mixins
             .firstWhere((e) => e.name == targetMixinName);
       } else {
-        targetElement = unitResult!.declaredElement!.classes
+        targetElement = unitResult.declaredElement!.classes
             .firstWhere((e) => e.name == targetClassName);
       }
     }
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_yaml_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_yaml_test.dart
index 866316c..00da884 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_yaml_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_yaml_test.dart
@@ -21,7 +21,9 @@
 }
 
 class AbstractYamlChangeBuilderTest extends AbstractChangeBuilderTest {
-  String get testFilePath => '/home/my/pubspec.yaml';
+  String get testFilePath {
+    return resourceProvider.convertPath('/home/my/pubspec.yaml');
+  }
 
   void createPubspec(String content) {
     resourceProvider.newFile(testFilePath, content);
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
index 5239e00..cd2eefa 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
@@ -469,7 +469,7 @@
     newFile(path, content: initialCode);
 
     var requestedResult =
-        await session.getLibraryByUri2(uriStr) as LibraryElementResult;
+        await session.getLibraryByUri(uriStr) as LibraryElementResult;
     var requestedLibrary = requestedResult.element;
     var requestedElement = requestedLibrary.exportNamespace.get(name);
     expect(requestedElement, isNotNull, reason: '`$name` in $uriStr');
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
index 71b649d..742f070 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
@@ -954,9 +954,9 @@
     newFile(path, content: content);
 
     var result = await resolveFile(path);
-    findElement = FindElement(result.unit!);
+    findElement = FindElement(result.unit);
 
-    target = CompletionTarget.forOffset(result.unit!, offset!);
+    target = CompletionTarget.forOffset(result.unit, offset!);
   }
 
   static String _executableNameStr(ExecutableElement executable) {
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
index 3c8fe89..79c9e0c 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -50,7 +50,7 @@
     //
     var resolvedUnit = await resolveFile(testPath);
     var completionTarget =
-        CompletionTarget.forOffset(resolvedUnit.unit!, completionOffset);
+        CompletionTarget.forOffset(resolvedUnit.unit, completionOffset);
     var opType = OpType.forCompletion(completionTarget, completionOffset);
     //
     // Validate the OpType.
diff --git a/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart b/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart
index 45179b0..5a76e0f 100644
--- a/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart
@@ -24,14 +24,16 @@
     var targetStartColumnA1 = 4;
     var targetKindA1 = ElementKind.CLASS;
     var targetLocationA1 = Location(fileA, targetOffsetA1, targetLengthA1,
-        targetStartLineA1, targetStartColumnA1, 0, 0);
+        targetStartLineA1, targetStartColumnA1,
+        endLine: 0, endColumn: 0);
     var targetOffsetA2 = 5;
     var targetLengthA2 = 6;
     var targetStartLineA2 = 7;
     var targetStartColumnA2 = 8;
     var targetKindA2 = ElementKind.FUNCTION;
     var targetLocationA2 = Location(fileA, targetOffsetA2, targetLengthA2,
-        targetStartLineA2, targetStartColumnA2, 0, 0);
+        targetStartLineA2, targetStartColumnA2,
+        endLine: 0, endColumn: 0);
 
     var fileB = 'b.dart';
     var targetOffsetB1 = 9;
@@ -40,14 +42,16 @@
     var targetStartColumnB1 = 12;
     var targetKindB1 = ElementKind.ENUM;
     var targetLocationB1 = Location(fileB, targetOffsetB1, targetLengthB1,
-        targetStartLineB1, targetStartColumnB1, 0, 0);
+        targetStartLineB1, targetStartColumnB1,
+        endLine: 0, endColumn: 0);
     var targetOffsetB2 = 13;
     var targetLengthB2 = 14;
     var targetStartLineB2 = 15;
     var targetStartColumnB2 = 16;
     var targetKindB2 = ElementKind.METHOD;
     var targetLocationB2 = Location(fileB, targetOffsetB2, targetLengthB2,
-        targetStartLineB2, targetStartColumnB2, 0, 0);
+        targetStartLineB2, targetStartColumnB2,
+        endLine: 0, endColumn: 0);
 
     // Six regions targeting a1, b1, a2, b1, a1, b2
     var regionOffsets = <int>[17, 18, 19, 20, 21, 22];
@@ -112,7 +116,8 @@
     var targetStartLine = 5;
     var targetStartColumn = 1;
     var targetLocation = Location(targetFile, targetOffset, targetLength,
-        targetStartLine, targetStartColumn, 0, 0);
+        targetStartLine, targetStartColumn,
+        endLine: 0, endColumn: 0);
     collector.addRegion(regionOffset, regionLength, targetKind, targetLocation);
     collector.createRegions();
     expect(collector.files, [targetFile]);
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart
index 6bd18116..6d58ad9 100644
--- a/pkg/analyzer_plugin/test/support/abstract_context.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -98,7 +98,7 @@
 
   Future<ResolvedUnitResult> resolveFile(String path) async {
     var session = contextFor(path).currentSession;
-    return await session.getResolvedUnit2(path) as ResolvedUnitResult;
+    return await session.getResolvedUnit(path) as ResolvedUnitResult;
   }
 
   void setUp() {
diff --git a/pkg/analyzer_plugin/test/support/abstract_single_unit.dart b/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
index afa5699..bdd1c69 100644
--- a/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
@@ -95,8 +95,8 @@
 
   Future<void> resolveTestFile() async {
     var result = await resolveFile(testFile);
-    testCode = result.content!;
-    testUnit = result.unit!;
+    testCode = result.content;
+    testUnit = result.unit;
     if (verifyNoTestUnitErrors) {
       expect(result.errors.where((AnalysisError error) {
         return error.errorCode != HintCode.DEAD_CODE &&
diff --git a/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart b/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
index d7cba95..a98ac39 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
@@ -418,7 +418,7 @@
         DartCompletionRequestImpl(resourceProvider, completionOffset!, result);
 
     var target =
-        CompletionTarget.forOffset(request!.result.unit!, request!.offset);
+        CompletionTarget.forOffset(request!.result.unit, request!.offset);
     var range = target.computeReplacementRange(request!.offset);
     replacementOffset = range.offset;
     replacementLength = range.length;
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 1ec7a90..412fcb7 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -1057,14 +1057,14 @@
           the range.
         </p>
       </field>
-      <field name="endLine">
+      <field name="endLine" optional="true">
         <ref>int</ref>
         <p>
           The one-based index of the line containing the character immediately
           following the range.
         </p>
       </field>
-      <field name="endColumn">
+      <field name="endColumn" optional="true">
         <ref>int</ref>
         <p>
           The one-based index of the column containing the character immediately
diff --git a/pkg/analyzer_utilities/lib/verify_tests.dart b/pkg/analyzer_utilities/lib/verify_tests.dart
index 201e88d..de1bf43 100644
--- a/pkg/analyzer_utilities/lib/verify_tests.dart
+++ b/pkg/analyzer_utilities/lib/verify_tests.dart
@@ -103,7 +103,7 @@
       if (isOkForTestAllToBeMissing(directory)) {
         fail('Found "test_all.dart" in $relativePath but did not expect one');
       }
-      var result = session.getParsedUnit2(testAllFile.path);
+      var result = session.getParsedUnit(testAllFile.path);
       if (result is! ParsedUnitResult) {
         fail('Could not parse ${testAllFile.path}');
       }
diff --git a/pkg/build_integration/lib/file_system/multi_root.dart b/pkg/build_integration/lib/file_system/multi_root.dart
index bfaead5..14772cc 100644
--- a/pkg/build_integration/lib/file_system/multi_root.dart
+++ b/pkg/build_integration/lib/file_system/multi_root.dart
@@ -47,7 +47,7 @@
 class MultiRootFileSystemEntity implements FileSystemEntity {
   final MultiRootFileSystem multiRootFileSystem;
   final Uri uri;
-  FileSystemEntity _delegate;
+  FileSystemEntity? _delegate;
   Future<FileSystemEntity> get delegate async =>
       _delegate ??= await _resolveEntity();
 
diff --git a/pkg/build_integration/pubspec.yaml b/pkg/build_integration/pubspec.yaml
index a7b79b1..899a5ed 100644
--- a/pkg/build_integration/pubspec.yaml
+++ b/pkg/build_integration/pubspec.yaml
@@ -6,7 +6,7 @@
 publish_to: none
 
 environment:
-  sdk: '>=2.1.0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
   front_end:
diff --git a/pkg/build_integration/test/file_system/multi_root_test.dart b/pkg/build_integration/test/file_system/multi_root_test.dart
index e92249a..09d3cc9 100644
--- a/pkg/build_integration/test/file_system/multi_root_test.dart
+++ b/pkg/build_integration/test/file_system/multi_root_test.dart
@@ -15,9 +15,8 @@
 var root = Uri.parse('org-dartlang-test:///');
 
 main() {
-  var memoryFs;
-  var rootUris;
-  var multiRoot;
+  late MemoryFileSystem memoryFs;
+  late MultiRootFileSystem multiRoot;
 
   write(String multiRoot, String path) {
     var realPath = multiRoot == '' ? path : '$multiRoot/$path';
@@ -32,11 +31,15 @@
       multiRoot.entityForUri(Uri.parse(uri)).exists();
 
   Future<String> effectiveUriOf(String uri) async =>
-      (await multiRoot.entityForUri(Uri.parse(uri)).delegate).uri.toString();
+      (await (multiRoot.entityForUri(Uri.parse(uri))
+                  as MultiRootFileSystemEntity)
+              .delegate)
+          .uri
+          .toString();
 
   setUp(() {
     memoryFs = new MemoryFileSystem(root);
-    rootUris = ['r1', 'r2/', 'A/B/', ''].map((r) => root.resolve(r)).toList();
+    final rootUris = ['r1', 'r2/', 'A/B/', ''].map((r) => root.resolve(r)).toList();
     multiRoot = new MultiRootFileSystem('multi-root', rootUris, memoryFs);
   });
 
diff --git a/pkg/build_integration/test/file_system/single_root_test.dart b/pkg/build_integration/test/file_system/single_root_test.dart
index 38ed4f8..50fb984 100644
--- a/pkg/build_integration/test/file_system/single_root_test.dart
+++ b/pkg/build_integration/test/file_system/single_root_test.dart
@@ -13,7 +13,7 @@
       'single-root', root.resolve('A/B'), new MemoryFileSystem(root));
 
   SingleRootFileSystemEntity entityOf(String uri) =>
-      fileSystem.entityForUri(Uri.parse(uri));
+      fileSystem.entityForUri(Uri.parse(uri)) as SingleRootFileSystemEntity;
 
   String effectiveUriOf(String uri) => '${entityOf(uri).delegate.uri}';
 
diff --git a/pkg/compiler/README.md b/pkg/compiler/README.md
index 6c9621a..3f493c5 100644
--- a/pkg/compiler/README.md
+++ b/pkg/compiler/README.md
@@ -351,11 +351,11 @@
     representation of JSInt31, JSArray, and other implementation-specific
     elements.
 
-* `lib/src/deferred_load.dart`: general analysis for deferred loading. This is
-  where we compute how to split the code in different JS chunks or fragments.
-  This is run after resolution, but at a time when no code is generated yet, so
-  the decisions made here are used later on by the emitter to dump code into
-  different files.
+* `lib/src/deferred_load/deferred_load.dart`: general analysis for deferred
+  loading. This is where we compute how to split the code in different JS chunks
+  or fragments.  This is run after resolution, but at a time when no code is
+  generated yet, so the decisions made here are used later on by the emitter to
+  dump code into different files.
 
 * `lib/src/dump_info.dart`: a special phase used to create a .info.json file.
   This file contains lots of information computed by dart2js including decisions
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index 92966bc..add5771 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -7,7 +7,7 @@
 import 'common.dart';
 import 'common/codegen.dart';
 import 'common/tasks.dart';
-import 'deferred_load.dart' show OutputUnitData;
+import 'deferred_load/deferred_load.dart' show OutputUnitData;
 import 'enqueue.dart';
 import 'elements/entities.dart';
 import 'inferrer/types.dart';
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 771756b..57ecf0f 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 library dart2js.cmdline.options;
 
 /// Commandline flags used in `dart2js.dart` and/or `apiimpl.dart`.
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 93bf848..bec3d57 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -9,7 +9,7 @@
 import '../common.dart';
 import '../common_elements.dart';
 import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart' show DartType, InterfaceType;
 import '../inferrer/abstract_value_domain.dart';
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index c8cd6d7..8fdefc4 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -217,7 +217,7 @@
   InterfaceType getConstantListTypeFor(InterfaceType sourceType);
 
   InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
-      {bool hasProtoKey: false, bool onlyStringKeys: false});
+      {bool onlyStringKeys: false});
 
   InterfaceType getConstantSetTypeFor(InterfaceType sourceType);
 
@@ -362,7 +362,6 @@
 
   ClassEntity get constantMapClass;
   ClassEntity get constantStringMapClass;
-  ClassEntity get constantProtoMapClass;
   ClassEntity get generalConstantMapClass;
 
   ClassEntity get annotationCreatesClass;
@@ -1037,10 +1036,9 @@
 
   @override
   InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
-      {bool hasProtoKey: false, bool onlyStringKeys: false}) {
-    ClassEntity classElement = onlyStringKeys
-        ? (hasProtoKey ? constantProtoMapClass : constantStringMapClass)
-        : generalConstantMapClass;
+      {bool onlyStringKeys: false}) {
+    ClassEntity classElement =
+        onlyStringKeys ? constantStringMapClass : generalConstantMapClass;
     if (dartTypes.treatAsRawType(sourceType)) {
       return _env.getRawType(classElement);
     } else {
@@ -1619,9 +1617,6 @@
   ClassEntity get constantStringMapClass =>
       _findHelperClass(constant_system.JavaScriptMapConstant.DART_STRING_CLASS);
   @override
-  ClassEntity get constantProtoMapClass =>
-      _findHelperClass(constant_system.JavaScriptMapConstant.DART_PROTO_CLASS);
-  @override
   ClassEntity get generalConstantMapClass => _findHelperClass(
       constant_system.JavaScriptMapConstant.DART_GENERAL_CLASS);
 
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 9d3ca36..d9303a6 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -18,7 +18,7 @@
 import 'common/work.dart' show WorkItem;
 import 'common.dart';
 import 'common_elements.dart' show ElementEnvironment;
-import 'deferred_load.dart' show DeferredLoadTask, OutputUnitData;
+import 'deferred_load/deferred_load.dart' show DeferredLoadTask, OutputUnitData;
 import 'diagnostics/code_location.dart';
 import 'diagnostics/messages.dart' show Message, MessageTemplate;
 import 'dump_info.dart' show DumpInfoTask;
@@ -91,10 +91,6 @@
   ImpactCacheDeleter get impactCacheDeleter => _impactCacheDeleter;
 
   final Environment environment;
-  // TODO(sigmund): delete once we migrate the rest of the compiler to use
-  // `environment` directly.
-  @deprecated
-  fromEnvironment(String name) => environment.valueOf(name);
 
   Entity get currentElement => _reporter.currentElement;
 
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index b10c628..d2d5b8f 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -157,23 +157,10 @@
     InterfaceType sourceType,
     List<ConstantValue> keys,
     List<ConstantValue> values) {
-  bool onlyStringKeys = true;
-  ConstantValue protoValue = null;
-  for (int i = 0; i < keys.length; i++) {
-    dynamic key = keys[i];
-    if (key.isString) {
-      if (key.stringValue == JavaScriptMapConstant.PROTO_PROPERTY) {
-        protoValue = values[i];
-      }
-    } else {
-      onlyStringKeys = false;
-      // Don't handle __proto__ values specially in the general map case.
-      protoValue = null;
-      break;
-    }
-  }
+  bool onlyStringKeys = keys.every((key) =>
+      key is StringConstantValue &&
+      key.stringValue != JavaScriptMapConstant.PROTO_PROPERTY);
 
-  bool hasProtoKey = (protoValue != null);
   InterfaceType keysType;
   if (commonElements.dartTypes.treatAsRawType(sourceType)) {
     keysType = commonElements.listType();
@@ -182,9 +169,8 @@
   }
   ListConstantValue keysList = createList(commonElements, keysType, keys);
   InterfaceType type = commonElements.getConstantMapTypeFor(sourceType,
-      hasProtoKey: hasProtoKey, onlyStringKeys: onlyStringKeys);
-  return new JavaScriptMapConstant(
-      type, keysList, values, protoValue, onlyStringKeys);
+      onlyStringKeys: onlyStringKeys);
+  return JavaScriptMapConstant(type, keysList, values, onlyStringKeys);
 }
 
 ConstantValue createSymbol(CommonElements commonElements, String text) {
@@ -1035,20 +1021,17 @@
   /// The dart class implementing constant map literals.
   static const String DART_CLASS = "ConstantMap";
   static const String DART_STRING_CLASS = "ConstantStringMap";
-  static const String DART_PROTO_CLASS = "ConstantProtoMap";
   static const String DART_GENERAL_CLASS = "GeneralConstantMap";
   static const String LENGTH_NAME = "_length";
   static const String JS_OBJECT_NAME = "_jsObject";
   static const String KEYS_NAME = "_keys";
-  static const String PROTO_VALUE = "_protoValue";
   static const String JS_DATA_NAME = "_jsData";
 
   final ListConstantValue keyList;
-  final ConstantValue protoValue;
   final bool onlyStringKeys;
 
   JavaScriptMapConstant(InterfaceType type, ListConstantValue keyList,
-      List<ConstantValue> values, this.protoValue, this.onlyStringKeys)
+      List<ConstantValue> values, this.onlyStringKeys)
       : this.keyList = keyList,
         super(type, keyList.entries, values);
   @override
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index f33c13b..4ef3a07 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -8,7 +8,7 @@
 import '../common_elements.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
-import '../deferred_load.dart' show OutputUnit;
+import '../deferred_load/deferred_load.dart' show OutputUnit;
 import '../js/js.dart' as js;
 import '../util/util.dart';
 
@@ -741,8 +741,7 @@
   int get length => keys.length;
 
   ConstantValue lookup(ConstantValue key) {
-    var lookupMap = _lookupMap ??=
-        new Map<ConstantValue, ConstantValue>.fromIterables(keys, values);
+    var lookupMap = _lookupMap ??= Map.fromIterables(keys, values);
     return lookupMap[key];
   }
 
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load/deferred_load.dart
similarity index 98%
rename from pkg/compiler/lib/src/deferred_load.dart
rename to pkg/compiler/lib/src/deferred_load/deferred_load.dart
index f3f6bac..bf7a202 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load/deferred_load.dart
@@ -10,31 +10,31 @@
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
 
-import '../compiler_new.dart' show OutputType;
-import 'common/metrics.dart' show Metric, Metrics, CountMetric, DurationMetric;
-import 'common/tasks.dart' show CompilerTask;
-import 'common.dart';
-import 'common_elements.dart' show CommonElements, KElementEnvironment;
-import 'compiler.dart' show Compiler;
-import 'constants/values.dart'
+import '../../compiler_new.dart' show OutputType;
+import '../common/metrics.dart' show Metric, Metrics, CountMetric, DurationMetric;
+import '../common/tasks.dart' show CompilerTask;
+import '../common.dart';
+import '../common_elements.dart' show CommonElements, KElementEnvironment;
+import '../compiler.dart' show Compiler;
+import '../constants/values.dart'
     show
         ConstantValue,
         ConstructedConstantValue,
         DeferredGlobalConstantValue,
         InstantiationConstantValue;
-import 'elements/types.dart';
-import 'elements/entities.dart';
-import 'ir/util.dart';
-import 'kernel/kelements.dart' show KLocalFunction;
-import 'kernel/element_map.dart';
-import 'serialization/serialization.dart';
-import 'options.dart';
-import 'universe/use.dart';
-import 'universe/world_impact.dart'
+import '../elements/types.dart';
+import '../elements/entities.dart';
+import '../ir/util.dart';
+import '../kernel/kelements.dart' show KLocalFunction;
+import '../kernel/element_map.dart';
+import '../serialization/serialization.dart';
+import '../options.dart';
+import '../universe/use.dart';
+import '../universe/world_impact.dart'
     show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
-import 'util/maplet.dart';
-import 'util/util.dart' show makeUnique;
-import 'world.dart' show KClosedWorld;
+import '../util/maplet.dart';
+import '../util/util.dart' show makeUnique;
+import '../world.dart' show KClosedWorld;
 
 /// A "hunk" of the program that will be loaded whenever one of its [imports]
 /// are loaded.
@@ -114,7 +114,7 @@
   /// Will be `true` if the program contains deferred libraries.
   bool isProgramSplit = false;
 
-  static const ImpactUseCase IMPACT_USE = const ImpactUseCase('Deferred load');
+  static const ImpactUseCase IMPACT_USE = ImpactUseCase('Deferred load');
 
   /// A cache of the result of calling `computeImportDeferName` on the keys of
   /// this map.
@@ -257,7 +257,7 @@
     // Fetch the internal node in order to skip annotations on the member.
     // TODO(sigmund): replace this pattern when the kernel-ast provides a better
     // way to skip annotations (issue 31565).
-    var visitor = new ConstantCollector(
+    var visitor = ConstantCollector(
         _elementMap, _elementMap.getStaticTypeContext(element), dependencies);
     if (node is ir.Field) {
       node.initializer?.accept(visitor);
@@ -1540,7 +1540,7 @@
   /// Returns the [OutputUnit] where [cls] belongs.
   // TODO(johnniwinther): Remove the need for [allowNull]. Dump-info currently
   // needs it.
-  OutputUnit outputUnitForClass(ClassEntity cls, {bool allowNull: false}) {
+  OutputUnit outputUnitForClass(ClassEntity cls, {bool allowNull = false}) {
     if (!isProgramSplit) return mainOutputUnit;
     OutputUnit unit = _classToUnit[cls];
     assert(allowNull || unit != null, 'No output unit for class $cls');
@@ -1551,7 +1551,7 @@
 
   /// Returns the [OutputUnit] where [cls]'s type belongs.
   // TODO(joshualitt): see above TODO regarding allowNull.
-  OutputUnit outputUnitForClassType(ClassEntity cls, {bool allowNull: false}) {
+  OutputUnit outputUnitForClassType(ClassEntity cls, {bool allowNull = false}) {
     if (!isProgramSplit) return mainOutputUnit;
     OutputUnit unit = _classTypeToUnit[cls];
     assert(allowNull || unit != null, 'No output unit for type $cls');
@@ -1665,7 +1665,7 @@
 /// The filename is of the form "<main output file>_<name>.part.js".
 /// If [addExtension] is false, the ".part.js" suffix is left out.
 String deferredPartFileName(CompilerOptions options, String name,
-    {bool addExtension: true}) {
+    {bool addExtension = true}) {
   assert(name != "");
   String outPath = options.outputUri != null ? options.outputUri.path : "out";
   String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
@@ -1811,7 +1811,7 @@
 
   CommonElements get commonElements => elementMap.commonElements;
 
-  void add(ir.Expression node, {bool required: true}) {
+  void add(ir.Expression node, {bool required = true}) {
     ConstantValue constant = elementMap
         .getConstantValue(staticTypeContext, node, requireConstant: required);
     if (constant != null) {
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index aff886a..c6448fb 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -19,7 +19,7 @@
 import 'common_elements.dart' show JElementEnvironment;
 import 'compiler.dart' show Compiler;
 import 'constants/values.dart' show ConstantValue, InterceptorConstantValue;
-import 'deferred_load.dart' show OutputUnit, deferredPartFileName;
+import 'deferred_load/deferred_load.dart' show OutputUnit, deferredPartFileName;
 import 'elements/entities.dart';
 import 'inferrer/abstract_value_domain.dart';
 import 'inferrer/types.dart'
diff --git a/pkg/compiler/lib/src/elements/entity_utils.dart b/pkg/compiler/lib/src/elements/entity_utils.dart
index 82be8db..2942392 100644
--- a/pkg/compiler/lib/src/elements/entity_utils.dart
+++ b/pkg/compiler/lib/src/elements/entity_utils.dart
@@ -7,6 +7,7 @@
 import 'package:front_end/src/api_unstable/dart2js.dart'
     show isUserDefinableOperator, isMinusOperator;
 
+import '../js_backend/namer.dart';
 import 'entities.dart';
 
 // Somewhat stable ordering for libraries using [Uri]s
@@ -154,7 +155,7 @@
   } else if (name == 'unary-') {
     return r'operator$negate';
   } else {
-    return name;
+    return Namer.replaceNonIdentifierCharacters(name);
   }
 }
 
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 41e58eb..7b34a8a 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -911,86 +911,29 @@
 
   R visit(covariant DartType type, A argument) => type.accept(this, argument);
 
-  R visitLegacyType(covariant LegacyType type, A argument) => null;
+  R visitLegacyType(covariant LegacyType type, A argument);
 
-  R visitNullableType(covariant NullableType type, A argument) => null;
+  R visitNullableType(covariant NullableType type, A argument);
 
-  R visitNeverType(covariant NeverType type, A argument) => null;
+  R visitNeverType(covariant NeverType type, A argument);
 
-  R visitVoidType(covariant VoidType type, A argument) => null;
+  R visitVoidType(covariant VoidType type, A argument);
 
-  R visitTypeVariableType(covariant TypeVariableType type, A argument) => null;
+  R visitTypeVariableType(covariant TypeVariableType type, A argument);
 
-  R visitFunctionTypeVariable(
-          covariant FunctionTypeVariable type, A argument) =>
-      null;
+  R visitFunctionTypeVariable(covariant FunctionTypeVariable type, A argument);
 
-  R visitFunctionType(covariant FunctionType type, A argument) => null;
+  R visitFunctionType(covariant FunctionType type, A argument);
 
-  R visitInterfaceType(covariant InterfaceType type, A argument) => null;
+  R visitInterfaceType(covariant InterfaceType type, A argument);
 
-  R visitDynamicType(covariant DynamicType type, A argument) => null;
+  R visitDynamicType(covariant DynamicType type, A argument);
 
-  R visitErasedType(covariant ErasedType type, A argument) => null;
+  R visitErasedType(covariant ErasedType type, A argument);
 
-  R visitAnyType(covariant AnyType type, A argument) => null;
+  R visitAnyType(covariant AnyType type, A argument);
 
-  R visitFutureOrType(covariant FutureOrType type, A argument) => null;
-}
-
-abstract class BaseDartTypeVisitor<R, A> extends DartTypeVisitor<R, A> {
-  const BaseDartTypeVisitor();
-
-  R visitType(covariant DartType type, A argument);
-
-  @override
-  R visitLegacyType(covariant LegacyType type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitNullableType(covariant NullableType type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitNeverType(covariant NeverType type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitVoidType(covariant VoidType type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitTypeVariableType(covariant TypeVariableType type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitFunctionTypeVariable(
-          covariant FunctionTypeVariable type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitFunctionType(covariant FunctionType type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitInterfaceType(covariant InterfaceType type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitDynamicType(covariant DynamicType type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitErasedType(covariant ErasedType type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitAnyType(covariant AnyType type, A argument) =>
-      visitType(type, argument);
-
-  @override
-  R visitFutureOrType(covariant FutureOrType type, A argument) =>
-      visitType(type, argument);
+  R visitFutureOrType(covariant FutureOrType type, A argument);
 }
 
 class _LegacyErasureVisitor extends DartTypeVisitor<DartType, Null> {
diff --git a/pkg/compiler/lib/src/frontend_strategy.dart b/pkg/compiler/lib/src/frontend_strategy.dart
index 3ea0ee2..5fb4571 100644
--- a/pkg/compiler/lib/src/frontend_strategy.dart
+++ b/pkg/compiler/lib/src/frontend_strategy.dart
@@ -8,7 +8,7 @@
 import 'common/tasks.dart';
 import 'common_elements.dart';
 import 'compiler.dart' show Compiler;
-import 'deferred_load.dart' show DeferredLoadTask;
+import 'deferred_load/deferred_load.dart' show DeferredLoadTask;
 import 'elements/entities.dart';
 import 'enqueue.dart';
 import 'js_backend/native_data.dart';
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index a59366a..9828b7f 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -7,9 +7,10 @@
 
 library dart2js.helpers;
 
+import 'package:kernel/text/indentation.dart' show Indentation;
+
 import '../common.dart';
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
-import '../util/util.dart';
 
 export 'debug_collection.dart';
 export 'expensive_map.dart';
@@ -89,6 +90,7 @@
 
 /// Implementation of [reportHere]
 _reportHere(DiagnosticReporter reporter, Spannable node, String debugMessage) {
+  // ignore: deprecated_member_use_from_same_package
   reporter.reportInfoMessage(
       node, MessageKind.GENERIC, {'text': 'HERE: $debugMessage'});
 }
diff --git a/pkg/compiler/lib/src/helpers/stats.dart b/pkg/compiler/lib/src/helpers/stats.dart
index e524b54..7ca7960 100644
--- a/pkg/compiler/lib/src/helpers/stats.dart
+++ b/pkg/compiler/lib/src/helpers/stats.dart
@@ -6,6 +6,8 @@
 import 'dart:collection';
 import 'dart:convert';
 
+import 'package:kernel/text/indentation.dart' show Indentation;
+
 import '../../compiler.dart';
 import '../common.dart';
 import '../compiler.dart' show Compiler;
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 6c90fb2..fe3d41c 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -1049,32 +1049,6 @@
         node, node.receiver, receiverType, selector, arguments, null);
   }
 
-  @override
-  TypeInformation visitMethodInvocation(ir.MethodInvocation node) {
-    Selector selector = _elementMap.getSelector(node);
-    ir.Expression receiver = node.receiver;
-    if (receiver is ir.VariableGet &&
-        receiver.variable.parent is ir.FunctionDeclaration) {
-      // TODO(johnniwinther). This triggers the computation of the mask for the
-      // receiver of the call to `call`. Remove this when the ssa builder
-      // recognizes local function invocation directly.
-      _typeOfReceiver(node, node.receiver);
-      // This is an invocation of a named local function.
-      return _handleLocalFunctionInvocation(
-          node, receiver.variable.parent, node.arguments, selector);
-    }
-
-    TypeInformation receiverType = visit(receiver);
-    ArgumentsTypes arguments = analyzeArguments(node.arguments);
-    if (selector.name == '==') {
-      return _handleEqualsCall(node, node.receiver, receiverType,
-          node.arguments.positional.first, arguments.positional[0]);
-    }
-
-    return _handleMethodInvocation(node, node.receiver, receiverType, selector,
-        arguments, node.interfaceTarget);
-  }
-
   ir.VariableDeclaration _getVariableDeclaration(ir.Expression node) {
     return node is ir.VariableGet ? node.variable : null;
   }
@@ -1671,12 +1645,6 @@
     return _handlePropertyGet(node, node.receiver);
   }
 
-  @override
-  TypeInformation visitPropertyGet(ir.PropertyGet node) {
-    return _handlePropertyGet(node, node.receiver,
-        interfaceTarget: node.interfaceTarget);
-  }
-
   TypeInformation _handlePropertySet(
       ir.Expression node, ir.Expression receiver, ir.Expression value,
       {ir.Member interfaceTarget}) {
@@ -1716,12 +1684,6 @@
   }
 
   @override
-  TypeInformation visitPropertySet(ir.PropertySet node) {
-    return _handlePropertySet(node, node.receiver, node.value,
-        interfaceTarget: node.interfaceTarget);
-  }
-
-  @override
   TypeInformation visitInstanceSet(ir.InstanceSet node) {
     return _handlePropertySet(node, node.receiver, node.value,
         interfaceTarget: node.interfaceTarget);
@@ -2314,7 +2276,7 @@
 
   @override
   TypeInformation visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
-    return builder.createStaticGetTypeInformation(node, node.procedure);
+    return builder.createStaticGetTypeInformation(node, node.target);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 45dea65..defc8a7 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -650,20 +650,17 @@
     // TODO(johnniwinther): Implement the ad-hoc check in ast inferrer? This
     // mimicks that ast inferrer which return `true` for [ast.Send] and
     // non-const [ast.NewExpression].
-    if (initializer is ir.MethodInvocation ||
-        initializer is ir.InstanceInvocation ||
+    if (initializer is ir.InstanceInvocation ||
         initializer is ir.InstanceGetterInvocation ||
         initializer is ir.DynamicInvocation ||
         initializer is ir.FunctionInvocation ||
         initializer is ir.LocalFunctionInvocation ||
         initializer is ir.EqualsNull ||
         initializer is ir.EqualsCall ||
-        initializer is ir.PropertyGet ||
         initializer is ir.InstanceGet ||
         initializer is ir.DynamicGet ||
         initializer is ir.InstanceTearOff ||
         initializer is ir.FunctionTearOff ||
-        initializer is ir.PropertySet ||
         initializer is ir.InstanceSet ||
         initializer is ir.DynamicSet ||
         initializer is ir.StaticInvocation ||
diff --git a/pkg/compiler/lib/src/ir/cached_static_type.dart b/pkg/compiler/lib/src/ir/cached_static_type.dart
index 2aca746..9fdb34b 100644
--- a/pkg/compiler/lib/src/ir/cached_static_type.dart
+++ b/pkg/compiler/lib/src/ir/cached_static_type.dart
@@ -46,17 +46,10 @@
   ir.DartType visitVariableGet(ir.VariableGet node) => _getStaticType(node);
 
   @override
-  ir.DartType visitPropertyGet(ir.PropertyGet node) => _getStaticType(node);
-
-  @override
   ir.DartType visitSuperPropertyGet(ir.SuperPropertyGet node) =>
       _getStaticType(node);
 
   @override
-  ir.DartType visitMethodInvocation(ir.MethodInvocation node) =>
-      _getStaticType(node);
-
-  @override
   ir.DartType visitStaticInvocation(ir.StaticInvocation node) =>
       _getStaticType(node);
 
diff --git a/pkg/compiler/lib/src/ir/closure.dart b/pkg/compiler/lib/src/ir/closure.dart
index f129216..39ceeb5 100644
--- a/pkg/compiler/lib/src/ir/closure.dart
+++ b/pkg/compiler/lib/src/ir/closure.dart
@@ -399,6 +399,11 @@
   }
 
   @override
+  R accept1<R, A>(ir.Visitor1<R, A> v, A arg) {
+    throw new UnsupportedError('TypeVariableTypeWithContext.accept1');
+  }
+
+  @override
   visitChildren(ir.Visitor v) {
     throw new UnsupportedError('TypeVariableTypeWithContext.visitChildren');
   }
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index 33640a7..16fbc15 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -678,7 +678,8 @@
   @override
   void handleConstantExpression(ir.ConstantExpression node) {
     ir.LibraryDependency import = getDeferredImport(node);
-    new ConstantImpactVisitor(this, import, node).visitConstant(node.constant);
+    new ConstantImpactVisitor(this, import, node, staticTypeContext)
+        .visitConstant(node.constant);
   }
 }
 
@@ -727,8 +728,10 @@
   final ImpactRegistry registry;
   final ir.LibraryDependency import;
   final ir.ConstantExpression expression;
+  final ir.StaticTypeContext staticTypeContext;
 
-  ConstantImpactVisitor(this.registry, this.import, this.expression);
+  ConstantImpactVisitor(
+      this.registry, this.import, this.expression, this.staticTypeContext);
 
   @override
   void defaultConstant(ir.Constant node) {
@@ -749,20 +752,13 @@
 
   @override
   void visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
-    ir.Member member = node.procedure;
-    if (member is ir.Procedure) {
-      registry.registerStaticTearOff(member, import);
-    } else {
-      throw new UnsupportedError("Unexpected member (${member.runtimeType}).");
-    }
+    registry.registerStaticTearOff(node.target, import);
   }
 
   @override
   void visitInstantiationConstant(ir.InstantiationConstant node) {
     registry.registerGenericInstantiation(
-        node.tearOffConstant.function.computeFunctionType(
-            node.tearOffConstant.member.enclosingLibrary.nonNullable),
-        node.types);
+        node.tearOffConstant.getType(staticTypeContext), node.types);
     visitConstant(node.tearOffConstant);
   }
 
diff --git a/pkg/compiler/lib/src/ir/runtime_type_analysis.dart b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
index 2fe49b8..3286fc3 100644
--- a/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
+++ b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
@@ -90,16 +90,14 @@
 
   /// Returns `true` if [node] is of the form `e.runtimeType`.
   bool isGetRuntimeType(ir.TreeNode node) {
-    return node is ir.PropertyGet &&
+    return node is ir.InstanceGet &&
             node.name.text == Identifiers.runtimeType_ ||
-        node is ir.InstanceGet && node.name.text == Identifiers.runtimeType_ ||
         node is ir.DynamicGet && node.name.text == Identifiers.runtimeType_;
   }
 
   /// Returns `true` if [node] is of the form `e.toString()`.
   bool isInvokeToString(ir.TreeNode node) {
-    return node is ir.MethodInvocation && node.name.text == 'toString' ||
-        node is ir.InstanceInvocation && node.name.text == 'toString';
+    return node is ir.InstanceInvocation && node.name.text == 'toString';
   }
 
   assert(isGetRuntimeType(node));
@@ -427,17 +425,13 @@
 
 /// Returns `true` if [node] is a potential invocation of an Object method.
 bool _isObjectMethodInvocation(ir.TreeNode node) {
-  return node is ir.MethodInvocation ||
-      node is ir.InstanceInvocation ||
-      node is ir.EqualsCall;
+  return node is ir.InstanceInvocation || node is ir.EqualsCall;
 }
 
 /// Returns the [_RuntimeTypeAccess] corresponding to [node] if it is an access
 /// of `.runtimeType`, and `null` otherwise.
 _RuntimeTypeAccess _getRuntimeTypeAccess(ir.TreeNode node) {
-  if (node is ir.PropertyGet && node.name.text == 'runtimeType') {
-    return _RuntimeTypeAccess(node, node.receiver);
-  } else if (node is ir.InstanceGet && node.name.text == 'runtimeType') {
+  if (node is ir.InstanceGet && node.name.text == 'runtimeType') {
     return _RuntimeTypeAccess(node, node.receiver);
   } else if (node is ir.DynamicGet && node.name.text == 'runtimeType') {
     return _RuntimeTypeAccess(node, node.receiver);
@@ -455,10 +449,7 @@
 /// Returns the [_EqualsInvocation] corresponding to [node] if it is a call to
 /// of `==`, and `null` otherwise.
 _EqualsInvocation _getEqualsInvocation(ir.TreeNode node) {
-  if (node is ir.MethodInvocation && node.name.text == '==') {
-    return _EqualsInvocation(
-        node, node.receiver, node.arguments.positional.single);
-  } else if (node is ir.EqualsCall) {
+  if (node is ir.EqualsCall) {
     return _EqualsInvocation(node, node.left, node.right);
   }
   return null;
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 075e6aa..6fe6cff 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -1026,35 +1026,6 @@
   }
 
   @override
-  EvaluationComplexity visitMethodInvocation(ir.MethodInvocation node) {
-    node.receiver = _handleExpression(node.receiver);
-    EvaluationComplexity receiverComplexity = _lastExpressionComplexity;
-    ir.TreeNode receiver = node.receiver;
-    if (node.arguments.types.isNotEmpty) {
-      VariableUse usage;
-      if (receiver is ir.VariableGet &&
-          (receiver.variable.parent is ir.LocalFunction)) {
-        usage =
-            new VariableUse.localTypeArgument(receiver.variable.parent, node);
-      } else {
-        usage = new VariableUse.instanceTypeArgument(node);
-      }
-      visitNodesInContext(node.arguments.types, usage);
-    }
-    EvaluationComplexity complexity = visitArguments(node.arguments);
-    ir.Member interfaceTarget = node.interfaceTarget;
-    if (receiverComplexity.combine(complexity).isConstant &&
-        interfaceTarget is ir.Procedure &&
-        interfaceTarget.kind == ir.ProcedureKind.Operator) {
-      // Only operator invocations can be part of constant expressions so we
-      // only try to compute an implicit constant when the receiver and all
-      // arguments are constant - and are used in an operator call.
-      return _evaluateImplicitConstant(node);
-    }
-    return const EvaluationComplexity.lazy();
-  }
-
-  @override
   EvaluationComplexity visitInstanceInvocation(ir.InstanceInvocation node) {
     node.receiver = _handleExpression(node.receiver);
     EvaluationComplexity receiverComplexity = _lastExpressionComplexity;
@@ -1169,16 +1140,6 @@
   }
 
   @override
-  EvaluationComplexity visitPropertyGet(ir.PropertyGet node) {
-    node.receiver = _handleExpression(node.receiver);
-    EvaluationComplexity complexity = _lastExpressionComplexity;
-    if (complexity.isConstant && node.name.text == 'length') {
-      return _evaluateImplicitConstant(node);
-    }
-    return const EvaluationComplexity.lazy();
-  }
-
-  @override
   EvaluationComplexity visitInstanceGet(ir.InstanceGet node) {
     node.receiver = _handleExpression(node.receiver);
     EvaluationComplexity complexity = _lastExpressionComplexity;
@@ -1211,13 +1172,6 @@
   }
 
   @override
-  EvaluationComplexity visitPropertySet(ir.PropertySet node) {
-    node.receiver = _handleExpression(node.receiver);
-    node.value = _handleExpression(node.value);
-    return const EvaluationComplexity.lazy();
-  }
-
-  @override
   EvaluationComplexity visitInstanceSet(ir.InstanceSet node) {
     node.receiver = _handleExpression(node.receiver);
     node.value = _handleExpression(node.value);
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 0ea8c89..1baf922 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -14,7 +14,6 @@
 import 'scope.dart';
 import 'static_type_base.dart';
 import 'static_type_cache.dart';
-import 'util.dart';
 
 /// Enum values for how the target of a static type should be interpreted.
 enum ClassRelation {
@@ -268,28 +267,6 @@
         .substituteType(interfaceTarget.getterType);
   }
 
-  /// Computes the result type of the property access [node] on a receiver of
-  /// type [receiverType].
-  ///
-  /// If the `node.interfaceTarget` is `null` but matches an `Object` member
-  /// it is updated to target this member.
-  ir.DartType _computePropertyGetType(
-      ir.PropertyGet node, ir.DartType receiverType) {
-    node.interfaceTarget ??= _resolveDynamicTarget(receiverType, node.name);
-    ir.Member interfaceTarget = node.interfaceTarget;
-    if (interfaceTarget != null) {
-      return _computeInstanceGetType(receiverType, interfaceTarget);
-    }
-    // Treat the properties of Object specially.
-    String nameString = node.name.text;
-    if (nameString == 'hashCode') {
-      return typeEnvironment.coreTypes.intNonNullableRawType;
-    } else if (nameString == 'runtimeType') {
-      return typeEnvironment.coreTypes.typeNonNullableRawType;
-    }
-    return const ir.DynamicType();
-  }
-
   /// Replaces [original] with [replacement] in the AST and removes cached
   /// expression type information for [original].
   void _replaceExpression(ir.Expression original, ir.Expression replacement) {
@@ -308,23 +285,6 @@
   void handleRuntimeTypeUse(ir.Expression node, RuntimeTypeUseKind kind,
       ir.DartType receiverType, ir.DartType argumentType) {}
 
-  @override
-  ir.DartType visitPropertyGet(ir.PropertyGet node) {
-    ir.DartType receiverType = visitNode(node.receiver);
-    ir.DartType resultType = _staticTypeCache._expressionTypes[node] =
-        _computePropertyGetType(node, receiverType);
-    receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
-    if (node.interfaceTarget != null) {
-      handleInstanceGet(node, receiverType, node.interfaceTarget, resultType);
-    } else {
-      handleDynamicGet(node, receiverType, node.name, resultType);
-    }
-    if (node.name.text == Identifiers.runtimeType_) {
-      handleRuntimeTypeGet(receiverType, node);
-    }
-    return resultType;
-  }
-
   void handleRuntimeTypeGet(ir.DartType receiverType, ir.Expression node) {
     RuntimeTypeUseData data =
         computeRuntimeTypeUse(_pendingRuntimeTypeUseData, node);
@@ -461,37 +421,6 @@
   }
 
   @override
-  ir.DartType visitPropertySet(ir.PropertySet node) {
-    ir.DartType receiverType = visitNode(node.receiver);
-    ir.DartType valueType = super.visitPropertySet(node);
-    ir.Member interfaceTarget = node.interfaceTarget;
-    if (interfaceTarget == null) {
-      interfaceTarget = _resolveDynamicSet(receiverType, node.name);
-      if (interfaceTarget != null) {
-        ir.DartType setterType =
-            _computeInstanceSetType(receiverType, interfaceTarget);
-        ir.AsExpression implicitCast =
-            _createImplicitAsIfNeeded(node.value, valueType, setterType);
-        if (implicitCast != null) {
-          node.value = implicitCast..parent = node;
-          // Visit the newly created as expression; the original value has
-          // already been visited.
-          handleAsExpression(implicitCast, valueType);
-          valueType = setterType;
-        }
-        node.interfaceTarget = interfaceTarget;
-      }
-    }
-    receiverType = _narrowInstanceReceiver(interfaceTarget, receiverType);
-    if (interfaceTarget != null) {
-      handleInstanceSet(node, receiverType, node.interfaceTarget, valueType);
-    } else {
-      handleDynamicSet(node, receiverType, node.name, valueType);
-    }
-    return valueType;
-  }
-
-  @override
   ir.DartType visitDynamicSet(ir.DynamicSet node) {
     ir.DartType receiverType = visitNode(node.receiver);
     ir.DartType valueType = visitNode(node.value);
@@ -911,69 +840,6 @@
   }
 
   @override
-  ir.DartType visitMethodInvocation(ir.MethodInvocation node) {
-    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
-    ir.DartType receiverType = visitNode(node.receiver);
-    ir.Member interfaceTarget = node.interfaceTarget ??
-        _resolveDynamicInvocationTarget(
-            receiverType, node.name, node.arguments);
-    ir.DartType returnType;
-    if (interfaceTarget != null) {
-      ir.DartType functionType = _computeInstanceInvocationType(
-          receiverType, interfaceTarget, node.arguments, argumentTypes);
-      if (node.interfaceTarget == null) {
-        // We change [node] from being a dynamic invocation to an instance
-        // invocation, so we need to add static type checks to the arguments to
-        // match instance invocations created by the CFE.
-        // TODO(johnniwinther): Handle incremental target improvement.
-        _updateMethodInvocationTarget(node, argumentTypes, functionType);
-        node.interfaceTarget = interfaceTarget;
-      }
-      returnType = _getFunctionReturnType(functionType);
-    } else {
-      returnType = _computeDynamicInvocationReturnType(node, receiverType);
-    }
-    receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
-    if (node.name.text == '==') {
-      TypeMap afterInvocation = typeMap;
-      ir.Expression left = node.receiver;
-      ir.Expression right = node.arguments.positional[0];
-      if (isNullLiteral(right)) {
-        _registerEqualsNull(afterInvocation, left);
-      }
-      if (isNullLiteral(left)) {
-        _registerEqualsNull(afterInvocation, right);
-      }
-      assert(node.interfaceTarget != null);
-      handleEqualsCall(left, receiverType, right, argumentTypes.positional[0],
-          node.interfaceTarget);
-    } else if (node.interfaceTarget != null) {
-      handleInstanceInvocation(
-          node, receiverType, interfaceTarget, argumentTypes);
-    } else {
-      ir.Expression receiver = node.receiver;
-      if (receiver is ir.VariableGet &&
-          receiver.variable.isFinal &&
-          receiver.variable.parent is ir.FunctionDeclaration) {
-        handleLocalFunctionInvocation(
-            node, receiver.variable.parent, argumentTypes, returnType);
-      } else {
-        handleDynamicInvocation(node, receiverType, argumentTypes, returnType);
-        // TODO(johnniwinther): Avoid treating a known function call as a
-        // dynamic call when CFE provides a way to distinguish the two.
-        if (operatorFromString(node.name.text) == null &&
-            receiverType is ir.DynamicType) {
-          // We might implicitly call a getter that returns a function.
-          handleFunctionInvocation(
-              node, const ir.DynamicType(), argumentTypes, returnType);
-        }
-      }
-    }
-    _staticTypeCache._expressionTypes[node] = returnType;
-    return returnType;
-  }
-
-  @override
   ir.DartType visitInstanceInvocation(ir.InstanceInvocation node) {
     ArgumentTypes argumentTypes = _visitArguments(node.arguments);
     ir.DartType receiverType = visitNode(node.receiver);
@@ -1060,9 +926,6 @@
       receiverType = _narrowInstanceReceiver(interfaceTarget, receiverType);
       handleInstanceInvocation(
           replacement, receiverType, interfaceTarget, argumentTypes);
-      if (replacement is ir.MethodInvocation) {
-        _staticTypeCache._expressionTypes[replacement] = resultType;
-      }
       return resultType;
     } else if (node.name == ir.Name.callName &&
         (receiverType is ir.FunctionType ||
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
index 315ee23..05a45ee1 100644
--- a/pkg/compiler/lib/src/ir/static_type_base.dart
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -157,11 +157,6 @@
   }
 
   @override
-  ir.DartType visitPropertySet(ir.PropertySet node) {
-    return visitNode(node.value);
-  }
-
-  @override
   ThisInterfaceType visitThisExpression(ir.ThisExpression node) => thisType;
 
   @override
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index eab6a08..5c5021f 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -119,18 +119,7 @@
     if (node.variable.name == null &&
         node.variable.isFinal &&
         body is ir.ConditionalExpression) {
-      if (body.condition is ir.MethodInvocation && isNullLiteral(body.then)) {
-        ir.MethodInvocation invocation = body.condition;
-        ir.Expression receiver = invocation.receiver;
-        if (invocation.name.text == '==' &&
-            receiver is ir.VariableGet &&
-            receiver.variable == node.variable &&
-            isNullLiteral(invocation.arguments.positional.single)) {
-          // We have
-          //   let #t1 = e0 in #t1 == null ? null : e1
-          return new NullAwareExpression(node.variable, body.otherwise);
-        }
-      } else if (body.condition is ir.EqualsNull) {
+      if (body.condition is ir.EqualsNull) {
         ir.EqualsNull equalsNull = body.condition;
         ir.Expression receiver = equalsNull.expression;
         if (receiver is ir.VariableGet && receiver.variable == node.variable) {
@@ -161,12 +150,10 @@
   //
   //   (let _ = check(prefix) in prefix::field).property
   if (node is ir.StaticGet || node is ir.ConstantExpression) {
-    while (parent is ir.PropertyGet ||
-        parent is ir.InstanceGet ||
+    while (parent is ir.InstanceGet ||
         parent is ir.DynamicGet ||
         parent is ir.InstanceTearOff ||
         parent is ir.FunctionTearOff ||
-        parent is ir.MethodInvocation ||
         parent is ir.InstanceInvocation ||
         parent is ir.InstanceGetterInvocation ||
         parent is ir.DynamicInvocation ||
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index 0335a73..cbcfda9 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -213,15 +213,10 @@
 
   @override
   ConstantValue visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
-    ir.Member member = node.procedure;
-    if (member is ir.Procedure) {
-      FunctionEntity function = elementMap.getMethod(member);
-      DartType type = elementMap.getFunctionType(member.function);
-      return new FunctionConstantValue(function, type);
-    } else {
-      throw new UnsupportedError(
-          "Unexpected torn off member kind (${member.runtimeType}).");
-    }
+    ir.Procedure member = node.target;
+    FunctionEntity function = elementMap.getMethod(member);
+    DartType type = elementMap.getFunctionType(member.function);
+    return new FunctionConstantValue(function, type);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js/js_debug.dart b/pkg/compiler/lib/src/js/js_debug.dart
index 9eaca9f..f37ce23 100644
--- a/pkg/compiler/lib/src/js/js_debug.dart
+++ b/pkg/compiler/lib/src/js/js_debug.dart
@@ -7,9 +7,9 @@
 library js.debug;
 
 import 'package:js_ast/js_ast.dart';
+import 'package:kernel/text/indentation.dart' show Indentation, Tagging;
 
 import '../io/code_output.dart' show BufferedCodeOutput;
-import '../util/util.dart' show Indentation, Tagging;
 
 /// Unparse the JavaScript [node].
 String nodeToString(Node node, {bool pretty: false}) {
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index d17db87..8d15b8c 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -6,7 +6,7 @@
 
 import '../common.dart';
 import '../common/codegen.dart';
-import '../deferred_load.dart' show DeferredLoadTask;
+import '../deferred_load/deferred_load.dart' show DeferredLoadTask;
 import '../dump_info.dart' show DumpInfoTask;
 import '../elements/entities.dart';
 import '../enqueue.dart' show ResolutionEnqueuer;
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index d50ddc1b..4dcff21 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -284,7 +284,6 @@
   BackendImpact get constantMapLiteral {
     return _constantMapLiteral ??= new BackendImpact(instantiatedClasses: [
       _commonElements.constantMapClass,
-      _commonElements.constantProtoMapClass,
       _commonElements.constantStringMapClass,
       _commonElements.generalConstantMapClass,
     ]);
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index dd67c4a..b05bc22 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -330,10 +330,6 @@
           constant_system.JavaScriptMapConstant.KEYS_NAME) {
         arguments.add(_constantReferenceGenerator(constant.keyList));
       } else if (field.name ==
-          constant_system.JavaScriptMapConstant.PROTO_VALUE) {
-        assert(constant.protoValue != null);
-        arguments.add(_constantReferenceGenerator(constant.protoValue));
-      } else if (field.name ==
           constant_system.JavaScriptMapConstant.JS_DATA_NAME) {
         arguments.add(jsGeneralMap());
       } else {
@@ -344,8 +340,6 @@
     });
     if ((className == constant_system.JavaScriptMapConstant.DART_STRING_CLASS &&
             emittedArgumentCount != 3) ||
-        (className == constant_system.JavaScriptMapConstant.DART_PROTO_CLASS &&
-            emittedArgumentCount != 4) ||
         (className ==
                 constant_system.JavaScriptMapConstant.DART_GENERAL_CLASS &&
             emittedArgumentCount != 1)) {
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index e8b00b7..359d642 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -435,6 +435,26 @@
         ..remove('P')
         ..remove('W');
 
+  static final RegExp _identifierStartRE = RegExp(r'[A-Za-z_$]');
+  static final RegExp _nonIdentifierRE = RegExp(r'[^A-Za-z0-9_$]');
+
+  /// Returns `true` iff [s] begins with an ASCII character that can begin a
+  /// JavaScript identifier.
+  ///
+  /// In particular, [s] must begin with an ASCII letter, an underscore, or a
+  /// dollar sign.
+  static bool startsWithIdentifierCharacter(String s) =>
+      s.startsWith(_identifierStartRE);
+
+  /// Returns a copy of [s] in which characters which cannot be part of an ASCII
+  /// JavaScript identifier have been replaced by underscores.
+  ///
+  /// Note that the result may not be unconditionally used as a JavaScript
+  /// identifier. For example, the result may still begin with a digit or it may
+  /// be a reserved keyword.
+  static String replaceNonIdentifierCharacters(String s) =>
+      s.replaceAll(_nonIdentifierRE, '_');
+
   Set<String> _jsReserved = null;
 
   /// Names that cannot be used by members, top level and static
@@ -557,9 +577,12 @@
   /// key into maps.
   final Map<LibraryEntity, String> _libraryKeys = {};
 
+  _TypeConstantRepresentationVisitor _typeConstantRepresenter;
+
   Namer(this._closedWorld, this.fixedNames) {
     _literalGetterPrefix = new StringBackedName(fixedNames.getterPrefix);
     _literalSetterPrefix = new StringBackedName(fixedNames.setterPrefix);
+    _typeConstantRepresenter = _TypeConstantRepresentationVisitor(this);
   }
 
   JElementEnvironment get _elementEnvironment =>
@@ -618,9 +641,7 @@
   ///
   /// The resulting name is a *proposed name* and is never minified.
   String privateName(Name originalName) {
-    String text = originalName.text;
-
-    text = text.replaceAll(_nonIdentifierRE, '_');
+    String text = replaceNonIdentifierCharacters(originalName.text);
 
     // Public names are easy.
     if (!originalName.isPrivate) return text;
@@ -670,7 +691,7 @@
       // TODO(sra): If the generator is for a closure's 'call' method, we don't
       // need to incorporate the enclosing class.
       String className =
-          method.enclosingClass.name.replaceAll(_nonIdentifierRE, '_');
+          replaceNonIdentifierCharacters(method.enclosingClass.name);
       return '${invocationName}\$body\$${className}';
     });
   }
@@ -844,9 +865,8 @@
     if (element is JSEntity) {
       return _disambiguateInternalMember(
           element,
-          () => (element as JSEntity)
-              .declaredName
-              .replaceAll(_nonIdentifierRE, '_'));
+          () => replaceNonIdentifierCharacters(
+              (element as JSEntity).declaredName));
     }
 
     // If the name of the field might clash with another field,
@@ -859,8 +879,8 @@
     if (_closedWorld.isUsedAsMixin(enclosingClass) ||
         _isShadowingSuperField(element) ||
         _isUserClassExtendingNative(enclosingClass)) {
-      String proposeName() => '${enclosingClass.name}_${element.name}'
-          .replaceAll(_nonIdentifierRE, '_');
+      String proposeName() => replaceNonIdentifierCharacters(
+          '${enclosingClass.name}_${element.name}');
       return _disambiguateInternalMember(element, proposeName);
     }
 
@@ -1204,11 +1224,9 @@
   /// Returns a proposed name for the given typedef or class [element].
   /// The returned id is guaranteed to be a valid JavaScript identifier.
   String _proposeNameForType(Entity element) {
-    return element.name.replaceAll(_nonIdentifierRE, '_');
+    return replaceNonIdentifierCharacters(element.name);
   }
 
-  static RegExp _nonIdentifierRE = new RegExp(r'[^A-Za-z0-9_$]');
-
   /// Returns a proposed name for the given top-level or static member
   /// [element]. The returned id is guaranteed to be a valid JavaScript
   /// identifier.
@@ -1219,10 +1237,10 @@
       return _proposeNameForMember(element.function) + r'$body';
     } else if (element.enclosingClass != null) {
       ClassEntity enclosingClass = element.enclosingClass;
-      return '${enclosingClass.name}_${element.name}'
-          .replaceAll(_nonIdentifierRE, '_');
+      return replaceNonIdentifierCharacters(
+          '${enclosingClass.name}_${element.name}');
     }
-    return element.name.replaceAll(_nonIdentifierRE, '_');
+    return replaceNonIdentifierCharacters(element.name);
   }
 
   String _proposeNameForLazyStaticGetter(MemberEntity element) {
@@ -1357,7 +1375,7 @@
     String enclosing =
         element.enclosingClass == null ? "" : element.enclosingClass.name;
     String library = _proposeNameForLibrary(element.library);
-    String name = element.name.replaceAll(_nonIdentifierRE, '_');
+    String name = replaceNonIdentifierCharacters(element.name);
     return _disambiguateInternalGlobal(
         "${library}_${enclosing}_${name}\$closure");
   }
@@ -1460,32 +1478,79 @@
     }
   }
 
-  String getTypeRepresentationForTypeConstant(DartType type) {
-    type = type.withoutNullability;
-    if (type is DynamicType) return "dynamic";
-    if (type is NeverType) return "Never";
-    if (type is FutureOrType) {
-      return "FutureOr<dynamic>";
-    }
-    if (type is FunctionType) {
-      // TODO(johnniwinther): Add naming scheme for function type literals.
-      // These currently only occur from kernel.
-      return '()->';
-    }
-    InterfaceType interface = type;
-    String name = uniqueNameForTypeConstantElement(
-        interface.element.library, interface.element);
+  String getTypeRepresentationForTypeConstant(DartType type) =>
+      _typeConstantRepresenter.visit(type, null);
+}
+
+class _TypeConstantRepresentationVisitor extends DartTypeVisitor<String, Null> {
+  final Namer _namer;
+
+  _TypeConstantRepresentationVisitor(this._namer);
+
+  String _represent(DartType type) => visit(type, null);
+
+  @override
+  String visitLegacyType(LegacyType type, _) => '${_represent(type.baseType)}*';
+
+  @override
+  String visitNullableType(NullableType type, _) =>
+      '${_represent(type.baseType)}?';
+
+  @override
+  String visitNeverType(NeverType type, _) => 'Never';
+
+  @override
+  String visitVoidType(VoidType type, _) => 'void';
+
+  @override
+  String visitTypeVariableType(TypeVariableType type, _) {
+    throw StateError('Unexpected TypeVariableType $type');
+  }
+
+  @override
+  String visitFunctionTypeVariable(FunctionTypeVariable type, _) {
+    throw StateError('Unexpected FunctionTypeVariable $type');
+  }
+
+  @override
+  String visitFunctionType(FunctionType type, _) {
+    // TODO(johnniwinther): Add naming scheme for function type literals.
+    // These currently only occur from kernel.
+    return '()->';
+  }
+
+  @override
+  String visitInterfaceType(InterfaceType type, _) {
+    String name = _namer.uniqueNameForTypeConstantElement(
+        type.element.library, type.element);
 
     // Type constants can currently only be raw types, so there is no point
     // adding ground-term type parameters, as they would just be 'dynamic'.
     // TODO(sra): Since the result string is used only in constructing constant
     // names, it would result in more readable names if the final string was a
     // legal JavaScript identifier.
-    if (interface.typeArguments.isEmpty) return name;
+    if (type.typeArguments.isEmpty) return name;
     String arguments =
-        new List.filled(interface.typeArguments.length, 'dynamic').join(', ');
+        new List.filled(type.typeArguments.length, 'dynamic').join(', ');
     return '$name<$arguments>';
   }
+
+  @override
+  String visitDynamicType(DynamicType type, _) => 'dynamic';
+
+  @override
+  String visitErasedType(ErasedType type, _) {
+    throw StateError('Unexpected ErasedType $type');
+  }
+
+  @override
+  String visitAnyType(AnyType type, _) {
+    throw StateError('Unexpected AnyType $type');
+  }
+
+  @override
+  String visitFutureOrType(FutureOrType type, _) =>
+      'FutureOr<${_represent(type.typeArgument)}>';
 }
 
 /// Returns a unique suffix for an intercepted accesses to [classes]. This is
diff --git a/pkg/compiler/lib/src/js_backend/resolution_listener.dart b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
index faff4b7..0239d25 100644
--- a/pkg/compiler/lib/src/js_backend/resolution_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
@@ -7,7 +7,7 @@
 import '../common/names.dart' show Identifiers;
 import '../common_elements.dart' show KCommonElements, KElementEnvironment;
 import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../enqueue.dart' show Enqueuer, EnqueuerListener;
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index e7113df..90b7b7c 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -829,8 +829,23 @@
   }
 
   @override
-  void visitFutureOrType(FutureOrType type, _) {
-    collect(type.typeArgument);
+  void visitNeverType(NeverType type, _) {}
+
+  @override
+  void visitVoidType(VoidType type, _) {}
+
+  @override
+  void visitTypeVariableType(TypeVariableType type, _) {}
+
+  @override
+  void visitFunctionTypeVariable(FunctionTypeVariable type, _) {}
+
+  @override
+  void visitFunctionType(FunctionType type, _) {
+    collect(type.returnType);
+    collectAll(type.parameterTypes);
+    collectAll(type.optionalParameterTypes);
+    collectAll(type.namedParameterTypes);
   }
 
   @override
@@ -840,11 +855,17 @@
   }
 
   @override
-  void visitFunctionType(FunctionType type, _) {
-    collect(type.returnType);
-    collectAll(type.parameterTypes);
-    collectAll(type.optionalParameterTypes);
-    collectAll(type.namedParameterTypes);
+  void visitDynamicType(DynamicType type, _) {}
+
+  @override
+  void visitErasedType(ErasedType type, _) {}
+
+  @override
+  void visitAnyType(AnyType type, _) {}
+
+  @override
+  void visitFutureOrType(FutureOrType type, _) {
+    collect(type.typeArgument);
   }
 }
 
@@ -913,8 +934,10 @@
       visitType(type.baseType, state);
 
   @override
-  void visitFutureOrType(FutureOrType type, TypeVisitorState state) =>
-      visitType(type.typeArgument, state);
+  void visitNeverType(NeverType type, TypeVisitorState state) {}
+
+  @override
+  void visitVoidType(VoidType type, TypeVisitorState state) {}
 
   @override
   void visitTypeVariableType(TypeVariableType type, TypeVisitorState state) {
@@ -924,15 +947,14 @@
   }
 
   @override
-  visitInterfaceType(InterfaceType type, TypeVisitorState state) {
-    if (onClass != null) {
-      onClass(type.element, state: state);
+  visitFunctionTypeVariable(FunctionTypeVariable type, TypeVisitorState state) {
+    if (_visitedFunctionTypeVariables.add(type)) {
+      visitType(type.bound, state);
     }
-    visitTypes(type.typeArguments, covariantArgument(state));
   }
 
   @override
-  visitFunctionType(FunctionType type, TypeVisitorState state) {
+  void visitFunctionType(FunctionType type, TypeVisitorState state) {
     if (onFunctionType != null) {
       onFunctionType(type, state: state);
     }
@@ -946,11 +968,25 @@
   }
 
   @override
-  visitFunctionTypeVariable(FunctionTypeVariable type, TypeVisitorState state) {
-    if (_visitedFunctionTypeVariables.add(type)) {
-      visitType(type.bound, state);
+  void visitInterfaceType(InterfaceType type, TypeVisitorState state) {
+    if (onClass != null) {
+      onClass(type.element, state: state);
     }
+    visitTypes(type.typeArguments, covariantArgument(state));
   }
+
+  @override
+  void visitDynamicType(DynamicType type, TypeVisitorState state) {}
+
+  @override
+  void visitErasedType(ErasedType type, TypeVisitorState state) {}
+
+  @override
+  void visitAnyType(AnyType type, TypeVisitorState state) {}
+
+  @override
+  void visitFutureOrType(FutureOrType type, TypeVisitorState state) =>
+      visitType(type.typeArgument, state);
 }
 
 /// Runtime type usage for a class.
diff --git a/pkg/compiler/lib/src/js_backend/specialized_checks.dart b/pkg/compiler/lib/src/js_backend/specialized_checks.dart
index dfaabfd..41e8ea7 100644
--- a/pkg/compiler/lib/src/js_backend/specialized_checks.dart
+++ b/pkg/compiler/lib/src/js_backend/specialized_checks.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../common_elements.dart' show ElementEnvironment, JCommonElements;
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../js_backend/interceptor_data.dart' show InterceptorData;
diff --git a/pkg/compiler/lib/src/js_backend/type_reference.dart b/pkg/compiler/lib/src/js_backend/type_reference.dart
index 4ec5745..a845b95 100644
--- a/pkg/compiler/lib/src/js_backend/type_reference.dart
+++ b/pkg/compiler/lib/src/js_backend/type_reference.dart
@@ -77,6 +77,7 @@
 import '../serialization/serialization.dart';
 import '../util/util.dart' show Hashing;
 import 'frequency_assignment.dart';
+import 'namer.dart';
 import 'runtime_types_new.dart' show RecipeEncoder;
 
 /// Run the minifier for 'type$' property names even in non-minified mode,
@@ -582,9 +583,6 @@
   final Map<DartType, int> _backrefs = Map.identity();
   final List<String> _fragments = [];
 
-  static RegExp identifierStartRE = RegExp(r'[A-Za-z_$]');
-  static RegExp nonIdentifierRE = RegExp(r'[^A-Za-z0-9_$]');
-
   String run(TypeRecipe recipe) {
     if (recipe is TypeExpressionRecipe) {
       _visit(recipe.type, null);
@@ -605,7 +603,7 @@
       throw StateError('Unexpected recipe: $recipe');
     }
     String result = _fragments.join('_');
-    if (result.startsWith(identifierStartRE)) return result;
+    if (Namer.startsWithIdentifierCharacter(result)) return result;
     return 'z' + result;
   }
 
@@ -614,7 +612,7 @@
   }
 
   void _identifier(String text) {
-    _add(text.replaceAll(nonIdentifierRE, '_'));
+    _add(Namer.replaceNonIdentifierCharacters(text));
   }
 
   bool _comma(bool needsComma) {
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 18f96cd..0a0a8f7 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -9,12 +9,14 @@
 import '../common/tasks.dart' show CompilerTask;
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart';
-import '../deferred_load.dart' show OutputUnit;
+import '../deferred_load/deferred_load.dart' show OutputUnit;
 import '../elements/entities.dart';
 import '../js/js.dart' as jsAst;
 import '../js_backend/backend.dart' show CodegenInputs;
 import '../js_backend/inferred_data.dart';
 import '../js_backend/namer.dart' show Namer;
+import '../js_backend/runtime_types.dart'
+    show RuntimeTypesChecks;
 import '../js_model/js_strategy.dart';
 import '../options.dart';
 import '../universe/codegen_world_builder.dart';
@@ -26,14 +28,13 @@
 import 'metadata_collector.dart' show MetadataCollector;
 import 'model.dart';
 import 'native_emitter.dart' show NativeEmitter;
-import 'type_test_registry.dart' show TypeTestRegistry;
 
 /// Generates the code for all used classes in the program. Static fields (even
 /// in classes) are ignored, since they can be treated as non-class elements.
 ///
 /// The code for the containing (used) methods must exist in the `universe`.
 class CodeEmitterTask extends CompilerTask {
-  TypeTestRegistry typeTestRegistry;
+  RuntimeTypesChecks _rtiChecks;
   NativeEmitter _nativeEmitter;
   MetadataCollector metadataCollector;
   Emitter _emitter;
@@ -77,8 +78,7 @@
   void _finalizeRti(CodegenInputs codegen, CodegenWorld codegenWorld) {
     // Compute the required type checks to know which classes need a
     // 'is$' method.
-    typeTestRegistry.computeRequiredTypeChecks(
-        _backendStrategy.rtiChecksBuilder, codegenWorld);
+    _rtiChecks = _backendStrategy.rtiChecksBuilder.computeRequiredChecks(codegenWorld, options);
   }
 
   /// Creates the [Emitter] for this task.
@@ -101,7 +101,6 @@
           _generateSourceMap);
       metadataCollector = new MetadataCollector(
           _compiler.reporter, _emitter, codegen.rtiRecipeEncoder);
-      typeTestRegistry = new TypeTestRegistry(_compiler.options);
     });
   }
 
@@ -126,7 +125,7 @@
           closedWorld.nativeData,
           closedWorld.rtiNeed,
           closedWorld.interceptorData,
-          typeTestRegistry.rtiChecks,
+          _rtiChecks,
           codegenInputs.rtiRecipeEncoder,
           codegenWorld.oneShotInterceptorData,
           _backendStrategy.customElementsCodegenAnalysis,
@@ -138,7 +137,7 @@
           inferredData,
           _backendStrategy.sourceInformationStrategy,
           closedWorld.sorter,
-          typeTestRegistry.rtiNeededClasses,
+          _rtiChecks.requiredClasses,
           closedWorld.elementEnvironment.mainFunction);
       int size = emitter.emitProgram(programBuilder, codegenWorld);
       // TODO(floitsch): we shouldn't need the `neededClasses` anymore.
diff --git a/pkg/compiler/lib/src/js_emitter/js_emitter.dart b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
index 7ad49b8..b5d4f85 100644
--- a/pkg/compiler/lib/src/js_emitter/js_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
@@ -14,4 +14,3 @@
 export 'native_generator.dart';
 export 'parameter_stub_generator.dart';
 export 'runtime_type_generator.dart';
-export 'type_test_registry.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index 4923f10..6e1cfaa 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -7,7 +7,7 @@
 import 'package:js_ast/src/precedence.dart' as js_precedence;
 
 import '../common.dart';
-import '../deferred_load.dart' show OutputUnit;
+import '../deferred_load/deferred_load.dart' show OutputUnit;
 
 import '../elements/types.dart';
 import '../js/js.dart' as jsAst;
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 156ccb1..147a80c 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -6,7 +6,7 @@
 
 import '../common_elements.dart';
 import '../constants/values.dart' show ConstantValue;
-import '../deferred_load.dart' show OutputUnit;
+import '../deferred_load/deferred_load.dart' show OutputUnit;
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../js/js.dart' as js show Expression, Name, Statement, TokenFinalizer;
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index b6144a9..f11fd8b 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -9,7 +9,7 @@
 import '../../constants/values.dart'
     show ConstantValue, InterceptorConstantValue;
 import '../../common_elements.dart' show JCommonElements, JElementEnvironment;
-import '../../deferred_load.dart'
+import '../../deferred_load/deferred_load.dart'
     show deferredPartFileName, OutputUnit, OutputUnitData;
 import '../../elements/entities.dart';
 import '../../elements/types.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index d9bfaab..d77743f 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -5,7 +5,7 @@
 library dart2js.js_emitter.runtime_type_generator;
 
 import '../common_elements.dart' show CommonElements;
-import '../deferred_load.dart' show OutputUnit, OutputUnitData;
+import '../deferred_load/deferred_load.dart' show OutputUnit, OutputUnitData;
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../js/js.dart' as jsAst;
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 0d7a896..3ca343dd 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -8,7 +8,7 @@
 import '../../common.dart';
 import '../../common/codegen.dart';
 import '../../constants/values.dart';
-import '../../deferred_load.dart' show OutputUnit;
+import '../../deferred_load/deferred_load.dart' show OutputUnit;
 import '../../dump_info.dart';
 import '../../elements/entities.dart';
 import '../../io/source_information.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
index 9fae89c..58fc707 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
@@ -4,7 +4,7 @@
 
 import 'dart:collection';
 import '../../common_elements.dart' show ElementEnvironment;
-import '../../deferred_load.dart'
+import '../../deferred_load/deferred_load.dart'
     show ImportDescription, OutputUnit, OutputUnitData, deferredPartFileName;
 import '../../elements/entities.dart';
 import '../../js/js.dart' as js;
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 d660d94..f905d82 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
@@ -37,7 +37,7 @@
 import '../../constants/values.dart'
     show ConstantValue, FunctionConstantValue, LateSentinelConstantValue;
 import '../../common_elements.dart' show CommonElements, JElementEnvironment;
-import '../../deferred_load.dart' show OutputUnit;
+import '../../deferred_load/deferred_load.dart' show OutputUnit;
 import '../../dump_info.dart';
 import '../../elements/entities.dart';
 import '../../elements/types.dart';
@@ -352,17 +352,17 @@
 
   /// Generates a simple header that provides the compiler's build id.
   js.Comment buildGeneratedBy() {
-    StringBuffer flavor = new StringBuffer();
-    flavor.write('fast startup emitter');
-    // TODO(johnniwinther): Remove this flavor.
-    flavor.write(', strong');
+    final flavor = StringBuffer();
+    flavor.write(_options.nullSafetyMode);
     if (_options.trustPrimitives) flavor.write(', trust primitives');
     if (_options.omitImplicitChecks) flavor.write(', omit checks');
     if (_options.laxRuntimeTypeToString) {
       flavor.write(', lax runtime type');
     }
     if (_options.useContentSecurityPolicy) flavor.write(', CSP');
-    return new js.Comment(generatedBy(_options, flavor: '$flavor'));
+    var featureString = _options.features.flavorString();
+    if (featureString.isNotEmpty) flavor.write(', $featureString');
+    return js.Comment(generatedBy(_options, flavor: '$flavor'));
   }
 
   js.Statement buildDeferredInitializerGlobal() {
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
deleted file mode 100644
index c61de53..0000000
--- a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.js_emitter.type_test_registry;
-
-import '../common.dart';
-import '../elements/entities.dart';
-import '../js_backend/runtime_types.dart'
-    show RuntimeTypesChecks, RuntimeTypesChecksBuilder;
-import '../options.dart';
-import '../universe/codegen_world_builder.dart';
-
-/// TODO(joshualitt): Delete this class and store [RuntimeTypeChecks] on
-/// [CodeEmitterTask] directly.
-class TypeTestRegistry {
-  final CompilerOptions _options;
-
-  RuntimeTypesChecks _rtiChecks;
-
-  TypeTestRegistry(this._options);
-
-  RuntimeTypesChecks get rtiChecks {
-    assert(
-        _rtiChecks != null,
-        failedAt(NO_LOCATION_SPANNABLE,
-            "RuntimeTypesChecks has not been computed yet."));
-    return _rtiChecks;
-  }
-
-  Iterable<ClassEntity> get rtiNeededClasses {
-    return rtiChecks.requiredClasses;
-  }
-
-  void computeRequiredTypeChecks(
-      RuntimeTypesChecksBuilder rtiChecksBuilder, CodegenWorld codegenWorld) {
-    _rtiChecks = rtiChecksBuilder.computeRequiredChecks(codegenWorld, _options);
-  }
-}
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 a1c35bf..a2f7118 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -9,7 +9,7 @@
 import 'package:kernel/class_hierarchy.dart' as ir;
 import 'package:kernel/core_types.dart' as ir;
 import 'package:kernel/src/bounds_checks.dart' as ir;
-
+import 'package:kernel/text/debug_printer.dart';
 import 'package:kernel/type_environment.dart' as ir;
 
 import '../closure.dart' show BoxLocal, ThisLocal;
@@ -17,7 +17,7 @@
 import '../common/names.dart';
 import '../common_elements.dart';
 import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/entity_utils.dart' as utils;
 import '../elements/indexed.dart';
@@ -27,7 +27,6 @@
 import '../ir/cached_static_type.dart';
 import '../ir/closure.dart';
 import '../ir/constants.dart';
-import '../ir/debug.dart';
 import '../ir/element_map.dart';
 import '../ir/types.dart';
 import '../ir/visitors.dart';
@@ -1245,9 +1244,6 @@
     // TODO(efortuna): This is screaming for a common interface between
     // PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel
     // folks.
-    if (node is ir.PropertyGet) {
-      return getGetterSelector(node.name);
-    }
     if (node is ir.InstanceGet) {
       return getGetterSelector(node.name);
     }
@@ -1263,9 +1259,6 @@
     if (node is ir.SuperPropertyGet) {
       return getGetterSelector(node.name);
     }
-    if (node is ir.PropertySet) {
-      return getSetterSelector(node.name);
-    }
     if (node is ir.InstanceSet) {
       return getSetterSelector(node.name);
     }
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 431efc6..c24a46b 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -13,7 +13,7 @@
 import '../common/work.dart';
 import '../common_elements.dart' show CommonElements, ElementEnvironment;
 import '../compiler.dart';
-import '../deferred_load.dart' hide WorkItem;
+import '../deferred_load/deferred_load.dart' hide WorkItem;
 import '../dump_info.dart';
 import '../elements/entities.dart';
 import '../enqueue.dart';
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 66f8efc..f2c3c08 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -9,7 +9,7 @@
 import '../common.dart';
 import '../common/names.dart';
 import '../common_elements.dart' show JCommonElements, JElementEnvironment;
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/entity_utils.dart' as utils;
 import '../elements/names.dart';
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index 8a4928d..087d57a 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -9,7 +9,7 @@
 import '../common_elements.dart';
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
 import '../elements/entities.dart';
 import '../elements/indexed.dart';
 import '../elements/names.dart';
@@ -944,15 +944,13 @@
     DartType type = typeConverter.visit(constant.type, toBackendEntity);
     ListConstantValue keys = constant.keyList.accept(this, null);
     List<ConstantValue> values = _handleValues(constant.values);
-    ConstantValue protoValue = constant.protoValue?.accept(this, null);
     if (identical(keys, constant.keys) &&
         identical(values, constant.values) &&
-        type == constant.type &&
-        protoValue == constant.protoValue) {
+        type == constant.type) {
       return constant;
     }
     return new constant_system.JavaScriptMapConstant(
-        type, keys, values, protoValue, constant.onlyStringKeys);
+        type, keys, values, constant.onlyStringKeys);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index dc97091..74ad9f6 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 // TODO(johnniwinther): Add a test that ensure that this library doesn't depend
 // on the dart2js internals.
 library compiler.src.kernel.dart2js_target;
@@ -78,9 +80,7 @@
   @override
   final String name;
 
-  final CompilerOptions options;
-
-  Map<String, ir.Class> _nativeClasses;
+  final CompilerOptions? options;
 
   Dart2jsTarget(this.name, this.flags, {this.options});
 
@@ -89,7 +89,7 @@
 
   @override
   int get enabledLateLowerings =>
-      (options != null && options.experimentLateInstanceVariables)
+      (options != null && options!.experimentLateInstanceVariables)
           ? LateLowering.none
           : _enabledLateLowerings;
 
@@ -105,13 +105,10 @@
   bool get supportsExplicitGetterCalls => false;
 
   @override
-  bool get supportsNewMethodInvocationEncoding => true;
-
-  @override
   int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.none;
 
   @override
-  List<String> get extraRequiredLibraries => _requiredLibraries[name];
+  List<String> get extraRequiredLibraries => _requiredLibraries[name]!;
 
   @override
   List<String> get extraIndexedLibraries => const [
@@ -151,12 +148,12 @@
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       List<ir.Library> libraries,
-      Map<String, String> environmentDefines,
+      Map<String, String>? environmentDefines,
       DiagnosticReporter diagnosticReporter,
-      ReferenceFromIndex referenceFromIndex,
-      {void logger(String msg),
-      ChangedStructureNotifier changedStructureNotifier}) {
-    _nativeClasses ??= JsInteropChecks.getNativeClasses(component);
+      ReferenceFromIndex? referenceFromIndex,
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
+    var nativeClasses = JsInteropChecks.getNativeClasses(component);
     var jsUtilOptimizer = JsUtilOptimizer(coreTypes, hierarchy);
     for (var library in libraries) {
       // TODO (rileyporter): Merge js_util optimizations with other lowerings
@@ -165,7 +162,7 @@
       JsInteropChecks(
               coreTypes,
               diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
-              _nativeClasses)
+              nativeClasses)
           .visitLibrary(library);
     }
     lowering.transformLibraries(libraries, coreTypes, hierarchy, options);
@@ -192,7 +189,7 @@
     }
     return new ir.StaticInvocation(
         coreTypes.index
-            .getTopLevelMember('dart:core', '_createInvocationMirror'),
+            .getTopLevelProcedure('dart:core', '_createInvocationMirror'),
         new ir.Arguments(<ir.Expression>[
           new ir.StringLiteral(name)..fileOffset = offset,
           new ir.ListLiteral(
@@ -282,7 +279,7 @@
   @override
   final bool supportsUnevaluatedConstants;
 
-  const Dart2jsConstantsBackend({this.supportsUnevaluatedConstants});
+  const Dart2jsConstantsBackend({required this.supportsUnevaluatedConstants});
 
   @override
   NumberSemantics get numberSemantics => NumberSemantics.js;
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index d568cea..7bf5db7 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -11,6 +11,7 @@
 import 'package:kernel/class_hierarchy.dart' as ir;
 import 'package:kernel/core_types.dart' as ir;
 import 'package:kernel/src/bounds_checks.dart' as ir;
+import 'package:kernel/text/debug_printer.dart';
 import 'package:kernel/type_environment.dart' as ir;
 
 import '../common.dart';
@@ -26,7 +27,6 @@
 import '../frontend_strategy.dart';
 import '../ir/annotations.dart';
 import '../ir/constants.dart';
-import '../ir/debug.dart';
 import '../ir/element_map.dart';
 import '../ir/impact.dart';
 import '../ir/impact_data.dart';
diff --git a/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart b/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
index 246429e..1d24a30 100644
--- a/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
+++ b/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 const int invocationMirrorMethodKind = 0;
 const int invocationMirrorGetterKind = 1;
 const int invocationMirrorSetterKind = 2;
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index eb961d7..43b81f4 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -15,7 +15,7 @@
 import '../common/work.dart';
 import '../common_elements.dart';
 import '../compiler.dart';
-import '../deferred_load.dart' show DeferredLoadTask;
+import '../deferred_load/deferred_load.dart' show DeferredLoadTask;
 import '../elements/entities.dart';
 import '../enqueue.dart';
 import '../environment.dart' as env;
diff --git a/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart b/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
index ebc00ae..87ad9f3 100644
--- a/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 import 'package:kernel/kernel.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart';
@@ -26,10 +28,6 @@
   TreeNode transformStaticInvocation(
       StaticInvocation invocation, Member contextMember) {
     final target = invocation.target;
-    if (target == null) {
-      return invocation;
-    }
-
     final transformer = transformers[target];
     if (transformer != null) {
       return transformer(invocation, contextMember);
diff --git a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
index 210bbcb..212aac6 100644
--- a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/type_algebra.dart';
@@ -11,9 +13,9 @@
 class _Reader {
   final Procedure _procedure;
   final FunctionType _type;
-  FunctionType _typeWithoutTypeParameters;
+  late final FunctionType _typeWithoutTypeParameters;
 
-  _Reader(this._procedure) : _type = _procedure.getterType {
+  _Reader(this._procedure) : _type = _procedure.getterType as FunctionType {
     _typeWithoutTypeParameters = _type.withoutTypeParameters;
   }
 }
@@ -31,7 +33,8 @@
 
   // Each map contains the mapping from late local variables to cells for a
   // given function scope. All late local variables are lowered to cells.
-  final List<Map<VariableDeclaration, VariableDeclaration>> _variableCells = [];
+  final List<Map<VariableDeclaration, VariableDeclaration>?> _variableCells =
+      [];
 
   // Uninitialized late static fields are lowered to cells.
   final Map<Field, Field> _fieldCells = {};
@@ -44,9 +47,9 @@
   // [Reference] to its [Field].
   final Map<Procedure, Field> _getterToField = {};
 
-  Member _contextMember;
+  Member? _contextMember;
 
-  LateLowering(this._coreTypes, CompilerOptions _options)
+  LateLowering(this._coreTypes, CompilerOptions? _options)
       : _omitLateNames = _options?.omitLateNames ?? false,
         _lowerInstanceVariables =
             _options?.experimentLateInstanceVariables ?? false,
@@ -55,7 +58,7 @@
         _readInitialized = _Reader(_coreTypes.initializedCellRead),
         _readInitializedFinal = _Reader(_coreTypes.initializedCellReadFinal);
 
-  Nullability get nonNullable => _contextMember.enclosingLibrary.nonNullable;
+  Nullability get nonNullable => _contextMember!.enclosingLibrary.nonNullable;
 
   bool _shouldLowerVariable(VariableDeclaration variable) => variable.isLate;
 
@@ -73,7 +76,7 @@
 
   String _mangleFieldName(Field field) {
     assert(_shouldLowerInstanceField(field));
-    Class cls = field.parent;
+    Class cls = field.enclosingClass!;
     return '_#${cls.name}#${field.name.text}';
   }
 
@@ -81,7 +84,7 @@
     List<Reference> additionalExports = library.additionalExports;
     Set<Reference> newExports = {};
     additionalExports.removeWhere((Reference reference) {
-      Field cell = _fieldCells[reference.node];
+      Field? cell = _fieldCells[reference.node];
       if (cell == null) return false;
       newExports.add(cell.getterReference);
       return true;
@@ -123,7 +126,7 @@
           Arguments([name, initializer])..fileOffset = fileOffset)
         ..fileOffset = fileOffset;
 
-  StringLiteral _nameLiteral(String name, int fileOffset) =>
+  StringLiteral _nameLiteral(String? name, int fileOffset) =>
       StringLiteral(name ?? '')..fileOffset = fileOffset;
 
   InstanceInvocation _callReader(
@@ -138,7 +141,8 @@
         interfaceTarget: procedure,
         functionType:
             Substitution.fromPairs(reader._type.typeParameters, typeArguments)
-                .substituteType(reader._typeWithoutTypeParameters))
+                    .substituteType(reader._typeWithoutTypeParameters)
+                as FunctionType)
       ..fileOffset = fileOffset;
   }
 
@@ -161,7 +165,7 @@
     _variableCells.removeLast();
   }
 
-  VariableDeclaration _lookupVariableCell(VariableDeclaration variable) {
+  VariableDeclaration? _lookupVariableCell(VariableDeclaration variable) {
     assert(_shouldLowerVariable(variable));
     for (final scope in _variableCells) {
       if (scope == null) continue;
@@ -190,7 +194,7 @@
   VariableDeclaration _uninitializedVariableCell(VariableDeclaration variable) {
     assert(_shouldLowerUninitializedVariable(variable));
     int fileOffset = variable.fileOffset;
-    String name = variable.name;
+    String? name = variable.name;
     final cell = VariableDeclaration(name,
         initializer:
             _callCellConstructor(_nameLiteral(name, fileOffset), fileOffset),
@@ -213,11 +217,11 @@
   VariableDeclaration _initializedVariableCell(VariableDeclaration variable) {
     assert(_shouldLowerInitializedVariable(variable));
     int fileOffset = variable.fileOffset;
-    String name = variable.name;
+    String? name = variable.name;
     final cell = VariableDeclaration(name,
         initializer: _callInitializedCellConstructor(
             _nameLiteral(name, fileOffset),
-            _initializerClosure(variable.initializer, variable.type),
+            _initializerClosure(variable.initializer!, variable.type),
             fileOffset),
         type: InterfaceType(_coreTypes.initializedCellClass, nonNullable),
         isFinal: true)
@@ -226,7 +230,7 @@
   }
 
   TreeNode transformVariableDeclaration(
-      VariableDeclaration variable, Member contextMember) {
+      VariableDeclaration variable, Member? contextMember) {
     _contextMember = contextMember;
 
     if (!_shouldLowerVariable(variable)) return variable;
@@ -309,8 +313,8 @@
     Name name = field.name;
     String nameText = name.text;
     DartType type = field.type;
-    Expression initializer = field.initializer;
-    Class enclosingClass = field.enclosingClass;
+    Expression? initializer = field.initializer;
+    Class enclosingClass = field.enclosingClass!;
 
     Name mangledName = Name(_mangleFieldName(field), field.enclosingLibrary);
     Field backingField = Field.mutable(mangledName,
@@ -436,7 +440,7 @@
     VariableGet setterValueRead() =>
         VariableGet(setterValue)..fileOffset = fileOffset;
 
-    Statement setterBody() {
+    Statement? setterBody() {
       if (!field.isFinal) {
         // The lowered setter for `late T field;` and `late T field = e;` is
         //
@@ -470,7 +474,7 @@
       }
     }
 
-    Statement body = setterBody();
+    Statement? body = setterBody();
     if (body != null) {
       Procedure setter = Procedure(
           name,
@@ -506,17 +510,14 @@
     // getter for the backing field.
     // TODO(fishythefish): Clean this up when [FieldInitializer] maintains a
     // correct [Reference] to its [Field].
-    NamedNode node = initializer.fieldReference.node;
-    assert(node != null);
+    NamedNode node = initializer.fieldReference.node!;
     Field backingField;
     if (node is Field) {
       if (!_shouldLowerInstanceField(node)) return initializer;
       backingField = _backingInstanceField(node);
     } else {
-      backingField = _getterToField[node];
+      backingField = _getterToField[node]!;
     }
-    assert(backingField != null);
-
     return FieldInitializer(backingField, initializer.value)
       ..fileOffset = initializer.fileOffset;
   }
diff --git a/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart b/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
index c315199..7df3d66 100644
--- a/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
@@ -26,11 +28,11 @@
 
   ListFactorySpecializer(this.coreTypes, this.hierarchy)
       : _listGenerateFactory =
-            coreTypes.index.getMember('dart:core', 'List', 'generate'),
+            coreTypes.index.getProcedure('dart:core', 'List', 'generate'),
         _arrayAllocateFixedFactory = coreTypes.index
-            .getMember('dart:_interceptors', 'JSArray', 'allocateFixed'),
+            .getProcedure('dart:_interceptors', 'JSArray', 'allocateFixed'),
         _arrayAllocateGrowableFactory = coreTypes.index
-            .getMember('dart:_interceptors', 'JSArray', 'allocateGrowable'),
+            .getProcedure('dart:_interceptors', 'JSArray', 'allocateGrowable'),
         _jsArrayClass =
             coreTypes.index.getClass('dart:_interceptors', 'JSArray'),
         _intClass = coreTypes.index.getClass('dart:core', 'int') {
@@ -42,17 +44,14 @@
     });
   }
 
-  Procedure _intPlus;
-  Procedure get intPlus =>
-      _intPlus ??= hierarchy.getInterfaceMember(_intClass, Name('+'));
+  late final Procedure intPlus =
+      hierarchy.getInterfaceMember(_intClass, Name('+')) as Procedure;
 
-  Procedure _intLess;
-  Procedure get intLess =>
-      _intLess ??= hierarchy.getInterfaceMember(_intClass, Name('<'));
+  late final Procedure intLess =
+      hierarchy.getInterfaceMember(_intClass, Name('<')) as Procedure;
 
-  Procedure _jsArrayIndexSet;
-  Procedure get jsArrayIndexSet => _jsArrayIndexSet ??=
-      hierarchy.getInterfaceMember(_jsArrayClass, Name('[]='));
+  late final Procedure jsArrayIndexSet =
+      hierarchy.getInterfaceMember(_jsArrayClass, Name('[]=')) as Procedure;
 
   /// Replace calls to `List.generate(length, (i) => e)` with an expansion
   ///
@@ -74,7 +73,7 @@
     assert(args.positional.length == 2);
     final length = args.positional[0];
     final generator = args.positional[1];
-    final bool growable =
+    final bool? growable =
         _getConstantNamedOptionalArgument(args, 'growable', true);
     if (growable == null) return node;
 
@@ -90,18 +89,18 @@
 
     // If the length is a constant, use the constant directly so that the
     // inferrer can see the constant length.
-    int /*?*/ lengthConstant = _getLengthArgument(args);
-    VariableDeclaration lengthVariable;
+    int? lengthConstant = _getLengthArgument(args);
+    VariableDeclaration? lengthVariable;
 
     Expression getLength() {
       if (lengthConstant != null) return IntLiteral(lengthConstant);
       lengthVariable ??= VariableDeclaration('_length',
           initializer: length, isFinal: true, type: intType)
         ..fileOffset = node.fileOffset;
-      return VariableGet(lengthVariable)..fileOffset = node.fileOffset;
+      return VariableGet(lengthVariable!)..fileOffset = node.fileOffset;
     }
 
-    TreeNode allocation = StaticInvocation(
+    Expression allocation = StaticInvocation(
         growable ? _arrayAllocateGrowableFactory : _arrayAllocateFixedFactory,
         Arguments(
           [getLength()],
@@ -122,11 +121,8 @@
       initializer: IntLiteral(0),
       type: intType,
     )..fileOffset = node.fileOffset;
-    indexVariable.fileOffset = (generator as FunctionExpression)
-        .function
-        .positionalParameters
-        .first
-        .fileOffset;
+    indexVariable.fileOffset =
+        generator.function.positionalParameters.first.fileOffset;
 
     final loop = ForStatement(
       // initializers: _i = 0
@@ -138,7 +134,7 @@
         Name('<'),
         Arguments([getLength()]),
         interfaceTarget: intLess,
-        functionType: intLess.getterType,
+        functionType: intLess.getterType as FunctionType,
       ),
       // updates: _i++
       [
@@ -164,7 +160,7 @@
 
     return BlockExpression(
       Block([
-        if (lengthVariable != null) lengthVariable,
+        if (lengthVariable != null) lengthVariable!,
         listVariable,
         loop,
       ]),
@@ -185,7 +181,7 @@
 
   /// Returns constant value of the first argument in [args], or null if it is
   /// not a constant.
-  int /*?*/ _getLengthArgument(Arguments args) {
+  int? _getLengthArgument(Arguments args) {
     if (args.positional.length < 1) return null;
     final value = args.positional.first;
     if (value is IntLiteral) {
@@ -202,7 +198,7 @@
   /// Returns constant value of the only named optional argument in [args], or
   /// null if it is not a bool constant. Returns [defaultValue] if optional
   /// argument is not passed. Argument is asserted to have the given [name].
-  bool /*?*/ _getConstantNamedOptionalArgument(
+  bool? _getConstantNamedOptionalArgument(
       Arguments args, String name, bool defaultValue) {
     if (args.named.isEmpty) {
       return defaultValue;
@@ -224,15 +220,15 @@
   /// Choose a name for the `_list` temporary. If the `List.generate` expression
   /// is an initializer for a variable, use that name so that dart2js can try to
   /// use one JavaScript variable with the source name for 'both' variables.
-  String _listNameFromContext(Expression node) {
-    TreeNode parent = node.parent;
+  String? _listNameFromContext(Expression node) {
+    TreeNode? parent = node.parent;
     if (parent is VariableDeclaration) return parent.name;
     return '_list';
   }
 
   String _indexNameFromContext(FunctionExpression generator) {
     final function = generator.function;
-    String /*?*/ candidate = function.positionalParameters.first.name;
+    String? candidate = function.positionalParameters.first.name;
     if (candidate == null || candidate == '' || candidate == '_') return '_i';
     return candidate;
   }
@@ -246,8 +242,8 @@
   final int constructorFileOffset;
   final VariableDeclaration listVariable;
   final FunctionNode function;
-  VariableDeclaration argument;
-  VariableDeclaration parameter;
+  late final VariableDeclaration argument;
+  late final VariableDeclaration parameter;
   int functionNestingLevel = 0;
 
   ListGenerateLoopBodyInliner(this.listFactorySpecializer,
@@ -298,7 +294,7 @@
   }
 
   Statement run() {
-    final body = cloneInContext(function.body);
+    Statement body = cloneInContext(function.body!);
     return Block([parameter, body]);
   }
 
@@ -335,9 +331,11 @@
             value,
           ]),
           interfaceTarget: listFactorySpecializer.jsArrayIndexSet,
-          functionType: Substitution.fromInterfaceType(listVariable.type)
-              .substituteType(
-                  listFactorySpecializer.jsArrayIndexSet.getterType))
+          functionType:
+              Substitution.fromInterfaceType(listVariable.type as InterfaceType)
+                      .substituteType(
+                          listFactorySpecializer.jsArrayIndexSet.getterType)
+                  as FunctionType)
         ..isInvariant = true
         ..isBoundsSafe = true
         ..fileOffset = constructorFileOffset,
@@ -355,7 +353,7 @@
 
   @override
   VariableDeclaration getVariableClone(VariableDeclaration variable) {
-    VariableDeclaration clone = super.getVariableClone(variable);
+    VariableDeclaration? clone = super.getVariableClone(variable);
     return clone ?? variable;
   }
 }
diff --git a/pkg/compiler/lib/src/kernel/transformations/lowering.dart b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
index e9cad5b..e04314b 100644
--- a/pkg/compiler/lib/src/kernel/transformations/lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart' show CoreTypes;
@@ -16,7 +18,7 @@
 /// Each transformation is applied locally to AST nodes of certain types after
 /// transforming children nodes.
 void transformLibraries(List<Library> libraries, CoreTypes coreTypes,
-    ClassHierarchy hierarchy, CompilerOptions options) {
+    ClassHierarchy hierarchy, CompilerOptions? options) {
   final transformer = _Lowering(coreTypes, hierarchy, options);
   libraries.forEach(transformer.visitLibrary);
 
@@ -31,10 +33,10 @@
   final FactorySpecializer factorySpecializer;
   final LateLowering _lateLowering;
 
-  Member _currentMember;
+  Member? _currentMember;
 
   _Lowering(
-      CoreTypes coreTypes, ClassHierarchy hierarchy, CompilerOptions _options)
+      CoreTypes coreTypes, ClassHierarchy hierarchy, CompilerOptions? _options)
       : factorySpecializer = FactorySpecializer(coreTypes, hierarchy),
         _lateLowering = LateLowering(coreTypes, _options);
 
@@ -51,7 +53,7 @@
   @override
   TreeNode visitStaticInvocation(StaticInvocation node) {
     node.transformChildren(this);
-    return factorySpecializer.transformStaticInvocation(node, _currentMember);
+    return factorySpecializer.transformStaticInvocation(node, _currentMember!);
   }
 
   @override
@@ -71,37 +73,37 @@
   @override
   TreeNode visitVariableGet(VariableGet node) {
     node.transformChildren(this);
-    return _lateLowering.transformVariableGet(node, _currentMember);
+    return _lateLowering.transformVariableGet(node, _currentMember!);
   }
 
   @override
   TreeNode visitVariableSet(VariableSet node) {
     node.transformChildren(this);
-    return _lateLowering.transformVariableSet(node, _currentMember);
+    return _lateLowering.transformVariableSet(node, _currentMember!);
   }
 
   @override
   TreeNode visitField(Field node) {
     _currentMember = node;
     node.transformChildren(this);
-    return _lateLowering.transformField(node, _currentMember);
+    return _lateLowering.transformField(node, _currentMember!);
   }
 
   @override
   TreeNode visitFieldInitializer(FieldInitializer node) {
     node.transformChildren(this);
-    return _lateLowering.transformFieldInitializer(node, _currentMember);
+    return _lateLowering.transformFieldInitializer(node, _currentMember!);
   }
 
   @override
   TreeNode visitStaticGet(StaticGet node) {
     node.transformChildren(this);
-    return _lateLowering.transformStaticGet(node, _currentMember);
+    return _lateLowering.transformStaticGet(node, _currentMember!);
   }
 
   @override
   TreeNode visitStaticSet(StaticSet node) {
     node.transformChildren(this);
-    return _lateLowering.transformStaticSet(node, _currentMember);
+    return _lateLowering.transformStaticSet(node, _currentMember!);
   }
 }
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index c5288eb..3598ad3 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 library dart2js.src.options;
 
 import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
@@ -32,8 +34,8 @@
 class FeatureOption {
   final String flag;
   final bool isNegativeFlag;
-  bool _state;
-  bool get isEnabled => _state;
+  bool? _state;
+  bool get isEnabled => _state!;
   bool get isDisabled => !isEnabled;
   void set state(bool value) {
     assert(_state == null);
@@ -67,10 +69,10 @@
   FeatureOption newHolders = FeatureOption('new-holders');
 
   /// [FeatureOption]s which default to enabled.
-  List<FeatureOption> shipping;
+  late final List<FeatureOption> shipping = [legacyJavaScript];
 
   /// [FeatureOption]s which default to disabled.
-  List<FeatureOption> canary;
+  late final List<FeatureOption> canary = [newHolders];
 
   /// Forces canary feature on. This must run after [Option].parse.
   void forceCanary() {
@@ -79,12 +81,21 @@
     }
   }
 
-  // Initialize feature lists.
-  FeatureOptions() {
-    shipping = [legacyJavaScript];
-    canary = [newHolders];
+  /// Returns a list of enabled features as a comma separated string.
+  String flavorString() {
+    bool _shouldPrint(FeatureOption feature) {
+      return feature.isNegativeFlag ? feature.isDisabled : feature.isEnabled;
+    }
+    String _toString(FeatureOption feature) {
+      return feature.isNegativeFlag ? 'no-${feature.flag}' : feature.flag;
+    }
+    Iterable<String> _listToString(List<FeatureOption> options) {
+      return options.where(_shouldPrint).map(_toString);
+    }
+    return _listToString(shipping).followedBy(_listToString(canary)).join(', ');
   }
 
+  /// Parses a [List<String>] and enables / disables features as necessary.
   void parse(List<String> options) {
     _extractFeatures(options, shipping, FeatureStatus.shipping);
     _extractFeatures(options, canary, FeatureStatus.canary);
@@ -122,12 +133,12 @@
 /// as few as possible.
 class CompilerOptions implements DiagnosticOptions {
   /// The entry point of the application that is being compiled.
-  Uri entryPoint;
+  Uri? entryPoint;
 
   /// Location of the package configuration file.
   ///
   /// If not null then [packageRoot] should be null.
-  Uri packageConfig;
+  Uri? packageConfig;
 
   /// List of kernel files to load.
   ///
@@ -140,18 +151,18 @@
   /// At this time, this list points to full kernel files. In the future, we may
   /// use a list of outline files for modular compiles, and only use full kernel
   /// files for linking.
-  List<Uri> dillDependencies;
+  List<Uri>? dillDependencies;
 
   /// Location from which serialized inference data is read.
   ///
   /// If this is set, the [entryPoint] is expected to be a .dill file and the
   /// frontend work is skipped.
-  Uri readDataUri;
+  Uri? readDataUri;
 
   /// Location to which inference data is serialized.
   ///
   /// If this is set, the compilation stops after type inference.
-  Uri writeDataUri;
+  Uri? writeDataUri;
 
   /// Serialize data without the closed world.
   /// TODO(joshualitt) make this the default right after landing in Google3 and
@@ -162,22 +173,22 @@
   ///
   /// If this is set, the [entryPoint] is expected to be a .dill file and the
   /// frontend work is skipped.
-  Uri readClosedWorldUri;
+  Uri? readClosedWorldUri;
 
   /// Location to which inference data is serialized.
   ///
   /// If this is set, the compilation stops after computing the closed world.
-  Uri writeClosedWorldUri;
+  Uri? writeClosedWorldUri;
 
   /// Location from which codegen data is read.
   ///
   /// If this is set, the compilation starts at codegen enqueueing.
-  Uri readCodegenUri;
+  Uri? readCodegenUri;
 
   /// Location to which codegen data is serialized.
   ///
   /// If this is set, the compilation stops after code generation.
-  Uri writeCodegenUri;
+  Uri? writeCodegenUri;
 
   /// Whether to run only the CFE and emit the generated kernel file in
   /// [outputUri].
@@ -205,7 +216,7 @@
           explicitExperimentalFlags: explicitExperimentalFlags);
 
   /// A possibly null state object for kernel compilation.
-  fe.InitializedCompilerState kernelInitializedCompilerState;
+  fe.InitializedCompilerState? kernelInitializedCompilerState;
 
   /// Whether we allow mocking compilation of libraries such as dart:io and
   /// dart:html for unit testing purposes.
@@ -230,11 +241,11 @@
 
   /// Location where to generate a map containing details of how deferred
   /// libraries are subdivided.
-  Uri deferredMapUri;
+  Uri? deferredMapUri;
 
   /// Location where to generate an internal format representing the deferred
   /// graph.
-  Uri deferredGraphUri;
+  Uri? deferredGraphUri;
 
   /// The maximum number of deferred fragments to generate. If the number of
   /// fragments exceeds this amount, then they may be merged.
@@ -242,8 +253,8 @@
   /// will not merge fragments with unrelated dependencies and thus we may
   /// generate more fragments than the 'mergeFragmentsThreshold' under some
   /// situations.
-  int mergeFragmentsThreshold = null; // default value, no max.
-  int _mergeFragmentsThreshold;
+  int? mergeFragmentsThreshold = null; // default value, no max.
+  int? _mergeFragmentsThreshold;
 
   /// Whether to disable inlining during the backend optimizations.
   // TODO(sigmund): negate, so all flags are positive
@@ -276,7 +287,7 @@
   /// Diagnostic option: List of packages for which warnings and hints are
   /// reported. If `null`, no package warnings or hints are reported. If
   /// empty, all warnings and hints are reported.
-  List<String> shownPackageWarnings; // &&&&&
+  List<String>? shownPackageWarnings;
 
   /// Whether to disable global type inference.
   bool disableTypeInference = false;
@@ -304,7 +315,7 @@
 
   /// If set, SSA intermediate form is dumped for methods with names matching
   /// this RegExp pattern.
-  String dumpSsaPattern = null;
+  String? dumpSsaPattern = null;
 
   /// Whether we allow passing an extra argument to `assert`, containing a
   /// reason for why an assertion fails. (experimental)
@@ -354,19 +365,19 @@
   bool generateSourceMap = true;
 
   /// URI of the main output of the compiler.
-  Uri outputUri;
+  Uri? outputUri;
 
   /// Location of the libraries specification file.
-  Uri librariesSpecificationUri;
+  Uri? librariesSpecificationUri;
 
   /// Location of the kernel platform `.dill` files.
-  Uri platformBinaries;
+  Uri? platformBinaries;
 
   /// Whether to print legacy types as T* rather than T.
   bool printLegacyStars = false;
 
   /// URI where the compiler should generate the output source map file.
-  Uri sourceMapUri;
+  Uri? sourceMapUri;
 
   /// The compiler is run from the build bot.
   bool testMode = false;
@@ -387,29 +398,29 @@
   /// What should the compiler do with parameter type assertions.
   ///
   /// This is an internal configuration option derived from other flags.
-  CheckPolicy defaultParameterCheckPolicy;
+  late CheckPolicy defaultParameterCheckPolicy;
 
   /// What should the compiler do with implicit downcasts.
   ///
   /// This is an internal configuration option derived from other flags.
-  CheckPolicy defaultImplicitDowncastCheckPolicy;
+  late CheckPolicy defaultImplicitDowncastCheckPolicy;
 
   /// What the compiler should do with a boolean value in a condition context
   /// when the language specification says it is a runtime error for it to be
   /// null.
   ///
   /// This is an internal configuration option derived from other flags.
-  CheckPolicy defaultConditionCheckPolicy;
+  late CheckPolicy defaultConditionCheckPolicy;
 
   /// What should the compiler do with explicit casts.
   ///
   /// This is an internal configuration option derived from other flags.
-  CheckPolicy defaultExplicitCastCheckPolicy;
+  late CheckPolicy defaultExplicitCastCheckPolicy;
 
   /// What should the compiler do with List index bounds checks.
   ///
   /// This is an internal configuration option derived from other flags.
-  CheckPolicy defaultIndexBoundsCheckPolicy;
+  late CheckPolicy defaultIndexBoundsCheckPolicy;
 
   /// Whether to generate code compliant with content security policy (CSP).
   bool useContentSecurityPolicy = false;
@@ -492,14 +503,14 @@
   }
 
   /// If specified, a bundle of optimizations to enable (or disable).
-  int optimizationLevel = null;
+  int? optimizationLevel = null;
 
   /// The shard to serialize when using [writeCodegenUri].
-  int codegenShard;
+  int? codegenShard;
 
   /// The number of shards to serialize when using [writeCodegenUri] or to
   /// deserialize when using [readCodegenUri].
-  int codegenShards;
+  int? codegenShards;
 
   /// Arguments passed to the front end about how it is invoked.
   ///
@@ -515,7 +526,7 @@
   /// Verbosity level used for filtering messages during compilation.
   fe.Verbosity verbosity = fe.Verbosity.all;
 
-  FeatureOptions features;
+  late FeatureOptions features;
 
   // -------------------------------------------------
   // Options for deprecated features
@@ -523,11 +534,11 @@
 
   /// Create an options object by parsing flags from [options].
   static CompilerOptions parse(List<String> options,
-      {FeatureOptions featureOptions,
-      Uri librariesSpecificationUri,
-      Uri platformBinaries,
-      void Function(String) onError,
-      void Function(String) onWarning}) {
+      {FeatureOptions? featureOptions,
+      Uri? librariesSpecificationUri,
+      Uri? platformBinaries,
+      void Function(String)? onError,
+      void Function(String)? onWarning}) {
     if (featureOptions == null) featureOptions = FeatureOptions();
     featureOptions.parse(options);
     Map<fe.ExperimentalFlag, bool> explicitExperimentalFlags =
@@ -545,7 +556,7 @@
       ..benchmarkingExperiment =
           _hasOption(options, Flags.benchmarkingExperiment)
       ..buildId =
-          _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)
+          _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)!
       ..compileForServer = _hasOption(options, Flags.serverMode)
       ..deferredMapUri = _extractUriOption(options, '--deferred-map=')
       ..deferredGraphUri =
@@ -638,11 +649,11 @@
       .._mergeFragmentsThreshold =
           _extractIntOption(options, '${Flags.mergeFragmentsThreshold}=')
       ..cfeInvocationModes = fe.InvocationMode.parseArguments(
-          _extractStringOption(options, '${Flags.cfeInvocationModes}=', ''),
+          _extractStringOption(options, '${Flags.cfeInvocationModes}=', '')!,
           onError: onError)
       ..verbosity = fe.Verbosity.parseArgument(
           _extractStringOption(
-              options, '${Flags.verbosity}=', fe.Verbosity.defaultValue),
+              options, '${Flags.verbosity}=', fe.Verbosity.defaultValue)!,
           onError: onError)
       ..features = featureOptions;
   }
@@ -654,7 +665,7 @@
     if (librariesSpecificationUri == null) {
       throw new ArgumentError("[librariesSpecificationUri] is null.");
     }
-    if (librariesSpecificationUri.path.endsWith('/')) {
+    if (librariesSpecificationUri!.path.endsWith('/')) {
       throw new ArgumentError(
           "[librariesSpecificationUri] should be a file: $librariesSpecificationUri");
     }
@@ -697,12 +708,12 @@
         disableTypeInference = true;
         disableRtiOptimization = true;
       }
-      if (optimizationLevel >= 2) {
+      if (optimizationLevel! >= 2) {
         enableMinification = true;
         laxRuntimeTypeToString = true;
         omitLateNames = true;
       }
-      if (optimizationLevel >= 3) {
+      if (optimizationLevel! >= 3) {
         omitImplicitChecks = true;
       }
       if (optimizationLevel == 4) {
@@ -752,7 +763,7 @@
   /// Returns `true` if warnings and hints are shown for all packages.
   @override
   bool get showAllPackageWarnings {
-    return shownPackageWarnings != null && shownPackageWarnings.isEmpty;
+    return shownPackageWarnings != null && shownPackageWarnings!.isEmpty;
   }
 
   /// Returns `true` if warnings and hints are hidden for all packages.
@@ -767,7 +778,7 @@
     }
     if (shownPackageWarnings != null) {
       return uri.scheme == 'package' &&
-          shownPackageWarnings.contains(uri.pathSegments.first);
+          shownPackageWarnings!.contains(uri.pathSegments.first);
     }
     return false;
   }
@@ -794,8 +805,8 @@
       'isEmitted=$isEmitted)';
 }
 
-String _extractStringOption(
-    List<String> options, String prefix, String defaultValue) {
+String? _extractStringOption(
+    List<String> options, String prefix, String? defaultValue) {
   for (String option in options) {
     if (option.startsWith(prefix)) {
       return option.substring(prefix.length);
@@ -804,13 +815,13 @@
   return defaultValue;
 }
 
-Uri _extractUriOption(List<String> options, String prefix) {
-  String option = _extractStringOption(options, prefix, null);
+Uri? _extractUriOption(List<String> options, String prefix) {
+  String? option = _extractStringOption(options, prefix, null);
   return (option == null) ? null : Uri.parse(option);
 }
 
-int _extractIntOption(List<String> options, String prefix) {
-  String option = _extractStringOption(options, prefix, null);
+int? _extractIntOption(List<String> options, String prefix) {
+  String? option = _extractStringOption(options, prefix, null);
   return (option == null) ? null : int.parse(option);
 }
 
@@ -821,7 +832,7 @@
 /// Extract list of comma separated values provided for [flag]. Returns an
 /// empty list if [option] contain [flag] without arguments. Returns `null` if
 /// [option] doesn't contain [flag] with or without arguments.
-List<String> _extractOptionalCsvOption(List<String> options, String flag) {
+List<String>? _extractOptionalCsvOption(List<String> options, String flag) {
   String prefix = '$flag=';
   for (String option in options) {
     if (option == flag) {
@@ -837,15 +848,15 @@
 /// Extract list of comma separated Uris provided for [flag]. Returns an
 /// empty list if [option] contain [flag] without arguments. Returns `null` if
 /// [option] doesn't contain [flag] with or without arguments.
-List<Uri> _extractUriListOption(List<String> options, String flag) {
-  List<String> stringUris = _extractOptionalCsvOption(options, flag);
+List<Uri>? _extractUriListOption(List<String> options, String flag) {
+  List<String>? stringUris = _extractOptionalCsvOption(options, flag);
   if (stringUris == null) return null;
   return stringUris.map(Uri.parse).toList();
 }
 
 Map<fe.ExperimentalFlag, bool> _extractExperiments(List<String> options,
-    {void Function(String) onError, void Function(String) onWarning}) {
-  List<String> experiments =
+    {void Function(String)? onError, void Function(String)? onWarning}) {
+  List<String>? experiments =
       _extractOptionalCsvOption(options, Flags.enableLanguageExperiments);
   onError ??= (String error) => throw new ArgumentError(error);
   onWarning ??= (String warning) => print(warning);
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index 1bd824c..d4a4746 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -506,7 +506,6 @@
         writeDartType(constant.type);
         writeConstant(constant.keyList);
         writeConstants(constant.values);
-        writeConstantOrNull(constant.protoValue);
         writeBool(constant.onlyStringKeys);
         break;
       case ConstantValueKind.CONSTRUCTED:
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index a06007f..ed14321 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -519,10 +519,9 @@
         DartType type = readDartType();
         ListConstantValue keyList = readConstant();
         List<ConstantValue> values = readConstants();
-        ConstantValue protoValue = readConstantOrNull();
         bool onlyStringKeys = readBool();
         return new constant_system.JavaScriptMapConstant(
-            type, keyList, values, protoValue, onlyStringKeys);
+            type, keyList, values, onlyStringKeys);
       case ConstantValueKind.CONSTRUCTED:
         InterfaceType type = readDartType();
         Map<FieldEntity, ConstantValue> fields =
diff --git a/pkg/compiler/lib/src/serialization/node_indexer.dart b/pkg/compiler/lib/src/serialization/node_indexer.dart
index e0c56a2..1e52a8f 100644
--- a/pkg/compiler/lib/src/serialization/node_indexer.dart
+++ b/pkg/compiler/lib/src/serialization/node_indexer.dart
@@ -106,12 +106,6 @@
   }
 
   @override
-  void visitPropertyGet(ir.PropertyGet node) {
-    registerNode(node);
-    super.visitPropertyGet(node);
-  }
-
-  @override
   void visitInstanceGet(ir.InstanceGet node) {
     registerNode(node);
     super.visitInstanceGet(node);
@@ -136,12 +130,6 @@
   }
 
   @override
-  void visitPropertySet(ir.PropertySet node) {
-    registerNode(node);
-    super.visitPropertySet(node);
-  }
-
-  @override
   void visitInstanceSet(ir.InstanceSet node) {
     registerNode(node);
     super.visitInstanceSet(node);
@@ -154,12 +142,6 @@
   }
 
   @override
-  void visitMethodInvocation(ir.MethodInvocation node) {
-    registerNode(node);
-    super.visitMethodInvocation(node);
-  }
-
-  @override
   void visitInstanceInvocation(ir.InstanceInvocation node) {
     registerNode(node);
     super.visitInstanceInvocation(node);
@@ -313,6 +295,10 @@
   void visitConstructorTearOffConstant(ir.ConstructorTearOffConstant node) {}
 
   @override
+  void visitRedirectingFactoryTearOffConstant(
+      ir.RedirectingFactoryTearOffConstant node) {}
+
+  @override
   void visitInstantiationConstant(ir.InstantiationConstant node) {
     node.tearOffConstant.accept(this);
   }
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index e684b95..590efec 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -9,7 +9,7 @@
 import '../closure.dart';
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
 import '../diagnostics/source_span.dart';
 import '../elements/entities.dart';
 import '../elements/indexed.dart';
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 765039b..9afc681 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -12,7 +12,7 @@
 import '../common_elements.dart';
 import '../constants/constant_system.dart' as constant_system;
 import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
 import '../dump_info.dart';
 import '../elements/entities.dart';
 import '../elements/jumps.dart';
@@ -3467,11 +3467,6 @@
   }
 
   @override
-  void visitPropertyGet(ir.PropertyGet node) {
-    _handlePropertyGet(node, node.receiver, node.name);
-  }
-
-  @override
   void visitVariableGet(ir.VariableGet node) {
     ir.VariableDeclaration variable = node.variable;
     HInstruction letBinding = _letBindings[variable];
@@ -3516,11 +3511,6 @@
   }
 
   @override
-  void visitPropertySet(ir.PropertySet node) {
-    _handlePropertySet(node, node.receiver, node.name, node.value);
-  }
-
-  @override
   void visitSuperPropertySet(ir.SuperPropertySet node) {
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildAssignment(node);
@@ -4491,8 +4481,8 @@
     } else if (closure is ir.ConstantExpression &&
         closure.constant is ir.StaticTearOffConstant) {
       ir.StaticTearOffConstant tearOff = closure.constant;
-      ir.Member member = tearOff.procedure;
-      if (member is ir.Procedure && handleTarget(member)) {
+      ir.Procedure member = tearOff.target;
+      if (handleTarget(member)) {
         return;
       }
     }
@@ -5032,10 +5022,7 @@
           isIntercepted: isIntercepted);
     }
     invoke.instructionContext = _currentFrame.member;
-    if (node is ir.MethodInvocation) {
-      invoke.isInvariant = node.isInvariant;
-      invoke.isBoundsSafe = node.isBoundsSafe;
-    } else if (node is ir.InstanceInvocation) {
+    if (node is ir.InstanceInvocation) {
       invoke.isInvariant = node.isInvariant;
       invoke.isBoundsSafe = node.isBoundsSafe;
     }
@@ -5274,11 +5261,6 @@
         _sourceInformationBuilder.buildCall(node, node));
   }
 
-  @override
-  void visitMethodInvocation(ir.MethodInvocation node) {
-    _handleMethodInvocation(node, node.receiver, node.arguments);
-  }
-
   void _handleEquals(ir.Expression node, ir.Expression left,
       HInstruction leftInstruction, HInstruction rightInstruction) {
     _pushDynamicInvocation(
@@ -7229,15 +7211,6 @@
   }
 
   @override
-  visitPropertyGet(ir.PropertyGet node) {
-    registerCall();
-    registerRegularNode();
-    registerReductiveNode();
-    skipReductiveNodes(() => visit(node.name));
-    visit(node.receiver);
-  }
-
-  @override
   visitInstanceGet(ir.InstanceGet node) {
     registerCall();
     registerRegularNode();
@@ -7265,16 +7238,6 @@
   }
 
   @override
-  visitPropertySet(ir.PropertySet node) {
-    registerCall();
-    registerRegularNode();
-    registerReductiveNode();
-    skipReductiveNodes(() => visit(node.name));
-    visit(node.receiver);
-    visit(node.value);
-  }
-
-  @override
   visitInstanceSet(ir.InstanceSet node) {
     registerCall();
     registerRegularNode();
@@ -7343,16 +7306,6 @@
   }
 
   @override
-  visitMethodInvocation(ir.MethodInvocation node) {
-    registerRegularNode();
-    registerReductiveNode();
-    registerCall();
-    visit(node.receiver);
-    skipReductiveNodes(() => visit(node.name));
-    _processArguments(node.arguments, null);
-  }
-
-  @override
   visitInstanceInvocation(ir.InstanceInvocation node) {
     registerRegularNode();
     registerReductiveNode();
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index a02c499..c2c5c5f 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -4,11 +4,12 @@
 
 library tracer;
 
+import 'package:kernel/text/indentation.dart' show Indentation;
+
 import '../compiler_new.dart' as api;
 import 'options.dart' show CompilerOptions;
 import 'ssa/nodes.dart' as ssa show HGraph;
 import 'ssa/ssa_tracer.dart' show HTracer;
-import 'util/util.dart' show Indentation;
 import 'world.dart' show JClosedWorld;
 
 String TRACE_FILTER_PATTERN_FOR_TEST;
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index 3a9949d..6a7894f 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -2,16 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart=2.12
+
 library dart2js.util;
 
 import 'package:front_end/src/api_unstable/dart2js.dart'
-    show $BACKSLASH, $CR, $DEL, $DQ, $LF, $LS, $PS, $TAB, Link;
+    show $BACKSLASH, $CR, $DEL, $DQ, $LF, $LS, $PS, $TAB;
 
 export 'maplet.dart';
 export 'setlet.dart';
 
-part 'indentation.dart';
-
 /// Helper functions for creating hash codes.
 class Hashing {
   /// If an integer is masked by this constant, the result is guaranteed to be
@@ -45,13 +45,13 @@
   }
 
   /// Mix the bits of `object.hashCode` with [existing].
-  static int objectHash(Object object, [int existing = 0]) {
+  static int objectHash(Object? object, [int existing = 0]) {
     return mixHashCodeBits(existing, object.hashCode);
   }
 
   /// Mix the bits of `.hashCode` all non-null objects.
-  static int objectsHash(Object obj1,
-      [Object obj2, Object obj3, Object obj4, Object obj5]) {
+  static int objectsHash(Object? obj1,
+      [Object? obj2, Object? obj3, Object? obj4, Object? obj5]) {
     int hash = 0;
     if (obj5 != null) hash = objectHash(obj5, hash);
     if (obj4 != null) hash = objectHash(obj4, hash);
@@ -61,7 +61,7 @@
   }
 
   /// Mix the bits of the element hash codes of [list] with [existing].
-  static int listHash(List list, [int existing = 0]) {
+  static int listHash(List? list, [int existing = 0]) {
     int h = existing;
     if (list != null) {
       int length = list.length;
@@ -73,7 +73,7 @@
   }
 
   /// Mix the bits of the element hash codes of [iterable] with [existing].
-  static int setHash<E>(Iterable<E> iterable, [int existing = 0]) {
+  static int setHash<E>(Iterable<E>? iterable, [int existing = 0]) {
     int h = existing;
     if (iterable != null) {
       for (E e in iterable) {
@@ -111,7 +111,7 @@
   }
 }
 
-bool identicalElements<E>(List<E> a, List<E> b) {
+bool identicalElements<E>(List<E>? a, List<E>? b) {
   if (identical(a, b)) return true;
   if (a == null || b == null) return false;
   if (a.length != b.length) return false;
@@ -123,7 +123,7 @@
   return true;
 }
 
-bool equalElements<E>(List<E> a, List<E> b) {
+bool equalElements<E>(List<E>? a, List<E>? b) {
   if (identical(a, b)) return true;
   if (a == null || b == null) return false;
   if (a.length != b.length) return false;
@@ -135,13 +135,13 @@
   return true;
 }
 
-bool equalSets<E>(Set<E> a, Set<E> b) {
+bool equalSets<E>(Set<E>? a, Set<E>? b) {
   if (identical(a, b)) return true;
   if (a == null || b == null) return false;
   return a.length == b.length && a.containsAll(b) && b.containsAll(a);
 }
 
-bool equalMaps<K, V>(Map<K, V> a, Map<K, V> b) {
+bool equalMaps<K, V>(Map<K, V>? a, Map<K, V>? b) {
   if (identical(a, b)) return true;
   if (a == null || b == null) return false;
   if (a.length != b.length) return false;
@@ -153,7 +153,7 @@
 
 /// File name prefix used to shorten the file name in stack traces printed by
 /// [trace].
-String stackTraceFilePrefix = null;
+String? stackTraceFilePrefix = null;
 
 /// Writes the characters of [string] on [buffer].  The characters
 /// are escaped as suitable for JavaScript and JSON.  [buffer] is
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index e1f8a31..a17fc60 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -12,7 +12,7 @@
         JElementEnvironment,
         KCommonElements,
         KElementEnvironment;
-import 'deferred_load.dart';
+import 'deferred_load/deferred_load.dart';
 import 'diagnostics/diagnostic_listener.dart';
 import 'elements/entities.dart';
 import 'elements/names.dart';
diff --git a/pkg/compiler/test/analyses/dart2js_allowed.json b/pkg/compiler/test/analyses/dart2js_allowed.json
index 807fcb7..9048e82 100644
--- a/pkg/compiler/test/analyses/dart2js_allowed.json
+++ b/pkg/compiler/test/analyses/dart2js_allowed.json
@@ -43,7 +43,7 @@
     "Dynamic invocation of 'toSet'.": 1,
     "Dynamic invocation of 'toList'.": 1
   },
-  "pkg/compiler/lib/src/deferred_load.dart": {
+  "pkg/compiler/lib/src/deferred_load/deferred_load.dart": {
     "Dynamic access of 'memberContext'.": 1,
     "Dynamic access of 'name'.": 1
   },
diff --git a/pkg/compiler/test/codegen/data_2/unused_empty_map.dart b/pkg/compiler/test/codegen/data_2/unused_empty_map.dart
index d9e0363..0ac9666 100644
--- a/pkg/compiler/test/codegen/data_2/unused_empty_map.dart
+++ b/pkg/compiler/test/codegen/data_2/unused_empty_map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// ignore_for_file: unused_local_variable
+
 @pragma('dart2js:noInline')
 // No code to construct unused map.
 /*member: foo1:function() {
diff --git a/pkg/compiler/test/deferred/constant_emission_test_helper.dart b/pkg/compiler/test/deferred/constant_emission_test_helper.dart
index d8fc00a..0f05dc3 100644
--- a/pkg/compiler/test/deferred/constant_emission_test_helper.dart
+++ b/pkg/compiler/test/deferred/constant_emission_test_helper.dart
@@ -9,7 +9,7 @@
 
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/constants/values.dart';
-import 'package:compiler/src/deferred_load.dart';
+import 'package:compiler/src/deferred_load/deferred_load.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/elements/types.dart';
 import 'package:compiler/src/js_emitter/model.dart';
diff --git a/pkg/compiler/test/deferred/load_graph_segmentation_test.dart b/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
index 823899f..64ec62d 100644
--- a/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
+++ b/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
@@ -10,7 +10,7 @@
 
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/deferred_load.dart';
+import 'package:compiler/src/deferred_load/deferred_load.dart';
 import 'package:compiler/src/js_emitter/startup_emitter/fragment_merger.dart';
 import 'package:expect/expect.dart';
 import '../helpers/memory_compiler.dart';
@@ -42,6 +42,7 @@
 
     var mainOutputUnit = closedWorld.outputUnitData.mainOutputUnit;
     var backendStrategy = compiler.backendStrategy;
+    // ignore: deprecated_member_use_from_same_package
     var classes = backendStrategy.emitterTask.neededClasses;
     var inputElement = classes.where((e) => e.name == 'InputElement').single;
     dynamic lib1 = lookupLibrary("memory:lib1.dart");
diff --git a/pkg/compiler/test/deferred_loading/data/shadowed_types/lib_shared.dart b/pkg/compiler/test/deferred_loading/data/shadowed_types/lib_shared.dart
index 5b20db1..09e4bf0 100644
--- a/pkg/compiler/test/deferred_loading/data/shadowed_types/lib_shared.dart
+++ b/pkg/compiler/test/deferred_loading/data/shadowed_types/lib_shared.dart
@@ -4,7 +4,7 @@
 
 /*class: A:
  class_unit=1{libb},
- type_unit=2{libb, liba}
+ type_unit=2{liba, libb}
 */
 /*member: A.:member_unit=1{libb}*/
 class A {}
@@ -25,7 +25,7 @@
 
 /*class: D:
  class_unit=1{libb},
- type_unit=2{libb, liba}
+ type_unit=2{liba, libb}
 */
 /*member: D.:member_unit=1{libb}*/
 class D {}
diff --git a/pkg/compiler/test/deferred_loading/data/shadowed_types/main.dart b/pkg/compiler/test/deferred_loading/data/shadowed_types/main.dart
index d32f920..9c29878 100644
--- a/pkg/compiler/test/deferred_loading/data/shadowed_types/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/shadowed_types/main.dart
@@ -6,7 +6,7 @@
  a_pre_fragments=[
   p1: {units: [3{liba}], usedBy: [], needs: []},
   p2: {units: [1{libb}], usedBy: [], needs: []},
-  p3: {units: [2{libb, liba}], usedBy: [], needs: []}],
+  p3: {units: [2{liba, libb}], usedBy: [], needs: []}],
  b_finalized_fragments=[
   f1: [3{liba}],
   f2: [1{libb}]],
@@ -19,7 +19,7 @@
  a_pre_fragments=[
   p1: {units: [3{liba}], usedBy: [p3], needs: []},
   p2: {units: [1{libb}], usedBy: [p3], needs: []},
-  p3: {units: [2{libb, liba}], usedBy: [], needs: [p1, p2]}],
+  p3: {units: [2{liba, libb}], usedBy: [], needs: [p1, p2]}],
  b_finalized_fragments=[
   f1: [3{liba}],
   f2: [1{libb}]],
diff --git a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
index 621ba83..aecbf54 100644
--- a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
+++ b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
@@ -5,24 +5,10 @@
 // @dart = 2.7
 
 import 'dart:io' hide Link;
-import 'package:_fe_analyzer_shared/src/testing/features.dart';
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/closure.dart';
-import 'package:compiler/src/common.dart';
-import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/deferred_load.dart';
-import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/ir/util.dart';
-import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_world.dart';
-import 'package:compiler/src/js_emitter/startup_emitter/fragment_merger.dart';
-import 'package:compiler/src/kernel/kernel_strategy.dart';
-import 'package:expect/expect.dart';
-import '../equivalence/id_equivalence.dart';
+import 'package:compiler/src/deferred_load/deferred_load.dart';
 import '../equivalence/id_equivalence_helper.dart';
-import 'package:compiler/src/constants/values.dart';
-
-import 'package:kernel/ast.dart' as ir;
+import 'deferred_loading_test_helper.dart';
 
 ///  Add in options to pass to the compiler like
 /// `Flags.disableTypeInference` or `Flags.disableInlining`
@@ -44,342 +30,3 @@
             [twoDeferredFragmentConfig, threeDeferredFragmentConfig]);
   });
 }
-
-// For ease of testing and making our tests easier to read, we impose an
-// artificial constraint of requiring every deferred import use a different
-// named prefix per test. We enforce this constraint here by checking that no
-// prefix name responds to two different libraries.
-Map<String, Uri> importPrefixes = {};
-
-String importPrefixString(OutputUnit unit) {
-  StringBuffer sb = StringBuffer();
-  bool first = true;
-  for (ImportEntity import in unit.imports) {
-    if (!first) sb.write(', ');
-    sb.write('${import.name}');
-    first = false;
-    Expect.isTrue(import.isDeferred);
-
-    if (importPrefixes.containsKey(import.name)) {
-      var existing = importPrefixes[import.name];
-      var current = import.enclosingLibraryUri;
-      Expect.equals(
-          existing,
-          current,
-          '\n    Duplicate prefix \'${import.name}\' used in both:\n'
-          '     - $existing and\n'
-          '     - $current.\n'
-          '    We require using unique prefixes on these tests to make '
-          'the expectations more readable.');
-    }
-    importPrefixes[import.name] = import.enclosingLibraryUri;
-  }
-  return sb.toString();
-}
-
-/// Create a consistent string representation of [OutputUnit]s for both
-/// KImportEntities and ImportElements.
-String outputUnitString(OutputUnit unit) {
-  if (unit == null) return 'none';
-  String sb = importPrefixString(unit);
-  return '${unit.name}{$sb}';
-}
-
-Map<String, List<PreFragment>> buildPreFragmentMap(
-    Map<String, List<FinalizedFragment>> fragmentsToLoad,
-    List<PreFragment> preDeferredFragments) {
-  Map<FinalizedFragment, PreFragment> fragmentMap = {};
-  for (var preFragment in preDeferredFragments) {
-    fragmentMap[preFragment.finalizedFragment] = preFragment;
-  }
-  Map<String, List<PreFragment>> preFragmentMap = {};
-  fragmentsToLoad.forEach((loadId, fragments) {
-    List<PreFragment> preFragments = [];
-    for (var fragment in fragments) {
-      preFragments.add(fragmentMap[fragment]);
-    }
-    preFragmentMap[loadId] = preFragments.toList();
-  });
-  return preFragmentMap;
-}
-
-class Tags {
-  static const String cls = 'class_unit';
-  static const String member = 'member_unit';
-  static const String closure = 'closure_unit';
-  static const String constants = 'constants';
-  static const String type = 'type_unit';
-  // The below tags appear in a single block comment in the main file.
-  // To keep them appearing in sequential order we prefix characters.
-  static const String preFragments = 'a_pre_fragments';
-  static const String finalizedFragments = 'b_finalized_fragments';
-  static const String steps = 'c_steps';
-}
-
-class OutputUnitDataComputer extends DataComputer<Features> {
-  const OutputUnitDataComputer();
-
-  /// OutputData for [member] as a kernel based element.
-  ///
-  /// At this point the compiler has already been run, so it is holding the
-  /// relevant OutputUnits, we just need to extract that information from it. We
-  /// fill [actualMap] with the data computed about what the resulting OutputUnit
-  /// is.
-  @override
-  void computeMemberData(Compiler compiler, MemberEntity member,
-      Map<Id, ActualData<Features>> actualMap,
-      {bool verbose: false}) {
-    JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
-    JsToElementMap elementMap = closedWorld.elementMap;
-    MemberDefinition definition = elementMap.getMemberDefinition(member);
-    OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
-            closedWorld.outputUnitData, closedWorld.closureDataLookup)
-        .run(definition.node);
-  }
-
-  @override
-  void computeClassData(Compiler compiler, ClassEntity cls,
-      Map<Id, ActualData<Features>> actualMap,
-      {bool verbose: false}) {
-    JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
-    JsToElementMap elementMap = closedWorld.elementMap;
-    ClassDefinition definition = elementMap.getClassDefinition(cls);
-    OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
-            closedWorld.outputUnitData, closedWorld.closureDataLookup)
-        .computeForClass(definition.node);
-  }
-
-  @override
-  void computeLibraryData(Compiler compiler, LibraryEntity library,
-      Map<Id, ActualData<Features>> actualMap,
-      {bool verbose}) {
-    KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
-    ir.Library node = frontendStrategy.elementMap.getLibraryNode(library);
-    List<PreFragment> preDeferredFragments = compiler
-        .backendStrategy.emitterTask.emitter.preDeferredFragmentsForTesting;
-    Map<String, List<FinalizedFragment>> fragmentsToLoad =
-        compiler.backendStrategy.emitterTask.emitter.finalizedFragmentsToLoad;
-    Set<OutputUnit> omittedOutputUnits =
-        compiler.backendStrategy.emitterTask.emitter.omittedOutputUnits;
-    PreFragmentsIrComputer(compiler.reporter, actualMap, preDeferredFragments,
-            fragmentsToLoad, omittedOutputUnits)
-        .computeForLibrary(node);
-  }
-
-  @override
-  DataInterpreter<Features> get dataValidator =>
-      const FeaturesDataInterpreter();
-}
-
-class PreFragmentsIrComputer extends IrDataExtractor<Features> {
-  final List<PreFragment> _preDeferredFragments;
-  final Map<String, List<FinalizedFragment>> _fragmentsToLoad;
-  final Set<OutputUnit> _omittedOutputUnits;
-
-  PreFragmentsIrComputer(
-      DiagnosticReporter reporter,
-      Map<Id, ActualData<Features>> actualMap,
-      this._preDeferredFragments,
-      this._fragmentsToLoad,
-      this._omittedOutputUnits)
-      : super(reporter, actualMap);
-
-  @override
-  Features computeLibraryValue(Id id, ir.Library library) {
-    var name = '${library.importUri.pathSegments.last}';
-    Features features = new Features();
-    if (!name.startsWith('main')) return features;
-
-    // First build a list of pre fragments and their dependencies.
-    int index = 1;
-    Map<FinalizedFragment, int> finalizedFragmentIndices = {};
-    Map<PreFragment, int> preFragmentIndices = {};
-    Map<int, PreFragment> reversePreFragmentIndices = {};
-    Map<int, FinalizedFragment> reverseFinalizedFragmentIndices = {};
-    for (var preFragment in _preDeferredFragments) {
-      if (!preFragmentIndices.containsKey(preFragment)) {
-        var finalizedFragment = preFragment.finalizedFragment;
-        preFragmentIndices[preFragment] = index;
-        finalizedFragmentIndices[finalizedFragment] = index;
-        reversePreFragmentIndices[index] = preFragment;
-        reverseFinalizedFragmentIndices[index] = finalizedFragment;
-        index++;
-      }
-    }
-
-    for (int i = 1; i < index; i++) {
-      var preFragment = reversePreFragmentIndices[i];
-      List<String> needs = [];
-      List<OutputUnit> supplied = [];
-      List<String> usedBy = [];
-      for (var dependent in preFragment.successors) {
-        if (preFragmentIndices.containsKey(dependent)) {
-          usedBy.add('p${preFragmentIndices[dependent]}');
-        }
-      }
-
-      for (var dependency in preFragment.predecessors) {
-        if (preFragmentIndices.containsKey(dependency)) {
-          needs.add('p${preFragmentIndices[dependency]}');
-        }
-      }
-
-      for (var emittedOutputUnit in preFragment.emittedOutputUnits) {
-        supplied.add(emittedOutputUnit.outputUnit);
-      }
-
-      var suppliedString = '[${supplied.map(outputUnitString).join(', ')}]';
-      features.addElement(Tags.preFragments,
-          'p$i: {units: $suppliedString, usedBy: $usedBy, needs: $needs}');
-    }
-
-    // Now dump finalized fragments and load ids.
-    for (int i = 1; i < index; i++) {
-      var finalizedFragment = reverseFinalizedFragmentIndices[i];
-      List<String> supplied = [];
-
-      for (var codeFragment in finalizedFragment.codeFragments) {
-        List<String> outputUnitStrings = [];
-        for (var outputUnit in codeFragment.outputUnits) {
-          if (!_omittedOutputUnits.contains(outputUnit)) {
-            outputUnitStrings.add(outputUnitString(outputUnit));
-          }
-        }
-        if (outputUnitStrings.isNotEmpty) {
-          supplied.add(outputUnitStrings.join('+'));
-        }
-      }
-
-      if (supplied.isNotEmpty) {
-        var suppliedString = '[${supplied.join(', ')}]';
-        features.addElement(Tags.finalizedFragments, 'f$i: $suppliedString');
-      }
-    }
-
-    _fragmentsToLoad.forEach((loadId, finalizedFragments) {
-      List<String> finalizedFragmentNeeds = [];
-      for (var finalizedFragment in finalizedFragments) {
-        assert(finalizedFragmentIndices.containsKey(finalizedFragment));
-        finalizedFragmentNeeds
-            .add('f${finalizedFragmentIndices[finalizedFragment]}');
-      }
-      features.addElement(
-          Tags.steps, '$loadId=(${finalizedFragmentNeeds.join(', ')})');
-    });
-
-    return features;
-  }
-}
-
-class OutputUnitIrComputer extends IrDataExtractor<Features> {
-  final JsToElementMap _elementMap;
-  final OutputUnitData _data;
-  final ClosureData _closureDataLookup;
-
-  Set<String> _constants = {};
-
-  OutputUnitIrComputer(
-      DiagnosticReporter reporter,
-      Map<Id, ActualData<Features>> actualMap,
-      this._elementMap,
-      this._data,
-      this._closureDataLookup)
-      : super(reporter, actualMap);
-
-  Features getMemberValue(
-      String tag, MemberEntity member, Set<String> constants) {
-    Features features = Features();
-    features.add(tag,
-        value: outputUnitString(_data.outputUnitForMemberForTesting(member)));
-    for (var constant in constants) {
-      features.addElement(Tags.constants, constant);
-    }
-    return features;
-  }
-
-  @override
-  Features computeClassValue(Id id, ir.Class node) {
-    var cls = _elementMap.getClass(node);
-    Features features = Features();
-    features.add(Tags.cls,
-        value: outputUnitString(_data.outputUnitForClassForTesting(cls)));
-    features.add(Tags.type,
-        value: outputUnitString(_data.outputUnitForClassTypeForTesting(cls)));
-    return features;
-  }
-
-  @override
-  Features computeMemberValue(Id id, ir.Member node) {
-    if (node is ir.Field && node.isConst) {
-      ir.Expression initializer = node.initializer;
-      ConstantValue constant = _elementMap.getConstantValue(node, initializer);
-      if (!constant.isPrimitive) {
-        SourceSpan span = computeSourceSpanFromTreeNode(initializer);
-        if (initializer is ir.ConstructorInvocation) {
-          // Adjust the source-span to match the AST-based location. The kernel FE
-          // skips the "const" keyword for the expression offset and any prefix in
-          // front of the constructor. The "-6" is an approximation assuming that
-          // there is just a single space after "const" and no prefix.
-          // TODO(sigmund): offsets should be fixed in the FE instead.
-          span = SourceSpan(span.uri, span.begin - 6, span.end - 6);
-        }
-        _registerValue(
-            NodeId(span.begin, IdKind.node),
-            Features.fromMap({
-              Tags.member: outputUnitString(
-                  _data.outputUnitForConstantForTesting(constant))
-            }),
-            node,
-            span,
-            actualMap,
-            reporter);
-      }
-    }
-
-    Features features =
-        getMemberValue(Tags.member, _elementMap.getMember(node), _constants);
-    _constants = {};
-    return features;
-  }
-
-  @override
-  visitConstantExpression(ir.ConstantExpression node) {
-    ConstantValue constant = _elementMap.getConstantValue(null, node);
-    if (!constant.isPrimitive) {
-      _constants.add('${constant.toStructuredText(_elementMap.types)}='
-          '${outputUnitString(_data.outputUnitForConstant(constant))}');
-    }
-    return super.visitConstantExpression(node);
-  }
-
-  @override
-  Features computeNodeValue(Id id, ir.TreeNode node) {
-    if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
-      ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
-      return getMemberValue(Tags.closure, info.callMethod, const {});
-    }
-    return null;
-  }
-}
-
-/// Set [actualMap] to hold a key of [id] with the computed data [value]
-/// corresponding to [object] at location [sourceSpan]. We also perform error
-/// checking to ensure that the same [id] isn't added twice.
-void _registerValue<T>(Id id, T value, Object object, SourceSpan sourceSpan,
-    Map<Id, ActualData<T>> actualMap, CompilerDiagnosticReporter reporter) {
-  if (actualMap.containsKey(id)) {
-    ActualData<T> existingData = actualMap[id];
-    reportHere(reporter, sourceSpan,
-        "Duplicate id ${id}, value=$value, object=$object");
-    reportHere(
-        reporter,
-        sourceSpan,
-        "Duplicate id ${id}, value=${existingData.value}, "
-        "object=${existingData.object}");
-    Expect.fail("Duplicate id $id.");
-  }
-  if (value != null) {
-    actualMap[id] =
-        ActualData<T>(id, value, sourceSpan.uri, sourceSpan.begin, object);
-  }
-}
diff --git a/pkg/compiler/test/deferred_loading/deferred_loading_test_helper.dart b/pkg/compiler/test/deferred_loading/deferred_loading_test_helper.dart
new file mode 100644
index 0000000..73271f9
--- /dev/null
+++ b/pkg/compiler/test/deferred_loading/deferred_loading_test_helper.dart
@@ -0,0 +1,360 @@
+// 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.7
+
+import 'package:_fe_analyzer_shared/src/testing/features.dart';
+import 'package:compiler/src/closure.dart';
+import 'package:compiler/src/common.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/deferred_load/deferred_load.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/ir/util.dart';
+import 'package:compiler/src/js_model/element_map.dart';
+import 'package:compiler/src/js_model/js_world.dart';
+import 'package:compiler/src/js_emitter/startup_emitter/fragment_merger.dart';
+import 'package:compiler/src/kernel/kernel_strategy.dart';
+import 'package:expect/expect.dart';
+import '../equivalence/id_equivalence.dart';
+import '../equivalence/id_equivalence_helper.dart';
+import 'package:compiler/src/constants/values.dart';
+
+import 'package:kernel/ast.dart' as ir;
+
+// For ease of testing and making our tests easier to read, we impose an
+// artificial constraint of requiring every deferred import use a different
+// named prefix per test. We enforce this constraint here by checking that no
+// prefix name responds to two different libraries.
+Map<String, Uri> importPrefixes = {};
+
+String importPrefixString(OutputUnit unit) {
+  List<String> importNames = [];
+  for (ImportEntity import in unit.imports) {
+    importNames.add(import.name);
+    Expect.isTrue(import.isDeferred);
+
+    if (importPrefixes.containsKey(import.name)) {
+      var existing = importPrefixes[import.name];
+      var current = import.enclosingLibraryUri;
+      Expect.equals(
+          existing,
+          current,
+          '\n    Duplicate prefix \'${import.name}\' used in both:\n'
+          '     - $existing and\n'
+          '     - $current.\n'
+          '    We require using unique prefixes on these tests to make '
+          'the expectations more readable.');
+    }
+    importPrefixes[import.name] = import.enclosingLibraryUri;
+  }
+  importNames.sort();
+  return importNames.join(', ');
+}
+
+/// Create a consistent string representation of [OutputUnit]s for both
+/// KImportEntities and ImportElements.
+String outputUnitString(OutputUnit unit) {
+  if (unit == null) return 'none';
+  String sb = importPrefixString(unit);
+  return '${unit.name}{$sb}';
+}
+
+Map<String, List<PreFragment>> buildPreFragmentMap(
+    Map<String, List<FinalizedFragment>> fragmentsToLoad,
+    List<PreFragment> preDeferredFragments) {
+  Map<FinalizedFragment, PreFragment> fragmentMap = {};
+  for (var preFragment in preDeferredFragments) {
+    fragmentMap[preFragment.finalizedFragment] = preFragment;
+  }
+  Map<String, List<PreFragment>> preFragmentMap = {};
+  fragmentsToLoad.forEach((loadId, fragments) {
+    List<PreFragment> preFragments = [];
+    for (var fragment in fragments) {
+      preFragments.add(fragmentMap[fragment]);
+    }
+    preFragmentMap[loadId] = preFragments.toList();
+  });
+  return preFragmentMap;
+}
+
+class Tags {
+  static const String cls = 'class_unit';
+  static const String member = 'member_unit';
+  static const String closure = 'closure_unit';
+  static const String constants = 'constants';
+  static const String type = 'type_unit';
+  // The below tags appear in a single block comment in the main file.
+  // To keep them appearing in sequential order we prefix characters.
+  static const String preFragments = 'a_pre_fragments';
+  static const String finalizedFragments = 'b_finalized_fragments';
+  static const String steps = 'c_steps';
+}
+
+class OutputUnitDataComputer extends DataComputer<Features> {
+  const OutputUnitDataComputer();
+
+  /// OutputData for [member] as a kernel based element.
+  ///
+  /// At this point the compiler has already been run, so it is holding the
+  /// relevant OutputUnits, we just need to extract that information from it. We
+  /// fill [actualMap] with the data computed about what the resulting OutputUnit
+  /// is.
+  @override
+  void computeMemberData(Compiler compiler, MemberEntity member,
+      Map<Id, ActualData<Features>> actualMap,
+      {bool verbose: false}) {
+    JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JsToElementMap elementMap = closedWorld.elementMap;
+    MemberDefinition definition = elementMap.getMemberDefinition(member);
+    OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
+            closedWorld.outputUnitData, closedWorld.closureDataLookup)
+        .run(definition.node);
+  }
+
+  @override
+  void computeClassData(Compiler compiler, ClassEntity cls,
+      Map<Id, ActualData<Features>> actualMap,
+      {bool verbose: false}) {
+    JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JsToElementMap elementMap = closedWorld.elementMap;
+    ClassDefinition definition = elementMap.getClassDefinition(cls);
+    OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
+            closedWorld.outputUnitData, closedWorld.closureDataLookup)
+        .computeForClass(definition.node);
+  }
+
+  @override
+  void computeLibraryData(Compiler compiler, LibraryEntity library,
+      Map<Id, ActualData<Features>> actualMap,
+      {bool verbose}) {
+    KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
+    ir.Library node = frontendStrategy.elementMap.getLibraryNode(library);
+    List<PreFragment> preDeferredFragments = compiler
+        .backendStrategy.emitterTask.emitter.preDeferredFragmentsForTesting;
+    Map<String, List<FinalizedFragment>> fragmentsToLoad =
+        compiler.backendStrategy.emitterTask.emitter.finalizedFragmentsToLoad;
+    Set<OutputUnit> omittedOutputUnits =
+        compiler.backendStrategy.emitterTask.emitter.omittedOutputUnits;
+    PreFragmentsIrComputer(compiler.reporter, actualMap, preDeferredFragments,
+            fragmentsToLoad, omittedOutputUnits)
+        .computeForLibrary(node);
+  }
+
+  @override
+  DataInterpreter<Features> get dataValidator =>
+      const FeaturesDataInterpreter();
+}
+
+class PreFragmentsIrComputer extends IrDataExtractor<Features> {
+  final List<PreFragment> _preDeferredFragments;
+  final Map<String, List<FinalizedFragment>> _fragmentsToLoad;
+  final Set<OutputUnit> _omittedOutputUnits;
+
+  PreFragmentsIrComputer(
+      DiagnosticReporter reporter,
+      Map<Id, ActualData<Features>> actualMap,
+      this._preDeferredFragments,
+      this._fragmentsToLoad,
+      this._omittedOutputUnits)
+      : super(reporter, actualMap);
+
+  @override
+  Features computeLibraryValue(Id id, ir.Library library) {
+    var name = '${library.importUri.pathSegments.last}';
+    Features features = new Features();
+    if (!name.startsWith('main')) return features;
+
+    // First build a list of pre fragments and their dependencies.
+    int index = 1;
+    Map<FinalizedFragment, int> finalizedFragmentIndices = {};
+    Map<PreFragment, int> preFragmentIndices = {};
+    Map<int, PreFragment> reversePreFragmentIndices = {};
+    Map<int, FinalizedFragment> reverseFinalizedFragmentIndices = {};
+    for (var preFragment in _preDeferredFragments) {
+      if (!preFragmentIndices.containsKey(preFragment)) {
+        var finalizedFragment = preFragment.finalizedFragment;
+        preFragmentIndices[preFragment] = index;
+        finalizedFragmentIndices[finalizedFragment] = index;
+        reversePreFragmentIndices[index] = preFragment;
+        reverseFinalizedFragmentIndices[index] = finalizedFragment;
+        index++;
+      }
+    }
+
+    for (int i = 1; i < index; i++) {
+      var preFragment = reversePreFragmentIndices[i];
+      List<String> needs = [];
+      List<OutputUnit> supplied = [];
+      List<String> usedBy = [];
+      for (var dependent in preFragment.successors) {
+        if (preFragmentIndices.containsKey(dependent)) {
+          usedBy.add('p${preFragmentIndices[dependent]}');
+        }
+      }
+
+      for (var dependency in preFragment.predecessors) {
+        if (preFragmentIndices.containsKey(dependency)) {
+          needs.add('p${preFragmentIndices[dependency]}');
+        }
+      }
+
+      for (var emittedOutputUnit in preFragment.emittedOutputUnits) {
+        supplied.add(emittedOutputUnit.outputUnit);
+      }
+
+      var suppliedString = '[${supplied.map(outputUnitString).join(', ')}]';
+      features.addElement(Tags.preFragments,
+          'p$i: {units: $suppliedString, usedBy: $usedBy, needs: $needs}');
+    }
+
+    // Now dump finalized fragments and load ids.
+    for (int i = 1; i < index; i++) {
+      var finalizedFragment = reverseFinalizedFragmentIndices[i];
+      List<String> supplied = [];
+
+      for (var codeFragment in finalizedFragment.codeFragments) {
+        List<String> outputUnitStrings = [];
+        for (var outputUnit in codeFragment.outputUnits) {
+          if (!_omittedOutputUnits.contains(outputUnit)) {
+            outputUnitStrings.add(outputUnitString(outputUnit));
+          }
+        }
+        if (outputUnitStrings.isNotEmpty) {
+          supplied.add(outputUnitStrings.join('+'));
+        }
+      }
+
+      if (supplied.isNotEmpty) {
+        var suppliedString = '[${supplied.join(', ')}]';
+        features.addElement(Tags.finalizedFragments, 'f$i: $suppliedString');
+      }
+    }
+
+    _fragmentsToLoad.forEach((loadId, finalizedFragments) {
+      List<String> finalizedFragmentNeeds = [];
+      for (var finalizedFragment in finalizedFragments) {
+        assert(finalizedFragmentIndices.containsKey(finalizedFragment));
+        finalizedFragmentNeeds
+            .add('f${finalizedFragmentIndices[finalizedFragment]}');
+      }
+      features.addElement(
+          Tags.steps, '$loadId=(${finalizedFragmentNeeds.join(', ')})');
+    });
+
+    return features;
+  }
+}
+
+class OutputUnitIrComputer extends IrDataExtractor<Features> {
+  final JsToElementMap _elementMap;
+  final OutputUnitData _data;
+  final ClosureData _closureDataLookup;
+
+  Set<String> _constants = {};
+
+  OutputUnitIrComputer(
+      DiagnosticReporter reporter,
+      Map<Id, ActualData<Features>> actualMap,
+      this._elementMap,
+      this._data,
+      this._closureDataLookup)
+      : super(reporter, actualMap);
+
+  Features getMemberValue(
+      String tag, MemberEntity member, Set<String> constants) {
+    Features features = Features();
+    features.add(tag,
+        value: outputUnitString(_data.outputUnitForMemberForTesting(member)));
+    for (var constant in constants) {
+      features.addElement(Tags.constants, constant);
+    }
+    return features;
+  }
+
+  @override
+  Features computeClassValue(Id id, ir.Class node) {
+    var cls = _elementMap.getClass(node);
+    Features features = Features();
+    features.add(Tags.cls,
+        value: outputUnitString(_data.outputUnitForClassForTesting(cls)));
+    features.add(Tags.type,
+        value: outputUnitString(_data.outputUnitForClassTypeForTesting(cls)));
+    return features;
+  }
+
+  @override
+  Features computeMemberValue(Id id, ir.Member node) {
+    if (node is ir.Field && node.isConst) {
+      ir.Expression initializer = node.initializer;
+      ConstantValue constant = _elementMap.getConstantValue(node, initializer);
+      if (!constant.isPrimitive) {
+        SourceSpan span = computeSourceSpanFromTreeNode(initializer);
+        if (initializer is ir.ConstructorInvocation) {
+          // Adjust the source-span to match the AST-based location. The kernel FE
+          // skips the "const" keyword for the expression offset and any prefix in
+          // front of the constructor. The "-6" is an approximation assuming that
+          // there is just a single space after "const" and no prefix.
+          // TODO(sigmund): offsets should be fixed in the FE instead.
+          span = SourceSpan(span.uri, span.begin - 6, span.end - 6);
+        }
+        _registerValue(
+            NodeId(span.begin, IdKind.node),
+            Features.fromMap({
+              Tags.member: outputUnitString(
+                  _data.outputUnitForConstantForTesting(constant))
+            }),
+            node,
+            span,
+            actualMap,
+            reporter);
+      }
+    }
+
+    Features features =
+        getMemberValue(Tags.member, _elementMap.getMember(node), _constants);
+    _constants = {};
+    return features;
+  }
+
+  @override
+  visitConstantExpression(ir.ConstantExpression node) {
+    ConstantValue constant = _elementMap.getConstantValue(null, node);
+    if (!constant.isPrimitive) {
+      _constants.add('${constant.toStructuredText(_elementMap.types)}='
+          '${outputUnitString(_data.outputUnitForConstant(constant))}');
+    }
+    return super.visitConstantExpression(node);
+  }
+
+  @override
+  Features computeNodeValue(Id id, ir.TreeNode node) {
+    if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
+      ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
+      return getMemberValue(Tags.closure, info.callMethod, const {});
+    }
+    return null;
+  }
+}
+
+/// Set [actualMap] to hold a key of [id] with the computed data [value]
+/// corresponding to [object] at location [sourceSpan]. We also perform error
+/// checking to ensure that the same [id] isn't added twice.
+void _registerValue<T>(Id id, T value, Object object, SourceSpan sourceSpan,
+    Map<Id, ActualData<T>> actualMap, CompilerDiagnosticReporter reporter) {
+  if (actualMap.containsKey(id)) {
+    ActualData<T> existingData = actualMap[id];
+    reportHere(reporter, sourceSpan,
+        "Duplicate id ${id}, value=$value, object=$object");
+    reportHere(
+        reporter,
+        sourceSpan,
+        "Duplicate id ${id}, value=${existingData.value}, "
+        "object=${existingData.object}");
+    Expect.fail("Duplicate id $id.");
+  }
+  if (value != null) {
+    actualMap[id] =
+        ActualData<T>(id, value, sourceSpan.uri, sourceSpan.begin, object);
+  }
+}
diff --git a/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart b/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
index 0058660..ba061e2 100644
--- a/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
+++ b/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
@@ -56,6 +56,7 @@
   @override
   void reportInfoMessage(Spannable node, MessageKind errorCode,
       [Map<String, String> arguments = const {}]) {
+    // ignore: deprecated_member_use_from_same_package
     reporter.reportInfoMessage(node, errorCode, arguments);
   }
 
diff --git a/pkg/compiler/test/end_to_end/feature_options_test.dart b/pkg/compiler/test/end_to_end/feature_options_test.dart
index 3481941..d4f3908 100644
--- a/pkg/compiler/test/end_to_end/feature_options_test.dart
+++ b/pkg/compiler/test/end_to_end/feature_options_test.dart
@@ -128,7 +128,26 @@
   Expect.throwsArgumentError(() => test(['--cf1', '--no-cf1']));
 }
 
+void flavorStringTest(List<String> options, String expectedFlavorString) {
+  var tfo = test(options);
+  Expect.equals(expectedFlavorString, tfo.flavorString());
+}
+
+void flavorStringTests() {
+  flavorStringTest([], 'sf1, sf2, no-sf3, no-sf4');
+  flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4'], '');
+  flavorStringTest(['--no-sf1', '--no-sf2', '--sf3'], 'no-sf4');
+  flavorStringTest(['--no-sf1', '--sf3', '--sf4'], 'sf2');
+  flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4', '--cf1'], 'cf1');
+  flavorStringTest(['--cf1'], 'sf1, sf2, no-sf3, no-sf4, cf1');
+  flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4', '--no-cf3'], 'no-cf3');
+  flavorStringTest(['--no-cf3'], 'sf1, sf2, no-sf3, no-sf4, no-cf3');
+  flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4', '--cf1',
+      '--no-cf3'], 'cf1, no-cf3');
+}
+
 void main() {
+  // Test feature options functionality.
   testShipping();
   testNoShipping();
   testCanary();
@@ -138,4 +157,7 @@
   testNoCanaryEnabled();
   testNoShippingEnabled();
   testFlagCollision();
+
+  // Supplemental tests.
+  flavorStringTests();
 }
diff --git a/pkg/compiler/test/end_to_end/library_env_test.dart b/pkg/compiler/test/end_to_end/library_env_test.dart
index ac96c89..f194f37 100644
--- a/pkg/compiler/test/end_to_end/library_env_test.dart
+++ b/pkg/compiler/test/end_to_end/library_env_test.dart
@@ -85,48 +85,57 @@
 }
 
 runTest() async {
-  var compiler = new CustomCompiler([], {});
+  {
+    final compiler = new CustomCompiler([], {});
 
-  await compiler.setupSdk();
+    await compiler.setupSdk();
+    final lookup = compiler.environment.valueOf;
 
-  // Core libraries are always present.
-  Expect.equals("true", compiler.fromEnvironment("dart.library.collection"));
-  // Non-existing entries in the environment return 'null'.
-  Expect.isNull(compiler.fromEnvironment("not in env"));
-  // Check for client libraries (default if there are no flags to the compiler).
-  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.client"));
-  Expect.equals("true", compiler.fromEnvironment("dart.library.html"));
-  // Check for shared libraries..
-  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.shared"));
-  // Check server libraries are not present.
-  Expect.equals(null, compiler.fromEnvironment("dart.library.mock.server"));
-  Expect.equals(null, compiler.fromEnvironment("dart.library.io"));
+    // 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], {});
 
-  compiler = new CustomCompiler([Flags.serverMode], {});
+    await compiler.setupSdk();
+    final lookup = compiler.environment.valueOf;
 
-  await compiler.setupSdk();
+    // 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"
+    });
 
-  // Core libraries are always present.
-  Expect.equals("true", compiler.fromEnvironment("dart.library.collection"));
-  // Non-existing entries in the environment return 'null'.
-  Expect.isNull(compiler.fromEnvironment("not in env"));
-  // Check client libraries are not present.
-  Expect.equals(null, compiler.fromEnvironment("dart.library.mock.client"));
-  Expect.equals(null, compiler.fromEnvironment("dart.library.html"));
-  // Check for shared libraries..
-  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.shared"));
-  // Check for server libraries.
-  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.server"));
-  Expect.equals("true", compiler.fromEnvironment("dart.library.io"));
+    await compiler.setupSdk();
+    final lookup = compiler.environment.valueOf;
 
-  // Check that user-defined env-variables win.
-  compiler = new CustomCompiler([],
-      {'dart.library.collection': "false", 'dart.library.mock.client': "foo"});
-
-  await compiler.setupSdk();
-
-  Expect.equals("false", compiler.fromEnvironment("dart.library.collection"));
-  Expect.equals("foo", compiler.fromEnvironment("dart.library.mock.client"));
+    Expect.equals("false", lookup("dart.library.collection"));
+    Expect.equals("foo", lookup("dart.library.mock.client"));
+  }
 }
 
 main() {
diff --git a/pkg/compiler/test/equivalence/id_equivalence.dart b/pkg/compiler/test/equivalence/id_equivalence.dart
index 31ece9d..879d6b9 100644
--- a/pkg/compiler/test/equivalence/id_equivalence.dart
+++ b/pkg/compiler/test/equivalence/id_equivalence.dart
@@ -17,7 +17,7 @@
 
 SourceSpan computeSourceSpanFromUriOffset(Uri uri, int offset) {
   if (uri != null) {
-    if (offset != null) {
+    if (offset != null && offset != -1) {
       return new SourceSpan(uri, offset, offset + 1);
     } else {
       return new SourceSpan(uri, 0, 0);
diff --git a/pkg/compiler/test/helpers/program_lookup.dart b/pkg/compiler/test/helpers/program_lookup.dart
index 1c98822..c6f3393 100644
--- a/pkg/compiler/test/helpers/program_lookup.dart
+++ b/pkg/compiler/test/helpers/program_lookup.dart
@@ -6,7 +6,7 @@
 
 import 'package:expect/expect.dart';
 import 'package:compiler/src/common_elements.dart';
-import 'package:compiler/src/deferred_load.dart';
+import 'package:compiler/src/deferred_load/deferred_load.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_backend/namer.dart';
 import 'package:compiler/src/js_emitter/model.dart';
diff --git a/pkg/compiler/test/impact/data/constants/main.dart b/pkg/compiler/test/impact/data/constants/main.dart
index a29bd63..be9a623 100644
--- a/pkg/compiler/test/impact/data/constants/main.dart
+++ b/pkg/compiler/test/impact/data/constants/main.dart
@@ -108,13 +108,27 @@
   inst:List<bool*>]*/
 listLiteral() => const [true, false];
 
-/*member: mapLiteral:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool]*/
+/*member: mapLiteral:type=[
+  inst:ConstantMap<dynamic,dynamic>,
+  inst:ConstantStringMap<dynamic,dynamic>,
+  inst:GeneralConstantMap<dynamic,dynamic>,
+  inst:JSBool]*/
 mapLiteral() => const {true: false};
 
-/*member: stringMapLiteral:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:JSString]*/
+/*member: stringMapLiteral:type=[
+  inst:ConstantMap<dynamic,dynamic>,
+  inst:ConstantStringMap<dynamic,dynamic>,
+  inst:GeneralConstantMap<dynamic,dynamic>,
+  inst:JSBool,
+  inst:JSString]*/
 stringMapLiteral() => const {'foo': false};
 
-/*member: setLiteral:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:_UnmodifiableSet<dynamic>]*/
+/*member: setLiteral:type=[
+  inst:ConstantMap<dynamic,dynamic>,
+  inst:ConstantStringMap<dynamic,dynamic>,
+  inst:GeneralConstantMap<dynamic,dynamic>,
+  inst:JSBool,
+  inst:_UnmodifiableSet<dynamic>]*/
 setLiteral() => const {true, false};
 
 /*member: instanceConstant:
@@ -190,13 +204,27 @@
   inst:List<bool*>]*/
 listLiteralRef() => listLiteralField;
 
-/*member: mapLiteralRef:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool]*/
+/*member: mapLiteralRef:type=[
+  inst:ConstantMap<dynamic,dynamic>,
+  inst:ConstantStringMap<dynamic,dynamic>,
+  inst:GeneralConstantMap<dynamic,dynamic>,
+  inst:JSBool]*/
 mapLiteralRef() => mapLiteralField;
 
-/*member: stringMapLiteralRef:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:JSString]*/
+/*member: stringMapLiteralRef:type=[
+  inst:ConstantMap<dynamic,dynamic>,
+  inst:ConstantStringMap<dynamic,dynamic>,
+  inst:GeneralConstantMap<dynamic,dynamic>,
+  inst:JSBool,
+  inst:JSString]*/
 stringMapLiteralRef() => stringMapLiteralField;
 
-/*member: setLiteralRef:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:_UnmodifiableSet<dynamic>]*/
+/*member: setLiteralRef:type=[
+  inst:ConstantMap<dynamic,dynamic>,
+  inst:ConstantStringMap<dynamic,dynamic>,
+  inst:GeneralConstantMap<dynamic,dynamic>,
+  inst:JSBool,
+  inst:_UnmodifiableSet<dynamic>]*/
 setLiteralRef() => setLiteralField;
 
 /*member: instanceConstantRef:
@@ -263,15 +291,29 @@
 listLiteralDeferred() => defer.listLiteralField;
 
 // TODO(johnniwinther): Should we record that this is deferred?
-/*member: mapLiteralDeferred:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool]*/
+/*member: mapLiteralDeferred:type=[
+  inst:ConstantMap<dynamic,dynamic>,
+  inst:ConstantStringMap<dynamic,dynamic>,
+  inst:GeneralConstantMap<dynamic,dynamic>,
+  inst:JSBool]*/
 mapLiteralDeferred() => defer.mapLiteralField;
 
 // TODO(johnniwinther): Should we record that this is deferred?
-/*member: stringMapLiteralDeferred:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:JSString]*/
+/*member: stringMapLiteralDeferred:type=[
+  inst:ConstantMap<dynamic,dynamic>,
+  inst:ConstantStringMap<dynamic,dynamic>,
+  inst:GeneralConstantMap<dynamic,dynamic>,
+  inst:JSBool,
+  inst:JSString]*/
 stringMapLiteralDeferred() => defer.stringMapLiteralField;
 
 // TODO(johnniwinther): Should we record that this is deferred?
-/*member: setLiteralDeferred:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:_UnmodifiableSet<dynamic>]*/
+/*member: setLiteralDeferred:type=[
+  inst:ConstantMap<dynamic,dynamic>,
+  inst:ConstantStringMap<dynamic,dynamic>,
+  inst:GeneralConstantMap<dynamic,dynamic>,
+  inst:JSBool,
+  inst:_UnmodifiableSet<dynamic>]*/
 setLiteralDeferred() => defer.setLiteralField;
 
 /*member: instanceConstantDeferred:
diff --git a/pkg/compiler/test/impact/data/literals.dart b/pkg/compiler/test/impact/data/literals.dart
index 05b7c0c..e0e3ba5 100644
--- a/pkg/compiler/test/impact/data/literals.dart
+++ b/pkg/compiler/test/impact/data/literals.dart
@@ -179,7 +179,6 @@
 /*member: testEmptyMapLiteralConstant:
 type=[
  inst:ConstantMap<dynamic,dynamic>,
- inst:ConstantProtoMap<dynamic,dynamic>,
  inst:ConstantStringMap<dynamic,dynamic>,
  inst:GeneralConstantMap<dynamic,dynamic>]
 */
diff --git a/pkg/compiler/test/inference/inference_test_helper.dart b/pkg/compiler/test/inference/inference_test_helper.dart
index 33565b7..231a108 100644
--- a/pkg/compiler/test/inference/inference_test_helper.dart
+++ b/pkg/compiler/test/inference/inference_test_helper.dart
@@ -146,7 +146,7 @@
         node is ir.FunctionDeclaration) {
       ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
       return getMemberValue(info.callMethod);
-    } else if (node is ir.MethodInvocation ||
+    } else if (
         node is ir.InstanceInvocation ||
         node is ir.InstanceGetterInvocation ||
         node is ir.DynamicInvocation ||
@@ -154,13 +154,13 @@
         node is ir.EqualsNull ||
         node is ir.EqualsCall) {
       return getTypeMaskValue(result.typeOfReceiver(node));
-    } else if (node is ir.PropertyGet ||
+    } else if (
         node is ir.InstanceGet ||
         node is ir.DynamicGet ||
         node is ir.InstanceTearOff ||
         node is ir.FunctionTearOff) {
       return getTypeMaskValue(result.typeOfReceiver(node));
-    } else if (node is ir.PropertySet ||
+    } else if (
         node is ir.InstanceSet ||
         node is ir.DynamicSet) {
       return getTypeMaskValue(result.typeOfReceiver(node));
diff --git a/pkg/compiler/test/rti/rti_need_test_helper.dart b/pkg/compiler/test/rti/rti_need_test_helper.dart
index 4206006..5b15bb6 100644
--- a/pkg/compiler/test/rti/rti_need_test_helper.dart
+++ b/pkg/compiler/test/rti/rti_need_test_helper.dart
@@ -187,14 +187,16 @@
 }
 
 /// Visitor that determines whether a type refers to [entity].
-class FindTypeVisitor extends BaseDartTypeVisitor<bool, Null> {
+class FindTypeVisitor extends DartTypeVisitor<bool, Null> {
   final Entity entity;
 
   FindTypeVisitor(this.entity);
 
-  bool visitTypes(List<DartType> types) {
+  bool check(DartType type) => visit(type, null);
+
+  bool checkList(List<DartType> types) {
     for (DartType type in types) {
-      if (type.accept(this, null)) {
+      if (check(type)) {
         return true;
       }
     }
@@ -202,39 +204,47 @@
   }
 
   @override
-  bool visitType(DartType type, _) => false;
-
-  @override
   bool visitLegacyType(LegacyType type, _) => visit(type.baseType, _);
 
   @override
   bool visitNullableType(NullableType type, _) => visit(type.baseType, _);
 
   @override
-  bool visitInterfaceType(InterfaceType type, _) {
-    if (type.element == entity) return true;
-    return visitTypes(type.typeArguments);
-  }
+  bool visitNeverType(NeverType type, _) => false;
 
   @override
-  bool visitFunctionType(FunctionType type, _) {
-    if (type.returnType.accept(this, null)) return true;
-    if (visitTypes(type.typeVariables)) return true;
-    if (visitTypes(type.parameterTypes)) return true;
-    if (visitTypes(type.optionalParameterTypes)) return true;
-    if (visitTypes(type.namedParameterTypes)) return true;
-    return false;
-  }
+  bool visitVoidType(VoidType type, _) => false;
 
   @override
-  bool visitTypeVariableType(TypeVariableType type, _) {
-    return type.element.typeDeclaration == entity;
-  }
+  bool visitTypeVariableType(TypeVariableType type, _) =>
+      type.element.typeDeclaration == entity;
 
   @override
-  bool visitFutureOrType(FutureOrType type, _) {
-    return type.typeArgument.accept(this, null);
-  }
+  bool visitFunctionTypeVariable(FunctionTypeVariable type, _) => false;
+
+  @override
+  bool visitFunctionType(FunctionType type, _) =>
+      type.returnType.accept(this, null) ||
+      checkList(type.typeVariables) ||
+      checkList(type.parameterTypes) ||
+      checkList(type.optionalParameterTypes) ||
+      checkList(type.namedParameterTypes);
+
+  @override
+  bool visitInterfaceType(InterfaceType type, _) =>
+      type.element == entity || checkList(type.typeArguments);
+
+  @override
+  bool visitDynamicType(DynamicType type, _) => false;
+
+  @override
+  bool visitErasedType(ErasedType type, _) => false;
+
+  @override
+  bool visitAnyType(AnyType type, _) => false;
+
+  @override
+  bool visitFutureOrType(FutureOrType type, _) => check(type.typeArgument);
 }
 
 class RtiNeedDataComputer extends DataComputer<String> {
diff --git a/pkg/compiler/test/static_type/static_type_test.dart b/pkg/compiler/test/static_type/static_type_test.dart
index 15cf87d..0123144 100644
--- a/pkg/compiler/test/static_type/static_type_test.dart
+++ b/pkg/compiler/test/static_type/static_type_test.dart
@@ -86,9 +86,6 @@
   String computeNodeValue(Id id, ir.TreeNode node) {
     if (node is ir.VariableGet) {
       return typeToText(node.accept(staticTypeCache));
-    } else if (node is ir.MethodInvocation) {
-      return '[${typeToText(node.receiver.accept(staticTypeCache))}]->'
-          '${typeToText(node.accept(staticTypeCache))}';
     } else if (node is ir.InstanceInvocation) {
       return '[${typeToText(node.receiver.accept(staticTypeCache))}]->'
           '${typeToText(node.accept(staticTypeCache))}';
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
index 0e0f59c..a17a169 100644
--- a/pkg/dartdev/lib/src/analysis_server.dart
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -9,6 +9,7 @@
 import 'package:analysis_server/src/server/driver.dart' show Driver;
 import 'package:analysis_server_client/protocol.dart'
     show EditBulkFixesResult, ResponseDecoder;
+import 'package:args/args.dart';
 import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
 
@@ -16,17 +17,23 @@
 import 'sdk.dart';
 import 'utils.dart';
 
+/// When set, this function is executed just before the Analysis Server starts.
+void Function(String cmdName, List<FileSystemEntity> analysisRoots,
+    ArgResults argResults) preAnalysisServerStart;
+
 /// A class to provide an API wrapper around an analysis server process.
 class AnalysisServer {
   AnalysisServer(
     this.sdkPath,
     this.analysisRoots, {
     @required this.commandName,
+    @required this.argResults,
   });
 
   final Directory sdkPath;
   final List<FileSystemEntity> analysisRoots;
   final String commandName;
+  final ArgResults argResults;
 
   Process _process;
 
@@ -69,6 +76,7 @@
   final Map<String, Completer<Map<String, dynamic>>> _requestCompleters = {};
 
   Future<void> start() async {
+    preAnalysisServerStart?.call(commandName, analysisRoots, argResults);
     final List<String> command = <String>[
       sdk.analysisServerSnapshot,
       '--${Driver.SUPPRESS_ANALYTICS_FLAG}',
@@ -285,12 +293,14 @@
     return messages.map((message) => DiagnosticMessage(message)).toList();
   }
 
-  // TODO(jwren) add some tests to verify that the results are what we are
-  // expecting, 'other' is not always on the RHS of the subtraction in the
-  // implementation.
   @override
   int compareTo(AnalysisError other) {
-    // Sort in order of file path, error location, severity, and message.
+    // Sort in order of severity, file path, error location, and message.
+    final int diff = _severityLevel.index - other._severityLevel.index;
+    if (diff != 0) {
+      return diff;
+    }
+
     if (file != other.file) {
       return file.compareTo(other.file);
     }
@@ -299,11 +309,6 @@
       return offset - other.offset;
     }
 
-    final int diff = other._severityLevel.index - _severityLevel.index;
-    if (diff != 0) {
-      return diff;
-    }
-
     return message.compareTo(other.message);
   }
 
diff --git a/pkg/dartdev/lib/src/commands/analyze.dart b/pkg/dartdev/lib/src/commands/analyze.dart
index a4c02be..27fbf53 100644
--- a/pkg/dartdev/lib/src/commands/analyze.dart
+++ b/pkg/dartdev/lib/src/commands/analyze.dart
@@ -100,6 +100,7 @@
       io.Directory(sdk.sdkPath),
       targets,
       commandName: 'analyze',
+      argResults: argResults,
     );
 
     server.onErrors.listen((FileAnalysisErrors fileErrors) {
@@ -126,8 +127,6 @@
 
     progress?.finish(showTiming: true);
 
-    errors.sort();
-
     if (errors.isEmpty) {
       if (!machineFormat) {
         log.stdout('No issues found!');
@@ -135,6 +134,8 @@
       return 0;
     }
 
+    errors.sort();
+
     if (machineFormat) {
       emitMachineFormat(log, errors);
     } else if (jsonFormat) {
diff --git a/pkg/dartdev/lib/src/commands/fix.dart b/pkg/dartdev/lib/src/commands/fix.dart
index 60d2e46..08d4d36 100644
--- a/pkg/dartdev/lib/src/commands/fix.dart
+++ b/pkg/dartdev/lib/src/commands/fix.dart
@@ -93,6 +93,7 @@
       io.Directory(sdk.sdkPath),
       [dir],
       commandName: 'fix',
+      argResults: argResults,
     );
 
     await server.start();
diff --git a/pkg/dartdev/lib/src/core.dart b/pkg/dartdev/lib/src/core.dart
index 2da96fc..b84cd86 100644
--- a/pkg/dartdev/lib/src/core.dart
+++ b/pkg/dartdev/lib/src/core.dart
@@ -18,6 +18,10 @@
 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;
+
 abstract class DartdevCommand extends Command<int> {
   final String _name;
   final String _description;
@@ -29,7 +33,9 @@
   final bool hidden;
 
   DartdevCommand(this._name, this._description, this._verbose,
-      {this.hidden = false});
+      {this.hidden = false}) {
+    flagContributor?.call(argParser, _name);
+  }
 
   @override
   String get name => _name;
diff --git a/pkg/dartdev/test/analysis_server_test.dart b/pkg/dartdev/test/analysis_server_test.dart
index dba2ccc..05f7597 100644
--- a/pkg/dartdev/test/analysis_server_test.dart
+++ b/pkg/dartdev/test/analysis_server_test.dart
@@ -25,14 +25,14 @@
 
     test('can start', () async {
       AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), [p.dir],
-          commandName: 'testing');
+          commandName: 'testing', argResults: null);
       await server.start();
       await server.shutdown();
     });
 
     test('can send message', () async {
       AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), [p.dir],
-          commandName: 'testing');
+          commandName: 'testing', argResults: null);
       await server.start();
 
       final response = await server.getVersion();
diff --git a/pkg/dartdev/test/commands/analyze_test.dart b/pkg/dartdev/test/commands/analyze_test.dart
index 293c139..d2a43e3 100644
--- a/pkg/dartdev/test/commands/analyze_test.dart
+++ b/pkg/dartdev/test/commands/analyze_test.dart
@@ -56,6 +56,119 @@
       expect(error.contextMessages, hasLength(2));
     });
   });
+
+  group('sorting', () {
+    test('severity', () {
+      var errors = <AnalysisError>[
+        AnalysisError({
+          'severity': 'INFO',
+          'location': {
+            'file': 'a.dart',
+          }
+        }),
+        AnalysisError({
+          'severity': 'WARNING',
+          'location': {
+            'file': 'a.dart',
+          }
+        }),
+        AnalysisError({
+          'severity': 'ERROR',
+          'location': {
+            'file': 'a.dart',
+          }
+        })
+      ];
+
+      errors.sort();
+
+      expect(errors, hasLength(3));
+      expect(errors[0].isError, isTrue);
+      expect(errors[1].isWarning, isTrue);
+      expect(errors[2].isInfo, isTrue);
+    });
+
+    test('file', () {
+      var errors = <AnalysisError>[
+        AnalysisError({
+          'severity': 'INFO',
+          'location': {
+            'file': 'c.dart',
+          }
+        }),
+        AnalysisError({
+          'severity': 'INFO',
+          'location': {
+            'file': 'b.dart',
+          }
+        }),
+        AnalysisError({
+          'severity': 'INFO',
+          'location': {
+            'file': 'a.dart',
+          }
+        })
+      ];
+
+      errors.sort();
+
+      expect(errors, hasLength(3));
+      expect(errors[0].file, equals('a.dart'));
+      expect(errors[1].file, equals('b.dart'));
+      expect(errors[2].file, equals('c.dart'));
+    });
+
+    test('offset', () {
+      var errors = <AnalysisError>[
+        AnalysisError({
+          'severity': 'INFO',
+          'location': {'file': 'a.dart', 'offset': 8}
+        }),
+        AnalysisError({
+          'severity': 'INFO',
+          'location': {'file': 'a.dart', 'offset': 6}
+        }),
+        AnalysisError({
+          'severity': 'INFO',
+          'location': {'file': 'a.dart', 'offset': 4}
+        })
+      ];
+
+      errors.sort();
+
+      expect(errors, hasLength(3));
+      expect(errors[0].offset, equals(4));
+      expect(errors[1].offset, equals(6));
+      expect(errors[2].offset, equals(8));
+    });
+
+    test('message', () {
+      var errors = <AnalysisError>[
+        AnalysisError({
+          'severity': 'INFO',
+          'location': {'file': 'a.dart', 'offset': 8},
+          'message': 'C'
+        }),
+        AnalysisError({
+          'severity': 'INFO',
+          'location': {'file': 'a.dart', 'offset': 6},
+          'message': 'B'
+        }),
+        AnalysisError({
+          'severity': 'INFO',
+          'location': {'file': 'a.dart', 'offset': 4},
+          'message': 'A'
+        })
+      ];
+
+      errors.sort();
+
+      expect(errors, hasLength(3));
+      expect(errors[0].message, equals('A'));
+      expect(errors[1].message, equals('B'));
+      expect(errors[2].message, equals('C'));
+    });
+  });
 }
 
 void defineAnalyze() {
diff --git a/pkg/dartdev/test/commands/format_test.dart b/pkg/dartdev/test/commands/format_test.dart
index 82e68d2..568f3ce 100644
--- a/pkg/dartdev/test/commands/format_test.dart
+++ b/pkg/dartdev/test/commands/format_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 'dart:convert';
 import 'dart:io';
 
 import 'package:test/test.dart';
@@ -98,4 +99,16 @@
         startsWith('No file or directory found at "$unknownFilePath".'));
     expect(result.stdout, startsWith('Formatted no files in '));
   });
+
+  test('formats from stdin and exits', () async {
+    p = project(mainSrc: 'int get foo => 1;\n');
+    var process = await p.start(['format']);
+    process.stdin.writeln('main(   ) { }');
+
+    var result = process.stdout.reduce((a, b) => a + b);
+
+    await process.stdin.close();
+    expect(await process.exitCode, 0);
+    expect(utf8.decode(await result), 'main() {}\n');
+  });
 }
diff --git a/pkg/dartdev/test/commands/test_test.dart b/pkg/dartdev/test/commands/test_test.dart
index b493403..bda022bb 100644
--- a/pkg/dartdev/test/commands/test_test.dart
+++ b/pkg/dartdev/test/commands/test_test.dart
@@ -30,7 +30,7 @@
     expect(result.stdout, startsWith('''
 Runs tests in this package.
 
-Usage: pub run test [files or directories...]
+Usage: dart test [files or directories...]
 '''));
     expect(result.stderr, isEmpty);
   });
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md
index 84e2e6a..9859145 100644
--- a/pkg/dds/CHANGELOG.md
+++ b/pkg/dds/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 2.0.2
+- Fix possibility of `LateInitializationError` being thrown when trying to
+  cleanup after an error during initialization.
+
 # 2.0.1
 - Update `package:vm_service` to ^7.0.0.
 
diff --git a/pkg/dds/analysis_options.yaml b/pkg/dds/analysis_options.yaml
index 413f412..1f83658 100644
--- a/pkg/dds/analysis_options.yaml
+++ b/pkg/dds/analysis_options.yaml
@@ -2,5 +2,6 @@
 
 linter:
   rules:
+    - depend_on_referenced_packages
     - directives_ordering
     - prefer_generic_function_type_aliases
diff --git a/pkg/dds/lib/src/dap/adapters/dart.dart b/pkg/dds/lib/src/dap/adapters/dart.dart
index d7811e0..64b66be 100644
--- a/pkg/dds/lib/src/dap/adapters/dart.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart.dart
@@ -139,6 +139,9 @@
   /// processed its initial paused state).
   Future<void> get debuggerInitialized => _debuggerInitializedCompleter.future;
 
+  bool get evaluateToStringInDebugViews =>
+      args.evaluateToStringInDebugViews ?? false;
+
   /// [attachRequest] is called by the client when it wants us to to attach to
   /// an existing app. This will only be called once (and only one of this or
   /// launchRequest will be called).
@@ -318,6 +321,15 @@
         sendResponse(protocols?.toJson());
         break;
 
+      /// Used to toggle debug settings such as whether SDK/Packages are
+      /// debuggable while the session is in progress.
+      case 'updateDebugOptions':
+        if (args != null) {
+          await _updateDebugOptions(args.args);
+        }
+        sendResponse(null);
+        break;
+
       default:
         await super.customRequest(request, args, sendResponse);
     }
@@ -421,7 +433,7 @@
       final resultString = await _converter.convertVmInstanceRefToDisplayString(
         thread,
         result,
-        allowCallingToString: true,
+        allowCallingToString: evaluateToStringInDebugViews,
       );
       // TODO(dantup): We may need to store `expression` with this data
       // to allow building nested evaluateNames.
@@ -845,7 +857,8 @@
             thread,
             variable.value,
             name: variable.name,
-            allowCallingToString: index <= maxToStringsPerEvaluation,
+            allowCallingToString: evaluateToStringInDebugViews &&
+                index <= maxToStringsPerEvaluation,
           );
         }
 
@@ -871,6 +884,7 @@
         variables.addAll(await _converter.convertVmInstanceToVariablesList(
           thread,
           object,
+          allowCallingToString: evaluateToStringInDebugViews,
           startItem: childStart,
           numItems: childCount,
         ));
@@ -972,8 +986,15 @@
       if (ref == null || ref.kind == vm.InstanceKind.kNull) {
         return null;
       }
-      // TODO(dantup): This should handle truncation and complex types.
-      return ref.valueAsString;
+      return _converter.convertVmInstanceRefToDisplayString(
+        thread,
+        ref,
+        // Always allow calling toString() here as the user expects the full
+        // string they logged regardless of the evaluateToStringInDebugViews
+        // setting.
+        allowCallingToString: true,
+        includeQuotesAroundString: false,
+      );
     }
 
     var loggerName = await asString(record.loggerName);
@@ -987,13 +1008,13 @@
     final prefix = '[$loggerName] ';
 
     if (message != null) {
-      sendPrefixedOutput('stdout', prefix, '$message\n');
+      sendPrefixedOutput('console', prefix, '$message\n');
     }
     if (error != null) {
-      sendPrefixedOutput('stderr', prefix, '$error\n');
+      sendPrefixedOutput('console', prefix, '$error\n');
     }
     if (stack != null) {
-      sendPrefixedOutput('stderr', prefix, '$stack\n');
+      sendPrefixedOutput('console', prefix, '$stack\n');
     }
   }
 
@@ -1009,7 +1030,29 @@
     // Notify IsolateManager if we'll be debugging so it knows whether to set
     // up breakpoints etc. when isolates are registered.
     final debug = !(args.noDebug ?? false);
-    _isolateManager.setDebugEnabled(debug);
+    _isolateManager.debug = debug;
+    _isolateManager.debugSdkLibraries = args.debugSdkLibraries ?? true;
+    _isolateManager.debugExternalPackageLibraries =
+        args.debugExternalPackageLibraries ?? true;
+  }
+
+  /// Updates the current debug options for the session.
+  ///
+  /// Clients may not know about all debug options, so anything not included
+  /// in the map will not be updated by this method.
+  Future<void> _updateDebugOptions(Map<String, Object?> args) async {
+    // TODO(dantup): Document this - it's a public API we expect to be used
+    //   by editors that can support it (although it will require custom
+    //   code as it's there's no DAP standard for this, or the settings it
+    //   toggles).
+    if (args.containsKey('debugSdkLibraries')) {
+      _isolateManager.debugSdkLibraries = args['debugSdkLibraries'] as bool;
+    }
+    if (args.containsKey('debugExternalPackageLibraries')) {
+      _isolateManager.debugExternalPackageLibraries =
+          args['debugExternalPackageLibraries'] as bool;
+    }
+    await _isolateManager.applyDebugOptions();
   }
 
   /// A wrapper around the same name function from package:vm_service that
diff --git a/pkg/dds/lib/src/dap/adapters/dart_cli.dart b/pkg/dds/lib/src/dap/adapters/dart_cli.dart
index b0fd701..c01214d 100644
--- a/pkg/dds/lib/src/dap/adapters/dart_cli.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart_cli.dart
@@ -53,7 +53,9 @@
           enableDds: enableDds,
           enableAuthCodes: enableAuthCodes,
           logger: logger,
-        );
+        ) {
+    channel.closed.then((_) => shutdown());
+  }
 
   Future<void> debuggerConnected(vm.VM vmInfo) async {
     if (!isAttach) {
diff --git a/pkg/dds/lib/src/dap/base_debug_adapter.dart b/pkg/dds/lib/src/dap/base_debug_adapter.dart
index cd2b99a..a74f1f3 100644
--- a/pkg/dds/lib/src/dap/base_debug_adapter.dart
+++ b/pkg/dds/lib/src/dap/base_debug_adapter.dart
@@ -65,14 +65,7 @@
     RawRequestArguments? args,
     void Function(Object?) sendResponse,
   ) async {
-    final response = Response(
-      success: false,
-      requestSeq: request.seq,
-      seq: _sequence++,
-      command: request.command,
-      message: 'Unknown command: ${request.command}',
-    );
-    sendResponse(response);
+    throw DebugAdapterException('Unknown command  ${request.command}');
   }
 
   Future<void> disconnectRequest(
@@ -251,7 +244,7 @@
     } else if (message is Response) {
       _handleIncomingResponse(message);
     } else {
-      throw Exception('Unknown Protocol message ${message.type}');
+      throw DebugAdapterException('Unknown Protocol message ${message.type}');
     }
   }
 
diff --git a/pkg/dds/lib/src/dap/isolate_manager.dart b/pkg/dds/lib/src/dap/isolate_manager.dart
index 99ee743..9c16536 100644
--- a/pkg/dds/lib/src/dap/isolate_manager.dart
+++ b/pkg/dds/lib/src/dap/isolate_manager.dart
@@ -23,15 +23,33 @@
   final Map<int, ThreadInfo> _threadsByThreadId = {};
   int _nextThreadNumber = 1;
 
-  /// Whether debugging is enabled.
+  /// Whether debugging is enabled for this session.
   ///
   /// This must be set before any isolates are spawned and controls whether
   /// breakpoints or exception pause modes are sent to the VM.
   ///
+  /// If false, requests to send breakpoints or exception pause mode will be
+  /// dropped. Other functionality (handling pause events, resuming, etc.) will
+  /// all still function.
+  ///
   /// This is used to support debug sessions that have VM Service connections
   /// but were run with noDebug: true (for example we may need a VM Service
   /// connection for a noDebug flutter app in order to support hot reload).
-  bool _debug = false;
+  bool debug = false;
+
+  /// Whether SDK libraries should be marked as debuggable.
+  ///
+  /// Calling [sendLibraryDebuggables] is required after changing this value to
+  /// apply changes. This allows applying both [debugSdkLibraries] and
+  /// [debugExternalPackageLibraries] in one step.
+  bool debugSdkLibraries = true;
+
+  /// Whether external package libraries should be marked as debuggable.
+  ///
+  /// Calling [sendLibraryDebuggables] is required after changing this value to
+  /// apply changes. This allows applying both [debugSdkLibraries] and
+  /// [debugExternalPackageLibraries] in one step.
+  bool debugExternalPackageLibraries = true;
 
   /// Tracks breakpoints last provided by the client so they can be sent to new
   /// isolates that appear after initial breakpoints were sent.
@@ -72,6 +90,18 @@
   /// not exited between accessing this list and trying to use the results.
   List<ThreadInfo> get threads => _threadsByIsolateId.values.toList();
 
+  /// Re-applies debug options to all isolates/libraries.
+  ///
+  /// This is required if options like debugSdkLibraries are modified, but is a
+  /// separate step to batch together changes to multiple options.
+  Future<void> applyDebugOptions() async {
+    await Future.wait(_threadsByThreadId.values.map(
+      // debuggable libraries is the only thing currently affected by these
+      // changable options.
+      (isolate) => _sendLibraryDebuggables(isolate.isolate),
+    ));
+  }
+
   Future<T> getObject<T extends vm.Response>(
       vm.IsolateRef isolate, vm.ObjRef object) async {
     final res = await _adapter.vmService?.getObject(isolate.id!, object.id!);
@@ -219,19 +249,6 @@
         .map((isolate) => _sendBreakpoints(isolate.isolate, uri: uri)));
   }
 
-  /// Sets whether debugging is enabled for this session.
-  ///
-  /// If not, requests to send breakpoints or exception pause mode will be
-  /// dropped. Other functionality (handling pause events, resuming, etc.) will
-  /// all still function.
-  ///
-  /// This is used to support debug sessions that have VM Service connections
-  /// but were run with noDebug: true (for example we may need a VM Service
-  /// connection for a noDebug flutter app in order to support hot reload).
-  void setDebugEnabled(bool debug) {
-    _debug = debug;
-  }
-
   /// 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 {
@@ -371,13 +388,13 @@
 
   /// Checks whether a library should be considered debuggable.
   ///
-  /// This usesthe settings from the launch arguments (debugSdkLibraries
-  /// and debugExternalPackageLibraries) against the type of library given.
+  /// Initial values are provided in the launch arguments, but may be updated
+  /// by the `updateDebugOptions` custom request.
   bool _libaryIsDebuggable(vm.LibraryRef library) {
     if (_isSdkLibrary(library)) {
-      return _adapter.args.debugSdkLibraries ?? false;
+      return debugSdkLibraries;
     } else if (_isExternalPackageLibrary(library)) {
-      return _adapter.args.debugExternalPackageLibraries ?? false;
+      return debugExternalPackageLibraries;
     } else {
       return true;
     }
@@ -391,7 +408,7 @@
   /// newly-created isolates).
   Future<void> _sendBreakpoints(vm.IsolateRef isolate, {String? uri}) async {
     final service = _adapter.vmService;
-    if (!_debug || service == null) {
+    if (!debug || service == null) {
       return;
     }
 
@@ -425,7 +442,7 @@
   /// Sets the exception pause mode for an individual isolate.
   Future<void> _sendExceptionPauseMode(vm.IsolateRef isolate) async {
     final service = _adapter.vmService;
-    if (!_debug || service == null) {
+    if (!debug || service == null) {
       return;
     }
 
@@ -436,7 +453,7 @@
   /// on the debug settings.
   Future<void> _sendLibraryDebuggables(vm.IsolateRef isolateRef) async {
     final service = _adapter.vmService;
-    if (!_debug || service == null) {
+    if (!debug || service == null) {
       return;
     }
 
diff --git a/pkg/dds/lib/src/dap/protocol_converter.dart b/pkg/dds/lib/src/dap/protocol_converter.dart
index 85ef5f8..6285121 100644
--- a/pkg/dds/lib/src/dap/protocol_converter.dart
+++ b/pkg/dds/lib/src/dap/protocol_converter.dart
@@ -57,21 +57,32 @@
     required bool allowCallingToString,
     bool includeQuotesAroundString = true,
   }) async {
-    final canCallToString = allowCallingToString &&
-        (_adapter.args.evaluateToStringInDebugViews ?? false);
+    final isTruncated = ref.valueAsStringIsTruncated ?? false;
+    if (ref.kind == vm.InstanceKind.kString && isTruncated) {
+      // Call toString() if allowed, otherwise (or if it returns null) fall back
+      // to the truncated value with "…" suffix.
+      var stringValue = allowCallingToString
+          ? await _callToString(
+              thread,
+              ref,
+              includeQuotesAroundString: includeQuotesAroundString,
+            )
+          : null;
+      stringValue ??= '${ref.valueAsString}…';
 
-    if (ref.kind == 'String' || ref.valueAsString != null) {
-      var stringValue = ref.valueAsString.toString();
-      if (ref.valueAsStringIsTruncated ?? false) {
-        stringValue = '$stringValue…';
-      }
-      if (ref.kind == 'String' && includeQuotesAroundString) {
-        stringValue = '"$stringValue"';
-      }
-      return stringValue;
+      return includeQuotesAroundString ? '"$stringValue"' : stringValue;
+    } else if (ref.kind == vm.InstanceKind.kString) {
+      // Untruncated strings.
+      return includeQuotesAroundString
+          ? '"${ref.valueAsString}"'
+          : ref.valueAsString.toString();
+    } else if (ref.valueAsString != null) {
+      return isTruncated
+          ? '${ref.valueAsString}…'
+          : ref.valueAsString.toString();
     } else if (ref.kind == 'PlainInstance') {
       var stringValue = ref.classRef?.name ?? '<unknown instance>';
-      if (canCallToString) {
+      if (allowCallingToString) {
         final toStringValue = await _callToString(
           thread,
           ref,
@@ -99,6 +110,7 @@
   Future<List<dap.Variable>> convertVmInstanceToVariablesList(
     ThreadInfo thread,
     vm.Instance instance, {
+    required bool allowCallingToString,
     int? startItem = 0,
     int? numItems,
   }) async {
@@ -112,7 +124,7 @@
         await convertVmResponseToVariable(
           thread,
           instance,
-          allowCallingToString: true,
+          allowCallingToString: allowCallingToString,
         )
       ];
     } else if (elements != null) {
@@ -121,10 +133,15 @@
       return Future.wait(elements
           .cast<vm.Response>()
           .sublist(start, numItems != null ? start + numItems : null)
-          .mapIndexed((index, response) async => convertVmResponseToVariable(
-              thread, response,
+          .mapIndexed(
+            (index, response) => convertVmResponseToVariable(
+              thread,
+              response,
               name: '${start + index}',
-              allowCallingToString: index <= maxToStringsPerEvaluation)));
+              allowCallingToString:
+                  allowCallingToString && index <= maxToStringsPerEvaluation,
+            ),
+          ));
     } else if (associations != null) {
       // For maps, create a variable for each entry (in the requested subset).
       // Use the keys and values to create a display string in the form
@@ -135,13 +152,14 @@
       return Future.wait(associations
           .sublist(start, numItems != null ? start + numItems : null)
           .mapIndexed((index, mapEntry) async {
-        final allowCallingToString = index <= maxToStringsPerEvaluation;
+        final callToString =
+            allowCallingToString && index <= maxToStringsPerEvaluation;
         final keyDisplay = await convertVmResponseToDisplayString(
             thread, mapEntry.key,
-            allowCallingToString: allowCallingToString);
+            allowCallingToString: callToString);
         final valueDisplay = await convertVmResponseToDisplayString(
             thread, mapEntry.value,
-            allowCallingToString: allowCallingToString);
+            allowCallingToString: callToString);
         return dap.Variable(
           name: '${start + index}',
           value: '$keyDisplay -> $valueDisplay',
@@ -154,7 +172,8 @@
           (index, field) async => convertVmResponseToVariable(
               thread, field.value,
               name: field.decl?.name ?? '<unnamed field>',
-              allowCallingToString: index <= maxToStringsPerEvaluation)));
+              allowCallingToString:
+                  allowCallingToString && index <= maxToStringsPerEvaluation)));
 
       // Also evaluate the getters if evaluateGettersInDebugViews=true enabled.
       final service = _adapter.vmService;
@@ -177,7 +196,8 @@
             thread,
             response,
             name: getterName,
-            allowCallingToString: index <= maxToStringsPerEvaluation,
+            allowCallingToString:
+                allowCallingToString && index <= maxToStringsPerEvaluation,
           );
         }
 
@@ -397,7 +417,7 @@
     if (service == null) {
       return null;
     }
-    final result = await service.invoke(
+    var result = await service.invoke(
       thread.isolate.id!,
       ref.id!,
       'toString',
@@ -405,10 +425,18 @@
       disableBreakpoints: true,
     );
 
+    // If the response is a string and is truncated, use getObject() to get the
+    // full value.
+    if (result is vm.InstanceRef &&
+        result.kind == 'String' &&
+        (result.valueAsStringIsTruncated ?? false)) {
+      result = await service.getObject(thread.isolate.id!, result.id!);
+    }
+
     return convertVmResponseToDisplayString(
       thread,
       result,
-      allowCallingToString: false,
+      allowCallingToString: false, // Don't allow recursing.
       includeQuotesAroundString: includeQuotesAroundString,
     );
   }
diff --git a/pkg/dds/lib/src/dap/protocol_stream_transformers.dart b/pkg/dds/lib/src/dap/protocol_stream_transformers.dart
index 6bd6caa..424fa84 100644
--- a/pkg/dds/lib/src/dap/protocol_stream_transformers.dart
+++ b/pkg/dds/lib/src/dap/protocol_stream_transformers.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 import 'dart:convert';
-import 'dart:typed_data';
 
 class InvalidEncodingError {
   final String headers;
@@ -107,28 +106,3 @@
   final String? encoding;
   ProtocolHeaders(this.rawHeaders, this.contentLength, this.encoding);
 }
-
-/// Transforms a stream of [Uint8List]s to [List<int>]s. Used because
-/// [ServerSocket] and [Socket] use [Uint8List] but stdin and stdout use
-/// [List<int>] and the LSP server needs to operate against both.
-class Uint8ListTransformer extends StreamTransformerBase<Uint8List, List<int>> {
-  // TODO(dantup): Is there a built-in (or better) way to do this?
-  @override
-  Stream<List<int>> bind(Stream<Uint8List> stream) {
-    late StreamSubscription<Uint8List> input;
-    late StreamController<List<int>> _output;
-    _output = StreamController<List<int>>(
-      onListen: () {
-        input = stream.listen(
-          (uints) => _output.add(uints),
-          onError: _output.addError,
-          onDone: _output.close,
-        );
-      },
-      onPause: () => input.pause(),
-      onResume: () => input.resume(),
-      onCancel: () => input.cancel(),
-    );
-    return _output.stream;
-  }
-}
diff --git a/pkg/dds/lib/src/dap/server.dart b/pkg/dds/lib/src/dap/server.dart
index f2530a3..8a38138 100644
--- a/pkg/dds/lib/src/dap/server.dart
+++ b/pkg/dds/lib/src/dap/server.dart
@@ -3,92 +3,45 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io';
 
 import 'package:dds/src/dap/adapters/dart.dart';
-import 'package:pedantic/pedantic.dart';
 
 import 'adapters/dart_cli.dart';
 import 'logging.dart';
 import 'protocol_stream.dart';
-import 'protocol_stream_transformers.dart';
 
-/// A DAP server that binds to a port and runs in multi-session mode.
+/// A DAP server that communicates over a [ByteStreamServerChannel], usually
+/// constructed from the processes stdin/stdout streams.
+///
+/// The server runs in single-user mode and services only a single client. For
+/// multiple debug sessions, there would be multiple servers (and the editor
+/// would have a client for each of them).
 class DapServer {
-  final ServerSocket _socket;
+  final ByteStreamServerChannel channel;
+  late final DartDebugAdapter adapter;
   final bool ipv6;
   final bool enableDds;
   final bool enableAuthCodes;
   final Logger? logger;
-  final _channels = <ByteStreamServerChannel>{};
-  final _adapters = <DartDebugAdapter>{};
 
-  DapServer._(
-    this._socket, {
+  DapServer(
+    Stream<List<int>> _input,
+    StreamSink<List<int>> _output, {
     this.ipv6 = false,
     this.enableDds = true,
     this.enableAuthCodes = true,
     this.logger,
-  }) {
-    _socket.listen(_acceptConnection);
-  }
-
-  String get host => _socket.address.host;
-  int get port => _socket.port;
-
-  Future<void> stop() async {
-    _channels.forEach((client) => client.close());
-    await _socket.close();
-  }
-
-  void _acceptConnection(Socket client) {
-    final address = client.remoteAddress;
-    logger?.call('Accepted connection from $address');
-    client.done.then((_) {
-      logger?.call('Connection from $address closed');
-    });
-    _createAdapter(client.transform(Uint8ListTransformer()), client);
-  }
-
-  void _createAdapter(Stream<List<int>> _input, StreamSink<List<int>> _output) {
-    // TODO(dantup): This is hard-coded to DartCliDebugAdapter but will
-    //   ultimately need to support having a factory passed in to support
-    //   tests and/or being used in flutter_tools.
-    final channel = ByteStreamServerChannel(_input, _output, logger);
-    final adapter = DartCliDebugAdapter(
+  }) : channel = ByteStreamServerChannel(_input, _output, logger) {
+    adapter = DartCliDebugAdapter(
       channel,
       ipv6: ipv6,
       enableDds: enableDds,
       enableAuthCodes: enableAuthCodes,
       logger: logger,
     );
-    _channels.add(channel);
-    _adapters.add(adapter);
-    unawaited(channel.closed.then((_) {
-      _channels.remove(channel);
-      _adapters.remove(adapter);
-      adapter.shutdown();
-    }));
   }
 
-  /// Starts a DAP Server listening on [host]:[port].
-  static Future<DapServer> create({
-    String? host,
-    int port = 0,
-    bool ipv6 = false,
-    bool enableDdds = true,
-    bool enableAuthCodes = true,
-    Logger? logger,
-  }) async {
-    final hostFallback =
-        ipv6 ? InternetAddress.loopbackIPv6 : InternetAddress.loopbackIPv4;
-    final _socket = await ServerSocket.bind(host ?? hostFallback, port);
-    return DapServer._(
-      _socket,
-      ipv6: ipv6,
-      enableDds: enableDdds,
-      enableAuthCodes: enableAuthCodes,
-      logger: logger,
-    );
+  void stop() {
+    channel.close();
   }
 }
diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart
index c65ba5d..4360bcc 100644
--- a/pkg/dds/lib/src/dds_impl.dart
+++ b/pkg/dds/lib/src/dds_impl.dart
@@ -67,7 +67,7 @@
 
   Future<void> startService() async {
     bool started = false;
-    final completer = Completer<void>();
+    DartDevelopmentServiceException? error;
     // TODO(bkonyi): throw if we've already shutdown.
     // Establish the connection to the VM service.
     _vmServiceSocket = webSocketBuilder(remoteVmServiceWsUri);
@@ -76,18 +76,25 @@
     unawaited(
       vmServiceClient.listen().then(
         (_) {
-          shutdown();
-          if (!started && !completer.isCompleted) {
-            completer
-                .completeError(DartDevelopmentServiceException.failedToStart());
+          if (started) {
+            shutdown();
+          } else {
+            // If we fail to connect to the service or the connection is
+            // terminated while we're starting up, we'll need to cleanup later
+            // once DDS has finished initializing to make sure all ports are
+            // closed before throwing the exception.
+            error = DartDevelopmentServiceException.failedToStart();
           }
         },
         onError: (e, st) {
-          shutdown();
-          if (!completer.isCompleted) {
-            completer.completeError(
-              DartDevelopmentServiceException.connectionIssue(e.toString()),
-              st,
+          if (started) {
+            shutdown();
+          } else {
+            // If we encounter an error while we're starting up, we'll need to
+            // cleanup later once DDS has finished initializing to make sure
+            // all ports are closed before throwing the exception.
+            error = DartDevelopmentServiceException.connectionIssue(
+              e.toString(),
             );
           }
         },
@@ -104,13 +111,15 @@
       // Once we have a connection to the VM service, we're ready to spawn the intermediary.
       await _startDDSServer();
       started = true;
-      completer.complete();
     } on StateError {
       /* Ignore json-rpc state errors */
-    } catch (e, st) {
-      completer.completeError(e, st);
     }
-    return completer.future;
+
+    // Check if we encountered any errors during startup, cleanup, and throw.
+    if (error != null) {
+      await shutdown();
+      throw error!;
+    }
   }
 
   Future<void> _startDDSServer() async {
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 2bf3136..012f3e3 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.0.1
+version: 2.0.2
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds
 
diff --git a/pkg/dds/test/common/fakes.dart b/pkg/dds/test/common/fakes.dart
index 7e11f9d..9ef5cf9 100644
--- a/pkg/dds/test/common/fakes.dart
+++ b/pkg/dds/test/common/fakes.dart
@@ -7,6 +7,7 @@
 import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 import 'package:test/fake.dart';
 import 'package:vm_service/vm_service.dart';
+import 'package:web_socket_channel/web_socket_channel.dart';
 
 /// [FakePeer] implements the bare minimum of the [Peer] interface needed for
 /// [DartDevelopmentService] to establish a connection with a VM service.
@@ -62,3 +63,18 @@
 
   int _idCount = 0;
 }
+
+class FakeWebSocketSink extends Fake implements WebSocketSink {
+  @override
+  Future close([int? closeCode, String? closeReason]) {
+    // Do nothing.
+    return Future.value();
+  }
+}
+
+/// [FakeWebSocketChannel] implements the bare minimum of the [WebSocket]
+/// interface required to finish DDS initialization.
+class FakeWebSocketChannel extends Fake implements WebSocketChannel {
+  @override
+  WebSocketSink get sink => FakeWebSocketSink();
+}
diff --git a/pkg/dds/test/dap/integration/debug_breakpoints_test.dart b/pkg/dds/test/dap/integration/debug_breakpoints_test.dart
index 9a50b03..62cacbf 100644
--- a/pkg/dds/test/dap/integration/debug_breakpoints_test.dart
+++ b/pkg/dds/test/dap/integration/debug_breakpoints_test.dart
@@ -9,56 +9,61 @@
 import 'test_support.dart';
 
 main() {
-  testDap((dap) async {
-    group('debug mode breakpoints', () {
-      test('stops at a line breakpoint', () async {
-        final client = dap.client;
-        final testFile = dap.createTestFile(simpleBreakpointProgram);
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+  late DapTestSession dap;
+  setUp(() async {
+    dap = await DapTestSession.setUp();
+  });
+  tearDown(() => dap.tearDown());
 
-        await client.hitBreakpoint(testFile, breakpointLine);
-      });
+  group('debug mode breakpoints', () {
+    test('stops at a line breakpoint', () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(simpleBreakpointProgram);
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-      test('stops at a line breakpoint and can be resumed', () async {
-        final client = dap.client;
-        final testFile = dap.createTestFile(simpleBreakpointProgram);
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      await client.hitBreakpoint(testFile, breakpointLine);
+    });
 
-        // Hit the initial breakpoint.
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
+    test('stops at a line breakpoint and can be resumed', () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(simpleBreakpointProgram);
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        // Resume and expect termination (as the script will get to the end).
-        await Future.wait([
-          client.event('terminated'),
-          client.continue_(stop.threadId!),
-        ], eagerError: true);
-      });
+      // Hit the initial breakpoint.
+      final stop = await client.hitBreakpoint(testFile, breakpointLine);
 
-      test('stops at a line breakpoint and can step over (next)', () async {
-        final testFile = dap.createTestFile(r'''
+      // Resume and expect termination (as the script will get to the end).
+      await Future.wait([
+        client.event('terminated'),
+        client.continue_(stop.threadId!),
+      ], eagerError: true);
+    });
+
+    test('stops at a line breakpoint and can step over (next)', () async {
+      final testFile = dap.createTestFile(r'''
 void main(List<String> args) async {
   print('Hello!'); // BREAKPOINT
   print('Hello!'); // STEP
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
-        final stepLine = lineWith(testFile, '// STEP');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final stepLine = lineWith(testFile, '// STEP');
 
-        // Hit the initial breakpoint.
-        final stop = await dap.client.hitBreakpoint(testFile, breakpointLine);
+      // Hit the initial breakpoint.
+      final stop = await dap.client.hitBreakpoint(testFile, breakpointLine);
 
-        // Step and expect stopping on the next line with a 'step' stop type.
-        await Future.wait([
-          dap.client.expectStop('step', file: testFile, line: stepLine),
-          dap.client.next(stop.threadId!),
-        ], eagerError: true);
-      });
+      // Step and expect stopping on the next line with a 'step' stop type.
+      await Future.wait([
+        dap.client.expectStop('step', file: testFile, line: stepLine),
+        dap.client.next(stop.threadId!),
+      ], eagerError: true);
+    });
 
-      test(
-          'stops at a line breakpoint and can step over (next) an async boundary',
-          () async {
-        final client = dap.client;
-        final testFile = dap.createTestFile(r'''
+    test(
+        'stops at a line breakpoint and can step over (next) an async boundary',
+        () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(r'''
 Future<void> main(List<String> args) async {
   await asyncPrint('Hello!'); // BREAKPOINT
   await asyncPrint('Hello!'); // STEP
@@ -68,30 +73,30 @@
   await Future.delayed(const Duration(milliseconds: 1));
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
-        final stepLine = lineWith(testFile, '// STEP');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final stepLine = lineWith(testFile, '// STEP');
 
-        // Hit the initial breakpoint.
-        final stop = await dap.client.hitBreakpoint(testFile, breakpointLine);
+      // Hit the initial breakpoint.
+      final stop = await dap.client.hitBreakpoint(testFile, breakpointLine);
 
-        // The first step will move from `asyncPrint` to the `await`.
-        await Future.wait([
-          client.expectStop('step', file: testFile, line: breakpointLine),
-          client.next(stop.threadId!),
-        ], eagerError: true);
+      // The first step will move from `asyncPrint` to the `await`.
+      await Future.wait([
+        client.expectStop('step', file: testFile, line: breakpointLine),
+        client.next(stop.threadId!),
+      ], eagerError: true);
 
-        // The next step should go over the async boundary and to stepLine (if
-        // we did not correctly send kOverAsyncSuspension we would end up in
-        // the asyncPrint method).
-        await Future.wait([
-          client.expectStop('step', file: testFile, line: stepLine),
-          client.next(stop.threadId!),
-        ], eagerError: true);
-      });
+      // The next step should go over the async boundary and to stepLine (if
+      // we did not correctly send kOverAsyncSuspension we would end up in
+      // the asyncPrint method).
+      await Future.wait([
+        client.expectStop('step', file: testFile, line: stepLine),
+        client.next(stop.threadId!),
+      ], eagerError: true);
+    });
 
-      test('stops at a line breakpoint and can step in', () async {
-        final client = dap.client;
-        final testFile = dap.createTestFile(r'''
+    test('stops at a line breakpoint and can step in', () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(r'''
 void main(List<String> args) async {
   log('Hello!'); // BREAKPOINT
 }
@@ -100,22 +105,22 @@
   print(message);
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
-        final stepLine = lineWith(testFile, '// STEP');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final stepLine = lineWith(testFile, '// STEP');
 
-        // Hit the initial breakpoint.
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
+      // Hit the initial breakpoint.
+      final stop = await client.hitBreakpoint(testFile, breakpointLine);
 
-        // Step and expect stopping in the inner function with a 'step' stop type.
-        await Future.wait([
-          client.expectStop('step', file: testFile, line: stepLine),
-          client.stepIn(stop.threadId!),
-        ], eagerError: true);
-      });
+      // Step and expect stopping in the inner function with a 'step' stop type.
+      await Future.wait([
+        client.expectStop('step', file: testFile, line: stepLine),
+        client.stepIn(stop.threadId!),
+      ], eagerError: true);
+    });
 
-      test('stops at a line breakpoint and can step out', () async {
-        final client = dap.client;
-        final testFile = dap.createTestFile(r'''
+    test('stops at a line breakpoint and can step out', () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(r'''
 void main(List<String> args) async {
   log('Hello!');
   log('Hello!'); // STEP
@@ -125,87 +130,119 @@
   print(message); // BREAKPOINT
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
-        final stepLine = lineWith(testFile, '// STEP');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final stepLine = lineWith(testFile, '// STEP');
 
-        // Hit the initial breakpoint.
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
+      // Hit the initial breakpoint.
+      final stop = await client.hitBreakpoint(testFile, breakpointLine);
 
-        // Step and expect stopping in the inner function with a 'step' stop type.
-        await Future.wait([
-          client.expectStop('step', file: testFile, line: stepLine),
-          client.stepOut(stop.threadId!),
-        ], eagerError: true);
-      });
+      // Step and expect stopping in the inner function with a 'step' stop type.
+      await Future.wait([
+        client.expectStop('step', file: testFile, line: stepLine),
+        client.stepOut(stop.threadId!),
+      ], eagerError: true);
+    });
 
-      test('does not step into SDK code with debugSdkLibraries=false',
-          () async {
-        final client = dap.client;
-        final testFile = dap.createTestFile(r'''
+    test('does not step into SDK code with debugSdkLibraries=false', () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(r'''
 void main(List<String> args) async {
   print('Hello!'); // BREAKPOINT
   print('Hello!'); // STEP
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
-        final stepLine = lineWith(testFile, '// STEP');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final stepLine = lineWith(testFile, '// STEP');
 
-        // Hit the initial breakpoint.
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
+      // Hit the initial breakpoint.
+      final stop = await client.hitBreakpoint(
+        testFile,
+        breakpointLine,
+        launch: () => client.launch(
+          testFile.path,
+          debugSdkLibraries: false,
+        ),
+      );
 
-        // Step in and expect stopping on the next line (don't go into print).
-        await Future.wait([
-          client.expectStop('step', file: testFile, line: stepLine),
-          client.stepIn(stop.threadId!),
-        ], eagerError: true);
-      });
+      // Step in and expect stopping on the next line (don't go into print).
+      await Future.wait([
+        client.expectStop('step', file: testFile, line: stepLine),
+        client.stepIn(stop.threadId!),
+      ], eagerError: true);
+    });
 
-      test('steps into SDK code with debugSdkLibraries=true', () async {
-        final client = dap.client;
-        final testFile = dap.createTestFile(r'''
+    test('steps into SDK code with debugSdkLibraries=true', () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(r'''
 void main(List<String> args) async {
   print('Hello!'); // BREAKPOINT
   print('Hello!');
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        // Hit the initial breakpoint.
-        final stop = await dap.client.hitBreakpoint(
-          testFile,
-          breakpointLine,
-          launch: () => client.launch(
-            testFile.path,
-            debugSdkLibraries: true,
-          ),
-        );
+      // Hit the initial breakpoint.
+      final stop = await dap.client.hitBreakpoint(
+        testFile,
+        breakpointLine,
+        launch: () => client.launch(
+          testFile.path,
+          debugSdkLibraries: true,
+        ),
+      );
 
-        // Step in and expect to go into print.
-        await Future.wait([
-          client.expectStop('step', sourceName: 'dart:core/print.dart'),
-          client.stepIn(stop.threadId!),
-        ], eagerError: true);
+      // Step in and expect to go into print.
+      await Future.wait([
+        client.expectStop('step', sourceName: 'dart:core/print.dart'),
+        client.stepIn(stop.threadId!),
+      ], eagerError: true);
+    });
+
+    test(
+        'does not step into external package code with debugExternalPackageLibraries=false',
+        () {
+      // TODO(dantup): Support for debugExternalPackageLibraries
+    }, skip: true);
+
+    test(
+        'steps into external package code with debugExternalPackageLibraries=true',
+        () {
+      // TODO(dantup): Support for debugExternalPackageLibraries
+    }, skip: true);
+
+    test('allows changing debug settings during session', () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(r'''
+void main(List<String> args) async {
+  print('Hello!'); // BREAKPOINT
+  print('Hello!'); // STEP
+}
+    ''');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final stepLine = lineWith(testFile, '// STEP');
+
+      // Start with debugSdkLibraryes _enabled_ and hit the breakpoint.
+      final stop = await client.hitBreakpoint(
+        testFile,
+        breakpointLine,
+        launch: () => client.launch(
+          testFile.path,
+          debugSdkLibraries: true,
+        ),
+      );
+
+      // Turn off debugSdkLibraries.
+      await client.custom('updateDebugOptions', {
+        'debugSdkLibraries': false,
       });
 
-      test(
-          'does not step into external package code with debugExternalPackageLibraries=false',
-          () {
-        // TODO(dantup): Support for debugExternalPackageLibraries
-      }, skip: true);
-
-      test(
-          'steps into external package code with debugExternalPackageLibraries=true',
-          () {
-        // TODO(dantup): Support for debugExternalPackageLibraries
-      }, skip: true);
-
-      test('allows changing debug settings during session', () {
-        // TODO(dantup): !
-        // Dart-Code's DAP has a custom method that allows an editor to change
-        // the debug settings (debugSdkLibraries/debugExternalPackageLibraries)
-        // during a debug session.
-      }, skip: true);
-      // These tests can be slow due to starting up the external server process.
-    }, timeout: Timeout.none);
-  });
+      // Step in and expect stopping on the next line (don't go into print
+      // because we turned off SDK debugging).
+      await Future.wait([
+        client.expectStop('step', file: testFile, line: stepLine),
+        client.stepIn(stop.threadId!),
+      ], eagerError: true);
+    });
+    // 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_eval_test.dart b/pkg/dds/test/dap/integration/debug_eval_test.dart
index 9b59310..ab24f0c 100644
--- a/pkg/dds/test/dap/integration/debug_eval_test.dart
+++ b/pkg/dds/test/dap/integration/debug_eval_test.dart
@@ -10,126 +10,131 @@
 import 'test_support.dart';
 
 main() {
-  testDap((dap) async {
-    group('debug mode evaluation', () {
-      test('evaluates expressions with simple results', () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+  late DapTestSession dap;
+  setUp(() async {
+    dap = await DapTestSession.setUp();
+  });
+  tearDown(() => dap.tearDown());
+
+  group('debug mode evaluation', () {
+    test('evaluates expressions with simple results', () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   var a = 1;
   var b = 2;
   var c = 'test';
   print('Hello!'); // BREAKPOINT
 }''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
-        await client.expectTopFrameEvalResult(stop.threadId!, 'a', '1');
-        await client.expectTopFrameEvalResult(stop.threadId!, 'a * b', '2');
-        await client.expectTopFrameEvalResult(stop.threadId!, 'c', '"test"');
-      });
+      final stop = await client.hitBreakpoint(testFile, breakpointLine);
+      await client.expectTopFrameEvalResult(stop.threadId!, 'a', '1');
+      await client.expectTopFrameEvalResult(stop.threadId!, 'a * b', '2');
+      await client.expectTopFrameEvalResult(stop.threadId!, 'c', '"test"');
+    });
 
-      test('evaluates expressions with complex results', () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(simpleBreakpointProgram);
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+    test('evaluates expressions with complex results', () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(simpleBreakpointProgram);
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
-        final result = await client.expectTopFrameEvalResult(
-          stop.threadId!,
-          'DateTime(2000, 1, 1)',
-          'DateTime',
-        );
+      final stop = await client.hitBreakpoint(testFile, breakpointLine);
+      final result = await client.expectTopFrameEvalResult(
+        stop.threadId!,
+        'DateTime(2000, 1, 1)',
+        'DateTime',
+      );
 
-        // Check we got a variablesReference that maps on to the fields.
-        expect(result.variablesReference, greaterThan(0));
-        await client.expectVariables(
-          result.variablesReference,
-          '''
+      // Check we got a variablesReference that maps on to the fields.
+      expect(result.variablesReference, greaterThan(0));
+      await client.expectVariables(
+        result.variablesReference,
+        '''
             isUtc: false
           ''',
-        );
-      });
+      );
+    });
 
-      test(
-          'evaluates complex expressions expressions with evaluateToStringInDebugViews=true',
-          () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(simpleBreakpointProgram);
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+    test(
+        'evaluates complex expressions expressions with evaluateToStringInDebugViews=true',
+        () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(simpleBreakpointProgram);
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        final stop = await client.hitBreakpoint(
-          testFile,
-          breakpointLine,
-          launch: () =>
-              client.launch(testFile.path, evaluateToStringInDebugViews: true),
-        );
+      final stop = await client.hitBreakpoint(
+        testFile,
+        breakpointLine,
+        launch: () =>
+            client.launch(testFile.path, evaluateToStringInDebugViews: true),
+      );
 
-        await client.expectTopFrameEvalResult(
-          stop.threadId!,
-          'DateTime(2000, 1, 1)',
-          'DateTime (2000-01-01 00:00:00.000)',
-        );
-      });
+      await client.expectTopFrameEvalResult(
+        stop.threadId!,
+        'DateTime(2000, 1, 1)',
+        'DateTime (2000-01-01 00:00:00.000)',
+      );
+    });
 
-      test(
-          'evaluates $threadExceptionExpression to the threads exception (simple type)',
-          () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+    test(
+        'evaluates $threadExceptionExpression to the threads exception (simple type)',
+        () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   throw 'my error';
 }''');
 
-        final stop = await client.hitException(testFile);
+      final stop = await client.hitException(testFile);
 
-        final result = await client.expectTopFrameEvalResult(
-          stop.threadId!,
-          threadExceptionExpression,
-          '"my error"',
-        );
-        expect(result.variablesReference, equals(0));
-      });
+      final result = await client.expectTopFrameEvalResult(
+        stop.threadId!,
+        threadExceptionExpression,
+        '"my error"',
+      );
+      expect(result.variablesReference, equals(0));
+    });
 
-      test(
-          'evaluates $threadExceptionExpression to the threads exception (complex type)',
-          () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+    test(
+        'evaluates $threadExceptionExpression to the threads exception (complex type)',
+        () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   throw Exception('my error');
 }''');
 
-        final stop = await client.hitException(testFile);
-        final result = await client.expectTopFrameEvalResult(
-          stop.threadId!,
-          threadExceptionExpression,
-          '_Exception',
-        );
-        expect(result.variablesReference, greaterThan(0));
-      });
+      final stop = await client.hitException(testFile);
+      final result = await client.expectTopFrameEvalResult(
+        stop.threadId!,
+        threadExceptionExpression,
+        '_Exception',
+      );
+      expect(result.variablesReference, greaterThan(0));
+    });
 
-      test(
-          'evaluates $threadExceptionExpression.x.y to x.y on the threads exception',
-          () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+    test(
+        'evaluates $threadExceptionExpression.x.y to x.y on the threads exception',
+        () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   throw Exception('12345');
 }
     ''');
 
-        final stop = await client.hitException(testFile);
-        await client.expectTopFrameEvalResult(
-          stop.threadId!,
-          '$threadExceptionExpression.message.length',
-          '5',
-        );
-      });
+      final stop = await client.hitException(testFile);
+      await client.expectTopFrameEvalResult(
+        stop.threadId!,
+        '$threadExceptionExpression.message.length',
+        '5',
+      );
+    });
 
-      test('can evaluate expressions in non-top frames', () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+    test('can evaluate expressions in non-top frames', () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   var a = 999;
   foo();
@@ -138,17 +143,16 @@
 void foo() {
   var a = 111; // BREAKPOINT
 }''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
-        final stack = await client.getValidStack(stop.threadId!,
-            startFrame: 0, numFrames: 2);
-        final secondFrameId = stack.stackFrames[1].id;
+      final stop = await client.hitBreakpoint(testFile, breakpointLine);
+      final stack = await client.getValidStack(stop.threadId!,
+          startFrame: 0, numFrames: 2);
+      final secondFrameId = stack.stackFrames[1].id;
 
-        await client.expectEvalResult(secondFrameId, 'a', '999');
-      });
+      await client.expectEvalResult(secondFrameId, 'a', '999');
+    });
 
-      // These tests can be slow due to starting up the external server process.
-    }, timeout: Timeout.none);
-  });
+    // 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_logging_test.dart b/pkg/dds/test/dap/integration/debug_logging_test.dart
index 1df090c..27578f5 100644
--- a/pkg/dds/test/dap/integration/debug_logging_test.dart
+++ b/pkg/dds/test/dap/integration/debug_logging_test.dart
@@ -4,13 +4,19 @@
 
 import 'package:test/test.dart';
 
+import 'test_client.dart';
 import 'test_support.dart';
 
 main() {
-  testDap((dap) async {
-    group('debug mode', () {
-      test('prints messages from dart:developer log()', () async {
-        final testFile = dap.createTestFile(r'''
+  late DapTestSession dap;
+  setUp(() async {
+    dap = await DapTestSession.setUp();
+  });
+  tearDown(() => dap.tearDown());
+
+  group('debug mode', () {
+    test('prints messages from dart:developer log()', () async {
+      final testFile = dap.createTestFile(r'''
 import 'dart:developer';
 
 void main(List<String> args) async {
@@ -19,19 +25,45 @@
 }
     ''');
 
-        var outputEvents = await dap.client.collectOutput(file: testFile);
+      var outputEvents = await dap.client.collectOutput(file: testFile);
 
-        // Skip the first line because it's the VM Service connection info.
-        final output = outputEvents.skip(1).map((e) => e.output).join();
-        expectLines(output, [
-          '[log] this is a test',
-          '      across two lines',
-          '[foo] this is a test',
-          '',
-          'Exited.',
-        ]);
-      });
-      // These tests can be slow due to starting up the external server process.
-    }, timeout: Timeout.none);
-  });
+      // Skip the first line because it's the VM Service connection info.
+      final output = outputEvents.skip(1).map((e) => e.output).join();
+      expectLines(output, [
+        '[log] this is a test',
+        '      across two lines',
+        '[foo] this is a test',
+        '',
+        'Exited.',
+      ]);
+    });
+
+    test('prints long messages from dart:developer log()', () async {
+      // Make a long message that's more than 255 chars (where the VM truncates
+      // log strings by default).
+      final longMessage = 'this is a test' * 20;
+      final testFile = dap.createTestFile('''
+import 'dart:developer';
+
+void main(List<String> args) async {
+  log('$longMessage');
+  // Prevent us exiting before the async log messages may have completed.
+  // The test will terminate the script early once the expectations are met.
+  await Future.delayed(const Duration(seconds: 30));
+}
+    ''');
+      final expectedLogMessage = '[log] $longMessage\n';
+
+      final consoleOutputs = dap.client.outputEvents
+          .where((event) => event.category == 'console')
+          .map((event) => event.output);
+
+      await Future.wait([
+        expectLater(consoleOutputs, emitsThrough(expectedLogMessage)),
+        dap.client.start(file: testFile),
+      ]);
+      await dap.client.terminate();
+    });
+    // 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_test.dart b/pkg/dds/test/dap/integration/debug_test.dart
index 7b80af0..41863f9 100644
--- a/pkg/dds/test/dap/integration/debug_test.dart
+++ b/pkg/dds/test/dap/integration/debug_test.dart
@@ -10,10 +10,15 @@
 import 'test_support.dart';
 
 main() {
-  testDap((dap) async {
-    group('debug mode', () {
-      test('runs a simple script', () async {
-        final testFile = dap.createTestFile(r'''
+  group('debug mode', () {
+    late DapTestSession dap;
+    setUp(() async {
+      dap = await DapTestSession.setUp();
+    });
+    tearDown(() => dap.tearDown());
+
+    test('runs a simple script', () async {
+      final testFile = dap.createTestFile(r'''
 void main(List<String> args) async {
   print('Hello!');
   print('World!');
@@ -21,100 +26,99 @@
 }
     ''');
 
-        final outputEvents = await dap.client.collectOutput(
-          launch: () => dap.client.launch(
-            testFile.path,
-            args: ['one', 'two'],
-          ),
-        );
+      final outputEvents = await dap.client.collectOutput(
+        launch: () => dap.client.launch(
+          testFile.path,
+          args: ['one', 'two'],
+        ),
+      );
 
-        // Expect a "console" output event that prints the URI of the VM Service
-        // the debugger connects to.
-        final vmConnection = outputEvents.first;
-        expect(vmConnection.output,
-            startsWith('Connecting to VM Service at ws://127.0.0.1:'));
-        expect(vmConnection.category, equals('console'));
+      // Expect a "console" output event that prints the URI of the VM Service
+      // the debugger connects to.
+      final vmConnection = outputEvents.first;
+      expect(vmConnection.output,
+          startsWith('Connecting to VM Service at ws://127.0.0.1:'));
+      expect(vmConnection.category, equals('console'));
 
-        // Expect the normal applications output.
-        final output = outputEvents.skip(1).map((e) => e.output).join();
-        expectLines(output, [
-          'Hello!',
-          'World!',
-          'args: [one, two]',
-          '',
-          'Exited.',
-        ]);
-      });
+      // Expect the normal applications output.
+      final output = outputEvents.skip(1).map((e) => e.output).join();
+      expectLines(output, [
+        'Hello!',
+        'World!',
+        'args: [one, two]',
+        '',
+        'Exited.',
+      ]);
+    });
 
-      test('provides a list of threads', () async {
-        final client = dap.client;
-        final testFile = dap.createTestFile(simpleBreakpointProgram);
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+    test('provides a list of threads', () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(simpleBreakpointProgram);
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        await client.hitBreakpoint(testFile, breakpointLine);
-        final response = await client.getValidThreads();
+      await client.hitBreakpoint(testFile, breakpointLine);
+      final response = await client.getValidThreads();
 
-        expect(response.threads, hasLength(1));
-        expect(response.threads.first.name, equals('main'));
-      });
+      expect(response.threads, hasLength(1));
+      expect(response.threads.first.name, equals('main'));
+    });
 
-      test('runs with DDS', () async {
-        final client = dap.client;
-        final testFile = dap.createTestFile(simpleBreakpointProgram);
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+    test('runs with DDS by default', () async {
+      final client = dap.client;
+      final testFile = dap.createTestFile(simpleBreakpointProgram);
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        await client.hitBreakpoint(testFile, breakpointLine);
-        expect(await client.ddsAvailable, isTrue);
-      });
-      // These tests can be slow due to starting up the external server process.
-    }, timeout: Timeout.none);
+      await client.hitBreakpoint(testFile, breakpointLine);
+      expect(await client.ddsAvailable, isTrue);
+    });
 
-    test('runs with auth codes enabled', () async {
+    test('runs with auth codes enabled by default', () async {
       final testFile = dap.createTestFile(emptyProgram);
 
       final outputEvents = await dap.client.collectOutput(file: testFile);
-      expect(_hasAuthCode(outputEvents.first), isTrue);
+      final vmServiceUri = _extractVmServiceUri(outputEvents.first);
+      expect(vmServiceUri.path, matches(vmServiceAuthCodePathPattern));
     });
-  });
+    // These tests can be slow due to starting up the external server process.
+  }, timeout: Timeout.none);
 
-  testDap((dap) async {
-    group('debug mode', () {
-      test('runs without DDS', () async {
-        final client = dap.client;
-        final testFile = dap.createTestFile(simpleBreakpointProgram);
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+  group('debug mode', () {
+    test('can run without DDS', () async {
+      final dap = await DapTestSession.setUp(additionalArgs: ['--no-dds']);
+      addTearDown(dap.tearDown);
 
-        await client.hitBreakpoint(testFile, breakpointLine);
+      final client = dap.client;
+      final testFile = dap.createTestFile(simpleBreakpointProgram);
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        expect(await client.ddsAvailable, isFalse);
-      });
+      await client.hitBreakpoint(testFile, breakpointLine);
 
-      test('runs with auth tokens disabled', () async {
-        final testFile = dap.createTestFile(emptyProgram);
+      expect(await client.ddsAvailable, isFalse);
+    });
 
-        final outputEvents = await dap.client.collectOutput(file: testFile);
-        expect(_hasAuthCode(outputEvents.first), isFalse);
-      });
-      // These tests can be slow due to starting up the external server process.
-    }, timeout: Timeout.none);
-  }, additionalArgs: ['--no-dds', '--no-auth-codes']);
+    test('can run without auth codes', () async {
+      final dap =
+          await DapTestSession.setUp(additionalArgs: ['--no-auth-codes']);
+      addTearDown(dap.tearDown);
 
-  testDap((dap) async {
-    group('debug mode', () {
-      test('can run with ipv6', () async {
-        final testFile = dap.createTestFile(emptyProgram);
+      final testFile = dap.createTestFile(emptyProgram);
+      final outputEvents = await dap.client.collectOutput(file: testFile);
+      final vmServiceUri = _extractVmServiceUri(outputEvents.first);
+      expect(vmServiceUri.path, isNot(matches(vmServiceAuthCodePathPattern)));
+    });
 
-        final outputEvents = await dap.client.collectOutput(file: testFile);
-        final vmServiceUri = _extractVmServiceUri(outputEvents.first);
+    test('can run with ipv6', () async {
+      final dap = await DapTestSession.setUp(additionalArgs: ['--ipv6']);
+      addTearDown(dap.tearDown);
 
-        // Check DAP server host.
-        expect(dap.server.host, equals('::1'));
-        // Check VM Service/DDS host.
-        expect(vmServiceUri.host, equals('::1'));
-      });
-      // These tests can be slow due to starting up the external server process.
-    }, timeout: Timeout.none);
-  }, additionalArgs: ['--ipv6']);
+      final testFile = dap.createTestFile(emptyProgram);
+      final outputEvents = await dap.client.collectOutput(file: testFile);
+      final vmServiceUri = _extractVmServiceUri(outputEvents.first);
+
+      expect(vmServiceUri.host, equals('::1'));
+    });
+    // These tests can be slow due to starting up the external server process.
+  }, timeout: Timeout.none);
 }
 
 /// Extracts the VM Service URI from the "Connecting to ..." banner output by
@@ -122,15 +126,6 @@
 Uri _extractVmServiceUri(OutputEventBody vmConnectionBanner) {
   // TODO(dantup): Change this to use the dart.debuggerUris custom event
   //   if implemented (whch VS Code also needs).
-  final vmServiceUriPattern = RegExp(r'Connecting to VM Service at ([^\s]+)\s');
   final match = vmServiceUriPattern.firstMatch(vmConnectionBanner.output);
   return Uri.parse(match!.group(1)!);
 }
-
-/// Checks for the presence of an auth token in a VM Service URI in the
-/// "Connecting to VM Service" [OutputEvent].
-bool _hasAuthCode(OutputEventBody vmConnectionBanner) {
-  final vmServiceUri = _extractVmServiceUri(vmConnectionBanner);
-  final authCodePattern = RegExp(r'^/[\w=]{5,15}/ws');
-  return authCodePattern.hasMatch(vmServiceUri.path);
-}
diff --git a/pkg/dds/test/dap/integration/debug_variables_test.dart b/pkg/dds/test/dap/integration/debug_variables_test.dart
index e04e36e..b5e357c 100644
--- a/pkg/dds/test/dap/integration/debug_variables_test.dart
+++ b/pkg/dds/test/dap/integration/debug_variables_test.dart
@@ -8,11 +8,16 @@
 import 'test_support.dart';
 
 main() {
-  testDap((dap) async {
-    group('debug mode variables', () {
-      test('provides variable list for frames', () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+  late DapTestSession dap;
+  setUp(() async {
+    dap = await DapTestSession.setUp();
+  });
+  tearDown(() => dap.tearDown());
+
+  group('debug mode variables', () {
+    test('provides variable list for frames', () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   final myVariable = 1;
   foo();
@@ -23,135 +28,135 @@
   print('Hello!'); // BREAKPOINT
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
-        final stack = await client.getValidStack(
-          stop.threadId!,
-          startFrame: 0,
-          numFrames: 2,
-        );
+      final stop = await client.hitBreakpoint(testFile, breakpointLine);
+      final stack = await client.getValidStack(
+        stop.threadId!,
+        startFrame: 0,
+        numFrames: 2,
+      );
 
-        // Check top two frames (in `foo` and in `main`).
-        await client.expectScopeVariables(
-          stack.stackFrames[0].id, // Top frame: foo
-          'Variables',
-          '''
+      // Check top two frames (in `foo` and in `main`).
+      await client.expectScopeVariables(
+        stack.stackFrames[0].id, // Top frame: foo
+        'Variables',
+        '''
             b: 2
           ''',
-        );
-        await client.expectScopeVariables(
-          stack.stackFrames[1].id, // Second frame: main
-          'Variables',
-          '''
+      );
+      await client.expectScopeVariables(
+        stack.stackFrames[1].id, // Second frame: main
+        'Variables',
+        '''
             args: List (0 items)
             myVariable: 1
           ''',
-        );
-      });
+      );
+    });
 
-      test('provides simple exception types for frames', () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+    test('provides simple exception types for frames', () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   throw 'my error';
 }
     ''');
 
-        final stop = await client.hitException(testFile);
-        final stack = await client.getValidStack(
-          stop.threadId!,
-          startFrame: 0,
-          numFrames: 1,
-        );
-        final topFrameId = stack.stackFrames.first.id;
+      final stop = await client.hitException(testFile);
+      final stack = await client.getValidStack(
+        stop.threadId!,
+        startFrame: 0,
+        numFrames: 1,
+      );
+      final topFrameId = stack.stackFrames.first.id;
 
-        // Check for an additional Scope named "Exceptions" that includes the
-        // exception.
-        await client.expectScopeVariables(
-          topFrameId,
-          'Exceptions',
-          '''
+      // Check for an additional Scope named "Exceptions" that includes the
+      // exception.
+      await client.expectScopeVariables(
+        topFrameId,
+        'Exceptions',
+        '''
             String: "my error"
           ''',
-        );
-      });
+      );
+    });
 
-      test('provides complex exception types frames', () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+    test('provides complex exception types frames', () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   throw ArgumentError.notNull('args');
 }
     ''');
 
-        final stop = await client.hitException(testFile);
-        final stack = await client.getValidStack(
-          stop.threadId!,
-          startFrame: 0,
-          numFrames: 1,
-        );
-        final topFrameId = stack.stackFrames.first.id;
+      final stop = await client.hitException(testFile);
+      final stack = await client.getValidStack(
+        stop.threadId!,
+        startFrame: 0,
+        numFrames: 1,
+      );
+      final topFrameId = stack.stackFrames.first.id;
 
-        // Check for an additional Scope named "Exceptions" that includes the
-        // exception.
-        await client.expectScopeVariables(
-          topFrameId,
-          'Exceptions',
-          // TODO(dantup): evaluateNames
-          '''
+      // Check for an additional Scope named "Exceptions" that includes the
+      // exception.
+      await client.expectScopeVariables(
+        topFrameId,
+        'Exceptions',
+        // TODO(dantup): evaluateNames
+        '''
             invalidValue: null
             message: "Must not be null"
             name: "args"
           ''',
-        );
-      });
+      );
+    });
 
-      test('includes simple variable fields', () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+    test('includes simple variable fields', () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   final myVariable = DateTime(2000, 1, 1);
   print('Hello!'); // BREAKPOINT
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
-        await client.expectLocalVariable(
-          stop.threadId!,
-          expectedName: 'myVariable',
-          expectedDisplayString: 'DateTime',
-          expectedVariables: '''
+      final stop = await client.hitBreakpoint(testFile, breakpointLine);
+      await client.expectLocalVariable(
+        stop.threadId!,
+        expectedName: 'myVariable',
+        expectedDisplayString: 'DateTime',
+        expectedVariables: '''
             isUtc: false
           ''',
-        );
-      });
+      );
+    });
 
-      test('includes variable getters when evaluateGettersInDebugViews=true',
-          () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+    test('includes variable getters when evaluateGettersInDebugViews=true',
+        () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   final myVariable = DateTime(2000, 1, 1);
   print('Hello!'); // BREAKPOINT
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        final stop = await client.hitBreakpoint(
-          testFile,
-          breakpointLine,
-          launch: () => client.launch(
-            testFile.path,
-            evaluateGettersInDebugViews: true,
-          ),
-        );
-        await client.expectLocalVariable(
-          stop.threadId!,
-          expectedName: 'myVariable',
-          expectedDisplayString: 'DateTime',
-          expectedVariables: '''
+      final stop = await client.hitBreakpoint(
+        testFile,
+        breakpointLine,
+        launch: () => client.launch(
+          testFile.path,
+          evaluateGettersInDebugViews: true,
+        ),
+      );
+      await client.expectLocalVariable(
+        stop.threadId!,
+        expectedName: 'myVariable',
+        expectedDisplayString: 'DateTime',
+        expectedVariables: '''
             day: 1
             hour: 0
             isUtc: false
@@ -165,72 +170,71 @@
             weekday: 6
             year: 2000
           ''',
-          ignore: {
-            // Don't check fields that may very based on timezone as it'll make
-            // these tests fragile, and this isn't really what's being tested.
-            'timeZoneName',
-            'microsecondsSinceEpoch',
-            'millisecondsSinceEpoch',
-          },
-        );
-      });
+        ignore: {
+          // Don't check fields that may very based on timezone as it'll make
+          // these tests fragile, and this isn't really what's being tested.
+          'timeZoneName',
+          'microsecondsSinceEpoch',
+          'millisecondsSinceEpoch',
+        },
+      );
+    });
 
-      test('renders a simple list', () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+    test('renders a simple list', () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   final myVariable = ["first", "second", "third"];
   print('Hello!'); // BREAKPOINT
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
-        await client.expectLocalVariable(
-          stop.threadId!,
-          expectedName: 'myVariable',
-          expectedDisplayString: 'List (3 items)',
-          // TODO(dantup): evaluateNames
-          expectedVariables: '''
+      final stop = await client.hitBreakpoint(testFile, breakpointLine);
+      await client.expectLocalVariable(
+        stop.threadId!,
+        expectedName: 'myVariable',
+        expectedDisplayString: 'List (3 items)',
+        // TODO(dantup): evaluateNames
+        expectedVariables: '''
             0: "first"
             1: "second"
             2: "third"
           ''',
-        );
-      });
+      );
+    });
 
-      test('renders a simple list subset', () async {
-        final client = dap.client;
-        final testFile = await dap.createTestFile(r'''
+    test('renders a simple list subset', () async {
+      final client = dap.client;
+      final testFile = await dap.createTestFile(r'''
 void main(List<String> args) {
   final myVariable = ["first", "second", "third"];
   print('Hello!'); // BREAKPOINT
 }
     ''');
-        final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+      final breakpointLine = lineWith(testFile, '// BREAKPOINT');
 
-        final stop = await client.hitBreakpoint(testFile, breakpointLine);
-        await client.expectLocalVariable(
-          stop.threadId!,
-          expectedName: 'myVariable',
-          expectedDisplayString: 'List (3 items)',
-          // TODO(dantup): evaluateNames
-          expectedVariables: '''
+      final stop = await client.hitBreakpoint(testFile, breakpointLine);
+      await client.expectLocalVariable(
+        stop.threadId!,
+        expectedName: 'myVariable',
+        expectedDisplayString: 'List (3 items)',
+        // TODO(dantup): evaluateNames
+        expectedVariables: '''
             1: "second"
           ''',
-          start: 1,
-          count: 1,
-        );
-      });
+        start: 1,
+        count: 1,
+      );
+    });
 
-      test('renders a simple map', () {
-        // TODO(dantup): Implement this (inc evaluateNames)
-      }, skip: true);
+    test('renders a simple map', () {
+      // TODO(dantup): Implement this (inc evaluateNames)
+    }, skip: true);
 
-      test('renders a simple map subset', () {
-        // TODO(dantup): Implement this (inc evaluateNames)
-      }, skip: true);
-      // These tests can be slow due to starting up the external server process.
-    }, timeout: Timeout.none);
-  });
+    test('renders a simple map subset', () {
+      // TODO(dantup): Implement this (inc evaluateNames)
+    }, skip: true);
+    // These tests can be slow due to starting up the external server process.
+  }, timeout: Timeout.none);
 }
diff --git a/pkg/dds/test/dap/integration/no_debug_test.dart b/pkg/dds/test/dap/integration/no_debug_test.dart
index e9f5dd2..bb0af1d 100644
--- a/pkg/dds/test/dap/integration/no_debug_test.dart
+++ b/pkg/dds/test/dap/integration/no_debug_test.dart
@@ -4,13 +4,19 @@
 
 import 'package:test/test.dart';
 
+import 'test_client.dart';
 import 'test_support.dart';
 
 main() {
-  testDap((dap) async {
-    group('noDebug mode', () {
-      test('runs a simple script', () async {
-        final testFile = dap.createTestFile(r'''
+  late DapTestSession dap;
+  setUp(() async {
+    dap = await DapTestSession.setUp();
+  });
+  tearDown(() => dap.tearDown());
+
+  group('noDebug mode', () {
+    test('runs a simple script', () async {
+      final testFile = dap.createTestFile(r'''
 void main(List<String> args) async {
   print('Hello!');
   print('World!');
@@ -18,24 +24,23 @@
 }
     ''');
 
-        final outputEvents = await dap.client.collectOutput(
-          launch: () => dap.client.launch(
-            testFile.path,
-            noDebug: true,
-            args: ['one', 'two'],
-          ),
-        );
+      final outputEvents = await dap.client.collectOutput(
+        launch: () => dap.client.launch(
+          testFile.path,
+          noDebug: true,
+          args: ['one', 'two'],
+        ),
+      );
 
-        final output = outputEvents.map((e) => e.output).join();
-        expectLines(output, [
-          'Hello!',
-          'World!',
-          'args: [one, two]',
-          '',
-          'Exited.',
-        ]);
-      });
-      // These tests can be slow due to starting up the external server process.
-    }, timeout: Timeout.none);
-  });
+      final output = outputEvents.map((e) => e.output).join();
+      expectLines(output, [
+        'Hello!',
+        'World!',
+        'args: [one, two]',
+        '',
+        'Exited.',
+      ]);
+    });
+    // These tests can be slow due to starting up the external server process.
+  }, timeout: Timeout.none);
 }
diff --git a/pkg/dds/test/dap/integration/test_client.dart b/pkg/dds/test/dap/integration/test_client.dart
index c130e00..bfa05c6 100644
--- a/pkg/dds/test/dap/integration/test_client.dart
+++ b/pkg/dds/test/dap/integration/test_client.dart
@@ -10,7 +10,6 @@
 import 'package:dds/src/dap/logging.dart';
 import 'package:dds/src/dap/protocol_generated.dart';
 import 'package:dds/src/dap/protocol_stream.dart';
-import 'package:dds/src/dap/protocol_stream_transformers.dart';
 import 'package:test/test.dart';
 import 'package:vm_service/vm_service.dart' as vm;
 
@@ -22,19 +21,17 @@
 /// Methods on this class should map directly to protocol methods. Additional
 /// helpers are available in [DapTestClientExtension].
 class DapTestClient {
-  final Socket _socket;
   final ByteStreamServerChannel _channel;
   late final StreamSubscription<String> _subscription;
 
   final Logger? _logger;
   final bool captureVmServiceTraffic;
-  final _requestWarningDuration = const Duration(seconds: 2);
+  final _requestWarningDuration = const Duration(seconds: 5);
   final Map<int, _OutgoingRequest> _pendingRequests = {};
   final _eventController = StreamController<Event>.broadcast();
   int _seq = 1;
 
   DapTestClient._(
-    this._socket,
     this._channel,
     this._logger, {
     this.captureVmServiceTraffic = false,
@@ -57,21 +54,6 @@
   Stream<OutputEventBody> get outputEvents => events('output')
       .map((e) => OutputEventBody.fromJson(e.body as Map<String, Object?>));
 
-  /// Collects all output events until the program terminates.
-  Future<List<OutputEventBody>> collectOutput(
-      {File? file, Future<Response> Function()? launch}) async {
-    final outputEventsFuture = outputEvents.toList();
-
-    // Launch script and wait for termination.
-    await Future.wait([
-      event('terminated'),
-      initialize(),
-      launch?.call() ?? this.launch(file!.path),
-    ], eagerError: true);
-
-    return outputEventsFuture;
-  }
-
   /// Sends a continue request for the given thread.
   ///
   /// Returns a Future that completes when the server returns a corresponding
@@ -210,6 +192,19 @@
       sendRequest(StackTraceArguments(
           threadId: threadId, startFrame: startFrame, levels: numFrames));
 
+  /// Initializes the debug adapter and launches [file] or calls the custom
+  /// [launch] method.
+  Future<void> start({
+    File? file,
+    Future<Response> Function()? launch,
+  }) {
+    // Launch script and wait for termination.
+    return Future.wait([
+      initialize(),
+      launch?.call() ?? this.launch(file!.path),
+    ], eagerError: true);
+  }
+
   /// Sends a stepIn request for the given thread.
   ///
   /// Returns a Future that completes when the server returns a corresponding
@@ -226,7 +221,6 @@
 
   Future<void> stop() async {
     _channel.close();
-    await _socket.close();
     await _subscription.cancel();
   }
 
@@ -305,16 +299,12 @@
   /// Creates a [DapTestClient] that connects the server listening on
   /// [host]:[port].
   static Future<DapTestClient> connect(
-    String host,
-    int port, {
+    DapTestServer server, {
     bool captureVmServiceTraffic = false,
     Logger? logger,
   }) async {
-    final socket = await Socket.connect(host, port);
-    final channel = ByteStreamServerChannel(
-        socket.transform(Uint8ListTransformer()), socket, logger);
-
-    return DapTestClient._(socket, channel, logger,
+    final channel = ByteStreamServerChannel(server.stream, server.sink, logger);
+    return DapTestClient._(channel, logger,
         captureVmServiceTraffic: captureVmServiceTraffic);
   }
 }
@@ -441,6 +431,21 @@
     return ThreadsResponseBody.fromJson(response.body as Map<String, Object?>);
   }
 
+  /// Collects all output events until the program terminates.
+  ///
+  /// These results include all events in the order they are recieved, including
+  /// console, stdout and stderr.
+  Future<List<OutputEventBody>> collectOutput({
+    File? file,
+    Future<Response> Function()? launch,
+  }) async {
+    final outputEventsFuture = outputEvents.toList();
+
+    await start(file: file, launch: launch);
+
+    return outputEventsFuture;
+  }
+
   /// A helper that fetches scopes for a frame, checks for one with the name
   /// [expectedName] and verifies its variables.
   Future<Scope> expectScopeVariables(
diff --git a/pkg/dds/test/dap/integration/test_server.dart b/pkg/dds/test/dap/integration/test_server.dart
index c2a11f7..dc96dc7 100644
--- a/pkg/dds/test/dap/integration/test_server.dart
+++ b/pkg/dds/test/dap/integration/test_server.dart
@@ -13,10 +13,9 @@
 import 'package:pedantic/pedantic.dart';
 
 abstract class DapTestServer {
-  List<String> get errorLogs;
-  String get host;
-  int get port;
   Future<void> stop();
+  StreamSink<List<int>> get sink;
+  Stream<List<int>> get stream;
 }
 
 /// An instance of a DAP server running in-process (to aid debugging).
@@ -25,22 +24,27 @@
 /// serialized and deserialized but it's not quite the same running out of
 /// process.
 class InProcessDapTestServer extends DapTestServer {
-  final DapServer _server;
+  late final DapServer _server;
+  final stdinController = StreamController<List<int>>();
+  final stdoutController = StreamController<List<int>>();
 
-  InProcessDapTestServer._(this._server);
+  StreamSink<List<int>> get sink => stdinController.sink;
+  Stream<List<int>> get stream => stdoutController.stream;
 
-  String get host => _server.host;
-  int get port => _server.port;
-  List<String> get errorLogs => const []; // In-proc errors just throw in-line.
+  InProcessDapTestServer._() {
+    _server = DapServer(stdinController.stream, stdoutController.sink);
+  }
 
   @override
   Future<void> stop() async {
-    await _server.stop();
+    _server.stop();
   }
 
-  static Future<InProcessDapTestServer> create({Logger? logger}) async {
-    final DapServer server = await DapServer.create(logger: logger);
-    return InProcessDapTestServer._(server);
+  static Future<InProcessDapTestServer> create({
+    Logger? logger,
+    List<String>? additionalArgs,
+  }) async {
+    return InProcessDapTestServer._();
   }
 }
 
@@ -52,28 +56,22 @@
 class OutOfProcessDapTestServer extends DapTestServer {
   var _isShuttingDown = false;
   final Process _process;
-  final int port;
-  final String host;
-  final List<String> _errors = [];
 
-  List<String> get errorLogs => _errors;
+  StreamSink<List<int>> get sink => _process.stdin;
+  Stream<List<int>> get stream => _process.stdout;
 
   OutOfProcessDapTestServer._(
     this._process,
-    this.host,
-    this.port,
     Logger? logger,
   ) {
     // Treat anything written to stderr as the DAP crashing and fail the test.
     _process.stderr.transform(utf8.decoder).listen((error) {
       logger?.call(error);
-      _errors.add(error);
       throw error;
     });
     unawaited(_process.exitCode.then((code) {
       final message = 'Out-of-process DAP server terminated with code $code';
       logger?.call(message);
-      _errors.add(message);
       if (!_isShuttingDown && code != 0) {
         throw message;
       }
@@ -107,27 +105,6 @@
       ],
     );
 
-    final startedCompleter = Completer<void>();
-    late String host;
-    late int port;
-
-    // Scrape the `started` event to get the host/port. Any other output
-    // should be sent to the logger (as it may be verbose output for diagnostic
-    // purposes).
-    _process.stdout.transform(utf8.decoder).listen((text) {
-      if (!startedCompleter.isCompleted) {
-        final event = jsonDecode(text);
-        if (event['state'] == 'started') {
-          host = event['dapHost'];
-          port = event['dapPort'];
-          startedCompleter.complete();
-          return;
-        }
-      }
-      logger?.call(text);
-    });
-    await startedCompleter.future;
-
-    return OutOfProcessDapTestServer._(_process, host, port, logger);
+    return OutOfProcessDapTestServer._(_process, logger);
   }
 }
diff --git a/pkg/dds/test/dap/integration/test_support.dart b/pkg/dds/test/dap/integration/test_support.dart
index 45460b2..a44a791 100644
--- a/pkg/dds/test/dap/integration/test_support.dart
+++ b/pkg/dds/test/dap/integration/test_support.dart
@@ -12,20 +12,6 @@
 import 'test_client.dart';
 import 'test_server.dart';
 
-/// A logger to use to log all traffic (both DAP and VM) to stdout.
-///
-/// If the enviroment variable is `DAP_TEST_VERBOSE` then `print` will be used,
-/// otherwise there will be no verbose logging.
-///
-///   DAP_TEST_VERBOSE=true pub run test --chain-stack-traces test/dap/integration
-///
-///
-/// When using the out-of-process DAP, this causes `--verbose` to be passed to
-/// the server which causes it to write all traffic to `stdout` which is then
-/// picked up by [OutOfProcessDapTestServer] and passed to this logger.
-final logger =
-    Platform.environment['DAP_TEST_VERBOSE'] == 'true' ? print : null;
-
 /// Whether to run the DAP server in-process with the tests, or externally in
 /// another process.
 ///
@@ -35,6 +21,14 @@
 /// simplified in VS Code by using a launch config with custom CodeLens links).
 final useInProcessDap = Platform.environment['DAP_TEST_INTERNAL'] == 'true';
 
+/// A [RegExp] that matches the `path` part of a VM Service URI that contains
+/// an authentication token.
+final vmServiceAuthCodePathPattern = RegExp(r'^/[\w_\-=]{5,15}/ws$');
+
+/// A [RegExp] that matches the "Connecting to VM Service" banner that is sent
+/// as the first output event for a debug session.
+final vmServiceUriPattern = RegExp(r'Connecting to VM Service at ([^\s]+)\s');
+
 /// Expects [actual] to equal the lines [expected], ignoring differences in line
 /// endings.
 void expectLines(String actual, List<String> expected) {
@@ -45,33 +39,13 @@
 int lineWith(File file, String searchText) =>
     file.readAsLinesSync().indexWhere((line) => line.contains(searchText)) + 1;
 
-/// A helper function to wrap all tests in a library with setup/teardown functions
-/// to start a shared server for all tests in the library and an individual
-/// client for each test.
-testDap(
-  Future<void> Function(DapTestSession session) tests, {
-  List<String>? additionalArgs,
-}) {
-  final session = DapTestSession(additionalArgs: additionalArgs);
-
-  setUpAll(session.setUpAll);
-  tearDownAll(session.tearDownAll);
-  setUp(session.setUp);
-  tearDown(session.tearDown);
-
-  return tests(session);
-}
-
-/// A helper class provided to DAP integration tests run with [testDap] to
-/// easily share setup/teardown without sharing state across tests from different
-/// files.
+/// A helper class containing the DAP server/client for DAP integration tests.
 class DapTestSession {
-  late DapTestServer server;
-  late DapTestClient client;
+  DapTestServer server;
+  DapTestClient client;
   final _testFolders = <Directory>[];
-  final List<String>? additionalArgs;
 
-  DapTestSession({this.additionalArgs});
+  DapTestSession._(this.server, this.client);
 
   /// Creates a file in a temporary folder to be used as an application for testing.
   ///
@@ -84,60 +58,32 @@
     return testFile;
   }
 
-  Future<void> setUp() async {
-    client = await _startClient(server);
+  static Future<DapTestSession> setUp({List<String>? additionalArgs}) async {
+    final server = await _startServer(additionalArgs: additionalArgs);
+    final client = await DapTestClient.connect(server);
+    return DapTestSession._(server, client);
   }
 
-  Future<void> setUpAll() async {
-    server = await _startServer(logger: logger, additionalArgs: additionalArgs);
-  }
-
-  Future<void> tearDown() => client.stop();
-
-  Future<void> tearDownAll() async {
+  Future<void> tearDown() async {
+    await client.stop();
     await server.stop();
 
     // Clean up any temp folders created during the test runs.
-    _testFolders.forEach((dir) => dir.deleteSync(recursive: true));
-  }
-
-  /// Creates and connects a new [DapTestClient] to [server].
-  Future<DapTestClient> _startClient(DapTestServer server) async {
-    // Since we don't get a signal from the DAP server when it's ready and we
-    // just started it, add a short retry to connections.
-    // Since the bots can be quite slow, it may take 6-7 seconds for the server
-    // to initially start up (including compilation).
-    var attempt = 1;
-    while (attempt++ <= 100) {
-      try {
-        return await DapTestClient.connect(server.host, server.port);
-      } catch (e) {
-        await Future.delayed(const Duration(milliseconds: 200));
-      }
-    }
-
-    final errorMessage = StringBuffer();
-    errorMessage.writeln(
-      'Failed to connect to DAP server on port ${server.port}'
-      ' after $attempt attempts. Did the server start correctly?',
-    );
-
-    final serverErrorLogs = server.errorLogs;
-    if (serverErrorLogs.isNotEmpty) {
-      errorMessage.writeln('Server errors:');
-      errorMessage.writeAll(serverErrorLogs);
-    }
-
-    throw Exception(errorMessage.toString());
+    _testFolders
+      ..forEach((dir) => dir.deleteSync(recursive: true))
+      ..clear();
   }
 
   /// Starts a DAP server that can be shared across tests.
-  Future<DapTestServer> _startServer({
+  static Future<DapTestServer> _startServer({
     Logger? logger,
     List<String>? additionalArgs,
   }) async {
     return useInProcessDap
-        ? await InProcessDapTestServer.create(logger: logger)
+        ? await InProcessDapTestServer.create(
+            logger: logger,
+            additionalArgs: additionalArgs,
+          )
         : await OutOfProcessDapTestServer.create(
             logger: logger,
             additionalArgs: additionalArgs,
diff --git a/pkg/dds/test/handles_client_disconnect_state_error_test.dart b/pkg/dds/test/handles_client_disconnect_state_error_test.dart
index 816703b..c9d35fa 100644
--- a/pkg/dds/test/handles_client_disconnect_state_error_test.dart
+++ b/pkg/dds/test/handles_client_disconnect_state_error_test.dart
@@ -9,7 +9,6 @@
 import 'package:dds/src/rpc_error_codes.dart';
 import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 import 'package:pedantic/pedantic.dart';
-import 'package:test/fake.dart';
 import 'package:test/test.dart';
 import 'package:web_socket_channel/web_socket_channel.dart';
 
@@ -42,19 +41,6 @@
   }
 }
 
-class FakeWebSocketSink extends Fake implements WebSocketSink {
-  @override
-  Future close([int? closeCode, String? closeReason]) {
-    // Do nothing.
-    return Future.value();
-  }
-}
-
-class FakeWebSocketChannel extends Fake implements WebSocketChannel {
-  @override
-  WebSocketSink get sink => FakeWebSocketSink();
-}
-
 void main() {
   webSocketBuilder = (Uri _) => FakeWebSocketChannel();
   peerBuilder =
diff --git a/pkg/dds/test/handles_shutdown_before_startup_test.dart b/pkg/dds/test/handles_shutdown_before_startup_test.dart
new file mode 100644
index 0000000..ae1b06a
--- /dev/null
+++ b/pkg/dds/test/handles_shutdown_before_startup_test.dart
@@ -0,0 +1,54 @@
+// 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/dds.dart';
+import 'package:dds/src/dds_impl.dart';
+import 'package:test/test.dart';
+import 'package:web_socket_channel/web_socket_channel.dart';
+
+import 'common/fakes.dart';
+
+class ImmediatelyClosedPeer extends FakePeer {
+  // Immediately complete the returned future to act as if we've closed.
+  @override
+  Future<void> listen() => Future.value();
+}
+
+class ImmediatelyClosedErrorPeer extends FakePeer {
+  // Immediately complete the returned future with an error to act as if we've
+  // encountered a connection issue.
+  @override
+  Future<void> listen() => Future.error('Connection lost');
+}
+
+// Regression test for https://github.com/flutter/flutter/issues/86361.
+void main() {
+  webSocketBuilder = (Uri _) => FakeWebSocketChannel();
+
+  test('Shutdown before server startup complete', () async {
+    peerBuilder =
+        (WebSocketChannel _, dynamic __) async => ImmediatelyClosedPeer();
+    try {
+      await DartDevelopmentService.startDartDevelopmentService(
+        Uri(scheme: 'http'),
+      );
+    } on DartDevelopmentServiceException {
+      /* We expect to fail to start */
+    }
+  });
+
+  test('Error shutdown before server startup complete', () async {
+    peerBuilder =
+        (WebSocketChannel _, dynamic __) async => ImmediatelyClosedErrorPeer();
+    try {
+      await DartDevelopmentService.startDartDevelopmentService(
+        Uri(scheme: 'http'),
+      );
+    } on DartDevelopmentServiceException {
+      /* We expect to fail to start */
+    }
+  });
+}
diff --git a/pkg/dds/tool/dap/run_server.dart b/pkg/dds/tool/dap/run_server.dart
index 5fd19f2..cfddd48 100644
--- a/pkg/dds/tool/dap/run_server.dart
+++ b/pkg/dds/tool/dap/run_server.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:convert';
+import 'dart:async';
 import 'dart:io';
 
 import 'package:args/command_runner.dart';
@@ -12,7 +12,7 @@
   // TODO(dantup): "dap_tool" is a placeholder and will likely eventually be a
   // "dart" command.
   final runner = CommandRunner('dap_tool', 'Dart DAP Tool')
-    ..addCommand(DapCommand());
+    ..addCommand(DapCommand(stdin, stdout.nonBlocking));
 
   try {
     await runner.run(arguments);
@@ -23,33 +23,22 @@
 }
 
 class DapCommand extends Command {
-  static const argHost = 'host';
-  static const argPort = 'port';
   static const argIpv6 = 'ipv6';
   static const argDds = 'dds';
   static const argAuthCodes = 'auth-codes';
   static const argVerbose = 'verbose';
 
+  final Stream<List<int>> _inputStream;
+  final StreamSink<List<int>> _outputSink;
+
   @override
   final String description = 'Start a DAP debug server.';
 
   @override
   final String name = 'dap';
 
-  DapCommand() {
+  DapCommand(this._inputStream, this._outputSink) {
     argParser
-      ..addOption(
-        argHost,
-        help: 'The hostname/IP to bind the server to. If not supplied, will'
-            ' use the appropriate loopback address depending on whether'
-            ' --ipv6 is set',
-      )
-      ..addOption(
-        argPort,
-        abbr: 'p',
-        defaultsTo: '0',
-        help: 'The port to bind the server to',
-      )
       ..addFlag(
         argIpv6,
         help: 'Whether to bind DAP/VM Service/DDS to IPv6 addresses',
@@ -63,33 +52,21 @@
         argAuthCodes,
         defaultsTo: true,
         help: 'Whether to enable authentication codes for VM Services',
-      )
-      ..addFlag(
-        argVerbose,
-        abbr: 'v',
-        help: 'Whether to print diagnostic output to stdout',
       );
   }
 
   Future<void> run() async {
     final args = argResults!;
-    final port = int.parse(args[argPort]);
-    final host = args[argHost];
     final ipv6 = args[argIpv6] as bool;
 
-    final server = await DapServer.create(
-      host: host,
-      port: port,
+    final server = DapServer(
+      _inputStream,
+      _outputSink,
       ipv6: ipv6,
-      enableDdds: args[argDds],
+      enableDds: args[argDds],
       enableAuthCodes: args[argAuthCodes],
-      logger: args[argVerbose] ? print : null,
     );
 
-    stdout.write(jsonEncode({
-      'state': 'started',
-      'dapHost': server.host,
-      'dapPort': server.port,
-    }));
+    await server.channel.closed;
   }
 }
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 4d73fb2..54fd3b5 100644
--- a/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart
+++ b/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart
@@ -16,11 +16,18 @@
 /// A wrapper around asset server that redirects file read requests
 /// to http get requests to the asset server.
 class AssetFileSystem implements FileSystem {
-  FileSystem original;
+  final FileSystem original;
   final String server;
   final String port;
+  final RetryTimeoutClient client;
 
-  AssetFileSystem(this.original, this.server, this.port);
+  AssetFileSystem(this.original, this.server, this.port)
+      : client = RetryTimeoutClient(
+            HttpClient()
+              ..maxConnectionsPerHost = 200
+              ..connectionTimeout = const Duration(seconds: 30)
+              ..idleTimeout = const Duration(seconds: 30),
+            retries: 4);
 
   /// Convert the uri to a server uri.
   Uri _resourceUri(Uri uri) => Uri.parse('http://$server:$port/${uri.path}');
@@ -34,6 +41,10 @@
     // Pass the uri to the asset server in the debugger.
     return AssetFileSystemEntity(this, _resourceUri(uri));
   }
+
+  void close() {
+    client?.close(force: true);
+  }
 }
 
 class AssetFileSystemEntity implements FileSystemEntity {
@@ -85,20 +96,16 @@
     });
   }
 
-  /// Execute the [body] with the new http client.
+  /// Execute the [body] with the http client created in [fileSystem].
   ///
   /// Throws a [FileSystemException] on failure,
   /// and cleans up the client on return or error.
   Future<T> _runWithClient<T>(
       Future<T> Function(RetryTimeoutClient httpClient) body) async {
-    RetryTimeoutClient httpClient;
     try {
-      httpClient = RetryTimeoutClient(HttpClient(), retries: 4);
-      return await body(httpClient);
+      return await body(fileSystem.client);
     } on Exception catch (e, s) {
       throw FileSystemException(uri, '$e:$s');
-    } finally {
-      httpClient?.close(force: true);
     }
   }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index c0e4c51..408d757 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -18,6 +18,7 @@
 import 'package:kernel/kernel.dart';
 import 'package:kernel/target/targets.dart';
 import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
+import 'package:kernel/text/debug_printer.dart';
 import 'package:path/path.dart' as p;
 import 'package:source_maps/source_maps.dart' show SourceMapBuilder;
 
@@ -88,7 +89,7 @@
     ..addOption('packages', help: 'The package spec file to use.')
     // TODO(jmesserly): is this still useful for us, or can we remove it now?
     ..addFlag('summarize-text',
-        help: 'Emit API summary in a .js.txt file.',
+        help: 'Emit API summary and AST in .js.txt and .ast.xml files.',
         defaultsTo: false,
         hide: true)
     ..addFlag('track-widget-creation',
@@ -413,6 +414,8 @@
     var sb = StringBuffer();
     kernel.Printer(sb).writeComponentFile(component);
     outFiles.add(File(outPaths.first + '.txt').writeAsString(sb.toString()));
+    outFiles.add(File(outPaths.first.split('.')[0] + '.ast.xml')
+        .writeAsString(DebugPrinter.prettyPrint(compiledLibraries)));
   }
 
   final importToSummary = Map<Library, Component>.identity();
@@ -729,7 +732,8 @@
       : null;
 
   var debugSymbols = emitDebugSymbols
-      ? _emitSymbols(compiler, nameListener.identifierNames, component)
+      ? _emitSymbols(
+          compiler, moduleTree.name, nameListener.identifierNames, component)
       : null;
 
   return JSCode(text, builtMap, symbols: debugSymbols, metadata: debugMetadata);
@@ -741,19 +745,23 @@
 /// Uses information from the [compiler] used to compile the JS module combined
 /// with [identifierNames] that maps JavaScript identifier nodes to their actual
 /// names used when outputting the JavaScript.
-ModuleSymbols _emitSymbols(ProgramCompiler compiler,
+ModuleSymbols _emitSymbols(ProgramCompiler compiler, String moduleName,
     Map<js_ast.Identifier, String> identifierNames, Component component) {
   var classJsNames = <Class, String>{
     for (var e in compiler.classIdentifiers.entries)
       e.key: identifierNames[e.value],
   };
+  var procedureJsNames = <Procedure, String>{
+    for (var e in compiler.procedureIdentifiers.entries)
+      e.key: identifierNames[e.value],
+  };
   var variableJsNames = <VariableDeclaration, String>{
     for (var e in compiler.variableIdentifiers.entries)
       e.key: identifierNames[e.value],
   };
 
-  return ModuleSymbolsCollector(
-          classJsNames, compiler.memberNames, variableJsNames)
+  return ModuleSymbolsCollector(moduleName, classJsNames, compiler.memberNames,
+          procedureJsNames, variableJsNames)
       .collectSymbolInfo(component);
 }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index c11ced8..e777ddf 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -61,6 +61,13 @@
   /// module.
   final memberNames = <Member, String>{};
 
+  /// Maps each `Procedure` node compiled in the module to the `Identifier`s
+  /// used to name the class in JavaScript.
+  ///
+  /// This mapping is used when generating the symbol information for the
+  /// module.
+  final procedureIdentifiers = <Procedure, js_ast.Identifier>{};
+
   /// Maps each `VariableDeclaration` node compiled in the module to the name
   /// used for the variable in JavaScript.
   ///
@@ -1670,7 +1677,7 @@
       ctorFields = ctor.initializers
           .map((c) => c is FieldInitializer ? c.field : null)
           .toSet()
-            ..remove(null);
+        ..remove(null);
     }
 
     var body = <js_ast.Statement>[];
@@ -2368,8 +2375,9 @@
       Class memberClass}) {
     // Static members skip the rename steps and may require JS interop renames.
     if (isStatic) {
-      // TODO(nshahan) Record the name for this member in memberNames.
-      return _emitStaticMemberName(name, member);
+      var memberName = _emitStaticMemberName(name, member);
+      memberNames[member] = memberName.valueWithoutQuotes;
+      return memberName;
     }
 
     // We allow some (illegal in Dart) member names to be used in our private
@@ -2379,6 +2387,7 @@
       var runtimeName = _jsExportName(member);
       if (runtimeName != null) {
         var parts = runtimeName.split('.');
+        // TODO(nshahan) Record the name for this member in memberNames.
         if (parts.length < 2) return propertyName(runtimeName);
 
         js_ast.Expression result = _emitIdentifier(parts[0]);
@@ -2652,8 +2661,9 @@
     _currentUri = node.fileUri;
 
     var name = node.name.text;
+    memberNames[node] = name;
     var result = js_ast.Method(
-        propertyName(name), _emitFunction(node.function, node.name.text),
+        propertyName(name), _emitFunction(node.function, name),
         isGetter: node.isGetter, isSetter: node.isSetter)
       ..sourceInformation = _nodeEnd(node.fileEndOffset);
 
@@ -2678,8 +2688,10 @@
 
     var nameExpr = _emitTopLevelName(p);
     var jsName = _safeFunctionNameForSafari(p.name.text, fn);
-    body.add(js.statement('# = #',
-        [nameExpr, js_ast.NamedFunction(_emitTemporaryId(jsName), fn)]));
+    var functionName = _emitTemporaryId(jsName);
+    procedureIdentifiers[p] = functionName;
+    body.add(js.statement(
+        '# = #', [nameExpr, js_ast.NamedFunction(functionName, fn)]));
 
     _currentUri = savedUri;
     _staticTypeContext.leaveMember(p);
@@ -2872,27 +2884,15 @@
     js_ast.Expression typeRep;
 
     // Type parameters don't matter as JS interop types cannot be reified.
-    // We have to use lazy JS types because until we have proper module
-    // loading for JS libraries bundled with Dart libraries, we will sometimes
-    // need to load Dart libraries before the corresponding JS libraries are
-    // actually loaded.
-    // Given a JS type such as:
-    //     @JS('google.maps.Location')
-    //     class Location { ... }
-    // We can't emit a reference to MyType because the JS library that defines
-    // it may be loaded after our code. So for now, we use a special lazy type
-    // object to represent MyType.
-    // Anonymous JS types do not have a corresponding concrete JS type so we
-    // have to use a helper to define them.
-    if (isJSAnonymousType(c)) {
-      typeRep = runtimeCall(
-          'anonymousJSType(#)', [js.escapedString(getLocalClassName(c))]);
-    } else {
-      var jsName = _emitJsNameWithoutGlobal(c);
-      if (jsName != null) {
-        typeRep = runtimeCall('lazyJSType(() => #, #)',
-            [_emitJSInteropForGlobal(jsName), js.escapedString(jsName)]);
-      }
+    // package:js types fall under either named or anonymous types. Named types
+    // are used to correspond to JS types that exist, but we do not use the
+    // underlying type for type checks, so they operate virtually the same as
+    // anonymous types. We represent package:js types with a corresponding type
+    // object.
+    var jsName = isJSAnonymousType(c) ?
+        getLocalClassName(c) : _emitJsNameWithoutGlobal(c);
+    if (jsName != null) {
+      typeRep = runtimeCall('packageJSType(#)', [js.escapedString(jsName)]);
     }
 
     if (typeRep != null) {
@@ -3605,7 +3605,7 @@
     }
 
     for (var p in f.positionalParameters) {
-      var jsParam = _emitVariableDef(p);
+      var jsParam = _emitVariableRef(p);
       if (_checkParameters) {
         initParameter(p, jsParam);
       }
@@ -4510,13 +4510,9 @@
     var name = v.name;
     if (name == null || name.startsWith('#')) {
       name = name == null ? 't${_tempVariables.length}' : name.substring(1);
-      // TODO(nshahan) Record the Identifier for this variable in
-      // variableIdentifiers.
       return _tempVariables.putIfAbsent(v, () => _emitTemporaryId(name));
     }
-    var identifier = _emitIdentifier(name);
-    variableIdentifiers[v] = identifier;
-    return identifier;
+    return _emitIdentifier(name);
   }
 
   /// Emits the declaration of a variable.
@@ -4524,7 +4520,9 @@
   /// This is similar to [_emitVariableRef] but it also attaches source
   /// location information, so hover will work as expected.
   js_ast.Identifier _emitVariableDef(VariableDeclaration v) {
-    return _emitVariableRef(v)..sourceInformation = _nodeStart(v);
+    var identifier = _emitVariableRef(v)..sourceInformation = _nodeStart(v);
+    variableIdentifiers[v] = identifier;
+    return identifier;
   }
 
   js_ast.Statement _initLetVariables() {
@@ -4563,12 +4561,6 @@
   }
 
   @override
-  js_ast.Expression visitPropertyGet(PropertyGet node) {
-    return _emitPropertyGet(
-        node.receiver, node.interfaceTarget, node.name.text);
-  }
-
-  @override
   js_ast.Expression visitDynamicSet(DynamicSet node) {
     return _emitPropertySet(node.receiver, null, node.value, node.name.text);
   }
@@ -4579,12 +4571,6 @@
         node.receiver, node.interfaceTarget, node.value, node.name.text);
   }
 
-  @override
-  js_ast.Expression visitPropertySet(PropertySet node) {
-    return _emitPropertySet(
-        node.receiver, node.interfaceTarget, node.value, node.name.text);
-  }
-
   js_ast.Expression _emitPropertyGet(Expression receiver, Member member,
       [String memberName]) {
     memberName ??= member.name.text;
@@ -4759,12 +4745,6 @@
         negated: false);
   }
 
-  @override
-  js_ast.Expression visitMethodInvocation(MethodInvocation node) {
-    return _emitMethodCall(
-        node.receiver, node.interfaceTarget, node.arguments, node);
-  }
-
   js_ast.Expression _emitMethodCall(Expression receiver, Member target,
       Arguments arguments, InvocationExpression node) {
     var name = node.name.text;
@@ -5749,11 +5729,7 @@
   @override
   js_ast.Expression visitNot(Not node) {
     var operand = node.operand;
-    if (operand is MethodInvocation && operand.name.text == '==') {
-      return _emitEqualityOperator(operand.receiver, operand.interfaceTarget,
-          operand.arguments.positional[0],
-          negated: true);
-    } else if (operand is EqualsCall) {
+    if (operand is EqualsCall) {
       return _emitEqualityOperator(
           operand.left, operand.interfaceTarget, operand.right,
           negated: true);
@@ -5853,6 +5829,12 @@
   }
 
   @override
+  js_ast.Expression visitRedirectingFactoryTearOff(
+      RedirectingFactoryTearOff node) {
+    throw UnsupportedError('RedirectingFactory tear off');
+  }
+
+  @override
   js_ast.Expression visitTypedefTearOff(TypedefTearOff node) {
     throw UnsupportedError('Typedef instantiation');
   }
@@ -6241,13 +6223,13 @@
   js_ast.Expression visitConstant(Constant node) {
     if (node is StaticTearOffConstant) {
       // JS() or external JS consts should not be lazily loaded.
-      var isSdk = node.procedure.enclosingLibrary.importUri.scheme == 'dart';
+      var isSdk = node.target.enclosingLibrary.importUri.scheme == 'dart';
       if (_isInForeignJS) {
-        return _emitStaticTarget(node.procedure);
+        return _emitStaticTarget(node.target);
       }
-      if (node.procedure.isExternal && !isSdk) {
+      if (node.target.isExternal && !isSdk) {
         return runtimeCall(
-            'tearoffInterop(#)', [_emitStaticTarget(node.procedure)]);
+            'tearoffInterop(#)', [_emitStaticTarget(node.target)]);
       }
     }
     if (node is TypeLiteralConstant) {
@@ -6419,15 +6401,16 @@
       Library library, String className, Member member,
       [js_ast.TemporaryId id]) {
     var name = '$className.${member.name.text}';
-    // Names used in the symbols for the public fields
-    // memberNames[member] = 'Symbol($name)';
+    // Wrap the name as a symbol here so it matches what you would find at
+    // runtime when you get all properties and symbols from an instance.
+    memberNames[member] = 'Symbol($name)';
     return emitPrivateNameSymbol(library, name, id);
   }
 
   @override
   js_ast.Expression visitStaticTearOffConstant(StaticTearOffConstant node) {
-    _declareBeforeUse(node.procedure.enclosingClass);
-    return _emitStaticGet(node.procedure);
+    _declareBeforeUse(node.target.enclosingClass);
+    return _emitStaticGet(node.target);
   }
 
   @override
diff --git a/pkg/dev_compiler/lib/src/kernel/constants.dart b/pkg/dev_compiler/lib/src/kernel/constants.dart
index d5b538f..87df7e3 100644
--- a/pkg/dev_compiler/lib/src/kernel/constants.dart
+++ b/pkg/dev_compiler/lib/src/kernel/constants.dart
@@ -2,8 +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.
 
-// @dart = 2.9
-
+import 'package:collection/collection.dart';
 import 'package:kernel/kernel.dart';
 import 'package:kernel/target/targets.dart';
 
@@ -21,7 +20,7 @@
   /// failed, or if the constant was unavailable.
   ///
   /// Returns [NullConstant] to represent the `null` value.
-  Constant evaluate(Expression e) {
+  Constant? evaluate(Expression e) {
     return e is ConstantExpression ? e.constant : null;
   }
 
@@ -43,13 +42,12 @@
   ///     main() { ... }
   ///
   /// Given the node for `@MyAnnotation('FooBar')` this will return `'FooBar'`.
-  Object getFieldValueFromAnnotation(Expression node, String name) {
+  Object? getFieldValueFromAnnotation(Expression node, String name) {
     if (node is ConstantExpression) {
       var constant = node.constant;
       if (constant is InstanceConstant) {
         var value = constant.fieldValues.entries
-            .firstWhere((e) => e.key.asField.name.text == name,
-                orElse: () => null)
+            .firstWhereOrNull((e) => e.key.asField.name.text == name)
             ?.value;
         if (value is PrimitiveConstant) return value.value;
         if (value is UnevaluatedConstant) {
@@ -64,11 +62,10 @@
     //
     // We may need to address this in the kernel outline files.
     if (node is ConstructorInvocation) {
-      Expression first;
+      Expression? first;
       var named = node.arguments.named;
       if (named.isNotEmpty) {
-        first =
-            named.firstWhere((n) => n.name == name, orElse: () => null)?.value;
+        first = named.firstWhereOrNull((n) => n.name == name)?.value;
       }
       var positional = node.arguments.positional;
       if (positional.isNotEmpty) first ??= positional[0];
@@ -79,7 +76,7 @@
     return null;
   }
 
-  Object _evaluateAnnotationArgument(Expression node) {
+  Object? _evaluateAnnotationArgument(Expression node) {
     if (node is ConstantExpression) {
       var constant = node.constant;
       if (constant is PrimitiveConstant) return constant.value;
@@ -87,7 +84,7 @@
     if (node is StaticGet) {
       var target = node.target;
       if (target is Field) {
-        return _evaluateAnnotationArgument(target.initializer);
+        return _evaluateAnnotationArgument(target.initializer!);
       }
     }
     return node is BasicLiteral ? node.value : null;
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
index 7ac69c9..23cc5bb 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
@@ -28,7 +28,7 @@
         Member,
         Node,
         Procedure,
-        RedirectingFactoryConstructor,
+        RedirectingFactory,
         TreeNode,
         TypeParameter,
         VariableDeclaration,
@@ -253,7 +253,7 @@
     if (node is Constructor) return node.fileEndOffset;
     if (node is Procedure) return node.fileEndOffset;
     if (node is Field) return node.fileEndOffset;
-    if (node is RedirectingFactoryConstructor) return node.fileEndOffset;
+    if (node is RedirectingFactory) return node.fileEndOffset;
     if (node is FunctionNode) return node.fileEndOffset;
     return noOffset;
   }
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 1cdbd66..86a0cc2 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
@@ -113,24 +113,30 @@
   /// receive port corresponding to [sendPort].
   static Future<void> createAndStart(List<String> args,
       {SendPort sendPort}) async {
+    ExpressionCompilerWorker worker;
     if (sendPort != null) {
       var receivePort = ReceivePort();
       sendPort.send(receivePort.sendPort);
       try {
-        var worker = await createFromArgs(args,
+        worker = await createFromArgs(args,
             requestStream: receivePort.cast<Map<String, dynamic>>(),
             sendResponse: sendPort.send);
-        await worker.start();
+        await worker.run();
       } catch (e, s) {
         sendPort
             .send({'exception': '$e', 'stackTrace': '$s', 'succeeded': false});
         rethrow;
       } finally {
         receivePort.close();
+        worker?.close();
       }
     } else {
-      var worker = await createFromArgs(args);
-      await worker.start();
+      try {
+        worker = await createFromArgs(args);
+        await worker.run();
+      } finally {
+        worker?.close();
+      }
     }
   }
 
@@ -243,7 +249,7 @@
   ///
   /// Completes when the [requestStream] closes and we finish handling the
   /// requests.
-  Future<void> start() async {
+  Future<void> run() async {
     await for (var request in requestStream) {
       try {
         var command = request['command'] as String;
@@ -275,6 +281,11 @@
     _processedOptions.ticker.logMs('Stopped expression compiler worker.');
   }
 
+  void close() {
+    var fileSystem = _processedOptions?.fileSystem;
+    if (fileSystem != null && fileSystem is AssetFileSystem) fileSystem.close();
+  }
+
   /// Handles a `CompileExpression` request.
   Future<Map<String, dynamic>> _compileExpression(
       CompileExpressionRequest request) async {
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index 0c4e313..166080a 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -2,19 +2,18 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:collection';
+import 'package:collection/collection.dart';
 import 'package:front_end/src/api_unstable/ddc.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/kernel.dart';
 
-Constructor unnamedConstructor(Class c) =>
-    c.constructors.firstWhere((c) => c.name.text == '', orElse: () => null);
+Constructor? unnamedConstructor(Class c) =>
+    c.constructors.firstWhereOrNull((c) => c.name.text == '');
 
 /// Returns the enclosing library for reference [node].
-Library getLibrary(NamedNode node) {
-  for (TreeNode n = node; n != null; n = n.parent) {
+Library? getLibrary(NamedNode node) {
+  for (TreeNode? n = node; n != null; n = n.parent) {
     if (n is Library) return n;
   }
   return null;
@@ -22,14 +21,14 @@
 
 final Pattern _syntheticTypeCharacters = RegExp('[&^#.|]');
 
-String escapeIdentifier(String identifier) {
+String? escapeIdentifier(String? identifier) {
   // Remove the special characters used to encode mixin application class names
   // and extension method / parameter names which are legal in Kernel, but not
   // in JavaScript.
   //
   // Note, there is an implicit assumption here that we won't have
   // collisions since everything is mapped to \$.  That may work out fine given
-  // how these are sythesized, but may need to revisit.
+  // how these are synthesized, but may need to revisit.
   return identifier?.replaceAll(_syntheticTypeCharacters, r'$');
 }
 
@@ -40,15 +39,15 @@
 ///
 /// In the current encoding, generic classes are generated in a function scope
 /// which avoids name clashes of the escaped class name.
-String getLocalClassName(Class node) => escapeIdentifier(node.name);
+String getLocalClassName(Class node) => escapeIdentifier(node.name)!;
 
 /// Returns the escaped name for the type parameter [node].
 ///
 /// In the current encoding, generic classes are generated in a function scope
 /// which avoids name clashes of the escaped parameter name.
-String getTypeParameterName(TypeParameter node) => escapeIdentifier(node.name);
+String? getTypeParameterName(TypeParameter node) => escapeIdentifier(node.name);
 
-String getTopLevelName(NamedNode n) {
+String? getTopLevelName(NamedNode n) {
   if (n is Procedure) return n.name.text;
   if (n is Class) return n.name;
   if (n is Typedef) return n.name;
@@ -69,7 +68,7 @@
 ///
 ///    (v) => v.type.name == 'Deprecated' && v.type.element.library.isDartCore
 ///
-Expression findAnnotation(TreeNode node, bool Function(Expression) test) {
+Expression? findAnnotation(TreeNode node, bool Function(Expression) test) {
   List<Expression> annotations;
   if (node is Class) {
     annotations = node.annotations;
@@ -84,7 +83,7 @@
   } else {
     return null;
   }
-  return annotations.firstWhere(test, orElse: () => null);
+  return annotations.firstWhereOrNull(test);
 }
 
 /// Returns true if [value] represents an annotation for class [className] in
@@ -108,7 +107,7 @@
 ///
 /// This function works regardless of whether the CFE is evaluating constants,
 /// or whether the constant is a field reference (such as "anonymous" above).
-Class getAnnotationClass(Expression node) {
+Class? getAnnotationClass(Expression node) {
   if (node is ConstantExpression) {
     var constant = node.constant;
     if (constant is InstanceConstant) return constant.classNode;
@@ -165,9 +164,9 @@
 /// A mixin alias class is a mixin application, that can also be itself used as
 /// a mixin.
 bool isMixinAliasClass(Class c) =>
-    c.isMixinApplication && c.superclass.superclass == null;
+    c.isMixinApplication && c.superclass!.superclass == null;
 
-List<Class> getSuperclasses(Class c) {
+List<Class> getSuperclasses(Class? c) {
   var result = <Class>[];
   var visited = HashSet<Class>();
   while (c != null && visited.add(c)) {
@@ -191,10 +190,8 @@
   return result;
 }
 
-Expression getInvocationReceiver(InvocationExpression node) {
-  if (node is MethodInvocation) {
-    return node.receiver;
-  } else if (node is InstanceInvocation) {
+Expression? getInvocationReceiver(InvocationExpression node) {
+  if (node is InstanceInvocation) {
     return node.receiver;
   } else if (node is DynamicInvocation) {
     return node.receiver;
@@ -251,7 +248,7 @@
 
 /// Returns the redirecting factory constructors for the enclosing class,
 /// if the field [f] is storing that information, otherwise returns `null`.
-Iterable<Member> getRedirectingFactories(Field f) {
+Iterable<Member>? getRedirectingFactories(Field f) {
   // TODO(jmesserly): this relies on implementation details in Kernel
   if (isRedirectingFactoryField(f)) {
     assert(f.isStatic);
@@ -269,14 +266,15 @@
 // TODO(jmesserly): consider replacing this with Kernel's mixin unrolling
 Class getSuperclassAndMixins(Class c, List<Class> mixins) {
   assert(mixins.isEmpty);
+  assert(c.superclass != null);
 
   var mixedInClass = c.mixedInClass;
   if (mixedInClass != null) mixins.add(mixedInClass);
 
-  var sc = c.superclass;
-  for (; sc.isAnonymousMixin; sc = sc.superclass) {
+  var sc = c.superclass!;
+  for (; sc.isAnonymousMixin; sc = sc.superclass!) {
     mixedInClass = sc.mixedInClass;
-    if (mixedInClass != null) mixins.add(sc.mixedInClass);
+    if (mixedInClass != null) mixins.add(sc.mixedInClass!);
   }
   return sc;
 }
@@ -291,7 +289,7 @@
 class LabelContinueFinder extends StatementVisitor<void> {
   var found = false;
 
-  void visit(Statement s) {
+  void visit(Statement? s) {
     if (!found && s != null) s.accept(this);
   }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
index 253facf..acb2bcd 100644
--- a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
+++ b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
@@ -15,23 +15,24 @@
   /// last element in the list represents the current scope.
   final _scopes = <ScopeSymbol>[];
 
-  final _moduleSymbols = ModuleSymbols(
-      // TODO(nshahan) version
-      // TODO(nshahan) moduleName
-      libraries: <LibrarySymbol>[],
-      scripts: <Script>[],
-      classes: <ClassSymbol>[],
-      // TODO(nshahan) functionTypes
-      // TODO(nshahan) functions
-      // TODO(nshahan) scopes
-      variables: <VariableSymbol>[]);
-
+  final ModuleSymbols _moduleSymbols;
   final Map<Class, String> _classJsNames;
   final Map<Member, String> _memberJsNames;
+  final Map<Procedure, String> _procedureJsNames;
   final Map<VariableDeclaration, String> _variableJsNames;
 
-  ModuleSymbolsCollector(
-      this._classJsNames, this._memberJsNames, this._variableJsNames);
+  ModuleSymbolsCollector(String moduleName, this._classJsNames,
+      this._memberJsNames, this._procedureJsNames, this._variableJsNames)
+      : _moduleSymbols = ModuleSymbols(
+            version: ModuleSymbols.current.version,
+            moduleName: moduleName,
+            libraries: <LibrarySymbol>[],
+            scripts: <Script>[],
+            classes: <ClassSymbol>[],
+            // TODO(nshahan) functionTypes
+            functions: <FunctionSymbol>[],
+            // TODO(nshahan) scopes
+            variables: <VariableSymbol>[]);
 
   ModuleSymbols collectSymbolInfo(Component node) {
     node.accept(this);
@@ -143,8 +144,27 @@
     // Legacy libraries contain procedures with no bodies for all Object methods
     // in every class. We can ignore these unless they actually contain a body.
     if (node.function.body == null) return;
-    // TODO(nshahan) implement visitProcedure
-    super.visitProcedure(node);
+    var functionSymbol = FunctionSymbol(
+        name: node.name.text,
+        // TODO(nshahan) typeId - probably should canonicalize but keep original
+        // type argument names.
+        isStatic: node.isStatic,
+        isConst: node.isConst,
+        localId: _memberJsNames[node] ?? _procedureJsNames[node],
+        scopeId: _scopes.last.id,
+        variableIds: <String>[],
+        scopeIds: <String>[],
+        location: SourceLocation(
+            scriptId: _scriptId(node.location.file),
+            tokenPos: node.fileOffset,
+            endTokenPos: node.fileEndOffset));
+
+    _scopes.add(functionSymbol);
+    node.visitChildren(this);
+    _scopes
+      ..removeLast()
+      ..last.scopeIds.add(functionSymbol.id);
+    _moduleSymbols.functions.add(functionSymbol);
   }
 
   @override
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index 07fa7d4..71aaed2 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -91,10 +91,6 @@
   bool visitVariableSet(VariableSet node) => isNullable(node.value);
 
   @override
-  bool visitPropertyGet(PropertyGet node) =>
-      _getterIsNullable(node.interfaceTarget, node);
-
-  @override
   bool visitInstanceGet(InstanceGet node) =>
       _getterIsNullable(node.interfaceTarget, node);
 
@@ -110,9 +106,6 @@
       _getterIsNullable(null, node);
 
   @override
-  bool visitPropertySet(PropertySet node) => isNullable(node.value);
-
-  @override
   bool visitInstanceSet(InstanceSet node) => isNullable(node.value);
 
   @override
@@ -136,10 +129,6 @@
   bool visitStaticSet(StaticSet node) => isNullable(node.value);
 
   @override
-  bool visitMethodInvocation(MethodInvocation node) => _invocationIsNullable(
-      node.interfaceTarget, node.name.text, node, node.receiver);
-
-  @override
   bool visitInstanceInvocation(InstanceInvocation node) =>
       _invocationIsNullable(
           node.interfaceTarget, node.name.text, node, node.receiver);
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 36a768e..dfaa3d9 100644
--- a/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart
+++ b/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart
@@ -99,7 +99,8 @@
   void close({bool force = false}) => _inner.close(force: force);
 }
 
-bool _defaultWhen(HttpClientResponse response) => response.statusCode == 503;
+bool _defaultWhen(HttpClientResponse response) =>
+    response.statusCode == 500 || response.statusCode == 503;
 
 bool _defaultWhenError(Object error, StackTrace stackTrace) =>
     error is OSError ||
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index b6020ee..1beb7d8 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.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:collection';
 
 import 'package:_fe_analyzer_shared/src/messages/codes.dart'
@@ -28,9 +26,9 @@
   @override
   final TargetFlags flags;
 
-  WidgetCreatorTracker _widgetTracker;
+  WidgetCreatorTracker? _widgetTracker;
 
-  Map<String, Class> _nativeClasses;
+  Map<String, Class>? _nativeClasses;
 
   @override
   bool get enableSuperMixins => true;
@@ -50,9 +48,6 @@
   bool get supportsExplicitGetterCalls => false;
 
   @override
-  bool get supportsNewMethodInvocationEncoding => true;
-
-  @override
   int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.none;
 
   @override
@@ -156,11 +151,11 @@
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       List<Library> libraries,
-      Map<String, String> environmentDefines,
+      Map<String, String>? environmentDefines,
       DiagnosticReporter diagnosticReporter,
-      ReferenceFromIndex referenceFromIndex,
-      {void Function(String msg) logger,
-      ChangedStructureNotifier changedStructureNotifier}) {
+      ReferenceFromIndex? referenceFromIndex,
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
     _nativeClasses ??= JsInteropChecks.getNativeClasses(component);
     var jsUtilOptimizer = JsUtilOptimizer(coreTypes, hierarchy);
     for (var library in libraries) {
@@ -169,7 +164,7 @@
       JsInteropChecks(
               coreTypes,
               diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
-              _nativeClasses)
+              _nativeClasses!)
           .visitLibrary(library);
     }
   }
@@ -180,11 +175,11 @@
       CoreTypes coreTypes,
       List<Library> libraries,
       DiagnosticReporter diagnosticReporter,
-      {void Function(String msg) logger,
-      ChangedStructureNotifier changedStructureNotifier}) {
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
     if (flags.trackWidgetCreation) {
       _widgetTracker ??= WidgetCreatorTracker();
-      _widgetTracker.transform(component, libraries, changedStructureNotifier);
+      _widgetTracker!.transform(component, libraries, changedStructureNotifier);
     }
   }
 
@@ -352,7 +347,7 @@
   /// If the member needs a check it will be stored in [_checkedMembers].
   ///
   /// See [transform] for more information.
-  void _checkTarget(Expression receiver, Member target) {
+  void _checkTarget(Expression receiver, Member? target) {
     if (target != null &&
         target.name.isPrivate &&
         target.isInstanceMember &&
@@ -370,7 +365,7 @@
   /// escape, and it also has a different runtime type.
   ///
   /// See [transform] for more information.
-  void _checkTearoff(Member target) {
+  void _checkTearoff(Member? target) {
     if (target != null &&
         target.name.isPrivate &&
         target.isInstanceMember &&
@@ -411,36 +406,18 @@
   }
 
   @override
-  void visitPropertyGet(PropertyGet node) {
-    _checkTearoff(node.interfaceTarget);
-    super.visitPropertyGet(node);
-  }
-
-  @override
   void visitInstanceGet(InstanceGet node) {
     _checkTearoff(node.interfaceTarget);
     super.visitInstanceGet(node);
   }
 
   @override
-  void visitPropertySet(PropertySet node) {
-    _checkTarget(node.receiver, node.interfaceTarget);
-    super.visitPropertySet(node);
-  }
-
-  @override
   void visitInstanceSet(InstanceSet node) {
     _checkTarget(node.receiver, node.interfaceTarget);
     super.visitInstanceSet(node);
   }
 
   @override
-  void visitMethodInvocation(MethodInvocation node) {
-    _checkTarget(node.receiver, node.interfaceTarget);
-    super.visitMethodInvocation(node);
-  }
-
-  @override
   void visitInstanceInvocation(InstanceInvocation node) {
     _checkTarget(node.receiver, node.interfaceTarget);
     super.visitInstanceInvocation(node);
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index 89ca585..e0271f3 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -3,7 +3,7 @@
 publish_to: none
 
 environment:
-  sdk: '>=2.3.0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
   _fe_analyzer_shared:
@@ -16,6 +16,7 @@
   build_integration:
     path: ../build_integration
   cli_util: any
+  collection: ^1.15.0
   front_end:
     path: ../front_end
   kernel:
@@ -28,7 +29,7 @@
   source_span: any
 
 dev_dependencies:
-  browser_launcher: ^0.1.9
+  browser_launcher: ^1.0.0
   expect:
     path: ../expect
   http_multi_server:
@@ -48,5 +49,5 @@
     path: ../testing
   vm:
     path: ../vm
-  webkit_inspection_protocol: ^0.7.4
+  webkit_inspection_protocol: ^1.0.0
 
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 a11668a..ca481dc 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
@@ -66,6 +66,35 @@
   return Response.internalServerError();
 }
 
+int _attempts = 0;
+FutureOr<Response> unreliableHandler(Request request) {
+  final uri = request.requestedUri;
+  final headers = {
+    'content-length': '${utf8.encode(_smallFileContents).length}',
+    ...request.headers,
+  };
+
+  if ((_attempts++) % 5 == 0) return Response.internalServerError();
+
+  if (request.method == 'HEAD') {
+    // 'exists'
+    return uri.pathSegments.last == _existingFile
+        ? Response.ok(null, headers: headers)
+        : Response.notFound(uri.toString());
+  }
+  if (request.method == 'GET') {
+    // 'readAsBytes'
+    return uri.pathSegments.last == _existingFile
+        ? Response.ok(_smallFileContents, headers: headers)
+        : Response.notFound(uri.toString());
+  }
+  return Response.internalServerError();
+}
+
+FutureOr<Response> alwaysFailingHandler(Request request) {
+  return Response.internalServerError();
+}
+
 void main() async {
   HttpServer server;
   AssetFileSystem fileSystem;
@@ -83,6 +112,7 @@
 
     tearDownAll(() async {
       await expectLater(server.close(), completes);
+      fileSystem.close();
     });
 
     test('can tell if file exists', () async {
@@ -119,12 +149,10 @@
     test('can read a lot of files concurrently', () async {
       var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
       var futures = [
-        for (var i = 0; i < 512; i++) entity.readAsBytes(),
+        for (var i = 0; i < 512; i++)
+          _expectContents(entity, _smallFileContents),
       ];
-      var results = await Future.wait(futures);
-      for (var result in results) {
-        expect(utf8.decode(result), _smallFileContents);
-      }
+      await Future.wait(futures);
     }, timeout: const Timeout.factor(2));
   });
 
@@ -142,6 +170,7 @@
 
     tearDownAll(() async {
       await expectLater(server.close(), completes);
+      fileSystem.close();
     });
 
     test('can tell if file exists', () async {
@@ -196,15 +225,124 @@
     });
 
     test('can read a lot of files concurrently', () async {
+      var fileContents = _largeFileContents();
       var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
       var futures = [
-        for (var i = 0; i < 512; i++) entity.readAsBytes(),
+        for (var i = 0; i < 512; i++) _expectContents(entity, fileContents),
       ];
-      var results = await Future.wait(futures);
-      var fileContents = _largeFileContents();
-      for (var result in results) {
-        expect(utf8.decode(result), fileContents);
-      }
+      await Future.wait(futures);
     }, timeout: const Timeout.factor(2));
   });
+
+  group('AssetFileSystem with an unreliable server', () {
+    setUpAll(() async {
+      var hostname = 'localhost';
+      var port = await findUnusedPort();
+
+      server = await HttpMultiServer.bind(hostname, port);
+      fileSystem =
+          AssetFileSystem(StandardFileSystem.instance, hostname, '$port');
+
+      serveRequests(server, unreliableHandler);
+    });
+
+    tearDownAll(() async {
+      await expectLater(server.close(), completes);
+      fileSystem.close();
+    });
+
+    test('can tell if file exists', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+      expect(await entity.exists(), true);
+    });
+
+    test('can tell if file does not exist', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
+      expect(await entity.exists(), false);
+    });
+
+    test('can read existing file using readAsBytes', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+      expect(await entity.readAsBytes(), _smallFileBytes);
+    });
+
+    test('can read and decode existing file using readAsBytes', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+      expect(utf8.decode(await entity.readAsBytes()), _smallFileContents);
+    });
+
+    test('can read existing file using readAsString', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+      expect(await entity.readAsString(), _smallFileContents);
+    });
+
+    test('cannot read non-existing file', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
+      await expectLater(
+          entity.readAsBytes(), throwsA(isA<FileSystemException>()));
+    });
+
+    test('can read a lot of files concurrently', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+      var futures = [
+        for (var i = 0; i < 512; i++)
+          _expectContents(entity, _smallFileContents),
+      ];
+      await Future.wait(futures);
+    }, timeout: const Timeout.factor(2));
+  });
+
+  group('AssetFileSystem with failing server', () {
+    setUpAll(() async {
+      var hostname = 'localhost';
+      var port = await findUnusedPort();
+
+      server = await HttpMultiServer.bind(hostname, port);
+      fileSystem =
+          AssetFileSystem(StandardFileSystem.instance, hostname, '$port');
+
+      serveRequests(server, alwaysFailingHandler);
+    });
+
+    tearDownAll(() async {
+      await expectLater(server.close(), completes);
+      fileSystem.close();
+    });
+
+    test('cannot tell if file exists', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+      expect(await entity.exists(), false);
+    });
+
+    test('cannot tell if file does not exist', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
+      expect(await entity.exists(), false);
+    });
+
+    test('cannot read existing file using readAsBytes', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+      await expectLater(
+          entity.readAsBytes(), throwsA(isA<FileSystemException>()));
+    });
+
+    test('cannot read existing file using readAsString', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+      await expectLater(
+          entity.readAsString(), throwsA(isA<FileSystemException>()));
+    });
+
+    test('cannot read non-existing file', () async {
+      var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
+      await expectLater(
+          entity.readAsBytes(), throwsA(isA<FileSystemException>()));
+    });
+  });
+}
+
+// Read the response (and free the socket) as soon as we get it.
+// That allows some connection to buffer and wait for free sockets
+// when the limit if connections is reached.
+Future<void> _expectContents(FileSystemEntity entity, String contents) async {
+  var result = await entity.readAsString();
+  expect(result, contents);
 }
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
index 1e1f94d..40f3f36 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
@@ -420,7 +420,7 @@
       await driver.check(
           breakpointId: 'globalFunctionBP',
           expression: 'C._staticField',
-          expectedError: "Error: Getter not found: '_staticField'.");
+          expectedResult: '2');
     });
 
     test('access field', () async {
@@ -476,7 +476,7 @@
       await driver.check(
           breakpointId: 'globalFunctionBP',
           expression: 'C._staticField = 2',
-          expectedError: "Setter not found: '_staticField'.");
+          expectedResult: '2');
     });
 
     test('static field modification', () async {
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
index 9a06c77..c54916b 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
@@ -836,13 +836,14 @@
       soundNullSafety: soundNullSafety,
       verbose: verbose,
     );
-    workerDone = worker.start();
+    workerDone = worker.run();
   }
 
   Future<void> tearDown() async {
     unawaited(requestController.close());
     await workerDone;
     unawaited(responseController.close());
+    worker?.close();
   }
 }
 
diff --git a/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart b/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart
index ee907ce..c08995f 100644
--- a/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart
+++ b/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart
@@ -293,6 +293,394 @@
           expect(fieldSymbol.isStatic, isFalse);
         });
       });
+      group('class public instance method debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            String publicInstanceMethod() => 'Cello';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicInstanceMethod'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class private instance method debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            String _privateInstanceMethod() => 'Cello';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|Symbol(_privateInstanceMethod)'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class public static method debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            static String publicStaticMethod() => 'Cello';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicStaticMethod'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
+      group('class private static method debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            static String _privateStaticMethod() => 'Fosse';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|_privateStaticMethod'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
+      group('class public instance getter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            String get publicGetter() => 'Fosse';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicGetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class private instance getter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            String get _privateGetter() => 'Fosse';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|Symbol(_privateGetter)'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class public instance setter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            var _value
+            set publicSetter(String v) => _value = v;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicSetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class private instance setter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            var _value
+            set _privateSetter(String v) => _value = v;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|Symbol(_privateSetter)'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class public static getter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            static String get publicGetter() => 'Fosse';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicGetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
+      group('class private static getter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            static String get _privateGetter() => 'Fosse';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|_privateGetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
+      group('class public static setter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            var _value;
+            static set publicSetter(String v) => _value = v;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicSetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
+      group('class private static setter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            var _value;
+            static set _privateSetter(String v) => _value = v;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|_privateSetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
     });
   }
 }
diff --git a/pkg/dev_compiler/test/module_symbols/function_symbols_test.dart b/pkg/dev_compiler/test/module_symbols/function_symbols_test.dart
new file mode 100644
index 0000000..f39f27b
--- /dev/null
+++ b/pkg/dev_compiler/test/module_symbols/function_symbols_test.dart
@@ -0,0 +1,326 @@
+// 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 'package:dev_compiler/src/kernel/module_symbols.dart';
+import 'package:test/test.dart';
+
+import '../shared_test_options.dart';
+import 'module_symbols_test_shared.dart';
+
+void main() async {
+  for (var mode in [
+    NullSafetyTestOption('Sound Mode:', true),
+    NullSafetyTestOption('Weak Mode:', false)
+  ]) {
+    group(mode.description, () {
+      var options = SetupCompilerOptions(soundNullSafety: mode.soundNullSafety);
+      group('top level function debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          void topLevelFunction() {
+            return;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          librarySymbol = result.symbols.libraries.single;
+          functionSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('has name', () async {
+          expect(functionSymbol.name, equals('topLevelFunction'));
+        });
+        // TODO(nshahan) Test for typeId.
+        test('is static', () async {
+          expect(functionSymbol.isStatic, isTrue);
+        });
+        test('is not const', () async {
+          expect(functionSymbol.isConst, isFalse);
+        });
+        test('has localId', () async {
+          expect(functionSymbol.localId, 'topLevelFunction');
+        });
+        test('has library scopeId', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+        test('no local variables', () async {
+          expect(functionSymbol.variableIds, isEmpty);
+        });
+        test('no scopes', () async {
+          expect(functionSymbol.scopeIds, isEmpty);
+        });
+        group('location', () {
+          test('has scriptId', () async {
+            expect(functionSymbol.location.scriptId, endsWith('/foo.dart'));
+          });
+          test('has start token', () async {
+            expect(functionSymbol.location.tokenPos,
+                27 + options.dartLangComment.length);
+          });
+          test('has end token', () async {
+            expect(functionSymbol.location.endTokenPos,
+                78 + options.dartLangComment.length);
+          });
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|topLevelFunction'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+      });
+      group('top level private function debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          void _topLevelFunction() {
+            return;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionSymbol = result.symbols.functions.single;
+          librarySymbol = result.symbols.libraries.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|_topLevelFunction'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+        test('scopeId is LibrarySymbol id', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+      });
+      group('top level public getter debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          String get topLevelGetter => 'Cello';
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionSymbol = result.symbols.functions.single;
+          librarySymbol = result.symbols.libraries.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|topLevelGetter'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+        test('scopeId is LibrarySymbol id', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+        test('is static', () async {
+          expect(functionSymbol.isStatic, isTrue);
+        });
+      });
+      group('top level private getter debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          String get _topLevelGetter => 'Cello';
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionSymbol = result.symbols.functions.single;
+          librarySymbol = result.symbols.libraries.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|_topLevelGetter'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+        test('scopeId is LibrarySymbol id', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+        test('is static', () async {
+          expect(functionSymbol.isStatic, isTrue);
+        });
+      });
+      group('top level public setter debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+          var _value;
+          set topLevelSetter(String v) => _value = v;
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionSymbol = result.symbols.functions.single;
+          librarySymbol = result.symbols.libraries.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|topLevelSetter'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+        test('scopeId is LibrarySymbol id', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+        test('is static', () async {
+          expect(functionSymbol.isStatic, isTrue);
+        });
+      });
+      group('top level private setter debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          var _value;
+          set _topLevelSetter(String v) => _value = v;
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionSymbol = result.symbols.functions.single;
+          librarySymbol = result.symbols.libraries.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|_topLevelSetter'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+        test('scopeId is LibrarySymbol id', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+        test('is static', () async {
+          expect(functionSymbol.isStatic, isTrue);
+        });
+      });
+      group('function arguments debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionWithPositionalArgSymbol;
+        FunctionSymbol functionWithOptionalArgSymbol;
+        FunctionSymbol functionWithNamedArgSymbol;
+        VariableSymbol xSymbol;
+        VariableSymbol ySymbol;
+        VariableSymbol zSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            const A();
+          }
+          const a = A();
+          void functionWithPositionalArg(A x) {}
+          void functionWithOptionalArg([A y = a]) {}
+          void functionWithNamedArg({A z = a}) {}
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionWithPositionalArgSymbol = result.symbols.functions
+              .singleWhere((f) => f.name == 'functionWithPositionalArg');
+          functionWithOptionalArgSymbol = result.symbols.functions
+              .singleWhere((f) => f.name == 'functionWithOptionalArg');
+          functionWithNamedArgSymbol = result.symbols.functions
+              .singleWhere((f) => f.name == 'functionWithNamedArg');
+          xSymbol = result.symbols.variables.singleWhere((v) => v.name == 'x');
+          ySymbol = result.symbols.variables.singleWhere((v) => v.name == 'y');
+          zSymbol = result.symbols.variables.singleWhere((v) => v.name == 'z');
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('function has a variable id for positional argument', () async {
+          var argumentId = functionWithPositionalArgSymbol.variableIds.single;
+          expect(argumentId, endsWith('|x'));
+          expect(argumentId, xSymbol.id);
+        });
+        test('positional argument symbol has a function scope', () async {
+          expect(xSymbol.scopeId, endsWith('|functionWithPositionalArg'));
+          expect(xSymbol.scopeId, functionWithPositionalArgSymbol.id);
+        });
+        test('function has a variable id for optional argument', () async {
+          var argumentId = functionWithOptionalArgSymbol.variableIds.single;
+          expect(argumentId, endsWith('|y'));
+          expect(argumentId, ySymbol.id);
+        });
+        test('optional argument symbol has a function scope', () async {
+          expect(ySymbol.scopeId, endsWith('|functionWithOptionalArg'));
+          expect(ySymbol.scopeId, functionWithOptionalArgSymbol.id);
+        });
+        test('function has a variable id for named argument', () async {
+          var argumentId = functionWithNamedArgSymbol.variableIds.single;
+          expect(argumentId, endsWith('|z'));
+          expect(argumentId, zSymbol.id);
+        });
+        test('named argument symbol has a function scope', () async {
+          expect(zSymbol.scopeId, endsWith('|functionWithNamedArg'));
+          expect(zSymbol.scopeId, functionWithNamedArgSymbol.id);
+        });
+      });
+      group('function local variable debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        VariableSymbol variableSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          int topLevelFunction() {
+            int i = 42;
+            return i;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          variableSymbol = result.symbols.variables.single;
+          functionSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('local variableId in FunctionSymbol', () async {
+          expect(variableSymbol.id, endsWith('|i'));
+          expect(variableSymbol.id, functionSymbol.variableIds.single);
+        });
+        test('scopeId is FunctionSymbol id', () async {
+          expect(variableSymbol.scopeId, endsWith('|topLevelFunction'));
+          expect(variableSymbol.scopeId, functionSymbol.id);
+        });
+      });
+    });
+  }
+}
diff --git a/pkg/dev_compiler/test/shared_test_options.dart b/pkg/dev_compiler/test/shared_test_options.dart
index 53d8879..88013a3 100644
--- a/pkg/dev_compiler/test/shared_test_options.dart
+++ b/pkg/dev_compiler/test/shared_test_options.dart
@@ -6,7 +6,6 @@
 
 import 'package:cli_util/cli_util.dart';
 import 'package:dev_compiler/dev_compiler.dart';
-import 'package:dev_compiler/src/compiler/module_builder.dart';
 import 'package:front_end/src/api_unstable/ddc.dart';
 import 'package:front_end/src/compute_platform_binaries_location.dart';
 import 'package:front_end/src/fasta/incremental_serializer.dart';
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index 12614bb..a6d071f 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -42,7 +42,7 @@
   /// Notice that the component has to include the platform, and that no other
   /// platform will be loaded.
   factory IncrementalKernelGenerator.fromComponent(
-      CompilerOptions options, Uri entryPoint, Component component,
+      CompilerOptions options, Uri entryPoint, Component? component,
       [bool? outlineOnly, IncrementalSerializer? incrementalSerializer]) {
     return new IncrementalCompiler.fromComponent(
         new CompilerContext(
@@ -72,7 +72,7 @@
 
   /// Returns a component whose libraries are the recompiled libraries,
   /// or - in the case of [fullComponent] - a full Component.
-  Future<Component> computeDelta({List<Uri> entryPoints, bool fullComponent});
+  Future<Component> computeDelta({List<Uri>? entryPoints, bool fullComponent});
 
   /// Returns [CoreTypes] used during compilation.
   /// Valid after [computeDelta] is called.
@@ -136,7 +136,7 @@
       List<TypeParameter> typeDefinitions,
       String syntheticProcedureName,
       Uri libraryUri,
-      [String className,
+      [String? className,
       bool isStatic = false]);
 
   /// Sets experimental features.
diff --git a/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart b/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart
index cf307b8..d1a2a4e 100644
--- a/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart
+++ b/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart
@@ -280,22 +280,7 @@
             block.statements.first is ExpressionStatement) {
           ExpressionStatement firstStatement =
               block.statements.first as ExpressionStatement;
-          if (firstStatement.expression is PropertySet) {
-            // We have
-            //
-            //    get field {
-            //      if (!_#isSet#field) {
-            //        this._#field = <init>;
-            //        ...
-            //      }
-            //      return _#field;
-            //    }
-            //
-            // in case `<init>` is the initializer.
-            PropertySet propertySet = firstStatement.expression as PropertySet;
-            assert(propertySet.interfaceTarget == getLateFieldTarget(node));
-            return propertySet.value;
-          } else if (firstStatement.expression is InstanceSet) {
+          if (firstStatement.expression is InstanceSet) {
             // We have
             //
             //    get field {
@@ -368,15 +353,6 @@
             //
             // in which case there is no initializer.
             return null;
-          } else if (then is PropertySet) {
-            // We have
-            //
-            //    get field => let # = this._#field in <is-unset>
-            //        ? this._#field = <init> : #;
-            //
-            // in which case `<init>` is the initializer.
-            assert(then.interfaceTarget == getLateFieldTarget(node));
-            return then.value;
           } else if (then is InstanceSet) {
             // We have
             //
diff --git a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 46566f1..8cf810b 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -58,7 +58,7 @@
 /// Re-uses cached components from [oldState.workerInputCache], and reloads them
 /// as necessary based on [workerInputDigests].
 Future<InitializedCompilerState> initializeIncrementalCompiler(
-    InitializedCompilerState oldState,
+    InitializedCompilerState? oldState,
     Set<String> tags,
     Uri sdkSummary,
     Uri packagesFile,
@@ -99,7 +99,7 @@
 }
 
 Future<InitializedCompilerState> initializeCompiler(
-  InitializedCompilerState oldState,
+  InitializedCompilerState? oldState,
   Uri sdkSummary,
   Uri librariesSpecificationUri,
   Uri packagesFile,
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index d29d1ea..ee007f5 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -240,7 +240,7 @@
 
 /// Desugar API to determine whether [member] is a redirecting factory
 /// constructor.
-// TODO(sigmund): Delete this API once `member.isRedirectingFactoryConstructor`
+// TODO(sigmund): Delete this API once `member.isRedirectingFactory`
 // is implemented correctly for patch files (Issue #33495).
 bool isRedirectingFactory(ir.Procedure member) {
   if (member.kind == ir.ProcedureKind.Factory) {
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index 35d7c8b..42a227f 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -53,6 +53,7 @@
         messageFfiLeafCallMustNotReturnHandle,
         messageFfiLeafCallMustNotTakeHandle,
         messageFfiPackedAnnotationAlignment,
+        messageFfiNativeAnnotationMustAnnotateStatic,
         messageNonPositiveArrayDimensions,
         noLength,
         templateFfiDartTypeMismatch,
diff --git a/pkg/front_end/lib/src/compute_platform_binaries_location.dart b/pkg/front_end/lib/src/compute_platform_binaries_location.dart
index 0ecacc07..96039c4 100644
--- a/pkg/front_end/lib/src/compute_platform_binaries_location.dart
+++ b/pkg/front_end/lib/src/compute_platform_binaries_location.dart
@@ -23,9 +23,17 @@
     case 'dartdevc':
       switch (nnbdMode) {
         case NnbdMode.Strong:
-          return 'ddc_platform_sound.dill';
+          // DDC is always compiled against the outline so we use it here by
+          // default.
+          return 'ddc_outline_sound.dill';
+        //TODO(johnniwinther): Support using the full dill.
+        //return 'ddc_platform_sound.dill';
         case NnbdMode.Weak:
-          return 'ddc_platform.dill';
+          // DDC is always compiled against the outline so we use it here by
+          // default.
+          return 'ddc_outline.dill';
+        //TODO(johnniwinther): Support using the full dill.
+        //return 'ddc_platform.dill';
         case NnbdMode.Agnostic:
           break;
       }
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 7701321..4de08b9 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -42,7 +42,7 @@
 
 import '../fasta_codes.dart';
 
-import '../kernel/redirecting_factory_body.dart' show getRedirectingFactoryBody;
+import '../kernel/kernel_helper.dart';
 
 import '../loader.dart';
 
@@ -74,7 +74,7 @@
 import 'named_type_builder.dart';
 import 'never_type_declaration_builder.dart';
 import 'nullability_builder.dart';
-import 'procedure_builder.dart';
+import 'factory_builder.dart';
 import 'type_alias_builder.dart';
 import 'type_builder.dart';
 import 'type_declaration_builder.dart';
@@ -123,7 +123,8 @@
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers);
+      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.
@@ -343,11 +344,12 @@
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     void build(String ignore, Builder declaration) {
       MemberBuilder member = declaration as MemberBuilder;
-      member.buildOutlineExpressions(
-          library, coreTypes, delayedActionPerformers);
+      member.buildOutlineExpressions(library, coreTypes,
+          delayedActionPerformers, synthesizedFunctionNodes);
     }
 
     MetadataBuilder.buildAnnotations(
@@ -914,8 +916,7 @@
           charOffset, fileUri);
     }
 
-    List<DartType>? typeArguments =
-        getRedirectingFactoryBody(factory.procedure)!.typeArguments;
+    List<DartType>? typeArguments = factory.getTypeArguments();
     FunctionType targetFunctionType =
         targetNode.computeFunctionType(library.nonNullable);
     if (typeArguments != null &&
@@ -1007,7 +1008,7 @@
     // 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.procedure.function
+    FunctionType factoryType = factory.function
         .computeThisFunctionType(library.nonNullable)
         .withoutTypeParameters;
     FunctionType? redirecteeType =
@@ -1129,6 +1130,10 @@
 
   @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;
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 f2810a8..4d0f32a 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -20,7 +20,7 @@
     show ExpressionGeneratorHelper;
 import '../kernel/kernel_builder.dart'
     show isRedirectingGenerativeConstructorImplementation;
-import '../kernel/kernel_target.dart' show ClonedFunctionNode;
+import '../kernel/kernel_helper.dart' show SynthesizedFunctionNode;
 
 import '../loader.dart' show Loader;
 
@@ -51,7 +51,6 @@
 abstract class ConstructorBuilder implements FunctionBuilder {
   abstract Token? beginInitializers;
 
-  @override
   ConstructorBuilder? get actualOrigin;
 
   ConstructorBuilder? get patchForTesting;
@@ -139,7 +138,7 @@
           ..fileEndOffset = charEndOffset
           ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
         _constructorTearOff = createConstructorTearOffProcedure(
-            name, compilationUnit, charOffset,
+            name, compilationUnit, compilationUnit.fileUri, charOffset,
             forAbstractClassOrEnum: forAbstractClassOrEnum),
         super(metadata, modifiers, returnType, name, typeVariables, formals,
             compilationUnit, charOffset, nativeMethodName);
@@ -230,8 +229,8 @@
             library == libraryBuilder,
             "Unexpected library builder ${libraryBuilder} for"
             " constructor $this in ${library}.");
-        libraryBuilder.loader.typeInferenceEngine.toBeInferred[_constructor] =
-            this;
+        libraryBuilder.loader
+            .registerConstructorToBeInferred(_constructor, this);
       }
     }
     return _constructor;
@@ -248,12 +247,21 @@
     }
   }
 
+  bool _hasBuiltOutlines = false;
+
   @override
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
-    super.buildOutlineExpressions(library, coreTypes, delayedActionPerformers);
+      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.
@@ -265,11 +273,11 @@
       bodyBuilder.parseInitializers(beginInitializers!);
       bodyBuilder.resolveRedirectingFactoryTargets();
     }
-    if (_constructorTearOff != null) {
-      buildConstructorTearOffOutline(
-          _constructorTearOff!, constructor, classBuilder!.cls);
-    }
     beginInitializers = null;
+    if (isConst && isPatch) {
+      _finishPatch();
+    }
+    _hasBuiltOutlines = true;
   }
 
   @override
@@ -391,10 +399,7 @@
     return null;
   }
 
-  @override
-  int finishPatch() {
-    if (!isPatch) return 0;
-
+  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;
@@ -409,6 +414,12 @@
     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;
   }
 
@@ -441,7 +452,7 @@
     // 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.length = 0;
+    _constructor.initializers = [];
     redirectingInitializer = null;
     superInitializer = null;
     hasMovedSuperInitializer = false;
@@ -470,31 +481,33 @@
 
 class SyntheticConstructorBuilder extends DillConstructorBuilder {
   MemberBuilderImpl? _origin;
-  ClonedFunctionNode? _clonedFunctionNode;
+  SynthesizedFunctionNode? _synthesizedFunctionNode;
 
   SyntheticConstructorBuilder(SourceClassBuilder parent,
       Constructor constructor, Procedure? constructorTearOff,
-      {MemberBuilderImpl? origin, ClonedFunctionNode? clonedFunctionNode})
+      {MemberBuilderImpl? origin,
+      SynthesizedFunctionNode? synthesizedFunctionNode})
       : _origin = origin,
-        _clonedFunctionNode = clonedFunctionNode,
+        _synthesizedFunctionNode = synthesizedFunctionNode,
         super(constructor, constructorTearOff, parent);
 
   @override
   void buildOutlineExpressions(
       SourceLibraryBuilder libraryBuilder,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
+      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);
+        _origin!.buildOutlineExpressions(originLibraryBuilder, coreTypes,
+            delayedActionPerformers, synthesizedFunctionNodes);
       }
-      _clonedFunctionNode!.cloneDefaultValues();
-      _clonedFunctionNode = null;
+      _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
index 8947531..98e54de 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -21,7 +21,6 @@
         ListLiteral,
         Name,
         ProcedureKind,
-        PropertyGet,
         Reference,
         ReturnStatement,
         StaticGet,
@@ -42,6 +41,8 @@
         templateDuplicatedDeclarationSyntheticCause,
         templateEnumConstantSameNameAsEnclosing;
 
+import '../kernel/kernel_helper.dart';
+
 import '../util/helpers.dart';
 
 import '../modifier.dart'
@@ -460,15 +461,10 @@
     Field nameField = nameFieldBuilder.field;
     ProcedureBuilder toStringBuilder =
         firstMemberNamed("toString") as ProcedureBuilder;
-    if (libraryBuilder
-        .loader.target.backendTarget.supportsNewMethodInvocationEncoding) {
-      toStringBuilder.body = new ReturnStatement(new InstanceGet(
-          InstanceAccessKind.Instance, new ThisExpression(), nameField.name,
-          interfaceTarget: nameField, resultType: nameField.type));
-    } else {
-      toStringBuilder.body = new ReturnStatement(
-          new PropertyGet(new ThisExpression(), nameField.name, nameField));
-    }
+    toStringBuilder.body = new ReturnStatement(new InstanceGet(
+        InstanceAccessKind.Instance, new ThisExpression(), nameField.name,
+        interfaceTarget: nameField, resultType: nameField.type));
+
     List<Expression> values = <Expression>[];
     if (enumConstantInfos != null) {
       for (EnumConstantInfo? enumConstantInfo in enumConstantInfos!) {
@@ -520,7 +516,8 @@
   void buildOutlineExpressions(
       SourceLibraryBuilder libraryBuilder,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     List<Expression> values = <Expression>[];
     if (enumConstantInfos != null) {
       for (EnumConstantInfo? enumConstantInfo in enumConstantInfos!) {
@@ -564,7 +561,8 @@
         }
       }
     }
-    super.buildOutlineExpressions(library, coreTypes, delayedActionPerformers);
+    super.buildOutlineExpressions(
+        library, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
   }
 
   @override
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 0ca4e45..d0250bf 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -7,6 +7,7 @@
 
 import '../fasta_codes.dart'
     show templateInternalProblemNotFoundIn, templateTypeArgumentMismatch;
+import '../kernel/kernel_helper.dart';
 import '../scope.dart';
 import '../source/source_library_builder.dart';
 import '../problems.dart';
@@ -36,7 +37,8 @@
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers);
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes);
 
   /// Looks up extension member by [name] taking privacy into account.
   ///
diff --git a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
new file mode 100644
index 0000000..22e54cb
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
@@ -0,0 +1,467 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All 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 '../dill/dill_member_builder.dart';
+
+import '../kernel/class_hierarchy_builder.dart';
+import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/forest.dart';
+import '../kernel/internal_ast.dart';
+import '../kernel/kernel_api.dart';
+import '../kernel/kernel_helper.dart';
+import '../kernel/redirecting_factory_body.dart'
+    show getRedirectingFactoryBody, RedirectingFactoryBody;
+
+import '../loader.dart' show Loader;
+
+import '../messages.dart'
+    show messageConstFactoryRedirectionToNonConst, noLength;
+
+import '../problems.dart' show unexpected, unhandled;
+
+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 'procedure_builder.dart';
+import 'type_builder.dart';
+import 'type_variable_builder.dart';
+
+class SourceFactoryBuilder extends FunctionBuilderImpl {
+  final int charOpenParenOffset;
+
+  AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
+
+  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,
+      AsyncMarker asyncModifier,
+      ProcedureNameScheme procedureNameScheme,
+      {String? nativeMethodName})
+      : _procedureInternal = new Procedure(
+            procedureNameScheme.getName(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),
+        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(Loader 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.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,
+      ProcedureNameScheme procedureNameScheme,
+      String? nativeMethodName,
+      this.redirectionTarget)
+      : super(
+            metadata,
+            modifiers,
+            returnType,
+            name,
+            typeVariables,
+            formals,
+            libraryBuilder,
+            startCharOffset,
+            charOffset,
+            charOpenParenOffset,
+            charEndOffset,
+            procedureReference,
+            AsyncMarker.Sync,
+            procedureNameScheme,
+            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.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;
+  }
+
+  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);
+      }
+      Arguments 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);
+      }
+      member.function!.body = new RedirectingFactoryBody(target, typeArguments);
+    }
+    if (_factoryTearOff != null &&
+        (target is Constructor || target is Procedure && target.isFactory)) {
+      synthesizedFunctionNodes.add(buildRedirectingFactoryTearOffBody(
+          _factoryTearOff!,
+          target!,
+          typeArguments ?? [],
+          _tearOffTypeParameters!));
+    }
+    if (isConst && isPatch) {
+      _finishPatch();
+    }
+    _hasBuiltOutlines = true;
+  }
+
+  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 12b9103..eceff88 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -17,6 +17,7 @@
 import '../kernel/body_builder.dart' show BodyBuilder;
 import '../kernel/class_hierarchy_builder.dart';
 import '../kernel/kernel_builder.dart' show ImplicitFieldType;
+import '../kernel/kernel_helper.dart';
 import '../kernel/late_lowering.dart' as late_lowering;
 import '../kernel/member_covariance.dart';
 
@@ -329,11 +330,7 @@
       internalProblem(
           messageInternalProblemAlreadyInitialized, charOffset, fileUri);
     }
-    _fieldEncoding.createBodies(
-        coreTypes,
-        initializer,
-        library
-            .loader.target.backendTarget.supportsNewMethodInvocationEncoding);
+    _fieldEncoding.createBodies(coreTypes, initializer);
   }
 
   @override
@@ -398,7 +395,8 @@
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     _fieldEncoding.completeSignature(coreTypes);
 
     for (Annotatable annotatable in _fieldEncoding.annotatables) {
@@ -612,8 +610,7 @@
   ///
   /// 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,
-      bool useNewMethodInvocationEncoding);
+  void createBodies(CoreTypes coreTypes, Expression? initializer);
 
   List<Initializer> createInitializer(int fileOffset, Expression value,
       {required bool isSynthetic});
@@ -723,8 +720,7 @@
   void completeSignature(CoreTypes coreTypes) {}
 
   @override
-  void createBodies(CoreTypes coreTypes, Expression? initializer,
-      bool useNewMethodInvocationEncoding) {
+  void createBodies(CoreTypes coreTypes, Expression? initializer) {
     if (initializer != null) {
       _field.initializer = initializer..parent = _field;
     }
@@ -960,8 +956,7 @@
   }
 
   @override
-  void createBodies(CoreTypes coreTypes, Expression? initializer,
-      bool useNewMethodInvocationEncoding) {
+  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,
@@ -978,15 +973,11 @@
         ..fileOffset = fileOffset
         ..parent = _lateIsSetField;
     }
-    _lateGetter.function.body = _createGetterBody(
-        coreTypes, name, initializer, useNewMethodInvocationEncoding)
+    _lateGetter.function.body = _createGetterBody(coreTypes, name, initializer)
       ..parent = _lateGetter.function;
     if (_lateSetter != null) {
       _lateSetter!.function.body = _createSetterBody(
-          coreTypes,
-          name,
-          _lateSetter!.function.positionalParameters.first,
-          useNewMethodInvocationEncoding)
+          coreTypes, name, _lateSetter!.function.positionalParameters.first)
         ..parent = _lateSetter!.function;
     }
   }
@@ -1013,62 +1004,48 @@
   /// 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 useNewMethodInvocationEncoding,
-      {bool needsPromotion: false}) {
+  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, useNewMethodInvocationEncoding),
+          _createFieldGet(_field),
           type: _type!.withDeclaredNullability(Nullability.nullable))
         ..fileOffset = fileOffset;
       return new Let(
           variable, new VariableGet(variable, _type)..fileOffset = fileOffset);
     } else {
-      return _createFieldGet(_field, useNewMethodInvocationEncoding);
+      return _createFieldGet(_field);
     }
   }
 
   /// Creates an [Expression] that reads [field].
-  Expression _createFieldGet(Field field, bool useNewMethodInvocationEncoding) {
+  Expression _createFieldGet(Field field) {
     if (field.isStatic) {
       return new StaticGet(field)..fileOffset = fileOffset;
     } else {
-      if (useNewMethodInvocationEncoding) {
-        // 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;
-      } else {
-        return new PropertyGet(
-            new ThisExpression()..fileOffset = fileOffset, field.name, field)
-          ..fileOffset = fileOffset;
-      }
+      // 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, bool useNewMethodInvocationEncoding) {
+  Expression _createFieldSet(Field field, Expression value) {
     if (field.isStatic) {
       return new StaticSet(field, value)..fileOffset = fileOffset;
     } else {
-      if (useNewMethodInvocationEncoding) {
-        return new InstanceSet(InstanceAccessKind.Instance,
-            new ThisExpression()..fileOffset = fileOffset, field.name, value,
-            interfaceTarget: field)
-          ..fileOffset = fileOffset;
-      } else {
-        return new PropertySet(new ThisExpression()..fileOffset = fileOffset,
-            field.name, value, field)
-          ..fileOffset = fileOffset;
-      }
+      return new InstanceSet(InstanceAccessKind.Instance,
+          new ThisExpression()..fileOffset = fileOffset, field.name, value,
+          interfaceTarget: field)
+        ..fileOffset = fileOffset;
     }
   }
 
-  Statement _createGetterBody(CoreTypes coreTypes, String name,
-      Expression? initializer, bool useNewMethodInvocationEncoding);
+  Statement _createGetterBody(
+      CoreTypes coreTypes, String name, Expression? initializer);
 
   Procedure? _createSetter(
       Name name, Uri fileUri, int charOffset, Reference? reference,
@@ -1092,8 +1069,8 @@
       ..isNonNullableByDefault = true;
   }
 
-  Statement _createSetterBody(CoreTypes coreTypes, String name,
-      VariableDeclaration parameter, bool useNewMethodInvocationEncoding);
+  Statement _createSetterBody(
+      CoreTypes coreTypes, String name, VariableDeclaration parameter);
 
   @override
   DartType get type {
@@ -1253,30 +1230,29 @@
 
 mixin NonFinalLate on AbstractLateFieldEncoding {
   @override
-  Statement _createSetterBody(CoreTypes coreTypes, String name,
-      VariableDeclaration parameter, bool useNewMethodInvocationEncoding) {
+  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, useNewMethodInvocationEncoding),
-        createIsSetWrite: (Expression value) => _createFieldSet(
-            _lateIsSetField!, value, useNewMethodInvocationEncoding),
+            _createFieldSet(_field, value),
+        createIsSetWrite: (Expression value) =>
+            _createFieldSet(_lateIsSetField!, value),
         isSetEncoding: isSetEncoding);
   }
 }
 
 mixin LateWithoutInitializer on AbstractLateFieldEncoding {
   @override
-  Statement _createGetterBody(CoreTypes coreTypes, String name,
-      Expression? initializer, bool useNewMethodInvocationEncoding) {
+  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, useNewMethodInvocationEncoding,
+        coreTypes, fileOffset, name, type,
         createVariableRead: _createFieldRead,
-        createIsSetRead: () =>
-            _createFieldGet(_lateIsSetField!, useNewMethodInvocationEncoding),
+        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
         isSetEncoding: isSetEncoding,
         forField: true);
   }
@@ -1346,18 +1322,17 @@
             isSetStrategy);
 
   @override
-  Statement _createGetterBody(CoreTypes coreTypes, String name,
-      Expression? initializer, bool useNewMethodInvocationEncoding) {
+  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!, useNewMethodInvocationEncoding,
+    return late_lowering.createGetterWithInitializer(
+        coreTypes, fileOffset, name, _type!, initializer!,
         createVariableRead: _createFieldRead,
         createVariableWrite: (Expression value) =>
-            _createFieldSet(_field, value, useNewMethodInvocationEncoding),
-        createIsSetRead: () =>
-            _createFieldGet(_lateIsSetField!, useNewMethodInvocationEncoding),
-        createIsSetWrite: (Expression value) => _createFieldSet(
-            _lateIsSetField!, value, useNewMethodInvocationEncoding),
+            _createFieldSet(_field, value),
+        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+        createIsSetWrite: (Expression value) =>
+            _createFieldSet(_lateIsSetField!, value),
         isSetEncoding: isSetEncoding);
   }
 }
@@ -1394,20 +1369,18 @@
             isSetStrategy);
 
   @override
-  Statement _createSetterBody(CoreTypes coreTypes, String name,
-      VariableDeclaration parameter, bool useNewMethodInvocationEncoding) {
+  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, useNewMethodInvocationEncoding,
+    return late_lowering.createSetterBodyFinal(
+        coreTypes, fileOffset, name, parameter, type,
         shouldReturnValue: false,
-        createVariableRead: (bool useNewMethodInvocationEncoding) =>
-            _createFieldGet(_field, useNewMethodInvocationEncoding),
+        createVariableRead: () => _createFieldGet(_field),
         createVariableWrite: (Expression value) =>
-            _createFieldSet(_field, value, useNewMethodInvocationEncoding),
-        createIsSetRead: () =>
-            _createFieldGet(_lateIsSetField!, useNewMethodInvocationEncoding),
-        createIsSetWrite: (Expression value) => _createFieldSet(
-            _lateIsSetField!, value, useNewMethodInvocationEncoding),
+            _createFieldSet(_field, value),
+        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+        createIsSetWrite: (Expression value) =>
+            _createFieldSet(_lateIsSetField!, value),
         isSetEncoding: isSetEncoding,
         forField: true);
   }
@@ -1443,18 +1416,17 @@
             isCovariant,
             isSetStrategy);
   @override
-  Statement _createGetterBody(CoreTypes coreTypes, String name,
-      Expression? initializer, bool useNewMethodInvocationEncoding) {
+  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!, useNewMethodInvocationEncoding,
+    return late_lowering.createGetterWithInitializerWithRecheck(
+        coreTypes, fileOffset, name, _type!, initializer!,
         createVariableRead: _createFieldRead,
         createVariableWrite: (Expression value) =>
-            _createFieldSet(_field, value, useNewMethodInvocationEncoding),
-        createIsSetRead: () =>
-            _createFieldGet(_lateIsSetField!, useNewMethodInvocationEncoding),
-        createIsSetWrite: (Expression value) => _createFieldSet(
-            _lateIsSetField!, value, useNewMethodInvocationEncoding),
+            _createFieldSet(_field, value),
+        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+        createIsSetWrite: (Expression value) =>
+            _createFieldSet(_lateIsSetField!, value),
         isSetEncoding: isSetEncoding,
         forField: true);
   }
@@ -1466,8 +1438,8 @@
       null;
 
   @override
-  Statement _createSetterBody(CoreTypes coreTypes, String name,
-          VariableDeclaration parameter, bool useNewMethodInvocationEncoding) =>
+  Statement _createSetterBody(
+          CoreTypes coreTypes, String name, VariableDeclaration parameter) =>
       throw new UnsupportedError(
           '$runtimeType._createSetterBody is not supported.');
 }
@@ -1690,8 +1662,7 @@
   void completeSignature(CoreTypes coreTypes) {}
 
   @override
-  void createBodies(CoreTypes coreTypes, Expression? initializer,
-      bool useNewMethodInvocationEncoding) {
+  void createBodies(CoreTypes coreTypes, Expression? initializer) {
     //assert(initializer != null);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
index d9894e4..14f3d3d 100644
--- a/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
@@ -12,8 +12,8 @@
 
 class FixedTypeBuilder extends TypeBuilder {
   final DartType type;
-  final Uri fileUri;
-  final int charOffset;
+  final Uri? fileUri;
+  final int? charOffset;
 
   const FixedTypeBuilder(this.type, this.fileUri, this.charOffset);
 
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 c1c89d3..cf242da 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
@@ -14,7 +14,6 @@
     show FormalParameterKind;
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-import 'package:front_end/src/fasta/builder/procedure_builder.dart';
 
 import 'package:kernel/ast.dart'
     show DartType, DynamicType, Expression, VariableDeclaration;
@@ -40,6 +39,7 @@
 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';
@@ -51,6 +51,8 @@
 /// constructor.
 class FormalParameterBuilder extends ModifierBuilderImpl
     implements VariableBuilder {
+  static const String noNameSentinel = 'no name sentinel';
+
   /// List of metadata builders for the metadata declared on this parameter.
   final List<MetadataBuilder>? metadata;
 
@@ -130,7 +132,8 @@
       if (!library.isNonNullableByDefault && builtType != null) {
         builtType = legacyErasure(builtType);
       }
-      variable = new VariableDeclarationImpl(name, functionNestingLevel,
+      variable = new VariableDeclarationImpl(
+          name == noNameSentinel ? null : name, functionNestingLevel,
           type: builtType,
           isFinal: isFinal,
           isConst: isConst,
@@ -202,7 +205,7 @@
       bool isConstConstructorParameter = false;
       if (parent is ConstructorBuilder) {
         isConstConstructorParameter = parent!.isConst;
-      } else if (parent is ProcedureBuilder) {
+      } else if (parent is SourceFactoryBuilder) {
         isConstConstructorParameter = parent!.isFactory && parent!.isConst;
       }
       if (isConstConstructorParameter || parent!.isClassInstanceMember) {
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 dd4d74a..71dc58a 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -4,8 +4,8 @@
 
 library fasta.procedure_builder;
 
-import 'package:front_end/src/fasta/kernel/kernel_api.dart';
 import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
 
 import 'package:kernel/type_algebra.dart' show containsTypeVariable, substitute;
 
@@ -13,7 +13,7 @@
 import '../scope.dart';
 
 import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
-import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
+import '../kernel/kernel_helper.dart';
 
 import '../loader.dart' show Loader;
 
@@ -28,8 +28,6 @@
 
 import '../modifier.dart';
 
-import '../problems.dart' show unexpected;
-
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
 import '../type_inference/type_inference_engine.dart'
@@ -93,14 +91,10 @@
 
   FunctionNode get function;
 
-  FunctionBuilder? get actualOrigin;
-
   Statement? get body;
 
   void set body(Statement? newBody);
 
-  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments);
-
   bool get isNative;
 
   /// Returns the [index]th parameter of this function.
@@ -317,19 +311,6 @@
   }
 
   @override
-  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
-    if (bodyInternal != null) {
-      unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
-    }
-    bodyInternal = new RedirectingFactoryBody(target, typeArguments);
-    function.body = bodyInternal;
-    bodyInternal?.parent = function;
-    if (isPatch) {
-      actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
-    }
-  }
-
-  @override
   Statement? get body => bodyInternal ??= new EmptyStatement();
 
   @override
@@ -498,7 +479,8 @@
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     if (!_hasBuiltOutlineExpressions) {
       DeclarationBuilder? classOrExtensionBuilder =
           isClassMember || isExtensionMember
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 14ae7c9..bae23b9 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -10,6 +10,7 @@
 import '../../base/common.dart';
 
 import '../kernel/class_hierarchy_builder.dart';
+import '../kernel/kernel_helper.dart';
 import '../modifier.dart';
 import '../problems.dart' show unsupported;
 import '../source/source_library_builder.dart';
@@ -78,7 +79,8 @@
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers);
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes);
 
   /// Returns the [ClassMember]s for the non-setter members created for this
   /// member builder.
@@ -184,7 +186,8 @@
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {}
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {}
 
   /// Builds the core AST structures for this member as needed for the outline.
   void buildMembers(
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 368e69c..8950e51 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -4,37 +4,20 @@
 
 import 'package:kernel/ast.dart';
 
-import '../dill/dill_member_builder.dart';
-
 import '../kernel/class_hierarchy_builder.dart';
-import '../kernel/forest.dart';
-import '../kernel/internal_ast.dart';
 import '../kernel/kernel_api.dart';
 import '../kernel/member_covariance.dart';
-import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
 
 import '../loader.dart' show Loader;
 
-import '../messages.dart'
-    show messageConstFactoryRedirectionToNonConst, noLength;
-
-import '../problems.dart' show unexpected, unhandled;
-
 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 'extension_builder.dart';
 import 'formal_parameter_builder.dart';
 import 'function_builder.dart';
 import 'member_builder.dart';
 import 'metadata_builder.dart';
-import 'library_builder.dart';
 import 'type_builder.dart';
 import 'type_variable_builder.dart';
 
@@ -62,28 +45,38 @@
   bool get isExtensionMethod;
 }
 
-abstract class ProcedureBuilderImpl extends FunctionBuilderImpl
+class SourceProcedureBuilder extends FunctionBuilderImpl
     implements ProcedureBuilder {
-  late Procedure _procedure;
-
   @override
   final int charOpenParenOffset;
 
   @override
-  final ProcedureKind kind;
-
-  @override
   AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
 
-  @override
-  ProcedureBuilder? actualOrigin;
-
-  @override
-  Procedure get actualProcedure => _procedure;
-
   final bool isExtensionInstanceMember;
 
-  ProcedureBuilderImpl(
+  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,
@@ -97,6 +90,8 @@
       this.charOpenParenOffset,
       int charEndOffset,
       Reference? procedureReference,
+      this._tearOffReference,
+      AsyncMarker asyncModifier,
       ProcedureNameScheme procedureNameScheme,
       {required bool isExtensionMember,
       required bool isInstanceMember,
@@ -105,6 +100,7 @@
       : 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) {
@@ -118,13 +114,20 @@
       ..fileOffset = charOffset
       ..fileEndOffset = charEndOffset
       ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
+    this.asyncModifier = asyncModifier;
+    if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
+      _extensionTearOff ??= new Procedure(
+          procedureNameScheme.getName(ProcedureKind.Getter, name),
+          ProcedureKind.Method,
+          new FunctionNode(null),
+          isStatic: true,
+          isExtensionMember: true,
+          reference: _tearOffReference,
+          fileUri: fileUri)
+        ..isNonNullableByDefault = library.isNonNullableByDefault;
+    }
   }
 
-  FunctionNode get function => _procedure.function;
-
-  @override
-  ProcedureBuilder get origin => actualOrigin ?? this;
-
   @override
   ProcedureBuilder? get patchForTesting =>
       dataForTesting?.patchForTesting as ProcedureBuilder?;
@@ -166,118 +169,19 @@
   }
 
   @override
-  Procedure get procedure => isPatch ? origin.procedure : _procedure;
-
-  @override
   Member get member => procedure;
 
   @override
-  void becomeNative(Loader loader) {
-    _procedure.isExternal = true;
-    super.becomeNative(loader);
-  }
+  SourceProcedureBuilder get origin => actualOrigin ?? this;
 
   @override
-  void applyPatch(Builder patch) {
-    if (patch is ProcedureBuilderImpl) {
-      if (checkPatch(patch)) {
-        patch.actualOrigin = this;
-        dataForTesting?.patchForTesting = patch;
-      }
-    } else {
-      reportPatchMismatch(patch);
-    }
-  }
+  Procedure get procedure => isPatch ? origin.procedure : _procedure;
 
   @override
-  int finishPatch() {
-    if (!isPatch) return 0;
+  Procedure get actualProcedure => _procedure;
 
-    // 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.isRedirectingFactoryConstructor =
-        _procedure.isRedirectingFactoryConstructor;
-    return 1;
-  }
-}
-
-class SourceProcedureBuilder extends ProcedureBuilderImpl {
-  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;
-
-  SourceProcedureBuilder(
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      TypeBuilder? returnType,
-      String name,
-      List<TypeVariableBuilder>? typeVariables,
-      List<FormalParameterBuilder>? formals,
-      ProcedureKind kind,
-      SourceLibraryBuilder libraryBuilder,
-      int startCharOffset,
-      int charOffset,
-      int charOpenParenOffset,
-      int charEndOffset,
-      Reference? procedureReference,
-      this._tearOffReference,
-      AsyncMarker asyncModifier,
-      ProcedureNameScheme procedureNameScheme,
-      {required bool isExtensionMember,
-      required bool isInstanceMember,
-      String? nativeMethodName})
-      : super(
-            metadata,
-            modifiers,
-            returnType,
-            name,
-            typeVariables,
-            formals,
-            kind,
-            libraryBuilder,
-            startCharOffset,
-            charOffset,
-            charOpenParenOffset,
-            charEndOffset,
-            procedureReference,
-            procedureNameScheme,
-            isExtensionMember: isExtensionMember,
-            isInstanceMember: isInstanceMember,
-            nativeMethodName: nativeMethodName) {
-    this.asyncModifier = asyncModifier;
-    if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
-      _extensionTearOff ??= new Procedure(
-          procedureNameScheme.getName(ProcedureKind.Getter, name),
-          ProcedureKind.Method,
-          new FunctionNode(null),
-          isStatic: true,
-          isExtensionMember: true,
-          reference: _tearOffReference,
-          fileUri: fileUri)
-        ..isNonNullableByDefault = library.isNonNullableByDefault;
-    }
-  }
+  @override
+  FunctionNode get function => _procedure.function;
 
   bool _typeEnsured = false;
   Set<ClassMember>? _overrideDependencies;
@@ -597,6 +501,45 @@
       _localSetters ??= isSetter && !isConflictingSetter
           ? <ClassMember>[new SourceProcedureMember(this)]
           : const <ClassMember>[];
+
+  @override
+  void becomeNative(Loader 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 {
@@ -647,216 +590,6 @@
   }
 }
 
-class RedirectingFactoryBuilder extends ProcedureBuilderImpl {
-  final ConstructorReferenceBuilder redirectionTarget;
-  List<DartType>? typeArguments;
-
-  RedirectingFactoryBuilder(
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      TypeBuilder returnType,
-      String name,
-      List<TypeVariableBuilder> typeVariables,
-      List<FormalParameterBuilder>? formals,
-      SourceLibraryBuilder compilationUnit,
-      int startCharOffset,
-      int charOffset,
-      int charOpenParenOffset,
-      int charEndOffset,
-      Reference? reference,
-      ProcedureNameScheme procedureNameScheme,
-      String? nativeMethodName,
-      this.redirectionTarget)
-      : super(
-            metadata,
-            modifiers,
-            returnType,
-            name,
-            typeVariables,
-            formals,
-            ProcedureKind.Factory,
-            compilationUnit,
-            startCharOffset,
-            charOffset,
-            charOpenParenOffset,
-            charEndOffset,
-            reference,
-            procedureNameScheme,
-            isExtensionMember: false,
-            isInstanceMember: false,
-            nativeMethodName: nativeMethodName);
-
-  @override
-  Member? get readTarget => null;
-
-  @override
-  Member? get writeTarget => null;
-
-  @override
-  Member? get invokeTarget => procedure;
-
-  @override
-  Iterable<Member> get exportedMembers => [procedure];
-
-  @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.body = bodyInternal;
-    bodyInternal?.parent = function;
-    procedure.isRedirectingFactoryConstructor = 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);
-  }
-
-  @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;
-    _procedure.isStatic = isStatic;
-    _procedure.isRedirectingFactoryConstructor = true;
-    if (redirectionTarget.typeArguments != null) {
-      typeArguments = new List<DartType>.generate(
-          redirectionTarget.typeArguments!.length,
-          (int i) => redirectionTarget.typeArguments![i].build(library),
-          growable: false);
-    }
-    updatePrivateMemberName(_procedure, libraryBuilder);
-    return _procedure;
-  }
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
-    super.buildOutlineExpressions(library, coreTypes, delayedActionPerformers);
-    LibraryBuilder thisLibrary = this.library;
-    if (thisLibrary is SourceLibraryBuilder) {
-      RedirectingFactoryBody redirectingFactoryBody =
-          procedure.function.body as RedirectingFactoryBody;
-      if (redirectingFactoryBody.typeArguments != null &&
-          redirectingFactoryBody.typeArguments!.any((t) => t is UnknownType)) {
-        TypeInferrerImpl inferrer = thisLibrary.loader.typeInferenceEngine
-                .createLocalTypeInferrer(
-                    fileUri, classBuilder!.thisType, thisLibrary, null)
-            as TypeInferrerImpl;
-        inferrer.helper = thisLibrary.loader
-            .createBodyBuilderForOutlineExpression(
-                thisLibrary, classBuilder, this, classBuilder!.scope, fileUri);
-        Builder? targetBuilder = redirectionTarget.target;
-        Member target;
-        if (targetBuilder is FunctionBuilder) {
-          target = targetBuilder.member;
-        } else if (targetBuilder is DillMemberBuilder) {
-          target = targetBuilder.member;
-        } else {
-          unhandled("${targetBuilder.runtimeType}", "buildOutlineExpressions",
-              charOffset, fileUri);
-        }
-        Arguments 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);
-        List<DartType> typeArguments;
-        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);
-        }
-        member.function!.body =
-            new RedirectingFactoryBody(target, typeArguments);
-      }
-    }
-  }
-
-  @override
-  List<ClassMember> get localMembers =>
-      throw new UnsupportedError('${runtimeType}.localMembers');
-
-  @override
-  List<ClassMember> get localSetters =>
-      throw new UnsupportedError('${runtimeType}.localSetters');
-
-  @override
-  int finishPatch() {
-    if (!isPatch) return 0;
-
-    super.finishPatch();
-
-    ProcedureBuilder redirectingOrigin = origin;
-    if (redirectingOrigin is RedirectingFactoryBuilder) {
-      redirectingOrigin.typeArguments = typeArguments;
-    }
-
-    return 1;
-  }
-}
-
 class ProcedureNameScheme {
   final bool isExtensionMember;
   final bool isStatic;
diff --git a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
index b012042..78e98ed 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
@@ -5,7 +5,6 @@
 library fasta.function_type_alias_builder;
 
 import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
 import 'package:kernel/src/legacy_erasure.dart';
 
 import 'package:kernel/type_algebra.dart' show substitute, uniteNullabilities;
@@ -20,7 +19,6 @@
 
 import '../problems.dart' show unhandled;
 import '../source/source_library_builder.dart';
-import '../util/helpers.dart';
 
 import 'class_builder.dart';
 import 'library_builder.dart';
@@ -113,10 +111,28 @@
   // as stated in the docs? It is not needed for the implementation.
   List<TypeBuilder>? unaliasTypeArguments(List<TypeBuilder>? typeArguments);
 
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers);
+  /// Returns the lowering for the constructor or factory named [name] on the
+  /// effective target class of this typedef.
+  ///
+  /// For instance, if we have
+  ///
+  ///     class A<T> {
+  ///       A();
+  ///     }
+  ///     typedef F = A<int>;
+  ///     typedef G = F;
+  ///     typedef H<X, Y> = A<X>;
+  ///
+  /// the lowering will create
+  ///
+  ///     A<int> _#F#new#tearOff() => new A<int>();
+  ///     A<int> _#G#new#tearOff() => new A<int>();
+  ///     A<int> _#H#new#tearOff<X, Y>() => new A<X>();
+  ///
+  /// which will be return by [findConstructorOrFactory] on `F`, `G`, `H` with
+  /// name 'new' or ''.
+  Procedure? findConstructorOrFactory(
+      String name, int charOffset, Uri uri, LibraryBuilder accessingLibrary);
 }
 
 abstract class TypeAliasBuilderImpl extends TypeDeclarationBuilderImpl
@@ -494,6 +510,17 @@
     }
     return currentTypeArguments;
   }
+
+  Map<Name, Procedure>? get tearOffs;
+
+  Procedure? findConstructorOrFactory(
+      String text, int charOffset, Uri uri, LibraryBuilder accessingLibrary) {
+    if (tearOffs != null) {
+      Name name = new Name(text == 'new' ? '' : text, accessingLibrary.library);
+      return tearOffs![name];
+    }
+    return null;
+  }
 }
 
 /// Used to detect cycles in the declaration of a typedef
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 fe9e63c..1462633 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
@@ -72,39 +72,42 @@
   @override
   Class get actualCls => cls;
 
-  void addMember(Member member) {
-    if (member is Field) {
-      DillFieldBuilder builder = new DillFieldBuilder(member, this);
-      String name = member.name.text;
-      scopeBuilder.addMember(name, builder);
-    } else if (member is Procedure) {
-      String name = member.name.text;
-      switch (member.kind) {
-        case ProcedureKind.Factory:
-          constructorScopeBuilder.addMember(
-              name, new DillFactoryBuilder(member, this));
-          break;
-        case ProcedureKind.Setter:
-          scopeBuilder.addSetter(name, new DillSetterBuilder(member, this));
-          break;
-        case ProcedureKind.Getter:
-          scopeBuilder.addMember(name, new DillGetterBuilder(member, this));
-          break;
-        case ProcedureKind.Operator:
-          scopeBuilder.addMember(name, new DillOperatorBuilder(member, this));
-          break;
-        case ProcedureKind.Method:
-          scopeBuilder.addMember(name, new DillMethodBuilder(member, this));
-          break;
-      }
-    } else if (member is Constructor) {
-      DillConstructorBuilder builder =
-          new DillConstructorBuilder(member, null, this);
-      String name = member.name.text;
-      constructorScopeBuilder.addMember(name, builder);
-    } else {
-      throw new UnsupportedError(
-          "Unexpected class member ${member} (${member.runtimeType})");
+  void addField(Field field) {
+    DillFieldBuilder builder = new DillFieldBuilder(field, this);
+    String name = field.name.text;
+    scopeBuilder.addMember(name, builder);
+  }
+
+  void addConstructor(Constructor constructor, Procedure? constructorTearOff) {
+    DillConstructorBuilder builder =
+        new DillConstructorBuilder(constructor, constructorTearOff, this);
+    String name = constructor.name.text;
+    constructorScopeBuilder.addMember(name, builder);
+  }
+
+  void addFactory(Procedure factory, Procedure? factoryTearOff) {
+    String name = factory.name.text;
+    constructorScopeBuilder.addMember(
+        name, new DillFactoryBuilder(factory, factoryTearOff, this));
+  }
+
+  void addProcedure(Procedure procedure) {
+    String name = procedure.name.text;
+    switch (procedure.kind) {
+      case ProcedureKind.Factory:
+        throw new UnsupportedError("Use addFactory for adding factories");
+      case ProcedureKind.Setter:
+        scopeBuilder.addSetter(name, new DillSetterBuilder(procedure, this));
+        break;
+      case ProcedureKind.Getter:
+        scopeBuilder.addMember(name, new DillGetterBuilder(procedure, this));
+        break;
+      case ProcedureKind.Operator:
+        scopeBuilder.addMember(name, new DillOperatorBuilder(procedure, this));
+        break;
+      case ProcedureKind.Method:
+        scopeBuilder.addMember(name, new DillMethodBuilder(procedure, this));
+        break;
     }
   }
 
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 94e7b8c..1a1857b 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
@@ -11,6 +11,8 @@
 import '../builder/type_builder.dart';
 import '../builder/type_variable_builder.dart';
 
+import '../kernel/kernel_helper.dart';
+
 import '../scope.dart';
 
 import '../util/helpers.dart';
@@ -103,8 +105,11 @@
   }
 
   @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
+  void buildOutlineExpressions(
+      LibraryBuilder library,
+      CoreTypes coreTypes,
+      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 c899e3df..4c1afba 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
@@ -6,28 +6,7 @@
 
 import 'dart:convert' show jsonDecode;
 
-import 'package:kernel/ast.dart'
-    show
-        Class,
-        ConstantExpression,
-        DartType,
-        DynamicType,
-        Expression,
-        Extension,
-        Field,
-        FunctionType,
-        Library,
-        ListLiteral,
-        Member,
-        NamedNode,
-        NeverType,
-        Procedure,
-        ProcedureKind,
-        Reference,
-        StaticGet,
-        StringConstant,
-        StringLiteral,
-        Typedef;
+import 'package:kernel/ast.dart';
 
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
@@ -48,6 +27,7 @@
         templateTypeNotFound,
         templateUnspecified;
 
+import '../kernel/constructor_tearoff_lowering.dart';
 import '../kernel/redirecting_factory_body.dart'
     show RedirectingFactoryBody, isRedirectingFactoryField;
 
@@ -120,8 +100,23 @@
     isBuilt = true;
     library.classes.forEach(addClass);
     library.extensions.forEach(addExtension);
+
+    Map<String, Map<Name, Procedure>> tearOffs = {};
+    List<Procedure> nonTearOffs = [];
+    for (Procedure procedure in library.procedures) {
+      List<Object>? names = extractTypedefNameFromTearOff(procedure.name);
+      if (names != null) {
+        Map<Name, Procedure> map = tearOffs[names[0] as String] ??= {};
+        map[names[1] as Name] = procedure;
+      } else {
+        nonTearOffs.add(procedure);
+      }
+    }
+    nonTearOffs.forEach(addMember);
     library.procedures.forEach(addMember);
-    library.typedefs.forEach(addTypedef);
+    for (Typedef typedef in library.typedefs) {
+      addTypedef(typedef, tearOffs[typedef.name]);
+    }
     library.fields.forEach(addMember);
 
     if (isReadyToFinalizeExports) {
@@ -167,10 +162,28 @@
   }
 
   void addClass(Class cls) {
-    DillClassBuilder classBulder = new DillClassBuilder(cls, this);
-    addBuilder(cls.name, classBulder, cls.fileOffset);
-    cls.procedures.forEach(classBulder.addMember);
-    cls.constructors.forEach(classBulder.addMember);
+    DillClassBuilder classBuilder = new DillClassBuilder(cls, this);
+    addBuilder(cls.name, classBuilder, cls.fileOffset);
+    Map<String, Procedure> tearOffs = {};
+    List<Procedure> nonTearOffs = [];
+    for (Procedure procedure in cls.procedures) {
+      String? name = extractConstructorNameFromTearOff(procedure.name);
+      if (name != null) {
+        tearOffs[name] = procedure;
+      } else {
+        nonTearOffs.add(procedure);
+      }
+    }
+    for (Procedure procedure in nonTearOffs) {
+      if (procedure.kind == ProcedureKind.Factory) {
+        classBuilder.addFactory(procedure, tearOffs[procedure.name.text]);
+      } else {
+        classBuilder.addProcedure(procedure);
+      }
+    }
+    for (Constructor constructor in cls.constructors) {
+      classBuilder.addConstructor(constructor, tearOffs[constructor.name.text]);
+    }
     for (Field field in cls.fields) {
       if (isRedirectingFactoryField(field)) {
         ListLiteral initializer = field.initializer as ListLiteral;
@@ -179,7 +192,7 @@
           RedirectingFactoryBody.restoreFromDill(get.target as Procedure);
         }
       } else {
-        classBulder.addMember(field);
+        classBuilder.addField(field);
       }
     }
   }
@@ -215,10 +228,6 @@
         addBuilder(name, new DillFieldBuilder(member, this), member.fileOffset);
       } else if (member is Procedure) {
         switch (member.kind) {
-          case ProcedureKind.Factory:
-            addBuilder(
-                name, new DillFactoryBuilder(member, this), member.fileOffset);
-            break;
           case ProcedureKind.Setter:
             addBuilder(
                 name, new DillSetterBuilder(member, this), member.fileOffset);
@@ -269,12 +278,12 @@
     return declaration;
   }
 
-  void addTypedef(Typedef typedef) {
+  void addTypedef(Typedef typedef, Map<Name, Procedure>? tearOffs) {
     DartType? type = typedef.type;
     if (type is FunctionType && type.typedefType == null) {
       unhandled("null", "addTypedef", typedef.fileOffset, typedef.fileUri);
     }
-    addBuilder(typedef.name, new DillTypeAliasBuilder(typedef, this),
+    addBuilder(typedef.name, new DillTypeAliasBuilder(typedef, tearOffs, this),
         typedef.fileOffset);
   }
 
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 d076161..54a3158 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
@@ -188,13 +188,15 @@
 
 class DillFactoryBuilder extends DillMemberBuilder {
   final Procedure procedure;
+  final Procedure? _factoryTearOff;
 
-  DillFactoryBuilder(this.procedure, Builder parent) : super(procedure, parent);
+  DillFactoryBuilder(this.procedure, this._factoryTearOff, Builder parent)
+      : super(procedure, parent);
 
   Member get member => procedure;
 
   @override
-  Member? get readTarget => null;
+  Member? get readTarget => _factoryTearOff ?? procedure;
 
   @override
   Member? get writeTarget => null;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
index f78420c..6dc3d32 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
@@ -4,8 +4,7 @@
 
 library fasta.dill_typedef_builder;
 
-import 'package:kernel/ast.dart' show DartType, InvalidType, NullType, Typedef;
-import 'package:kernel/core_types.dart';
+import 'package:kernel/ast.dart';
 
 import '../builder/library_builder.dart';
 import '../builder/metadata_builder.dart';
@@ -15,20 +14,20 @@
 
 import '../problems.dart' show unimplemented;
 
-import '../util/helpers.dart';
-
 import 'dill_class_builder.dart' show computeTypeVariableBuilders;
 import 'dill_library_builder.dart' show DillLibraryBuilder;
 
 class DillTypeAliasBuilder extends TypeAliasBuilderImpl {
   final Typedef typedef;
 
+  final Map<Name, Procedure>? tearOffs;
+
   List<TypeVariableBuilder>? _typeVariables;
   TypeBuilder? _type;
 
   DartType? thisType;
 
-  DillTypeAliasBuilder(this.typedef, DillLibraryBuilder parent)
+  DillTypeAliasBuilder(this.typedef, this.tearOffs, DillLibraryBuilder parent)
       : super(null, typedef.name, parent, typedef.fileOffset);
 
   List<MetadataBuilder> get metadata {
@@ -91,10 +90,4 @@
 
   @override
   bool get isNullAlias => typedef.type is NullType;
-
-  @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
-    // TODO(johnniwinther): Remove the need for this.
-  }
 }
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index cb1f2a1..48bbed7 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -1918,7 +1918,7 @@
         if (cls == null) return null;
       }
 
-      userCode!.loader.seenMessages.clear();
+      userCode!.loader.resetSeenMessages();
 
       for (TypeParameter typeParam in typeDefinitions) {
         if (!isLegalIdentifier(typeParam.name!)) {
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 4656d20..771e607 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -46,6 +46,7 @@
 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/fixed_type_builder.dart';
 import '../builder/formal_parameter_builder.dart';
@@ -702,7 +703,8 @@
     if (count == 0) {
       push(NullValue.Metadata);
     } else {
-      push(const GrowableList<Expression>().pop(stack, count) ??
+      push(const GrowableList<Expression>()
+              .popNonNullable(stack, count, dummyExpression) ??
           NullValue.Metadata /* Ignore parser recovery */);
     }
   }
@@ -950,7 +952,9 @@
 
   DartType _computeReturnTypeContext(MemberBuilder member) {
     if (member is ProcedureBuilder) {
-      return member.actualProcedure.function.returnType;
+      return member.function.returnType;
+    } else if (member is SourceFactoryBuilder) {
+      return member.function.returnType;
     } else {
       assert(member is ConstructorBuilder);
       return const DynamicType();
@@ -1018,6 +1022,8 @@
       finishConstructor(builder, asyncModifier, body);
     } else if (builder is ProcedureBuilder) {
       builder.asyncModifier = asyncModifier;
+    } else if (builder is SourceFactoryBuilder) {
+      builder.asyncModifier = asyncModifier;
     } else {
       unhandled("${builder.runtimeType}", "finishFunction", builder.charOffset,
           builder.fileUri);
@@ -1251,12 +1257,16 @@
       } else {
         Substitution substitution = Substitution.fromPairs(
             initialTarget.function.typeParameters, arguments.types);
-        arguments.types.clear();
-        arguments.types.length = redirectionTarget!.typeArguments.length;
-        for (int i = 0; i < arguments.types.length; i++) {
-          arguments.types[i] =
+        for (int i = 0; i < redirectionTarget!.typeArguments.length; i++) {
+          DartType typeArgument =
               substitution.substituteType(redirectionTarget.typeArguments[i]);
+          if (i < arguments.types.length) {
+            arguments.types[i] = typeArgument;
+          } else {
+            arguments.types.add(typeArgument);
+          }
         }
+        arguments.types.length = redirectionTarget.typeArguments.length;
 
         replacementNode = buildStaticInvocation(
             resolvedTarget,
@@ -1681,7 +1691,10 @@
   @override
   void handleSend(Token beginToken, Token endToken) {
     assert(checkState(beginToken, [
-      ValueKinds.ArgumentsOrNull,
+      unionOfKinds([
+        ValueKinds.ArgumentsOrNull,
+        ValueKinds.ParserRecovery,
+      ]),
       ValueKinds.TypeArgumentsOrNull,
       unionOfKinds([
         ValueKinds.Expression,
@@ -1692,12 +1705,12 @@
       ])
     ]));
     debugEvent("Send");
-    Arguments? arguments = pop() as Arguments?;
+    Object? arguments = pop();
     List<UnresolvedType>? typeArguments = pop() as List<UnresolvedType>?;
     Object receiver = pop()!;
     // Delay adding [typeArguments] to [forest] for type aliases: They
     // must be unaliased to the type arguments of the denoted type.
-    bool isInForest = arguments != null &&
+    bool isInForest = arguments is Arguments &&
         typeArguments != null &&
         (receiver is! TypeUseGenerator ||
             (receiver is TypeUseGenerator &&
@@ -1711,22 +1724,23 @@
           (receiver is TypeUseGenerator &&
               receiver.declaration is TypeAliasBuilder));
     }
-    if (receiver is Identifier) {
+    if (receiver is ParserRecovery || arguments is ParserRecovery) {
+      push(new ParserErrorGenerator(
+          this, beginToken, fasta.messageSyntheticToken));
+    } else if (receiver is Identifier) {
       Name name = new Name(receiver.name, libraryBuilder.nameOrigin);
       if (arguments == null) {
         push(new IncompletePropertyAccessGenerator(this, beginToken, name));
       } else {
         push(new SendAccessGenerator(
-            this, beginToken, name, typeArguments, arguments,
+            this, beginToken, name, typeArguments, arguments as Arguments,
             isTypeArgumentsInForest: isInForest));
       }
-    } else if (receiver is ParserRecovery) {
-      push(new ParserErrorGenerator(
-          this, beginToken, fasta.messageSyntheticToken));
     } else if (arguments == null) {
       push(receiver);
     } else {
-      push(finishSend(receiver, typeArguments, arguments, beginToken.charOffset,
+      push(finishSend(receiver, typeArguments, arguments as Arguments,
+          beginToken.charOffset,
           isTypeArgumentsInForest: isInForest));
     }
     assert(checkState(beginToken, [
@@ -2674,7 +2688,7 @@
     if (!libraryBuilder.isNonNullableByDefault) {
       reportNonNullableModifierError(lateToken);
     }
-    UnresolvedType type = pop() as UnresolvedType;
+    UnresolvedType? type = pop() as UnresolvedType?;
     int modifiers = (lateToken != null ? lateMask : 0) |
         Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
     _enterLocalState(inLateLocalInitializer: lateToken != null);
@@ -4949,7 +4963,8 @@
   @override
   void endTypeArguments(int count, Token beginToken, Token endToken) {
     debugEvent("TypeArguments");
-    push(const FixedNullableList<UnresolvedType>().pop(stack, count) ??
+    push(const FixedNullableList<UnresolvedType>()
+            .popNonNullable(stack, count, dummyUnresolvedType) ??
         NullValue.TypeArguments);
   }
 
@@ -4996,10 +5011,28 @@
   @override
   void handleNamedArgument(Token colon) {
     debugEvent("NamedArgument");
+    assert(checkState(colon, [
+      unionOfKinds([
+        ValueKinds.Expression,
+        ValueKinds.Generator,
+      ]),
+      unionOfKinds([
+        ValueKinds.Identifier,
+        ValueKinds.ParserRecovery,
+      ])
+    ]));
     Expression value = popForValue();
-    Identifier identifier = pop() as Identifier;
-    push(new NamedExpression(identifier.name, value)
-      ..fileOffset = identifier.charOffset);
+    Object? identifier = pop();
+    if (identifier is Identifier) {
+      push(new NamedExpression(identifier.name, value)
+        ..fileOffset = identifier.charOffset);
+    } else {
+      assert(
+          identifier is ParserRecovery,
+          "Unexpected argument name: "
+          "${identifier} (${identifier.runtimeType})");
+      push(identifier);
+    }
   }
 
   @override
@@ -6550,9 +6583,7 @@
               arguments))
         ..fileOffset = receiver.fileOffset;
     } else {
-      MethodInvocation node =
-          forest.createMethodInvocation(offset, receiver, name, arguments);
-      return node;
+      return forest.createMethodInvocation(offset, receiver, name, arguments);
     }
   }
 
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 a3f7c13..5bc55d2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -20,6 +20,7 @@
 
 import 'dart:io' as io;
 
+import 'package:front_end/src/fasta/kernel/constructor_tearoff_lowering.dart';
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/clone.dart';
@@ -40,6 +41,8 @@
         messageConstEvalCircularity,
         messageConstEvalContext,
         messageConstEvalExtension,
+        messageConstEvalExternalConstructor,
+        messageConstEvalExternalFactory,
         messageConstEvalFailedAssertion,
         messageConstEvalNotListOrSetInSpread,
         messageConstEvalNotMapInSpread,
@@ -453,8 +456,7 @@
       transformTypeParameterList(node.typeParameters, node);
       transformConstructorList(node.constructors, node);
       transformProcedureList(node.procedures, node);
-      transformRedirectingFactoryConstructorList(
-          node.redirectingFactoryConstructors, node);
+      transformRedirectingFactoryList(node.redirectingFactories, node);
     });
     _staticTypeContext = oldStaticTypeContext;
     return node;
@@ -511,17 +513,15 @@
   }
 
   @override
-  RedirectingFactoryConstructor visitRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor node, TreeNode? removalSentinel) {
+  RedirectingFactory visitRedirectingFactory(
+      RedirectingFactory node, TreeNode? removalSentinel) {
     // Currently unreachable as the compiler doesn't produce
     // RedirectingFactoryConstructor.
     StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
     _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
     constantEvaluator.withNewEnvironment(() {
       transformAnnotations(node.annotations, node);
-      transformTypeParameterList(node.typeParameters, node);
-      transformVariableDeclarationList(node.positionalParameters, node);
-      transformVariableDeclarationList(node.namedParameters, node);
+      node.function = transform(node.function)..parent = node;
     });
     _staticTypeContext = oldStaticTypeContext;
     return node;
@@ -701,21 +701,63 @@
 
   @override
   TreeNode visitStaticTearOff(StaticTearOff node, TreeNode? removalSentinel) {
-    final Member target = node.target;
-    if (target is Procedure && target.kind == ProcedureKind.Method) {
-      return evaluateAndTransformWithContext(node, node);
-    }
-    return super.visitStaticTearOff(node, removalSentinel);
+    return evaluateAndTransformWithContext(node, node);
+  }
+
+  @override
+  TreeNode visitConstructorTearOff(
+      ConstructorTearOff node, TreeNode? removalSentinel) {
+    return evaluateAndTransformWithContext(node, node);
+  }
+
+  @override
+  TreeNode visitRedirectingFactoryTearOff(
+      RedirectingFactoryTearOff node, TreeNode? removalSentinel) {
+    return evaluateAndTransformWithContext(node, node);
+  }
+
+  @override
+  TreeNode visitTypedefTearOff(TypedefTearOff node, TreeNode? removalSentinel) {
+    return evaluateAndTransformWithContext(node, node);
   }
 
   @override
   TreeNode visitInstantiation(Instantiation node, TreeNode? removalSentinel) {
     Instantiation result =
         super.visitInstantiation(node, removalSentinel) as Instantiation;
-    if (enableConstructorTearOff &&
-        result.expression is ConstantExpression &&
-        result.typeArguments.every(isInstantiated)) {
-      return evaluateAndTransformWithContext(node, result);
+    Expression expression = result.expression;
+    if (enableConstructorTearOff && expression is ConstantExpression) {
+      if (result.typeArguments.every(isInstantiated)) {
+        return evaluateAndTransformWithContext(node, result);
+      } else {
+        Constant constant = expression.constant;
+        if (constant is TypedefTearOffConstant) {
+          Substitution substitution =
+              Substitution.fromPairs(constant.parameters, node.typeArguments);
+          return new Instantiation(
+              new ConstantExpression(constant.tearOffConstant,
+                  constant.tearOffConstant.getType(_staticTypeContext!))
+                ..fileOffset = expression.fileOffset,
+              constant.types.map(substitution.substituteType).toList());
+        } else {
+          LoweredTypedefTearOff? loweredTypedefTearOff =
+              LoweredTypedefTearOff.fromConstant(constant);
+          if (loweredTypedefTearOff != null) {
+            Constant tearOffConstant = constantEvaluator
+                .canonicalize(loweredTypedefTearOff.targetTearOffConstant);
+            Substitution substitution = Substitution.fromPairs(
+                loweredTypedefTearOff.typedefTearOff.function.typeParameters,
+                node.typeArguments);
+            return new Instantiation(
+                new ConstantExpression(tearOffConstant,
+                    tearOffConstant.getType(_staticTypeContext!))
+                  ..fileOffset = expression.fileOffset,
+                loweredTypedefTearOff.typeArguments
+                    .map(substitution.substituteType)
+                    .toList());
+          }
+        }
+      }
     }
     return node;
   }
@@ -933,7 +975,7 @@
       : numberSemantics = backend.numberSemantics,
         coreTypes = typeEnvironment.coreTypes,
         canonicalizationCache = <Constant, Constant>{},
-        nodeCache = <Node, Constant>{},
+        nodeCache = <Node, Constant?>{},
         env = new EvaluationEnvironment() {
     if (environmentDefines == null && !backend.supportsUnevaluatedConstants) {
       throw new ArgumentError(
@@ -1250,7 +1292,7 @@
       // environment.
       // For const functions, recompute getters instead of using the cached
       // value.
-      bool isGetter = node is InstanceGet || node is PropertyGet;
+      bool isGetter = node is InstanceGet;
       if (nodeCache.containsKey(node) && !(enableConstFunctions && isGetter)) {
         Constant? cachedResult = nodeCache[node];
         if (cachedResult == null) {
@@ -1273,8 +1315,7 @@
     } else {
       bool sentinelInserted = false;
       if (nodeCache.containsKey(node)) {
-        bool isRecursiveFunctionCall = node is MethodInvocation ||
-            node is InstanceInvocation ||
+        bool isRecursiveFunctionCall = node is InstanceInvocation ||
             node is FunctionInvocation ||
             node is LocalFunctionInvocation ||
             node is StaticInvocation;
@@ -1612,6 +1653,8 @@
           node,
           'Constructor "$node" has non-trivial body '
           '"${constructor.function.body.runtimeType}".');
+    } else if (constructor.isExternal) {
+      return createErrorConstant(node, messageConstEvalExternalConstructor);
     }
     return null;
   }
@@ -2476,52 +2519,6 @@
   }
 
   @override
-  Constant visitMethodInvocation(MethodInvocation node) {
-    // We have no support for generic method invocation at the moment.
-    if (node.arguments.types.isNotEmpty && !enableConstFunctions) {
-      return createInvalidExpressionConstant(node, "generic method invocation");
-    }
-
-    // We have no support for method invocation with named arguments at the
-    // moment.
-    if (node.arguments.named.isNotEmpty && !enableConstFunctions) {
-      return createInvalidExpressionConstant(
-          node, "method invocation with named arguments");
-    }
-
-    final Constant receiver = _evaluateSubexpression(node.receiver);
-    if (receiver is AbortConstant) return receiver;
-
-    final List<Constant>? positionalArguments =
-        _evaluatePositionalArguments(node.arguments);
-
-    if (positionalArguments == null) {
-      AbortConstant error = _gotError!;
-      _gotError = null;
-      return error;
-    }
-    assert(_gotError == null);
-    // ignore: unnecessary_null_comparison
-    assert(positionalArguments != null);
-
-    if (shouldBeUnevaluated) {
-      return unevaluated(
-          node,
-          new MethodInvocation(
-              extract(receiver),
-              node.name,
-              unevaluatedArguments(
-                  positionalArguments, {}, node.arguments.types),
-              node.interfaceTarget)
-            ..fileOffset = node.fileOffset
-            ..flags = node.flags);
-    }
-
-    return _handleInvocation(node, node.name, receiver, positionalArguments,
-        arguments: node.arguments);
-  }
-
-  @override
   Constant visitLogicalExpression(LogicalExpression node) {
     final Constant left = _evaluateSubexpression(node.left);
     if (left is AbortConstant) return left;
@@ -2750,87 +2747,6 @@
   }
 
   @override
-  Constant visitPropertyGet(PropertyGet node) {
-    if (node.receiver is ThisExpression) {
-      // Probably unreachable unless trying to evaluate non-const stuff as
-      // const.
-      // Access "this" during instance creation.
-      if (instanceBuilder == null) {
-        return createErrorConstant(node, messageNotAConstantExpression);
-      }
-
-      for (final MapEntry<Field, Constant> entry
-          in instanceBuilder!.fields.entries) {
-        final Field field = entry.key;
-        if (field.name == node.name) {
-          return entry.value;
-        }
-      }
-
-      // Meant as a "stable backstop for situations where Fasta fails to
-      // rewrite various erroneous constructs into invalid expressions".
-      // Probably unreachable.
-      return createInvalidExpressionConstant(node,
-          'Could not evaluate field get ${node.name} on incomplete instance');
-    }
-
-    final Constant receiver = _evaluateSubexpression(node.receiver);
-    if (receiver is AbortConstant) return receiver;
-    if (receiver is StringConstant && node.name.text == 'length') {
-      return canonicalize(intFolder.makeIntConstant(receiver.value.length));
-    } else if (shouldBeUnevaluated) {
-      return unevaluated(node,
-          new PropertyGet(extract(receiver), node.name, node.interfaceTarget));
-    } else if (receiver is NullConstant) {
-      return createErrorConstant(node, messageConstEvalNullValue);
-    } else if (receiver is ListConstant && enableConstFunctions) {
-      switch (node.name.text) {
-        case 'first':
-          if (receiver.entries.isEmpty) {
-            return new _AbortDueToThrowConstant(
-                node, new StateError('No element'));
-          }
-          return receiver.entries.first;
-        case 'isEmpty':
-          return new BoolConstant(receiver.entries.isEmpty);
-        case 'isNotEmpty':
-          return new BoolConstant(receiver.entries.isNotEmpty);
-        // TODO(kallentu): case 'iterator'
-        case 'last':
-          if (receiver.entries.isEmpty) {
-            return new _AbortDueToThrowConstant(
-                node, new StateError('No element'));
-          }
-          return receiver.entries.last;
-        case 'length':
-          return new IntConstant(receiver.entries.length);
-        // TODO(kallentu): case 'reversed'
-        case 'single':
-          if (receiver.entries.isEmpty) {
-            return new _AbortDueToThrowConstant(
-                node, new StateError('No element'));
-          } else if (receiver.entries.length > 1) {
-            return new _AbortDueToThrowConstant(
-                node, new StateError('Too many elements'));
-          }
-          return receiver.entries.single;
-      }
-    } else if (receiver is InstanceConstant && enableConstFunctions) {
-      for (final MapEntry<Reference, Constant> entry
-          in receiver.fieldValues.entries) {
-        final Field field = entry.key.asField;
-        if (field.name == node.name) {
-          return entry.value;
-        }
-      }
-    }
-    return createErrorConstant(
-        node,
-        templateConstEvalInvalidPropertyGet.withArguments(
-            node.name.text, receiver, isNonNullableByDefault));
-  }
-
-  @override
   Constant visitLet(Let node) {
     Constant value = _evaluateSubexpression(node.variable.initializer!);
     if (value is AbortConstant) return value;
@@ -2931,21 +2847,7 @@
 
   @override
   Constant visitStaticTearOff(StaticTearOff node) {
-    return withNewEnvironment(() {
-      final Member target = node.target;
-      if (target is Procedure) {
-        if (target.kind == ProcedureKind.Method) {
-          return canonicalize(new StaticTearOffConstant(target));
-        }
-        return createErrorConstant(
-            node,
-            templateConstEvalInvalidStaticInvocation
-                .withArguments(target.name.text));
-      } else {
-        return createInvalidExpressionConstant(
-            node, 'No support for ${target.runtimeType} in a static tear-off.');
-      }
-    });
+    return canonicalize(new StaticTearOffConstant(node.target));
   }
 
   @override
@@ -2954,7 +2856,7 @@
     for (int i = 0; i < node.expressions.length; i++) {
       Constant constant = _evaluateSubexpression(node.expressions[i]);
       if (constant is AbortConstant) return constant;
-      if (constant is PrimitiveConstant<Object>) {
+      if (constant is PrimitiveConstant) {
         String value;
         if (constant is DoubleConstant && intFolder.isInt(constant)) {
           value = new BigInt.from(constant.value).toString();
@@ -3000,12 +2902,7 @@
   Constant _getFromEnvironmentDefaultValue(Procedure target) {
     VariableDeclaration variable = target.function.namedParameters
         .singleWhere((v) => v.name == 'defaultValue');
-    return variable.initializer != null
-        ? _evaluateExpressionInContext(target, variable.initializer!)
-        :
-        // Not reachable unless a defaultValue in fromEnvironment in dart:core
-        // becomes null.
-        nullConstant;
+    return _evaluateExpressionInContext(target, variable.initializer!);
   }
 
   Constant _handleFromEnvironment(
@@ -3118,30 +3015,33 @@
               isConst: true));
     }
     if (target.kind == ProcedureKind.Factory) {
-      if (target.isConst &&
-          target.enclosingLibrary == coreTypes.coreLibrary &&
-          positionals.length == 1 &&
-          (target.name.text == "fromEnvironment" ||
-              target.name.text == "hasEnvironment")) {
-        if (environmentDefines != null) {
-          // Evaluate environment constant.
-          Constant name = positionals.single;
-          if (name is StringConstant) {
-            if (target.name.text == "fromEnvironment") {
-              return _handleFromEnvironment(target, name, named);
-            } else {
-              return _handleHasEnvironment(name);
+      if (target.isConst) {
+        if (target.enclosingLibrary == coreTypes.coreLibrary &&
+            positionals.length == 1 &&
+            (target.name.text == "fromEnvironment" ||
+                target.name.text == "hasEnvironment")) {
+          if (environmentDefines != null) {
+            // Evaluate environment constant.
+            Constant name = positionals.single;
+            if (name is StringConstant) {
+              if (target.name.text == "fromEnvironment") {
+                return _handleFromEnvironment(target, name, named);
+              } else {
+                return _handleHasEnvironment(name);
+              }
+            } else if (name is NullConstant) {
+              return createErrorConstant(node, messageConstEvalNullValue);
             }
-          } else if (name is NullConstant) {
-            return createErrorConstant(node, messageConstEvalNullValue);
+          } else {
+            // Leave environment constant unevaluated.
+            return unevaluated(
+                node,
+                new StaticInvocation(target,
+                    unevaluatedArguments(positionals, named, arguments.types),
+                    isConst: true));
           }
-        } else {
-          // Leave environment constant unevaluated.
-          return unevaluated(
-              node,
-              new StaticInvocation(target,
-                  unevaluatedArguments(positionals, named, arguments.types),
-                  isConst: true));
+        } else if (target.isExternal) {
+          return createErrorConstant(node, messageConstEvalExternalFactory);
         }
       }
     } else if (target.name.text == 'identical') {
@@ -3393,7 +3293,7 @@
 
   @override
   Constant visitInstantiation(Instantiation node) {
-    final Constant constant = _evaluateSubexpression(node.expression);
+    Constant constant = _evaluateSubexpression(node.expression);
     if (constant is AbortConstant) return constant;
     if (shouldBeUnevaluated) {
       return unevaluated(
@@ -3401,41 +3301,58 @@
           new Instantiation(extract(constant),
               node.typeArguments.map((t) => env.substituteType(t)).toList()));
     }
-    if (constant is StaticTearOffConstant) {
-      Member constantMember = constant.procedure;
-      if (constantMember is Procedure) {
-        if (node.typeArguments.length ==
-            constantMember.function.typeParameters.length) {
-          List<DartType>? types = _evaluateDartTypes(node, node.typeArguments);
-          if (types == null) {
-            AbortConstant error = _gotError!;
-            _gotError = null;
-            return error;
-          }
-          assert(_gotError == null);
-          // ignore: unnecessary_null_comparison
-          assert(types != null);
-
-          final List<DartType> typeArguments = convertTypes(types);
-          return canonicalize(
-              new InstantiationConstant(constant, typeArguments));
-        } else {
-          // Probably unreachable.
-          return createInvalidExpressionConstant(
-              node,
-              'The number of type arguments supplied in the partial '
-              'instantiation does not match the number of type arguments '
-              'of the $constant.');
+    List<TypeParameter>? typeParameters;
+    if (constant is TearOffConstant) {
+      Member target = constant.target;
+      if (target is Procedure) {
+        typeParameters = target.function.typeParameters;
+      } else if (target is Constructor) {
+        typeParameters = target.enclosingClass.typeParameters;
+      }
+    } else if (constant is TypedefTearOffConstant) {
+      typeParameters = constant.parameters;
+    }
+    if (typeParameters != null) {
+      if (node.typeArguments.length == typeParameters.length) {
+        List<DartType>? types = _evaluateDartTypes(node, node.typeArguments);
+        if (types == null) {
+          AbortConstant error = _gotError!;
+          _gotError = null;
+          return error;
         }
-      } else if (constantMember is Constructor) {
-        // TODO(dmitryas): Add support for instantiated constructor tear-offs.
-        return defaultExpression(node);
+        assert(_gotError == null);
+        // ignore: unnecessary_null_comparison
+        assert(types != null);
+
+        List<DartType> typeArguments = convertTypes(types);
+        if (constant is TypedefTearOffConstant) {
+          Substitution substitution =
+              Substitution.fromPairs(constant.parameters, typeArguments);
+          typeArguments =
+              constant.types.map(substitution.substituteType).toList();
+          constant = constant.tearOffConstant;
+        } else {
+          LoweredTypedefTearOff? loweredTypedefTearOff =
+              LoweredTypedefTearOff.fromConstant(constant);
+          if (loweredTypedefTearOff != null) {
+            constant =
+                canonicalize(loweredTypedefTearOff.targetTearOffConstant);
+            Substitution substitution = Substitution.fromPairs(
+                loweredTypedefTearOff.typedefTearOff.function.typeParameters,
+                node.typeArguments);
+            typeArguments = loweredTypedefTearOff.typeArguments
+                .map(substitution.substituteType)
+                .toList();
+          }
+        }
+        return canonicalize(new InstantiationConstant(constant, typeArguments));
       } else {
         // Probably unreachable.
         return createInvalidExpressionConstant(
             node,
-            "Unsupported kind of a torn off member: "
-            "'${constantMember.runtimeType}'.");
+            'The number of type arguments supplied in the partial '
+            'instantiation does not match the number of type arguments '
+            'of the $constant.');
       }
     }
     // The inner expression in an instantiation can never be null, since
@@ -3447,12 +3364,33 @@
 
   @override
   Constant visitConstructorTearOff(ConstructorTearOff node) {
-    return defaultExpression(node);
+    return canonicalize(new ConstructorTearOffConstant(node.target));
+  }
+
+  @override
+  Constant visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+    return canonicalize(new RedirectingFactoryTearOffConstant(node.target));
   }
 
   @override
   Constant visitTypedefTearOff(TypedefTearOff node) {
-    return defaultExpression(node);
+    final Constant constant = _evaluateSubexpression(node.expression);
+    if (constant is TearOffConstant) {
+      FreshTypeParameters freshTypeParameters =
+          getFreshTypeParameters(node.typeParameters);
+      List<TypeParameter> typeParameters =
+          freshTypeParameters.freshTypeParameters;
+      List<DartType> typeArguments = new List<DartType>.generate(
+          node.typeArguments.length,
+          (int i) => freshTypeParameters.substitute(node.typeArguments[i]),
+          growable: false);
+      return canonicalize(
+          new TypedefTearOffConstant(typeParameters, constant, typeArguments));
+    } else {
+      // Probably unreachable.
+      return createInvalidExpressionConstant(
+          node, "Unexpected typedef tearoff target: ${constant}.");
+    }
   }
 
   @override
@@ -3784,9 +3722,6 @@
   Constant visitLoadLibrary(LoadLibrary node) => defaultExpression(node);
 
   @override
-  Constant visitPropertySet(PropertySet node) => defaultExpression(node);
-
-  @override
   Constant visitRethrow(Rethrow node) => defaultExpression(node);
 
   @override
@@ -4265,11 +4200,21 @@
   }
 
   @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
+    throw new UnimplementedError();
+  }
+
+  @override
   R acceptReference<R>(Visitor<R> v) {
     throw new UnimplementedError();
   }
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
+    throw new UnimplementedError();
+  }
+
+  @override
   Expression asExpression() {
     throw new UnimplementedError();
   }
@@ -4325,11 +4270,21 @@
   }
 
   @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
+    throw new UnimplementedError();
+  }
+
+  @override
   R acceptReference<R>(Visitor<R> v) {
     throw new UnimplementedError();
   }
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
+    throw new UnimplementedError();
+  }
+
+  @override
   Expression asExpression() {
     throw new UnimplementedError();
   }
@@ -4382,11 +4337,21 @@
   }
 
   @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
+    throw new UnimplementedError();
+  }
+
+  @override
   R acceptReference<R>(Visitor<R> v) {
     throw new UnimplementedError();
   }
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
+    throw new UnimplementedError();
+  }
+
+  @override
   Expression asExpression() {
     throw new UnimplementedError();
   }
@@ -4439,11 +4404,21 @@
   }
 
   @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
+    throw new UnimplementedError();
+  }
+
+  @override
   R acceptReference<R>(Visitor<R> v) {
     throw new UnimplementedError();
   }
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
+    throw new UnimplementedError();
+  }
+
+  @override
   Expression asExpression() {
     throw new UnimplementedError();
   }
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 33aa5d1..ada23ac 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
@@ -2,83 +2,323 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:front_end/src/fasta/kernel/kernel_api.dart';
 import 'package:kernel/ast.dart';
 import 'package:kernel/type_algebra.dart';
 import '../builder/member_builder.dart';
 import '../source/source_library_builder.dart';
+import 'kernel_api.dart';
+import 'kernel_helper.dart';
 
-/// Creates the synthesized name to use for the lowering of a generative
-/// constructor by the given [constructorName] in [library].
-Name constructorTearOffName(String constructorName, Library library) {
+const String _tearOffNamePrefix = '_#';
+const String _tearOffNameSuffix = '#tearOff';
+
+/// Creates the synthesized name to use for the lowering of the tear off of a
+/// constructor or factory by the given [name] in [library].
+Name constructorTearOffName(String name, Library library) {
   return new Name(
-      '_#${constructorName.isEmpty ? 'new' : constructorName}#tearOff',
+      '$_tearOffNamePrefix'
+      '${name.isEmpty ? 'new' : name}'
+      '$_tearOffNameSuffix',
       library);
 }
 
+/// Creates the synthesized name to use for the lowering of the tear off of a
+/// constructor or factory by the given [constructorName] in [library].
+Name typedefTearOffName(
+    String typedefName, String constructorName, Library library) {
+  return new Name(
+      '$_tearOffNamePrefix'
+      '$typedefName#'
+      '${constructorName.isEmpty ? 'new' : constructorName}'
+      '$_tearOffNameSuffix',
+      library);
+}
+
+/// Returns the name of the corresponding constructor or factory if [name] is
+/// the synthesized name of a lowering of the tear off of a constructor or
+/// factory. Returns `null` otherwise.
+String? extractConstructorNameFromTearOff(Name name) {
+  if (name.text.startsWith(_tearOffNamePrefix) &&
+      name.text.endsWith(_tearOffNameSuffix) &&
+      name.text.length >
+          _tearOffNamePrefix.length + _tearOffNameSuffix.length) {
+    String text =
+        name.text.substring(0, name.text.length - _tearOffNameSuffix.length);
+    text = text.substring(_tearOffNamePrefix.length);
+    if (text.contains('#')) {
+      return null;
+    }
+    return text == 'new' ? '' : text;
+  }
+  return null;
+}
+
+/// If [name] is the synthesized name of a lowering of a typedef tear off, a
+/// list containing the [String] name of the typedef and the [Name] name of the
+/// corresponding constructor or factory is returned. Returns `null` otherwise.
+List<Object>? extractTypedefNameFromTearOff(Name name) {
+  if (name.text.startsWith(_tearOffNamePrefix) &&
+      name.text.endsWith(_tearOffNameSuffix) &&
+      name.text.length >
+          _tearOffNamePrefix.length + _tearOffNameSuffix.length) {
+    String text =
+        name.text.substring(0, name.text.length - _tearOffNameSuffix.length);
+    text = text.substring(_tearOffNamePrefix.length);
+    int hashIndex = text.indexOf('#');
+    if (hashIndex == -1) {
+      return null;
+    }
+    String typedefName = text.substring(0, hashIndex);
+    String constructorName = text.substring(hashIndex + 1);
+    constructorName = constructorName == 'new' ? '' : constructorName;
+    return [typedefName, new Name(constructorName, name.library)];
+  }
+  return null;
+}
+
+/// Returns `true` if [procedure] is a lowered typedef tear off.
+bool isTypedefTearOffLowering(Procedure procedure) {
+  return extractTypedefNameFromTearOff(procedure.name) != null;
+}
+
 /// Creates the [Procedure] for the lowering of a generative constructor of
 /// the given [name] in [compilationUnit].
 ///
 /// If constructor tear off lowering is not enabled, `null` is returned.
-Procedure? createConstructorTearOffProcedure(
-    String name, SourceLibraryBuilder compilationUnit, int fileOffset,
+Procedure? createConstructorTearOffProcedure(String name,
+    SourceLibraryBuilder compilationUnit, Uri fileUri, int fileOffset,
     {required bool forAbstractClassOrEnum}) {
   if (!forAbstractClassOrEnum &&
       compilationUnit
           .loader.target.backendTarget.isConstructorTearOffLoweringEnabled) {
-    return new Procedure(constructorTearOffName(name, compilationUnit.library),
-        ProcedureKind.Method, new FunctionNode(null),
-        fileUri: compilationUnit.fileUri, isStatic: true)
-      ..startFileOffset = fileOffset
-      ..fileOffset = fileOffset
-      ..fileEndOffset = fileOffset
-      ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault;
+    return _createTearOffProcedure(
+        compilationUnit,
+        constructorTearOffName(name, compilationUnit.library),
+        fileUri,
+        fileOffset);
   }
   return null;
 }
 
-/// Creates the parameters and body for [tearOff] based on [constructor].
-void buildConstructorTearOffProcedure(
-    Procedure tearOff,
-    Constructor constructor,
-    Class enclosingClass,
-    SourceLibraryBuilder libraryBuilder) {
+/// Creates the [Procedure] for the lowering of a non-redirecting factory of
+/// the given [name] in [compilationUnit].
+///
+/// If constructor tear off lowering is not enabled, `null` is returned.
+Procedure? createFactoryTearOffProcedure(String name,
+    SourceLibraryBuilder compilationUnit, Uri fileUri, int fileOffset) {
+  if (compilationUnit
+      .loader.target.backendTarget.isFactoryTearOffLoweringEnabled) {
+    return _createTearOffProcedure(
+        compilationUnit,
+        constructorTearOffName(name, compilationUnit.library),
+        fileUri,
+        fileOffset);
+  }
+  return null;
+}
+
+/// Creates the [Procedure] for the lowering of a typedef tearoff of a
+/// constructor of the given [name] in with the typedef defined in
+/// [libraryBuilder].
+Procedure createTypedefTearOffProcedure(String typedefName, String name,
+    SourceLibraryBuilder libraryBuilder, Uri fileUri, int fileOffset) {
+  return _createTearOffProcedure(
+      libraryBuilder,
+      typedefTearOffName(typedefName, name, libraryBuilder.library),
+      fileUri,
+      fileOffset);
+}
+
+/// Creates the parameters and body for [tearOff] based on [constructor] in
+/// [enclosingClass].
+void buildConstructorTearOffProcedure(Procedure tearOff, Member constructor,
+    Class enclosingClass, SourceLibraryBuilder libraryBuilder) {
+  assert(
+      constructor is Constructor ||
+          (constructor is Procedure && constructor.isFactory) ||
+          (constructor is Procedure && constructor.isStatic),
+      "Unexpected constructor tear off target $constructor "
+      "(${constructor.runtimeType}).");
+
   int fileOffset = tearOff.fileOffset;
 
-  List<TypeParameter> classTypeParameters = enclosingClass.typeParameters;
-
-  List<TypeParameter> typeParameters;
-  List<DartType> typeArguments;
-  Substitution substitution = Substitution.empty;
-  if (classTypeParameters.isNotEmpty) {
-    FreshTypeParameters freshTypeParameters =
-        getFreshTypeParameters(classTypeParameters);
-    typeParameters = freshTypeParameters.freshTypeParameters;
-    typeArguments = freshTypeParameters.freshTypeArguments;
-    substitution = freshTypeParameters.substitution;
-    tearOff.function.typeParameters.addAll(typeParameters);
-    setParents(typeParameters, tearOff.function);
+  FunctionNode function = constructor.function!;
+  List<TypeParameter> classTypeParameters;
+  if (constructor is Constructor) {
+    // Generative constructors implicitly have the type parameters of the
+    // enclosing class.
+    classTypeParameters = enclosingClass.typeParameters;
   } else {
-    typeParameters = [];
-    typeArguments = [];
-    substitution = Substitution.empty;
+    // Factory constructors explicitly copy over the type parameters of the
+    // enclosing class.
+    classTypeParameters = function.typeParameters;
   }
 
-  List<Expression> positionalArguments = [];
+  FreshTypeParameters freshTypeParameters =
+      _createFreshTypeParameters(classTypeParameters, tearOff.function);
+
+  List<DartType> typeArguments = freshTypeParameters.freshTypeArguments;
+  Substitution substitution = freshTypeParameters.substitution;
+  _createParameters(tearOff, constructor, substitution, libraryBuilder);
+  Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
+  _createTearOffBody(tearOff, constructor, arguments);
+  tearOff.function.fileOffset = tearOff.fileOffset;
+  tearOff.function.fileEndOffset = tearOff.fileOffset;
+  updatePrivateMemberName(tearOff, libraryBuilder);
+}
+
+/// Creates the parameters and body for [tearOff] for a typedef tearoff of
+/// [constructor] in [enclosingClass] with [typeParameters] as the typedef
+/// parameters and [typeArguments] as the arguments passed to the
+/// [enclosingClass].
+void buildTypedefTearOffProcedure(
+    Procedure tearOff,
+    Member constructor,
+    Class enclosingClass,
+    List<TypeParameter> typeParameters,
+    List<DartType> typeArguments,
+    SourceLibraryBuilder libraryBuilder) {
+  assert(
+      constructor is Constructor ||
+          (constructor is Procedure && constructor.isFactory) ||
+          (constructor is Procedure && constructor.isStatic),
+      "Unexpected constructor tear off target $constructor "
+      "(${constructor.runtimeType}).");
+
+  int fileOffset = tearOff.fileOffset;
+
+  FunctionNode function = constructor.function!;
+  List<TypeParameter> classTypeParameters;
+  if (constructor is Constructor) {
+    // Generative constructors implicitly have the type parameters of the
+    // enclosing class.
+    classTypeParameters = enclosingClass.typeParameters;
+  } else {
+    // Factory constructors explicitly copy over the type parameters of the
+    // enclosing class.
+    classTypeParameters = function.typeParameters;
+  }
+
+  FreshTypeParameters freshTypeParameters =
+      _createFreshTypeParameters(typeParameters, tearOff.function);
+
+  Substitution substitution = freshTypeParameters.substitution;
+  if (!substitution.isEmpty) {
+    if (typeArguments.isNotEmpty) {
+      // Translate [typeArgument] into the context of the synthesized procedure.
+      typeArguments = new List<DartType>.generate(typeArguments.length,
+          (int index) => substitution.substituteType(typeArguments[index]));
+    }
+  }
+  _createParameters(
+      tearOff,
+      constructor,
+      Substitution.fromPairs(classTypeParameters, typeArguments),
+      libraryBuilder);
+  Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
+  _createTearOffBody(tearOff, constructor, arguments);
+  tearOff.function.fileOffset = tearOff.fileOffset;
+  tearOff.function.fileEndOffset = tearOff.fileOffset;
+  updatePrivateMemberName(tearOff, libraryBuilder);
+}
+
+/// Creates the parameters for the redirecting factory [tearOff] based on the
+/// [redirectingConstructor] declaration.
+FreshTypeParameters buildRedirectingFactoryTearOffProcedureParameters(
+    Procedure tearOff,
+    Procedure redirectingConstructor,
+    SourceLibraryBuilder libraryBuilder) {
+  assert(redirectingConstructor.isRedirectingFactory);
+  FunctionNode function = redirectingConstructor.function;
+  FreshTypeParameters freshTypeParameters =
+      _createFreshTypeParameters(function.typeParameters, tearOff.function);
+  Substitution substitution = freshTypeParameters.substitution;
+  _createParameters(
+      tearOff, redirectingConstructor, substitution, libraryBuilder);
+  tearOff.function.fileOffset = tearOff.fileOffset;
+  tearOff.function.fileEndOffset = tearOff.fileOffset;
+  updatePrivateMemberName(tearOff, libraryBuilder);
+  return freshTypeParameters;
+}
+
+/// Creates the body for the redirecting factory [tearOff] with the target
+/// [constructor] and [typeArguments].
+///
+/// Returns the [SynthesizedFunctionNode] object need to perform default value
+/// computation.
+SynthesizedFunctionNode buildRedirectingFactoryTearOffBody(
+    Procedure tearOff,
+    Member target,
+    List<DartType> typeArguments,
+    FreshTypeParameters freshTypeParameters) {
+  int fileOffset = tearOff.fileOffset;
+
+  if (!freshTypeParameters.substitution.isEmpty) {
+    if (typeArguments.isNotEmpty) {
+      // Translate [typeArgument] into the context of the synthesized procedure.
+      typeArguments = new List<DartType>.generate(
+          typeArguments.length,
+          (int index) => freshTypeParameters.substitution
+              .substituteType(typeArguments[index]));
+    }
+  }
+
+  Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
+  _createTearOffBody(tearOff, target, arguments);
+  return new SynthesizedFunctionNode(
+      new Map<TypeParameter, DartType>.fromIterables(
+          target.enclosingClass!.typeParameters, typeArguments),
+      target.function!,
+      tearOff.function,
+      identicalSignatures: false);
+}
+
+/// Creates the synthesized [Procedure] node for a tear off lowering by the
+/// given [name].
+Procedure _createTearOffProcedure(SourceLibraryBuilder libraryBuilder,
+    Name name, Uri fileUri, int fileOffset) {
+  return new Procedure(name, ProcedureKind.Method, new FunctionNode(null),
+      fileUri: fileUri, isStatic: true)
+    ..startFileOffset = fileOffset
+    ..fileOffset = fileOffset
+    ..fileEndOffset = fileOffset
+    ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
+}
+
+/// Creates the synthesized type parameters for a tear off lowering. The type
+/// parameters are based [originalTypeParameters] and are inserted into
+/// [newFunctionNode]. The created [FreshTypeParameters] is returned.
+FreshTypeParameters _createFreshTypeParameters(
+    List<TypeParameter> originalTypeParameters, FunctionNode newFunctionNode) {
+  FreshTypeParameters freshTypeParameters;
+  if (originalTypeParameters.isNotEmpty) {
+    freshTypeParameters = getFreshTypeParameters(originalTypeParameters);
+    List<TypeParameter> typeParameters =
+        freshTypeParameters.freshTypeParameters;
+    newFunctionNode.typeParameters.addAll(typeParameters);
+    setParents(typeParameters, newFunctionNode);
+  } else {
+    freshTypeParameters = new FreshTypeParameters([], [], Substitution.empty);
+  }
+  return freshTypeParameters;
+}
+
+/// Creates the parameters for the [tearOff] lowering based of the parameters
+/// in [constructor] and using the [substitution] to compute the parameter and
+/// return types.
+void _createParameters(Procedure tearOff, Member constructor,
+    Substitution substitution, SourceLibraryBuilder libraryBuilder) {
+  FunctionNode function = constructor.function!;
   for (VariableDeclaration constructorParameter
-      in constructor.function.positionalParameters) {
+      in function.positionalParameters) {
     VariableDeclaration tearOffParameter = new VariableDeclaration(
         constructorParameter.name,
         type: substitution.substituteType(constructorParameter.type))
       ..fileOffset = constructorParameter.fileOffset;
     tearOff.function.positionalParameters.add(tearOffParameter);
-    positionalArguments
-        .add(new VariableGet(tearOffParameter)..fileOffset = fileOffset);
     tearOffParameter.parent = tearOff.function;
   }
-  List<NamedExpression> namedArguments = [];
-  for (VariableDeclaration constructorParameter
-      in constructor.function.namedParameters) {
+  for (VariableDeclaration constructorParameter in function.namedParameters) {
     VariableDeclaration tearOffParameter = new VariableDeclaration(
         constructorParameter.name,
         type: substitution.substituteType(constructorParameter.type),
@@ -86,81 +326,106 @@
       ..fileOffset = constructorParameter.fileOffset;
     tearOff.function.namedParameters.add(tearOffParameter);
     tearOffParameter.parent = tearOff.function;
+  }
+  tearOff.function.returnType =
+      substitution.substituteType(function.returnType);
+  tearOff.function.requiredParameterCount = function.requiredParameterCount;
+  libraryBuilder.loader.registerTypeDependency(
+      tearOff, new TypeDependency(tearOff, constructor, substitution));
+}
+
+/// Creates the [Arguments] for passing the parameters from [tearOff] to its
+/// target, using [typeArguments] as the passed type arguments.
+Arguments _createArguments(
+    Procedure tearOff, List<DartType> typeArguments, int fileOffset) {
+  List<Expression> positionalArguments = [];
+  for (VariableDeclaration tearOffParameter
+      in tearOff.function.positionalParameters) {
+    positionalArguments
+        .add(new VariableGet(tearOffParameter)..fileOffset = fileOffset);
+  }
+  List<NamedExpression> namedArguments = [];
+  for (VariableDeclaration tearOffParameter
+      in tearOff.function.namedParameters) {
     namedArguments.add(new NamedExpression(tearOffParameter.name!,
         new VariableGet(tearOffParameter)..fileOffset = fileOffset)
       ..fileOffset = fileOffset);
   }
-  tearOff.function.returnType =
-      substitution.substituteType(constructor.function.returnType);
-  tearOff.function.requiredParameterCount =
-      constructor.function.requiredParameterCount;
-  tearOff.function.body = new ReturnStatement(
-      new ConstructorInvocation(
-          constructor,
-          new Arguments(positionalArguments,
-              named: namedArguments, types: typeArguments)
-            ..fileOffset = tearOff.fileOffset)
-        ..fileOffset = tearOff.fileOffset)
+  Arguments arguments = new Arguments(positionalArguments,
+      named: namedArguments, types: typeArguments)
+    ..fileOffset = tearOff.fileOffset;
+  return arguments;
+}
+
+/// Creates the tear of body for [tearOff] which calls [target] with
+/// [arguments].
+void _createTearOffBody(Procedure tearOff, Member target, Arguments arguments) {
+  assert(target is Constructor ||
+      (target is Procedure && target.isFactory) ||
+      (target is Procedure && target.isStatic));
+  Expression constructorInvocation;
+  if (target is Constructor) {
+    constructorInvocation = new ConstructorInvocation(target, arguments)
+      ..fileOffset = tearOff.fileOffset;
+  } else {
+    constructorInvocation = new StaticInvocation(target as Procedure, arguments)
+      ..fileOffset = tearOff.fileOffset;
+  }
+  tearOff.function.body = new ReturnStatement(constructorInvocation)
     ..fileOffset = tearOff.fileOffset
     ..parent = tearOff.function;
-  tearOff.function.fileOffset = tearOff.fileOffset;
-  tearOff.function.fileEndOffset = tearOff.fileOffset;
-  updatePrivateMemberName(tearOff, libraryBuilder);
 }
 
-/// Copies the parameter types from [constructor] to [tearOff].
-///
-/// These might have been inferred and therefore not available when the
-/// parameters were created.
-// TODO(johnniwinther): Add tests for inferred parameter types.
-// TODO(johnniwinther): Avoid doing this when parameter types are not inferred.
-void buildConstructorTearOffOutline(
-    Procedure tearOff, Constructor constructor, Class enclosingClass) {
-  List<TypeParameter> classTypeParameters = enclosingClass.typeParameters;
-  Substitution substitution = Substitution.empty;
-  if (classTypeParameters.isNotEmpty) {
-    List<DartType> typeArguments = [];
-    for (TypeParameter typeParameter in tearOff.function.typeParameters) {
-      typeArguments.add(new TypeParameterType(typeParameter,
-          TypeParameterType.computeNullabilityFromBound(typeParameter)));
+/// Reverse engineered typedef tear off information.
+class LoweredTypedefTearOff {
+  Procedure typedefTearOff;
+  Constant targetTearOffConstant;
+  List<DartType> typeArguments;
+
+  LoweredTypedefTearOff(
+      this.typedefTearOff, this.targetTearOffConstant, this.typeArguments);
+
+  /// Reverse engineers [constant] to a [LoweredTypedefTearOff] if [constant] is
+  /// the encoding of a lowered typedef tear off.
+  // TODO(johnniwinther): Check that this works with outlines.
+  static LoweredTypedefTearOff? fromConstant(Constant constant) {
+    if (constant is StaticTearOffConstant &&
+        isTypedefTearOffLowering(constant.target)) {
+      Procedure typedefTearOff = constant.target;
+      Statement? body = typedefTearOff.function.body;
+      if (body is ReturnStatement) {
+        Expression? constructorInvocation = body.expression;
+        Member? target;
+        List<DartType>? typeArguments;
+        if (constructorInvocation is ConstructorInvocation) {
+          target = constructorInvocation.target;
+          typeArguments = constructorInvocation.arguments.types;
+        } else if (constructorInvocation is StaticInvocation) {
+          target = constructorInvocation.target;
+          typeArguments = constructorInvocation.arguments.types;
+        }
+        if (target != null) {
+          Class cls = target.enclosingClass!;
+          Name tearOffName =
+              constructorTearOffName(target.name.text, cls.enclosingLibrary);
+          for (Procedure procedure in cls.procedures) {
+            if (procedure.name == tearOffName) {
+              target = procedure;
+              break;
+            }
+          }
+          Constant tearOffConstant;
+          if (target is Constructor ||
+              target is Procedure && target.isFactory) {
+            tearOffConstant = new ConstructorTearOffConstant(target!);
+          } else {
+            tearOffConstant = new StaticTearOffConstant(target as Procedure);
+          }
+          return new LoweredTypedefTearOff(
+              typedefTearOff, tearOffConstant, typeArguments!);
+        }
+      }
     }
-    substitution = Substitution.fromPairs(classTypeParameters, typeArguments);
-  }
-  for (int i = 0; i < constructor.function.positionalParameters.length; i++) {
-    VariableDeclaration tearOffParameter =
-        tearOff.function.positionalParameters[i];
-    VariableDeclaration constructorParameter =
-        constructor.function.positionalParameters[i];
-    tearOffParameter.type =
-        substitution.substituteType(constructorParameter.type);
-  }
-  for (int i = 0; i < constructor.function.namedParameters.length; i++) {
-    VariableDeclaration tearOffParameter = tearOff.function.namedParameters[i];
-    VariableDeclaration constructorParameter =
-        constructor.function.namedParameters[i];
-    tearOffParameter.type =
-        substitution.substituteType(constructorParameter.type);
-  }
-}
-
-void buildConstructorTearOffDefaultValues(
-    Procedure tearOff, Constructor constructor, Class enclosingClass) {
-  CloneVisitorNotMembers cloner = new CloneVisitorNotMembers();
-  for (int i = 0; i < constructor.function.positionalParameters.length; i++) {
-    VariableDeclaration tearOffParameter =
-        tearOff.function.positionalParameters[i];
-    VariableDeclaration constructorParameter =
-        constructor.function.positionalParameters[i];
-    tearOffParameter.initializer =
-        cloner.cloneOptional(constructorParameter.initializer);
-    tearOffParameter.initializer?.parent = tearOffParameter;
-  }
-  for (int i = 0; i < constructor.function.namedParameters.length; i++) {
-    VariableDeclaration tearOffParameter = tearOff.function.namedParameters[i];
-    VariableDeclaration constructorParameter =
-        constructor.function.namedParameters[i];
-    tearOffParameter.initializer =
-        cloner.cloneOptional(constructorParameter.initializer);
-    tearOffParameter.initializer?.parent = tearOffParameter;
+    return null;
   }
 }
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 5dc3f5b..82dbe5c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -11,6 +11,7 @@
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
 import 'package:kernel/ast.dart';
+import 'package:kernel/type_algebra.dart';
 
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
@@ -24,6 +25,7 @@
 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/unresolved_type.dart';
 
 import '../constant_context.dart' show ConstantContext;
@@ -61,7 +63,8 @@
 
 import 'constness.dart' show Constness;
 
-import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
+import 'expression_generator_helper.dart'
+    show ExpressionGeneratorHelper, isProperRenameForClass;
 
 import 'forest.dart';
 
@@ -749,7 +752,7 @@
   Expression buildSimpleRead() {
     VariableDeclarationImpl variable =
         _helper.createVariableDeclarationForValue(receiverExpression);
-    PropertyGet read = _forest.createPropertyGet(
+    Expression read = _forest.createPropertyGet(
         fileOffset,
         _helper.createVariableGet(variable, receiverExpression.fileOffset,
             forNullGuardedAccess: true),
@@ -762,7 +765,7 @@
   Expression buildAssignment(Expression value, {bool voidContext = false}) {
     VariableDeclarationImpl variable =
         _helper.createVariableDeclarationForValue(receiverExpression);
-    PropertySet read = _helper.forest.createPropertySet(
+    Expression read = _helper.forest.createPropertySet(
         fileOffset,
         _helper.createVariableGet(variable, receiverExpression.fileOffset,
             forNullGuardedAccess: true),
@@ -3099,6 +3102,7 @@
     TypeDeclarationBuilder? declarationBuilder = declaration;
     TypeAliasBuilder? aliasBuilder;
     List<TypeBuilder>? unaliasedTypeArguments;
+    bool isGenericTypedefTearOff = false;
     if (declarationBuilder is TypeAliasBuilder) {
       aliasBuilder = declarationBuilder;
       declarationBuilder = aliasBuilder.unaliasDeclaration(null,
@@ -3117,8 +3121,6 @@
             _uri);
       } else {
         if (declarationBuilder is DeclarationBuilder) {
-          unaliasedTypeArguments =
-              aliasBuilder.unaliasTypeArguments(aliasedTypeArguments);
           if (aliasedTypeArguments != null) {
             _helper.libraryBuilder.uncheckedTypedefTypes.add(
                 new UncheckedTypedefType(new TypedefType(
@@ -3129,6 +3131,23 @@
                   ..fileUri = _uri
                   ..offset = fileOffset);
           }
+
+          // If the arguments weren't supplied, the tear off is treated as
+          // generic, and the aliased type arguments match type parameters of
+          // the type alias.
+          if (aliasedTypeArguments == null &&
+              aliasBuilder.typeVariablesCount != 0) {
+            isGenericTypedefTearOff = true;
+            aliasedTypeArguments = <TypeBuilder>[];
+            for (TypeVariableBuilder typeVariable
+                in aliasBuilder.typeVariables!) {
+              aliasedTypeArguments.add(new NamedTypeBuilder(typeVariable.name,
+                  const NullabilityBuilder.omitted(), null, _uri, fileOffset)
+                ..bind(typeVariable));
+            }
+          }
+          unaliasedTypeArguments =
+              aliasBuilder.unaliasTypeArguments(aliasedTypeArguments);
         }
       }
     }
@@ -3162,8 +3181,13 @@
               tearOffExpression = _helper.forest
                   .createConstructorTearOff(token.charOffset, tearOff);
             } else if (tearOff is Procedure) {
-              tearOffExpression =
-                  _helper.forest.createStaticTearOff(token.charOffset, tearOff);
+              if (tearOff.isRedirectingFactory) {
+                tearOffExpression = _helper.forest
+                    .createRedirectingFactoryTearOff(token.charOffset, tearOff);
+              } else {
+                tearOffExpression = _helper.forest
+                    .createStaticTearOff(token.charOffset, tearOff);
+              }
             } else if (tearOff != null) {
               unhandled("${tearOff.runtimeType}", "buildPropertyAccess",
                   operatorOffset, _helper.uri);
@@ -3171,16 +3195,64 @@
             if (tearOffExpression != null) {
               List<DartType>? builtTypeArguments;
               if (unaliasedTypeArguments != null) {
-                builtTypeArguments = declarationBuilder.buildTypeArguments(
-                    _helper.libraryBuilder, unaliasedTypeArguments);
+                if (unaliasedTypeArguments.length !=
+                    declarationBuilder.typeVariablesCount) {
+                  // The type arguments are either aren't provided or mismatch
+                  // in number with the type variables of the RHS declaration.
+                  // We substitute them with the default types here: in the
+                  // first case that would be exactly what type inference fills
+                  // in for the RHS, and in the second case it's a reasonable
+                  // fallback, as the error is reported during a check on the
+                  // typedef.
+                  builtTypeArguments = <DartType>[];
+                  for (TypeParameter typeParameter
+                      in declarationBuilder.cls.typeParameters) {
+                    builtTypeArguments.add(typeParameter.defaultType);
+                  }
+                } else {
+                  builtTypeArguments = declarationBuilder.buildTypeArguments(
+                      _helper.libraryBuilder, unaliasedTypeArguments);
+                }
               } else if (typeArguments != null) {
                 builtTypeArguments =
                     _helper.buildDartTypeArguments(typeArguments);
               }
-              return builtTypeArguments != null && builtTypeArguments.isNotEmpty
-                  ? _helper.forest.createInstantiation(
-                      token.charOffset, tearOffExpression, builtTypeArguments)
-                  : tearOffExpression;
+              if (isGenericTypedefTearOff) {
+                if (isProperRenameForClass(
+                    _helper.typeEnvironment, aliasBuilder!.typedef)) {
+                  return tearOffExpression;
+                }
+                Procedure? tearOffLowering =
+                    aliasBuilder.findConstructorOrFactory(
+                        name.text, nameOffset, _uri, _helper.libraryBuilder);
+                if (tearOffLowering != null) {
+                  return _helper.forest
+                      .createStaticTearOff(token.charOffset, tearOffLowering);
+                }
+                FreshTypeParameters freshTypeParameters =
+                    getFreshTypeParameters(aliasBuilder.typedef.typeParameters);
+                List<DartType>? substitutedTypeArguments;
+                if (builtTypeArguments != null) {
+                  substitutedTypeArguments = <DartType>[];
+                  for (DartType builtTypeArgument in builtTypeArguments) {
+                    substitutedTypeArguments
+                        .add(freshTypeParameters.substitute(builtTypeArgument));
+                  }
+                }
+
+                tearOffExpression = _helper.forest.createTypedefTearOff(
+                    token.charOffset,
+                    freshTypeParameters.freshTypeParameters,
+                    tearOffExpression,
+                    substitutedTypeArguments ?? const <DartType>[]);
+              } else {
+                if (builtTypeArguments != null &&
+                    builtTypeArguments.isNotEmpty) {
+                  tearOffExpression = _helper.forest.createInstantiation(
+                      token.charOffset, tearOffExpression, builtTypeArguments);
+                }
+              }
+              return tearOffExpression;
             }
           }
           generator = new UnresolvedNameGenerator(_helper, send.token, name);
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 88a1430..c19553b 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
@@ -5,6 +5,8 @@
 library fasta.expression_generator_helper;
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+import 'package:kernel/type_algebra.dart';
+import 'package:kernel/type_environment.dart';
 
 import '../builder/builder.dart';
 import '../builder/formal_parameter_builder.dart';
@@ -30,12 +32,15 @@
         Expression,
         FunctionNode,
         Initializer,
+        InterfaceType,
         Member,
         Name,
         Procedure,
         StaticGet,
         TreeNode,
         TypeParameter,
+        TypeParameterType,
+        Typedef,
         VariableDeclaration;
 
 abstract class ExpressionGeneratorHelper implements InferenceHelper {
@@ -176,4 +181,45 @@
   ///
   /// This is needed for type promotion.
   void registerVariableAssignment(VariableDeclaration variable);
+
+  TypeEnvironment get typeEnvironment;
+}
+
+/// Checks that a generic [typedef] for a generic class.
+bool isProperRenameForClass(TypeEnvironment typeEnvironment, Typedef typedef) {
+  DartType? rhsType = typedef.type;
+  if (rhsType is! InterfaceType) {
+    return false;
+  }
+
+  List<TypeParameter> fromParameters = typedef.typeParameters;
+  List<TypeParameter> toParameters = rhsType.classNode.typeParameters;
+  List<DartType> typeArguments = rhsType.typeArguments;
+  if (fromParameters.length != typeArguments.length) {
+    return false;
+  }
+  for (int i = 0; i < fromParameters.length; ++i) {
+    if (typeArguments[i] !=
+        new TypeParameterType.withDefaultNullabilityForLibrary(
+            fromParameters[i], typedef.enclosingLibrary)) {
+      return false;
+    }
+  }
+
+  Map<TypeParameter, DartType> substitutionMap = {};
+  for (int i = 0; i < fromParameters.length; ++i) {
+    substitutionMap[fromParameters[i]] = new TypeParameterType.forAlphaRenaming(
+        fromParameters[i], toParameters[i]);
+  }
+  Substitution substitution = Substitution.fromMap(substitutionMap);
+  for (int i = 0; i < fromParameters.length; ++i) {
+    if (!typeEnvironment.areMutualSubtypes(
+        toParameters[i].bound,
+        substitution.substituteType(fromParameters[i].bound),
+        SubtypeCheckMode.withNullabilities)) {
+      return false;
+    }
+  }
+
+  return true;
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 0a6909a..fa8be39 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -722,7 +722,7 @@
       ..fileOffset = fileOffset;
   }
 
-  MethodInvocation createMethodInvocation(
+  Expression createMethodInvocation(
       int fileOffset, Expression expression, Name name, Arguments arguments) {
     // ignore: unnecessary_null_comparison
     assert(fileOffset != null);
@@ -758,19 +758,18 @@
     return new NullCheck(expression)..fileOffset = fileOffset;
   }
 
-  PropertyGet createPropertyGet(
-      int fileOffset, Expression receiver, Name name) {
+  Expression createPropertyGet(int fileOffset, Expression receiver, Name name) {
     // ignore: unnecessary_null_comparison
     assert(fileOffset != null);
     return new PropertyGet(receiver, name)..fileOffset = fileOffset;
   }
 
-  PropertySet createPropertySet(
+  Expression createPropertySet(
       int fileOffset, Expression receiver, Name name, Expression value,
       {required bool forEffect, bool readOnlyReceiver: false}) {
     // ignore: unnecessary_null_comparison
     assert(fileOffset != null);
-    return new PropertySetImpl(receiver, name, value,
+    return new PropertySet(receiver, name, value,
         forEffect: forEffect, readOnlyReceiver: readOnlyReceiver)
       ..fileOffset = fileOffset;
   }
@@ -836,9 +835,17 @@
   StaticTearOff createStaticTearOff(int fileOffset, Procedure procedure) {
     // ignore: unnecessary_null_comparison
     assert(fileOffset != null);
+    assert(!procedure.isRedirectingFactory);
     return new StaticTearOff(procedure)..fileOffset = fileOffset;
   }
 
+  RedirectingFactoryTearOff createRedirectingFactoryTearOff(
+      int fileOffset, Procedure procedure) {
+    // ignore: unnecessary_null_comparison
+    assert(fileOffset != null);
+    return new RedirectingFactoryTearOff(procedure)..fileOffset = fileOffset;
+  }
+
   Instantiation createInstantiation(
       int fileOffset, Expression expression, List<DartType> typeArguments) {
     // ignore: unnecessary_null_comparison
@@ -846,6 +853,17 @@
     return new Instantiation(expression, typeArguments)
       ..fileOffset = fileOffset;
   }
+
+  TypedefTearOff createTypedefTearOff(
+      int fileOffset,
+      List<TypeParameter> typeParameters,
+      Expression expression,
+      List<DartType> typeArguments) {
+    // ignore: unnecessary_null_comparison
+    assert(fileOffset != null);
+    return new TypedefTearOff(typeParameters, expression, typeArguments)
+      ..fileOffset = fileOffset;
+  }
 }
 
 class _VariablesDeclaration extends Statement {
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 d87c8f9..e820080 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -7,7 +7,7 @@
 import 'package:front_end/src/api_prototype/lowering_predicates.dart';
 import 'package:kernel/ast.dart';
 import 'package:kernel/src/legacy_erasure.dart';
-import 'package:kernel/type_algebra.dart' show Substitution;
+import 'package:kernel/type_algebra.dart';
 import 'package:kernel/type_environment.dart';
 
 import '../../base/instrumentation.dart'
@@ -191,6 +191,7 @@
   @override
   ExpressionInferenceResult visitStaticTearOff(
       StaticTearOff node, DartType typeContext) {
+    inferrer.ensureMemberType(node.target);
     DartType type =
         node.target.function.computeFunctionType(inferrer.library.nonNullable);
     return inferrer.instantiateTearOff(type, typeContext, node);
@@ -217,15 +218,53 @@
   @override
   ExpressionInferenceResult visitConstructorTearOff(
       ConstructorTearOff node, DartType typeContext) {
-    DartType type = node.constructor.function
-        .computeFunctionType(inferrer.library.nonNullable);
+    inferrer.ensureMemberType(node.target);
+    DartType type =
+        node.target.function!.computeFunctionType(inferrer.library.nonNullable);
+    return inferrer.instantiateTearOff(type, typeContext, node);
+  }
+
+  @override
+  ExpressionInferenceResult visitRedirectingFactoryTearOff(
+      RedirectingFactoryTearOff node, DartType typeContext) {
+    DartType type =
+        node.target.function.computeFunctionType(inferrer.library.nonNullable);
     return inferrer.instantiateTearOff(type, typeContext, node);
   }
 
   @override
   ExpressionInferenceResult visitTypedefTearOff(
       TypedefTearOff node, DartType typeContext) {
-    return _unhandledExpression(node, typeContext);
+    ExpressionInferenceResult expressionResult = inferrer.inferExpression(
+        node.expression, const UnknownType(), true,
+        isVoidAllowed: true);
+    node.expression = expressionResult.expression..parent = node;
+    assert(
+        expressionResult.inferredType is FunctionType,
+        "Expected a FunctionType from tearing off a constructor from "
+        "a typedef, but got '${expressionResult.inferredType.runtimeType}'.");
+    FunctionType expressionType = expressionResult.inferredType as FunctionType;
+
+    assert(expressionType.typeParameters.length == node.typeArguments.length);
+    Substitution substitution = Substitution.fromPairs(
+        expressionType.typeParameters, node.typeArguments);
+    FunctionType resultType = substitution
+        .substituteType(expressionType.withoutTypeParameters) as FunctionType;
+    FreshTypeParameters freshTypeParameters =
+        getFreshTypeParameters(node.typeParameters);
+    resultType = freshTypeParameters.substitute(resultType) as FunctionType;
+    resultType = new FunctionType(resultType.positionalParameters,
+        resultType.returnType, resultType.declaredNullability,
+        namedParameters: resultType.namedParameters,
+        typeParameters: freshTypeParameters.freshTypeParameters,
+        requiredParameterCount: resultType.requiredParameterCount,
+        typedefType: null);
+    ExpressionInferenceResult inferredResult =
+        inferrer.instantiateTearOff(resultType, typeContext, node);
+    Expression ensuredResultExpression =
+        inferrer.ensureAssignableResult(typeContext, inferredResult);
+    return new ExpressionInferenceResult(
+        inferredResult.inferredType, ensuredResultExpression);
   }
 
   @override
@@ -283,7 +322,7 @@
   }
 
   @override
-  void visitInvalidInitializer(Initializer node) {
+  void visitInvalidInitializer(InvalidInitializer node) {
     _unhandledInitializer(node);
   }
 
@@ -2039,7 +2078,7 @@
       DartType inferredKeyType,
       DartType inferredValueType,
       DartType spreadContext,
-      List<DartType?> actualTypes,
+      List<DartType> actualTypes,
       List<DartType> actualTypesForSet,
       Map<TreeNode, DartType> inferredSpreadTypes,
       Map<Expression, DartType> inferredConditionTypes,
@@ -2057,8 +2096,8 @@
       DartType spreadType = spreadResult.inferredType;
       inferredSpreadTypes[entry.expression] = spreadType;
       int length = actualTypes.length;
-      actualTypes.add(null);
-      actualTypes.add(null);
+      actualTypes.add(noInferredType);
+      actualTypes.add(noInferredType);
       storeSpreadMapEntryElementTypes(
           spreadType, entry.isNullAware, actualTypes, length);
       DartType? actualKeyType = actualTypes[length];
@@ -2069,7 +2108,7 @@
 
       MapLiteralEntry replacement = entry;
       if (typeChecksNeeded) {
-        if (actualKeyType == null) {
+        if (actualKeyType == noInferredType) {
           if (inferrer.coreTypes.isNull(spreadTypeBound) &&
               !entry.isNullAware) {
             replacement = new MapLiteralEntry(
@@ -2165,7 +2204,7 @@
                   1);
             }
           }
-          if (!inferrer.isAssignable(inferredValueType, actualValueType!)) {
+          if (!inferrer.isAssignable(inferredValueType, actualValueType)) {
             if (inferrer.isNonNullableByDefault) {
               IsSubtypeOf subtypeCheckResult = inferrer.typeSchemaEnvironment
                   .performNullabilityAwareSubtypeCheck(
@@ -2234,7 +2273,7 @@
       }
 
       // Use 'dynamic' for error recovery.
-      if (actualKeyType == null) {
+      if (actualKeyType == noInferredType) {
         actualKeyType = actualTypes[length] = const DynamicType();
         actualValueType = actualTypes[length + 1] = const DynamicType();
       }
@@ -2248,7 +2287,7 @@
       entry.entryType = new InterfaceType(
           mapEntryClass!,
           inferrer.library.nonNullable,
-          <DartType>[actualKeyType, actualValueType!]);
+          <DartType>[actualKeyType, actualValueType]);
 
       bool isMap = inferrer.typeSchemaEnvironment.isSubtypeOf(
           spreadType,
@@ -2315,10 +2354,10 @@
             typeChecksNeeded);
         int length = actualTypes.length;
         actualTypes[length - 2] = inferrer.typeSchemaEnvironment
-            .getStandardUpperBound(actualKeyType!, actualTypes[length - 2]!,
+            .getStandardUpperBound(actualKeyType, actualTypes[length - 2],
                 inferrer.library.library);
         actualTypes[length - 1] = inferrer.typeSchemaEnvironment
-            .getStandardUpperBound(actualValueType!, actualTypes[length - 1]!,
+            .getStandardUpperBound(actualValueType, actualTypes[length - 1],
                 inferrer.library.library);
         int lengthForSet = actualTypesForSet.length;
         actualTypesForSet[lengthForSet - 1] = inferrer.typeSchemaEnvironment
@@ -2583,7 +2622,7 @@
       inferredConditionTypes = new Map<Expression, DartType>.identity();
     }
     if (inferenceNeeded) {
-      inferredTypes = [const UnknownType(), const UnknownType()];
+      inferredTypes = [noInferredType, noInferredType];
       inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
           mapType,
           mapClass.typeParameters,
@@ -2662,7 +2701,7 @@
           formalTypesForSet.add(setType.typeArguments[0]);
         }
 
-        List<DartType> inferredTypesForSet = <DartType>[const UnknownType()];
+        List<DartType> inferredTypesForSet = <DartType>[noInferredType];
         inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
             setType,
             inferrer.coreTypes.setClass.typeParameters,
@@ -2767,7 +2806,6 @@
     return new ExpressionInferenceResult(inferredType, node);
   }
 
-  @override
   ExpressionInferenceResult visitMethodInvocation(
       MethodInvocation node, DartType typeContext) {
     assert(node.name != unaryMinusName);
@@ -3987,24 +4025,20 @@
         right, const UnknownType(), typeNeeded,
         isVoidAllowed: false);
 
-    if (inferrer.useNewMethodInvocationEncoding) {
-      if (_isNull(right)) {
-        equals = new EqualsNull(left)..fileOffset = fileOffset;
-      } else if (_isNull(left)) {
-        equals = new EqualsNull(rightResult.expression)
-          ..fileOffset = fileOffset;
+    if (_isNull(right)) {
+      equals = new EqualsNull(left)..fileOffset = fileOffset;
+    } else if (_isNull(left)) {
+      equals = new EqualsNull(rightResult.expression)..fileOffset = fileOffset;
+    }
+    if (equals != null) {
+      if (isNot) {
+        equals = new Not(equals)..fileOffset = fileOffset;
       }
-      if (equals != null) {
-        if (isNot) {
-          equals = new Not(equals)..fileOffset = fileOffset;
-        }
-        inferrer.flowAnalysis.equalityOp_end(
-            equals, rightResult.expression, rightResult.inferredType,
-            notEqual: isNot);
-        return new ExpressionInferenceResult(
-            inferrer.coreTypes.boolRawType(inferrer.library.nonNullable),
-            equals);
-      }
+      inferrer.flowAnalysis.equalityOp_end(
+          equals, rightResult.expression, rightResult.inferredType,
+          notEqual: isNot);
+      return new ExpressionInferenceResult(
+          inferrer.coreTypes.boolRawType(inferrer.library.nonNullable), equals);
     }
 
     ObjectAccessTarget equalsTarget = inferrer.findInterfaceMember(
@@ -4038,47 +4072,33 @@
         nullabilityNullTypeErrorTemplate:
             templateArgumentTypeNotAssignableNullabilityNullType);
 
-    if (inferrer.useNewMethodInvocationEncoding) {
-      if (equalsTarget.isInstanceMember || equalsTarget.isObjectMember) {
-        FunctionType functionType =
-            inferrer.getFunctionType(equalsTarget, leftType);
-        equals = new EqualsCall(left, right,
-            functionType: functionType,
-            interfaceTarget: equalsTarget.member as Procedure)
-          ..fileOffset = fileOffset;
-        if (isNot) {
-          equals = new Not(equals)..fileOffset = fileOffset;
-        }
-      } else {
-        assert(equalsTarget.isNever);
-        FunctionType functionType = new FunctionType([const DynamicType()],
-            const NeverType.nonNullable(), inferrer.library.nonNullable);
-        // Ensure operator == member even for `Never`.
-        Member target = inferrer
-            .findInterfaceMember(const DynamicType(), equalsName, -1,
-                instrumented: false)
-            .member!;
-        equals = new EqualsCall(left, right,
-            functionType: functionType, interfaceTarget: target as Procedure)
-          ..fileOffset = fileOffset;
-        if (isNot) {
-          equals = new Not(equals)..fileOffset = fileOffset;
-        }
+    if (equalsTarget.isInstanceMember || equalsTarget.isObjectMember) {
+      FunctionType functionType =
+          inferrer.getFunctionType(equalsTarget, leftType);
+      equals = new EqualsCall(left, right,
+          functionType: functionType,
+          interfaceTarget: equalsTarget.member as Procedure)
+        ..fileOffset = fileOffset;
+      if (isNot) {
+        equals = new Not(equals)..fileOffset = fileOffset;
       }
     } else {
-      equals = new MethodInvocation(
-          left,
-          equalsName,
-          new Arguments(<Expression>[
-            right,
-          ])
-            ..fileOffset = fileOffset,
-          equalsTarget.member)
+      assert(equalsTarget.isNever);
+      FunctionType functionType = new FunctionType([const DynamicType()],
+          const NeverType.nonNullable(), inferrer.library.nonNullable);
+      // Ensure operator == member even for `Never`.
+      Member target = inferrer
+          .findInterfaceMember(const DynamicType(), equalsName, -1,
+              instrumented: false)
+          .member!;
+      equals = new EqualsCall(left, right,
+          functionType: functionType, interfaceTarget: target as Procedure)
         ..fileOffset = fileOffset;
       if (isNot) {
         equals = new Not(equals)..fileOffset = fileOffset;
       }
     }
+
     inferrer.flowAnalysis.equalityOp_end(
         equals, right, rightResult.inferredType,
         notEqual: isNot);
@@ -4179,75 +4199,39 @@
           ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.invalid:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          binary = new DynamicInvocation(
-              DynamicAccessKind.Invalid,
-              left,
-              binaryName,
-              new Arguments(<Expression>[
-                right,
-              ])
-                ..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          binary = new MethodInvocation(
-              left,
-              binaryName,
-              new Arguments(<Expression>[
-                right,
-              ])
-                ..fileOffset = fileOffset,
-              binaryTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        binary = new DynamicInvocation(
+            DynamicAccessKind.Invalid,
+            left,
+            binaryName,
+            new Arguments(<Expression>[
+              right,
+            ])
+              ..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          binary = new DynamicInvocation(
-              DynamicAccessKind.Dynamic,
-              left,
-              binaryName,
-              new Arguments(<Expression>[
-                right,
-              ])
-                ..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          binary = new MethodInvocation(
-              left,
-              binaryName,
-              new Arguments(<Expression>[
-                right,
-              ])
-                ..fileOffset = fileOffset,
-              binaryTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        binary = new DynamicInvocation(
+            DynamicAccessKind.Dynamic,
+            left,
+            binaryName,
+            new Arguments(<Expression>[
+              right,
+            ])
+              ..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.never:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          binary = new DynamicInvocation(
-              DynamicAccessKind.Never,
-              left,
-              binaryName,
-              new Arguments(<Expression>[
-                right,
-              ])
-                ..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          binary = new MethodInvocation(
-              left,
-              binaryName,
-              new Arguments(<Expression>[
-                right,
-              ])
-                ..fileOffset = fileOffset,
-              binaryTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        binary = new DynamicInvocation(
+            DynamicAccessKind.Never,
+            left,
+            binaryName,
+            new Arguments(<Expression>[
+              right,
+            ])
+              ..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.instanceMember:
       case ObjectAccessTargetKind.objectMember:
@@ -4262,30 +4246,18 @@
               new InstrumentationValueForMember(binaryTarget.member!));
         }
 
-        if (inferrer.useNewMethodInvocationEncoding) {
-          binary = new InstanceInvocation(
-              InstanceAccessKind.Instance,
-              left,
-              binaryName,
-              new Arguments(<Expression>[
-                right,
-              ])
-                ..fileOffset = fileOffset,
-              functionType: new FunctionType(
-                  [rightType], binaryType, inferrer.library.nonNullable),
-              interfaceTarget: binaryTarget.member as Procedure)
-            ..fileOffset = fileOffset;
-        } else {
-          binary = new MethodInvocation(
-              left,
-              binaryName,
-              new Arguments(<Expression>[
-                right,
-              ])
-                ..fileOffset = fileOffset,
-              binaryTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        binary = new InstanceInvocation(
+            InstanceAccessKind.Instance,
+            left,
+            binaryName,
+            new Arguments(<Expression>[
+              right,
+            ])
+              ..fileOffset = fileOffset,
+            functionType: new FunctionType(
+                [rightType], binaryType, inferrer.library.nonNullable),
+            interfaceTarget: binaryTarget.member as Procedure)
+          ..fileOffset = fileOffset;
 
         if (binaryCheckKind ==
             MethodContravarianceCheckKind.checkMethodReturn) {
@@ -4367,48 +4339,21 @@
           ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.invalid:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          unary = new DynamicInvocation(DynamicAccessKind.Invalid, expression,
-              unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          unary = new MethodInvocation(
-              expression,
-              unaryName,
-              new Arguments(<Expression>[])..fileOffset = fileOffset,
-              unaryTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        unary = new DynamicInvocation(DynamicAccessKind.Invalid, expression,
+            unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.never:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          unary = new DynamicInvocation(DynamicAccessKind.Never, expression,
-              unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          unary = new MethodInvocation(
-              expression,
-              unaryName,
-              new Arguments(<Expression>[])..fileOffset = fileOffset,
-              unaryTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        unary = new DynamicInvocation(DynamicAccessKind.Never, expression,
+            unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          unary = new DynamicInvocation(DynamicAccessKind.Dynamic, expression,
-              unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          unary = new MethodInvocation(
-              expression,
-              unaryName,
-              new Arguments(<Expression>[])..fileOffset = fileOffset,
-              unaryTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        unary = new DynamicInvocation(DynamicAccessKind.Dynamic, expression,
+            unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.instanceMember:
       case ObjectAccessTargetKind.objectMember:
@@ -4423,24 +4368,12 @@
               new InstrumentationValueForMember(unaryTarget.member!));
         }
 
-        if (inferrer.useNewMethodInvocationEncoding) {
-          unary = new InstanceInvocation(
-              InstanceAccessKind.Instance,
-              expression,
-              unaryName,
-              new Arguments(<Expression>[])..fileOffset = fileOffset,
-              functionType: new FunctionType(
-                  <DartType>[], unaryType, inferrer.library.nonNullable),
-              interfaceTarget: unaryTarget.member as Procedure)
-            ..fileOffset = fileOffset;
-        } else {
-          unary = new MethodInvocation(
-              expression,
-              unaryName,
-              new Arguments(<Expression>[])..fileOffset = fileOffset,
-              unaryTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        unary = new InstanceInvocation(InstanceAccessKind.Instance, expression,
+            unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset,
+            functionType: new FunctionType(
+                <DartType>[], unaryType, inferrer.library.nonNullable),
+            interfaceTarget: unaryTarget.member as Procedure)
+          ..fileOffset = fileOffset;
 
         if (unaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
           if (inferrer.instrumentation != null) {
@@ -4519,117 +4452,69 @@
           ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.invalid:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          read = new DynamicInvocation(
-              DynamicAccessKind.Invalid,
-              readReceiver,
-              indexGetName,
-              new Arguments(<Expression>[
-                readIndex,
-              ])
-                ..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          read = new MethodInvocation(
-              readReceiver,
-              indexGetName,
-              new Arguments(<Expression>[
-                readIndex,
-              ])
-                ..fileOffset = fileOffset,
-              readTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        read = new DynamicInvocation(
+            DynamicAccessKind.Invalid,
+            readReceiver,
+            indexGetName,
+            new Arguments(<Expression>[
+              readIndex,
+            ])
+              ..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.never:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          read = new DynamicInvocation(
-              DynamicAccessKind.Never,
-              readReceiver,
-              indexGetName,
-              new Arguments(<Expression>[
-                readIndex,
-              ])
-                ..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          read = new MethodInvocation(
-              readReceiver,
-              indexGetName,
-              new Arguments(<Expression>[
-                readIndex,
-              ])
-                ..fileOffset = fileOffset,
-              readTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        read = new DynamicInvocation(
+            DynamicAccessKind.Never,
+            readReceiver,
+            indexGetName,
+            new Arguments(<Expression>[
+              readIndex,
+            ])
+              ..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          read = new DynamicInvocation(
-              DynamicAccessKind.Dynamic,
-              readReceiver,
-              indexGetName,
-              new Arguments(<Expression>[
-                readIndex,
-              ])
-                ..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          read = new MethodInvocation(
-              readReceiver,
-              indexGetName,
-              new Arguments(<Expression>[
-                readIndex,
-              ])
-                ..fileOffset = fileOffset,
-              readTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        read = new DynamicInvocation(
+            DynamicAccessKind.Dynamic,
+            readReceiver,
+            indexGetName,
+            new Arguments(<Expression>[
+              readIndex,
+            ])
+              ..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.instanceMember:
       case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          InstanceAccessKind kind;
-          switch (readTarget.kind) {
-            case ObjectAccessTargetKind.instanceMember:
-              kind = InstanceAccessKind.Instance;
-              break;
-            case ObjectAccessTargetKind.nullableInstanceMember:
-              kind = InstanceAccessKind.Nullable;
-              break;
-            case ObjectAccessTargetKind.objectMember:
-              kind = InstanceAccessKind.Object;
-              break;
-            default:
-              throw new UnsupportedError('Unexpected target kind $readTarget');
-          }
-          read = new InstanceInvocation(
-              kind,
-              readReceiver,
-              indexGetName,
-              new Arguments(<Expression>[
-                readIndex,
-              ])
-                ..fileOffset = fileOffset,
-              functionType: new FunctionType(
-                  [indexType], readType, inferrer.library.nonNullable),
-              interfaceTarget: readTarget.member as Procedure)
-            ..fileOffset = fileOffset;
-        } else {
-          read = new MethodInvocation(
-              readReceiver,
-              indexGetName,
-              new Arguments(<Expression>[
-                readIndex,
-              ])
-                ..fileOffset = fileOffset,
-              readTarget.member)
-            ..fileOffset = fileOffset;
+        InstanceAccessKind kind;
+        switch (readTarget.kind) {
+          case ObjectAccessTargetKind.instanceMember:
+            kind = InstanceAccessKind.Instance;
+            break;
+          case ObjectAccessTargetKind.nullableInstanceMember:
+            kind = InstanceAccessKind.Nullable;
+            break;
+          case ObjectAccessTargetKind.objectMember:
+            kind = InstanceAccessKind.Object;
+            break;
+          default:
+            throw new UnsupportedError('Unexpected target kind $readTarget');
         }
+        read = new InstanceInvocation(
+            kind,
+            readReceiver,
+            indexGetName,
+            new Arguments(<Expression>[
+              readIndex,
+            ])
+              ..fileOffset = fileOffset,
+            functionType: new FunctionType(
+                [indexType], readType, inferrer.library.nonNullable),
+            interfaceTarget: readTarget.member as Procedure)
+          ..fileOffset = fileOffset;
         if (readCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
           if (inferrer.instrumentation != null) {
             inferrer.instrumentation!.record(
@@ -4702,102 +4587,54 @@
           ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.invalid:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          write = new DynamicInvocation(
-              DynamicAccessKind.Invalid,
-              receiver,
-              indexSetName,
-              new Arguments(<Expression>[index, value])
-                ..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          write = new MethodInvocation(
-              receiver,
-              indexSetName,
-              new Arguments(<Expression>[index, value])
-                ..fileOffset = fileOffset,
-              writeTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        write = new DynamicInvocation(
+            DynamicAccessKind.Invalid,
+            receiver,
+            indexSetName,
+            new Arguments(<Expression>[index, value])..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.never:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          write = new DynamicInvocation(
-              DynamicAccessKind.Never,
-              receiver,
-              indexSetName,
-              new Arguments(<Expression>[index, value])
-                ..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-        } else {
-          write = new MethodInvocation(
-              receiver,
-              indexSetName,
-              new Arguments(<Expression>[index, value])
-                ..fileOffset = fileOffset,
-              writeTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        write = new DynamicInvocation(
+            DynamicAccessKind.Never,
+            receiver,
+            indexSetName,
+            new Arguments(<Expression>[index, value])..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          write = new DynamicInvocation(
-              DynamicAccessKind.Dynamic,
-              receiver,
-              indexSetName,
-              new Arguments(<Expression>[index, value])
-                ..fileOffset = fileOffset)
-            ..fileOffset = fileOffset;
-          break;
-        } else {
-          write = new MethodInvocation(
-              receiver,
-              indexSetName,
-              new Arguments(<Expression>[index, value])
-                ..fileOffset = fileOffset,
-              writeTarget.member)
-            ..fileOffset = fileOffset;
-          break;
-        }
+        write = new DynamicInvocation(
+            DynamicAccessKind.Dynamic,
+            receiver,
+            indexSetName,
+            new Arguments(<Expression>[index, value])..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
+        break;
       case ObjectAccessTargetKind.instanceMember:
       case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          InstanceAccessKind kind;
-          switch (writeTarget.kind) {
-            case ObjectAccessTargetKind.instanceMember:
-              kind = InstanceAccessKind.Instance;
-              break;
-            case ObjectAccessTargetKind.nullableInstanceMember:
-              kind = InstanceAccessKind.Nullable;
-              break;
-            case ObjectAccessTargetKind.objectMember:
-              kind = InstanceAccessKind.Object;
-              break;
-            default:
-              throw new UnsupportedError('Unexpected target kind $writeTarget');
-          }
-          write = new InstanceInvocation(
-              kind,
-              receiver,
-              indexSetName,
-              new Arguments(<Expression>[index, value])
-                ..fileOffset = fileOffset,
-              functionType: new FunctionType([indexType, valueType],
-                  const VoidType(), inferrer.library.nonNullable),
-              interfaceTarget: writeTarget.member as Procedure)
-            ..fileOffset = fileOffset;
-        } else {
-          write = new MethodInvocation(
-              receiver,
-              indexSetName,
-              new Arguments(<Expression>[index, value])
-                ..fileOffset = fileOffset,
-              writeTarget.member)
-            ..fileOffset = fileOffset;
+        InstanceAccessKind kind;
+        switch (writeTarget.kind) {
+          case ObjectAccessTargetKind.instanceMember:
+            kind = InstanceAccessKind.Instance;
+            break;
+          case ObjectAccessTargetKind.nullableInstanceMember:
+            kind = InstanceAccessKind.Nullable;
+            break;
+          case ObjectAccessTargetKind.objectMember:
+            kind = InstanceAccessKind.Object;
+            break;
+          default:
+            throw new UnsupportedError('Unexpected target kind $writeTarget');
         }
+        write = new InstanceInvocation(kind, receiver, indexSetName,
+            new Arguments(<Expression>[index, value])..fileOffset = fileOffset,
+            functionType: new FunctionType([indexType, valueType],
+                const VoidType(), inferrer.library.nonNullable),
+            interfaceTarget: writeTarget.member as Procedure)
+          ..fileOffset = fileOffset;
         break;
     }
     if (!inferrer.isTopLevel && writeTarget.isNullable) {
@@ -4877,42 +4714,20 @@
         }
         break;
       case ObjectAccessTargetKind.never:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          read = new DynamicGet(DynamicAccessKind.Never, receiver, propertyName)
-            ..fileOffset = fileOffset;
-        } else {
-          read = new PropertyGet(receiver, propertyName, readTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        read = new DynamicGet(DynamicAccessKind.Never, receiver, propertyName)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.dynamic:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          read =
-              new DynamicGet(DynamicAccessKind.Dynamic, receiver, propertyName)
-                ..fileOffset = fileOffset;
-        } else {
-          read = new PropertyGet(receiver, propertyName, readTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        read = new DynamicGet(DynamicAccessKind.Dynamic, receiver, propertyName)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.invalid:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          read =
-              new DynamicGet(DynamicAccessKind.Invalid, receiver, propertyName)
-                ..fileOffset = fileOffset;
-        } else {
-          read = new PropertyGet(receiver, propertyName, readTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        read = new DynamicGet(DynamicAccessKind.Invalid, receiver, propertyName)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          read = new FunctionTearOff(receiver)..fileOffset = fileOffset;
-        } else {
-          read = new PropertyGet(receiver, propertyName, readTarget.member)
-            ..fileOffset = fileOffset;
-        }
+        read = new FunctionTearOff(receiver)..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.instanceMember:
       case ObjectAccessTargetKind.objectMember:
@@ -4924,32 +4739,28 @@
           inferrer.instrumentation!.record(inferrer.uriForInstrumentation,
               fileOffset, 'target', new InstrumentationValueForMember(member));
         }
-        if (inferrer.useNewMethodInvocationEncoding) {
-          InstanceAccessKind kind;
-          switch (readTarget.kind) {
-            case ObjectAccessTargetKind.instanceMember:
-              kind = InstanceAccessKind.Instance;
-              break;
-            case ObjectAccessTargetKind.nullableInstanceMember:
-              kind = InstanceAccessKind.Nullable;
-              break;
-            case ObjectAccessTargetKind.objectMember:
-              kind = InstanceAccessKind.Object;
-              break;
-            default:
-              throw new UnsupportedError('Unexpected target kind $readTarget');
-          }
-          if (member is Procedure && member.kind == ProcedureKind.Method) {
-            read = new InstanceTearOff(kind, receiver, propertyName,
-                interfaceTarget: member, resultType: readType)
-              ..fileOffset = fileOffset;
-          } else {
-            read = new InstanceGet(kind, receiver, propertyName,
-                interfaceTarget: member, resultType: readType)
-              ..fileOffset = fileOffset;
-          }
+
+        InstanceAccessKind kind;
+        switch (readTarget.kind) {
+          case ObjectAccessTargetKind.instanceMember:
+            kind = InstanceAccessKind.Instance;
+            break;
+          case ObjectAccessTargetKind.nullableInstanceMember:
+            kind = InstanceAccessKind.Nullable;
+            break;
+          case ObjectAccessTargetKind.objectMember:
+            kind = InstanceAccessKind.Object;
+            break;
+          default:
+            throw new UnsupportedError('Unexpected target kind $readTarget');
+        }
+        if (member is Procedure && member.kind == ProcedureKind.Method) {
+          read = new InstanceTearOff(kind, receiver, propertyName,
+              interfaceTarget: member, resultType: readType)
+            ..fileOffset = fileOffset;
         } else {
-          read = new PropertyGet(receiver, propertyName, readTarget.member)
+          read = new InstanceGet(kind, receiver, propertyName,
+              interfaceTarget: member, resultType: readType)
             ..fileOffset = fileOffset;
         }
         bool checkReturn = false;
@@ -5070,66 +4881,42 @@
         }
         break;
       case ObjectAccessTargetKind.invalid:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          write = new DynamicSet(
-              DynamicAccessKind.Invalid, receiver, propertyName, value)
-            ..fileOffset = fileOffset;
-        } else {
-          write =
-              new PropertySet(receiver, propertyName, value, writeTarget.member)
-                ..fileOffset = fileOffset;
-        }
+        write = new DynamicSet(
+            DynamicAccessKind.Invalid, receiver, propertyName, value)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.never:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          write = new DynamicSet(
-              DynamicAccessKind.Never, receiver, propertyName, value)
-            ..fileOffset = fileOffset;
-        } else {
-          write =
-              new PropertySet(receiver, propertyName, value, writeTarget.member)
-                ..fileOffset = fileOffset;
-        }
+        write = new DynamicSet(
+            DynamicAccessKind.Never, receiver, propertyName, value)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          write = new DynamicSet(
-              DynamicAccessKind.Dynamic, receiver, propertyName, value)
-            ..fileOffset = fileOffset;
-        } else {
-          write =
-              new PropertySet(receiver, propertyName, value, writeTarget.member)
-                ..fileOffset = fileOffset;
-        }
+        write = new DynamicSet(
+            DynamicAccessKind.Dynamic, receiver, propertyName, value)
+          ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.instanceMember:
       case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
-        if (inferrer.useNewMethodInvocationEncoding) {
-          InstanceAccessKind kind;
-          switch (writeTarget.kind) {
-            case ObjectAccessTargetKind.instanceMember:
-              kind = InstanceAccessKind.Instance;
-              break;
-            case ObjectAccessTargetKind.nullableInstanceMember:
-              kind = InstanceAccessKind.Nullable;
-              break;
-            case ObjectAccessTargetKind.objectMember:
-              kind = InstanceAccessKind.Object;
-              break;
-            default:
-              throw new UnsupportedError('Unexpected target kind $writeTarget');
-          }
-          write = new InstanceSet(kind, receiver, propertyName, value,
-              interfaceTarget: writeTarget.member!)
-            ..fileOffset = fileOffset;
-        } else {
-          write =
-              new PropertySet(receiver, propertyName, value, writeTarget.member)
-                ..fileOffset = fileOffset;
+        InstanceAccessKind kind;
+        switch (writeTarget.kind) {
+          case ObjectAccessTargetKind.instanceMember:
+            kind = InstanceAccessKind.Instance;
+            break;
+          case ObjectAccessTargetKind.nullableInstanceMember:
+            kind = InstanceAccessKind.Nullable;
+            break;
+          case ObjectAccessTargetKind.objectMember:
+            kind = InstanceAccessKind.Object;
+            break;
+          default:
+            throw new UnsupportedError('Unexpected target kind $writeTarget');
         }
+        write = new InstanceSet(kind, receiver, propertyName, value,
+            interfaceTarget: writeTarget.member!)
+          ..fileOffset = fileOffset;
         break;
     }
     if (!inferrer.isTopLevel && writeTarget.isNullable) {
@@ -5821,9 +5608,8 @@
     return new ExpressionInferenceResult(inferredType, node);
   }
 
-  @override
   ExpressionInferenceResult visitPropertySet(
-      covariant PropertySetImpl node, DartType typeContext) {
+      PropertySet node, DartType typeContext) {
     ExpressionInferenceResult receiverResult = inferrer
         .inferNullAwareExpression(node.receiver, const UnknownType(), true,
             isVoidAllowed: false);
@@ -5844,7 +5630,6 @@
             'target',
             new InstrumentationValueForMember(target.member!));
       }
-      node.interfaceTarget = target.member;
     }
     DartType writeContext = inferrer.getSetterType(target, receiverType);
     ExpressionInferenceResult rhsResult = inferrer
@@ -5965,7 +5750,6 @@
         inferredType, replacement, nullAwareGuards.prepend(nullAwareGuard));
   }
 
-  @override
   ExpressionInferenceResult visitPropertyGet(
       PropertyGet node, DartType typeContext) {
     ExpressionInferenceResult result = inferrer.inferNullAwareExpression(
@@ -6167,11 +5951,8 @@
     }
 
     if (target is Procedure && target.kind == ProcedureKind.Method) {
-      Expression tearOff = node;
-      if (inferrer.useNewMethodInvocationEncoding) {
-        tearOff = new StaticTearOff(node.target as Procedure)
-          ..fileOffset = node.fileOffset;
-      }
+      Expression tearOff = new StaticTearOff(node.target as Procedure)
+        ..fileOffset = node.fileOffset;
       return inferrer.instantiateTearOff(type, typeContext, tearOff);
     } else {
       return new ExpressionInferenceResult(type, node);
@@ -6304,9 +6085,10 @@
 
     Set<Field?>? enumFields;
     if (expressionType is InterfaceType && expressionType.classNode.isEnum) {
-      enumFields = expressionType.classNode.fields
-          .where((Field field) => field.isConst && field.type == expressionType)
-          .toSet();
+      enumFields = <Field?>{
+        ...expressionType.classNode.fields.where(
+            (Field field) => field.isConst && field.type == expressionType)
+      };
       if (expressionType.isPotentiallyNullable) {
         enumFields.add(null);
       }
@@ -6569,18 +6351,10 @@
     DartType resultType = rhsResult.inferredType;
     Expression resultExpression;
     if (variable.lateSetter != null) {
-      if (inferrer.useNewMethodInvocationEncoding) {
-        resultExpression = new LocalFunctionInvocation(variable.lateSetter!,
-            new Arguments(<Expression>[rhs])..fileOffset = node.fileOffset,
-            functionType: variable.lateSetter!.type as FunctionType)
-          ..fileOffset = node.fileOffset;
-      } else {
-        resultExpression = new MethodInvocation(
-            new VariableGet(variable.lateSetter!)..fileOffset = node.fileOffset,
-            callName,
-            new Arguments(<Expression>[rhs])..fileOffset = node.fileOffset)
-          ..fileOffset = node.fileOffset;
-      }
+      resultExpression = new LocalFunctionInvocation(variable.lateSetter!,
+          new Arguments(<Expression>[rhs])..fileOffset = node.fileOffset,
+          functionType: variable.lateSetter!.type as FunctionType)
+        ..fileOffset = node.fileOffset;
       // Future calls to flow analysis will be using `resultExpression` to refer
       // to the variable set, so instruct flow analysis to forward the
       // expression information.
@@ -6714,8 +6488,7 @@
         result.add(isSetVariable);
       }
 
-      Expression createVariableRead(bool useNewMethodInvocationEncoding,
-          {bool needsPromotion: false}) {
+      Expression createVariableRead({bool needsPromotion: false}) {
         if (needsPromotion) {
           return new VariableGet(node, node.type)..fileOffset = fileOffset;
         } else {
@@ -6739,11 +6512,7 @@
           new FunctionNode(
               node.initializer == null
                   ? late_lowering.createGetterBodyWithoutInitializer(
-                      inferrer.coreTypes,
-                      fileOffset,
-                      node.name!,
-                      node.type,
-                      inferrer.useNewMethodInvocationEncoding,
+                      inferrer.coreTypes, fileOffset, node.name!, node.type,
                       createVariableRead: createVariableRead,
                       createIsSetRead: createIsSetRead,
                       isSetEncoding: isSetEncoding,
@@ -6755,7 +6524,6 @@
                           node.name!,
                           node.type,
                           node.initializer!,
-                          inferrer.useNewMethodInvocationEncoding,
                           createVariableRead: createVariableRead,
                           createVariableWrite: createVariableWrite,
                           createIsSetRead: createIsSetRead,
@@ -6768,7 +6536,6 @@
                           node.name!,
                           node.type,
                           node.initializer!,
-                          inferrer.useNewMethodInvocationEncoding,
                           createVariableRead: createVariableRead,
                           createVariableWrite: createVariableWrite,
                           createIsSetRead: createIsSetRead,
@@ -6801,7 +6568,6 @@
                             node.name!,
                             setterParameter,
                             node.type,
-                            inferrer.useNewMethodInvocationEncoding,
                             shouldReturnValue: true,
                             createVariableRead: createVariableRead,
                             createVariableWrite: createVariableWrite,
@@ -6878,18 +6644,10 @@
     if (variable.isLocalFunction) {
       return inferrer.instantiateTearOff(resultType, typeContext, node);
     } else if (variable.lateGetter != null) {
-      if (inferrer.useNewMethodInvocationEncoding) {
-        resultExpression = new LocalFunctionInvocation(variable.lateGetter!,
-            new Arguments(<Expression>[])..fileOffset = node.fileOffset,
-            functionType: variable.lateGetter!.type as FunctionType)
-          ..fileOffset = node.fileOffset;
-      } else {
-        resultExpression = new MethodInvocation(
-            new VariableGet(variable.lateGetter!)..fileOffset = node.fileOffset,
-            callName,
-            new Arguments(<Expression>[])..fileOffset = node.fileOffset)
-          ..fileOffset = node.fileOffset;
-      }
+      resultExpression = new LocalFunctionInvocation(variable.lateGetter!,
+          new Arguments(<Expression>[])..fileOffset = node.fileOffset,
+          functionType: variable.lateGetter!.type as FunctionType)
+        ..fileOffset = node.fileOffset;
       // Future calls to flow analysis will be using `resultExpression` to refer
       // to the variable get, so instruct flow analysis to forward the
       // expression information.
@@ -7250,7 +7008,6 @@
               'target',
               new InstrumentationValueForMember(writeTarget.member!));
         }
-        propertySet.interfaceTarget = writeTarget.member;
       }
       _rhs = propertySet.value;
     }
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 749419c..9364065 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -422,6 +422,7 @@
   IndexSet,
   LoadLibraryTearOff,
   LocalPostIncDec,
+  MethodInvocation,
   NullAwareCompoundSet,
   NullAwareExtension,
   NullAwareIfNullSet,
@@ -429,7 +430,9 @@
   NullAwarePropertyGet,
   NullAwarePropertySet,
   Parenthesized,
+  PropertyGet,
   PropertyPostIncDec,
+  PropertySet,
   StaticPostIncDec,
   SuperIndexSet,
   SuperPostIncDec,
@@ -442,16 +445,19 @@
 
   @override
   R accept<R>(ExpressionVisitor<R> visitor) {
-    if (visitor is Printer || visitor is Precedence) {
-      // Allow visitors needed for toString.
+    if (visitor is Printer || visitor is Precedence || visitor is Transformer) {
+      // Allow visitors needed for toString and replaceWith.
       return visitor.defaultExpression(this);
     }
-    return unsupported("${runtimeType}.accept", -1, null);
+    return unsupported(
+        "${runtimeType}.accept on ${visitor.runtimeType}", -1, null);
   }
 
   @override
-  R accept1<R, A>(ExpressionVisitor1<R, A> visitor, A arg) =>
-      unsupported("${runtimeType}.accept1", -1, null);
+  R accept1<R, A>(ExpressionVisitor1<R, A> visitor, A arg) {
+    return unsupported(
+        "${runtimeType}.accept1 on ${visitor.runtimeType}", -1, null);
+  }
 
   @override
   DartType getStaticType(StaticTypeContext context) =>
@@ -1248,7 +1254,7 @@
   @override
   void toTextInternal(AstPrinter printer) {
     Expression methodInvocation = invocation;
-    if (methodInvocation is MethodInvocation) {
+    if (methodInvocation is InstanceInvocation) {
       Expression receiver = methodInvocation.receiver;
       if (receiver is VariableGet && receiver.variable == variable) {
         // Special-case the usual use of this node.
@@ -1259,6 +1265,16 @@
         printer.writeArguments(methodInvocation.arguments);
         return;
       }
+    } else if (methodInvocation is DynamicInvocation) {
+      Expression receiver = methodInvocation.receiver;
+      if (receiver is VariableGet && receiver.variable == variable) {
+        // Special-case the usual use of this node.
+        printer.writeExpression(variable.initializer!);
+        printer.write('?.');
+        printer.writeName(methodInvocation.name);
+        printer.writeArguments(methodInvocation.arguments);
+        return;
+      }
     }
     printer.write('let ');
     printer.writeVariableDeclaration(variable);
@@ -1347,8 +1363,7 @@
         // Special-case the usual use of this node.
         printer.writeExpression(variable.initializer!);
         printer.write('?.');
-        printer.writeInterfaceMemberName(
-            propertyGet.interfaceTargetReference, propertyGet.name);
+        printer.writeName(propertyGet.name);
         return;
       }
     }
@@ -1433,7 +1448,7 @@
   @override
   void toTextInternal(AstPrinter printer) {
     Expression propertySet = write;
-    if (propertySet is PropertySet) {
+    if (propertySet is InstanceSet) {
       Expression receiver = propertySet.receiver;
       if (receiver is VariableGet && receiver.variable == variable) {
         // Special-case the usual use of this node.
@@ -1445,6 +1460,17 @@
         printer.writeExpression(propertySet.value);
         return;
       }
+    } else if (propertySet is DynamicSet) {
+      Expression receiver = propertySet.receiver;
+      if (receiver is VariableGet && receiver.variable == variable) {
+        // Special-case the usual use of this node.
+        printer.writeExpression(variable.initializer!);
+        printer.write('?.');
+        printer.writeName(propertySet.name);
+        printer.write(' = ');
+        printer.writeExpression(propertySet.value);
+        return;
+      }
     }
     printer.write('let ');
     printer.writeVariableDeclaration(variable);
@@ -4096,29 +4122,6 @@
   }
 }
 
-/// Front end specific implementation of [PropertySet].
-class PropertySetImpl extends PropertySet {
-  /// If `true` the assignment is need for its effect and not for its value.
-  final bool forEffect;
-
-  /// If `true` the receiver can be cloned and doesn't need a temporary variable
-  /// for multiple reads.
-  final bool readOnlyReceiver;
-
-  PropertySetImpl(Expression receiver, Name name, Expression value,
-      {required this.forEffect, required this.readOnlyReceiver})
-      // ignore: unnecessary_null_comparison
-      : assert(forEffect != null),
-        // ignore: unnecessary_null_comparison
-        assert(readOnlyReceiver != null),
-        super(receiver, name, value);
-
-  @override
-  String toString() {
-    return "PropertySetImpl(${toStringInternal()})";
-  }
-}
-
 /// Internal representation of a read of an extension instance member.
 ///
 /// A read of an extension instance member `o.foo` is encoded as the
@@ -4524,3 +4527,238 @@
   }
   throw new UnsupportedError("Clone not supported for ${node.runtimeType}.");
 }
+
+/// A dynamically bound method invocation of the form `o.foo()`.
+///
+/// This will be transformed into an [InstanceInvocation], [DynamicInvocation],
+/// [FunctionInvocation] or [StaticInvocation] (for implicit extension method
+/// invocation) after type inference.
+class MethodInvocation extends InternalExpression {
+  Expression receiver;
+
+  Name name;
+
+  Arguments arguments;
+
+  MethodInvocation(this.receiver, this.name, this.arguments)
+      // ignore: unnecessary_null_comparison
+      : assert(receiver != null),
+        // ignore: unnecessary_null_comparison
+        assert(arguments != null) {
+    receiver.parent = this;
+    arguments.parent = this;
+  }
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitMethodInvocation(this, typeContext);
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.MethodInvocation;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    receiver.accept(v);
+    arguments.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    // ignore: unnecessary_null_comparison
+    if (receiver != null) {
+      receiver = v.transform(receiver);
+      receiver.parent = this;
+    }
+    // ignore: unnecessary_null_comparison
+    if (arguments != null) {
+      arguments = v.transform(arguments);
+      arguments.parent = this;
+    }
+  }
+
+  @override
+  void transformOrRemoveChildren(RemovingTransformer v) {
+    // ignore: unnecessary_null_comparison
+    if (receiver != null) {
+      receiver = v.transform(receiver);
+      receiver.parent = this;
+    }
+    // ignore: unnecessary_null_comparison
+    if (arguments != null) {
+      arguments = v.transform(arguments);
+      arguments.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "MethodInvocation(${toStringInternal()})";
+  }
+
+  @override
+  int get precedence => Precedence.PRIMARY;
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver, minimumPrecedence: Precedence.PRIMARY);
+    printer.write('.');
+    printer.writeName(name);
+    printer.writeArguments(arguments);
+  }
+}
+
+/// A dynamically bound property read of the form `o.foo`.
+///
+/// This will be transformed into an [InstanceGet], [InstanceTearOff],
+/// [DynamicGet], [FunctionTearOff] or [StaticInvocation] (for implicit
+/// extension member access) after type inference.
+class PropertyGet extends InternalExpression {
+  Expression receiver;
+
+  Name name;
+
+  PropertyGet(this.receiver, this.name)
+      // ignore: unnecessary_null_comparison
+      : assert(receiver != null) {
+    receiver.parent = this;
+  }
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitPropertyGet(this, typeContext);
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.PropertyGet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    receiver.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    // ignore: unnecessary_null_comparison
+    if (receiver != null) {
+      receiver = v.transform(receiver);
+      receiver.parent = this;
+    }
+  }
+
+  @override
+  void transformOrRemoveChildren(RemovingTransformer v) {
+    // ignore: unnecessary_null_comparison
+    if (receiver != null) {
+      receiver = v.transform(receiver);
+      receiver.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "PropertyGet(${toStringInternal()})";
+  }
+
+  @override
+  int get precedence => Precedence.PRIMARY;
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver, minimumPrecedence: Precedence.PRIMARY);
+    printer.write('.');
+    printer.writeName(name);
+  }
+}
+
+/// A dynamically bound property write of the form `o.foo = e`.
+///
+/// This will be transformed into an [InstanceSet], [DynamicSet], or
+/// [StaticInvocation] (for implicit extension member access) after type
+/// inference.
+class PropertySet extends InternalExpression {
+  Expression receiver;
+  Name name;
+  Expression value;
+
+  /// If `true` the assignment is need for its effect and not for its value.
+  final bool forEffect;
+
+  /// If `true` the receiver can be cloned and doesn't need a temporary variable
+  /// for multiple reads.
+  final bool readOnlyReceiver;
+
+  PropertySet(this.receiver, this.name, this.value,
+      {required this.forEffect, required this.readOnlyReceiver})
+      // ignore: unnecessary_null_comparison
+      : assert(receiver != null),
+        // ignore: unnecessary_null_comparison
+        assert(value != null),
+        // ignore: unnecessary_null_comparison
+        assert(forEffect != null),
+        // ignore: unnecessary_null_comparison
+        assert(readOnlyReceiver != null) {
+    receiver.parent = this;
+    value.parent = this;
+  }
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitPropertySet(this, typeContext);
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.PropertySet;
+
+  @override
+  void visitChildren(Visitor v) {
+    receiver.accept(v);
+    name.accept(v);
+    value.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    // ignore: unnecessary_null_comparison
+    if (receiver != null) {
+      receiver = v.transform(receiver);
+      receiver.parent = this;
+    }
+    // ignore: unnecessary_null_comparison
+    if (value != null) {
+      value = v.transform(value);
+      value.parent = this;
+    }
+  }
+
+  @override
+  void transformOrRemoveChildren(RemovingTransformer v) {
+    // ignore: unnecessary_null_comparison
+    if (receiver != null) {
+      receiver = v.transform(receiver);
+      receiver.parent = this;
+    }
+    // ignore: unnecessary_null_comparison
+    if (value != null) {
+      value = v.transform(value);
+      value.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "PropertySet(${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver, minimumPrecedence: Precedence.PRIMARY);
+    printer.write('.');
+    printer.writeName(name);
+    printer.write(' = ');
+    printer.writeExpression(value);
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
index 775003f..7c62ddb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
@@ -48,7 +48,6 @@
         MapLiteralEntry,
         MapLiteral,
         Member,
-        MethodInvocation,
         Name,
         NamedExpression,
         NamedType,
@@ -56,8 +55,6 @@
         NullLiteral,
         Procedure,
         ProcedureKind,
-        PropertyGet,
-        PropertySet,
         Rethrow,
         ReturnStatement,
         Statement,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
index 6868aa7..d0033fa 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
@@ -46,6 +46,17 @@
 
   @override
   void reportInvalidExpression(InvalidExpression node) {
+    // TODO(johnniwinther): Improve the precision of this assertion. Do we
+    // for instance allow warnings only to have been reported in previous
+    // compilations.
+    assert(
+        // Either we have already reported an error
+        loader.hasSeenError ||
+            // or we have reported an error in a previous compilation.
+            loader.builders.values.any((builder) =>
+                builder.library.problemsAsJson?.isNotEmpty ?? false),
+        "No error reported before seeing: "
+        "${node.message}");
     // Assumed to be already reported.
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
new file mode 100644
index 0000000..71176e5
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library fasta.kernel_target;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
+import 'package:kernel/type_algebra.dart' show Substitution;
+
+/// Data for clone default values for synthesized function nodes once the
+/// original default values have been computed.
+///
+/// This is used for constructors in unnamed mixin application, which are
+/// created from the constructors in the superclass, and for tear off lowerings
+/// for redirecting factories, which are created from the effective target
+/// constructor.
+class SynthesizedFunctionNode {
+  /// Type parameter map from type parameters in scope [_original] to types
+  /// in scope of [_synthesized].
+  // TODO(johnniwinther): Is this ever needed? Should occurrence of type
+  //  variable types in default values be a compile time error?
+  final Map<TypeParameter, DartType> _typeSubstitution;
+
+  /// The original function node.
+  final FunctionNode _original;
+
+  /// The synthesized function node.
+  final FunctionNode _synthesized;
+
+  /// If `true`, the [_synthesized] is guaranteed to have the same parameters in
+  /// the same order as [_original]. Otherwise [_original] is only guaranteed to
+  /// be callable from [_synthesized], meaning that is has at most the same
+  /// number of positional parameters and a, possibly reordered, subset of the
+  /// named parameters.
+  final bool identicalSignatures;
+
+  SynthesizedFunctionNode(
+      this._typeSubstitution, this._original, this._synthesized,
+      {this.identicalSignatures: true});
+
+  void cloneDefaultValues() {
+    // TODO(ahe): It is unclear if it is legal to use type variables in
+    // default values, but Fasta is currently allowing it, and the VM
+    // accepts it. If it isn't legal, the we can speed this up by using a
+    // single cloner without substitution.
+    CloneVisitorNotMembers? cloner;
+
+    void cloneInitializer(VariableDeclaration originalParameter,
+        VariableDeclaration clonedParameter) {
+      if (originalParameter.initializer != null) {
+        cloner ??=
+            new CloneVisitorNotMembers(typeSubstitution: _typeSubstitution);
+        clonedParameter.initializer = cloner!
+            .clone(originalParameter.initializer!)
+              ..parent = clonedParameter;
+      }
+    }
+
+    // For mixin application constructors, the argument count is the same, but
+    // for redirecting tear off lowerings, the argument count of the tear off
+    // can be less than that of the redirection target.
+
+    assert(_synthesized.positionalParameters.length <=
+        _original.positionalParameters.length);
+    for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
+      cloneInitializer(_original.positionalParameters[i],
+          _synthesized.positionalParameters[i]);
+    }
+
+    if (identicalSignatures) {
+      assert(_synthesized.namedParameters.length ==
+          _original.namedParameters.length);
+      for (int i = 0; i < _synthesized.namedParameters.length; i++) {
+        cloneInitializer(
+            _original.namedParameters[i], _synthesized.namedParameters[i]);
+      }
+    } else if (_synthesized.namedParameters.isNotEmpty) {
+      Map<String, VariableDeclaration> originalParameters = {};
+      for (int i = 0; i < _original.namedParameters.length; i++) {
+        originalParameters[_original.namedParameters[i].name!] =
+            _original.namedParameters[i];
+      }
+      for (int i = 0; i < _synthesized.namedParameters.length; i++) {
+        cloneInitializer(
+            originalParameters[_synthesized.namedParameters[i].name!]!,
+            _synthesized.namedParameters[i]);
+      }
+    }
+  }
+}
+
+class TypeDependency {
+  final Member synthesized;
+  final Member original;
+  final Substitution substitution;
+
+  TypeDependency(this.synthesized, this.original, this.substitution);
+
+  void copyInferred() {
+    for (int i = 0; i < original.function!.positionalParameters.length; i++) {
+      VariableDeclaration synthesizedParameter =
+          synthesized.function!.positionalParameters[i];
+      VariableDeclaration constructorParameter =
+          original.function!.positionalParameters[i];
+      synthesizedParameter.type =
+          substitution.substituteType(constructorParameter.type);
+    }
+    for (int i = 0; i < original.function!.namedParameters.length; i++) {
+      VariableDeclaration synthesizedParameter =
+          synthesized.function!.namedParameters[i];
+      VariableDeclaration originalParameter =
+          original.function!.namedParameters[i];
+      synthesizedParameter.type =
+          substitution.substituteType(originalParameter.type);
+    }
+    synthesized.function!.returnType =
+        substitution.substituteType(original.function!.returnType);
+  }
+}
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 2531ba7..93fb9a8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -6,7 +6,6 @@
 
 import 'package:kernel/ast.dart';
 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;
 import 'package:kernel/target/changed_structure_notifier.dart'
@@ -82,6 +81,7 @@
         transformProcedure,
         ConstantCoverage;
 import 'kernel_constants.dart' show KernelConstantErrorReporter;
+import 'kernel_helper.dart';
 import 'verifier.dart' show verifyComponent, verifyGetStaticType;
 
 class KernelTarget extends TargetImplementation {
@@ -139,7 +139,8 @@
   final bool errorOnUnevaluatedConstant =
       CompilerContext.current.options.errorOnUnevaluatedConstant;
 
-  final List<ClonedFunctionNode> clonedFunctionNodes = <ClonedFunctionNode>[];
+  final List<SynthesizedFunctionNode> synthesizedFunctionNodes =
+      <SynthesizedFunctionNode>[];
 
   KernelTarget(this.fileSystem, this.includeComments, DillTarget dillTarget,
       UriTranslator uriTranslator)
@@ -330,13 +331,15 @@
       computeCoreTypes();
       loader.buildClassHierarchy(myClasses, objectClassBuilder);
       loader.computeHierarchy();
+      loader.installTypedefTearOffs();
       loader.performTopLevelInference(myClasses);
       loader.checkSupertypes(myClasses);
       loader.checkOverrides(myClasses);
       loader.checkAbstractMembers(myClasses);
       loader.addNoSuchMethodForwarders(myClasses);
       loader.checkMixins(myClasses);
-      loader.buildOutlineExpressions(loader.coreTypes);
+      loader.buildOutlineExpressions(
+          loader.coreTypes, synthesizedFunctionNodes);
       loader.checkTypes();
       loader.checkRedirectingFactories(myClasses);
       loader.checkMainMethods();
@@ -361,7 +364,7 @@
     return withCrashReporting<Component?>(() async {
       ticker.logMs("Building component");
       await loader.buildBodies();
-      finishClonedParameters();
+      finishSynthesizedParameters();
       loader.finishDeferredLoadTearoffs();
       loader.finishNoSuchMethodForwarders();
       List<SourceClassBuilder> myClasses = collectMyClasses();
@@ -598,7 +601,7 @@
     assert(!builder.isExtension);
     // TODO(askesc): Make this check light-weight in the absence of patches.
     if (builder.cls.constructors.isNotEmpty) return;
-    if (builder.cls.redirectingFactoryConstructors.isNotEmpty) return;
+    if (builder.cls.redirectingFactories.isNotEmpty) return;
     for (Procedure proc in builder.cls.procedures) {
       if (proc.isFactory) return;
     }
@@ -713,7 +716,9 @@
       Constructor? referenceFrom) {
     VariableDeclaration copyFormal(VariableDeclaration formal) {
       VariableDeclaration copy = new VariableDeclaration(formal.name,
-          isFinal: formal.isFinal, isConst: formal.isConst);
+          isFinal: formal.isFinal,
+          isConst: formal.isConst,
+          type: const UnknownType());
       if (formal.type is! UnknownType) {
         copy.type = substitute(formal.type, substitutionMap);
       } else {
@@ -757,16 +762,17 @@
         returnType: makeConstructorReturnType(cls));
     SuperInitializer initializer = new SuperInitializer(
         constructor, new Arguments(positional, named: named));
-    ClonedFunctionNode clonedFunctionNode =
-        new ClonedFunctionNode(substitutionMap, constructor.function, function);
+    SynthesizedFunctionNode synthesizedFunctionNode =
+        new SynthesizedFunctionNode(
+            substitutionMap, constructor.function, function);
     if (!isConst) {
       // For constant constructors default values are computed and cloned part
       // of the outline expression and therefore passed to the
       // [SyntheticConstructorBuilder] below.
       //
       // For non-constant constructors default values are cloned as part of the
-      // full compilation using [clonedFunctionNodes].
-      clonedFunctionNodes.add(clonedFunctionNode);
+      // full compilation using [synthesizedFunctionNodes].
+      synthesizedFunctionNodes.add(synthesizedFunctionNode);
     }
     return new SyntheticConstructorBuilder(
         classBuilder,
@@ -785,14 +791,15 @@
         // cloned function nodes to ensure that the default values are computed
         // and cloned for the outline.
         origin: isConst ? memberBuilder : null,
-        clonedFunctionNode: isConst ? clonedFunctionNode : null);
+        synthesizedFunctionNode: isConst ? synthesizedFunctionNode : null);
   }
 
-  void finishClonedParameters() {
-    for (ClonedFunctionNode clonedFunctionNode in clonedFunctionNodes) {
-      clonedFunctionNode.cloneDefaultValues();
+  void finishSynthesizedParameters() {
+    for (SynthesizedFunctionNode synthesizedFunctionNode
+        in synthesizedFunctionNodes) {
+      synthesizedFunctionNode.cloneDefaultValues();
     }
-    clonedFunctionNodes.clear();
+    synthesizedFunctionNodes.clear();
     ticker.logMs("Cloned default values of formals");
   }
 
@@ -810,7 +817,7 @@
       ..isNonNullableByDefault =
           enclosingClass.enclosingLibrary.isNonNullableByDefault;
     Procedure? constructorTearOff = createConstructorTearOffProcedure(
-        '', classBuilder.library, constructor.fileOffset,
+        '', classBuilder.library, classBuilder.fileUri, constructor.fileOffset,
         forAbstractClassOrEnum:
             enclosingClass.isAbstract || enclosingClass.isEnum);
     if (constructorTearOff != null) {
@@ -1046,8 +1053,12 @@
       // To report errors on the first definition of a constructor, we need to
       // iterate until that last element.
       ConstructorBuilder earliest = constructorBuilder;
-      while (earliest.next != null) {
-        earliest = earliest.next as ConstructorBuilder;
+      Builder earliestBuilder = constructorBuilder;
+      while (earliestBuilder.next != null) {
+        earliestBuilder = earliestBuilder.next!;
+        if (earliestBuilder is ConstructorBuilder) {
+          earliest = earliestBuilder;
+        }
       }
 
       bool isRedirecting = false;
@@ -1246,9 +1257,7 @@
     if (loader.target.context.options
         .isExperimentEnabledGlobally(ExperimentalFlag.valueClass)) {
       valueClass.transformComponent(
-          component!, loader.coreTypes, loader.hierarchy, environment,
-          useNewMethodInvocationEncoding:
-              backendTarget.supportsNewMethodInvocationEncoding);
+          component!, loader.coreTypes, loader.hierarchy, environment);
       ticker.logMs("Lowered value classes");
     }
 
@@ -1399,7 +1408,7 @@
 
   KernelDiagnosticReporter(this.loader);
 
-  void report(Message message, int charOffset, int length, Uri fileUri,
+  void report(Message message, int charOffset, int length, Uri? fileUri,
       {List<LocatedMessage>? context}) {
     loader.addProblem(message, charOffset, noLength, fileUri, context: context);
   }
@@ -1419,43 +1428,7 @@
 
   void updateType() {
     // ignore: unnecessary_null_comparison
-    assert(source.type != null, "No type computed for $source.");
+    assert(source.type is! UnknownType, "No type computed for $source.");
     target.type = substitute(source.type, substitutionMap);
   }
 }
-
-class ClonedFunctionNode {
-  final Map<TypeParameter, DartType> _typeSubstitution;
-  final FunctionNode _original;
-  final FunctionNode _clone;
-
-  ClonedFunctionNode(this._typeSubstitution, this._original, this._clone);
-
-  void cloneDefaultValues() {
-    // TODO(ahe): It is unclear if it is legal to use type variables in
-    // default values, but Fasta is currently allowing it, and the VM
-    // accepts it. If it isn't legal, the we can speed this up by using a
-    // single cloner without substitution.
-    CloneVisitorNotMembers? cloner;
-
-    void cloneInitializer(VariableDeclaration originalParameter,
-        VariableDeclaration clonedParameter) {
-      if (originalParameter.initializer != null) {
-        cloner ??=
-            new CloneVisitorNotMembers(typeSubstitution: _typeSubstitution);
-        clonedParameter.initializer = cloner!
-            .clone(originalParameter.initializer!)
-              ..parent = clonedParameter;
-      }
-    }
-
-    for (int i = 0; i < _original.positionalParameters.length; i++) {
-      cloneInitializer(
-          _original.positionalParameters[i], _clone.positionalParameters[i]);
-    }
-
-    for (int i = 0; i < _original.namedParameters.length; i++) {
-      cloneInitializer(_original.namedParameters[i], _clone.namedParameters[i]);
-    }
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
index 8a9c80c..4f1045c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
@@ -7,7 +7,6 @@
 
 import '../../base/nnbd_mode.dart';
 import '../source/source_library_builder.dart';
-import '../names.dart';
 
 const String lateFieldPrefix = '_#';
 const String lateIsSetSuffix = '#isSet';
@@ -20,15 +19,9 @@
 ///
 /// Late final fields and locals need to detect writes during initialization and
 /// therefore uses [createGetterWithInitializerWithRecheck] instead.
-Statement createGetterWithInitializer(
-    CoreTypes coreTypes,
-    int fileOffset,
-    String name,
-    DartType type,
-    Expression initializer,
-    bool useNewMethodInvocationEncoding,
-    {required Expression createVariableRead(bool useNewMethodInvocationEncoding,
-        {bool needsPromotion}),
+Statement createGetterWithInitializer(CoreTypes coreTypes, int fileOffset,
+    String name, DartType type, Expression initializer,
+    {required Expression createVariableRead({bool needsPromotion}),
     required Expression createVariableWrite(Expression value),
     required Expression createIsSetRead(),
     required Expression createIsSetWrite(Expression value),
@@ -64,8 +57,7 @@
             // If [type] is a type variable with undetermined nullability we
             // need to create a read of the field that is promoted to the type
             // variable type.
-            createVariableRead(useNewMethodInvocationEncoding,
-                needsPromotion: type.isPotentiallyNonNullable))
+            createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
           ..fileOffset = fileOffset
       ])
         ..fileOffset = fileOffset;
@@ -74,9 +66,7 @@
       //
       //    return let # = _#field in isSentinel(#) ? _#field = <init> : #;
       VariableDeclaration variable = new VariableDeclaration.forValue(
-          createVariableRead(useNewMethodInvocationEncoding,
-              needsPromotion: false)
-            ..fileOffset = fileOffset,
+          createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
           type: type.withDeclaredNullability(Nullability.nullable))
         ..fileOffset = fileOffset;
       return new ReturnStatement(
@@ -101,46 +91,30 @@
       //
       //    return let # = _#field in # == null ? _#field = <init> : #;
       VariableDeclaration variable = new VariableDeclaration.forValue(
-          createVariableRead(useNewMethodInvocationEncoding,
-              needsPromotion: false)
-            ..fileOffset = fileOffset,
+          createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
           type: type.withDeclaredNullability(Nullability.nullable))
         ..fileOffset = fileOffset;
-      return new ReturnStatement(new Let(
-          variable,
-          new ConditionalExpression(
-              useNewMethodInvocationEncoding
-                  ? (new EqualsNull(
+      return new ReturnStatement(
+          new Let(
+              variable,
+              new ConditionalExpression(
+                  new EqualsNull(
                       new VariableGet(variable)..fileOffset = fileOffset)
-                    ..fileOffset = fileOffset)
-                  : new MethodInvocation(
-                      new VariableGet(variable)..fileOffset = fileOffset,
-                      equalsName,
-                      new Arguments(<Expression>[
-                        new NullLiteral()..fileOffset = fileOffset
-                      ])
-                        ..fileOffset = fileOffset)
-                ..fileOffset = fileOffset,
-              createVariableWrite(initializer)..fileOffset = fileOffset,
-              new VariableGet(variable, type)..fileOffset = fileOffset,
-              type)
+                    ..fileOffset = fileOffset,
+                  createVariableWrite(initializer)..fileOffset = fileOffset,
+                  new VariableGet(variable, type)..fileOffset = fileOffset,
+                  type)
+                ..fileOffset = fileOffset)
             ..fileOffset = fileOffset)
-        ..fileOffset = fileOffset)
         ..fileOffset = fileOffset;
   }
 }
 
 /// Creates the body for the synthesized getter used to encode the lowering
 /// of a late final field or local with an initializer.
-Statement createGetterWithInitializerWithRecheck(
-    CoreTypes coreTypes,
-    int fileOffset,
-    String name,
-    DartType type,
-    Expression initializer,
-    bool useNewMethodInvocationEncoding,
-    {required Expression createVariableRead(bool useNewMethodInvocationEncoding,
-        {bool needsPromotion}),
+Statement createGetterWithInitializerWithRecheck(CoreTypes coreTypes,
+    int fileOffset, String name, DartType type, Expression initializer,
+    {required Expression createVariableRead({bool needsPromotion}),
     required Expression createVariableWrite(Expression value),
     required Expression createIsSetRead(),
     required Expression createIsSetWrite(Expression value),
@@ -202,8 +176,7 @@
             // If [type] is a type variable with undetermined nullability we
             // need to create a read of the field that is promoted to the type
             // variable type.
-            createVariableRead(useNewMethodInvocationEncoding,
-                needsPromotion: type.isPotentiallyNonNullable))
+            createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
           ..fileOffset = fileOffset
       ])
         ..fileOffset = fileOffset;
@@ -215,43 +188,41 @@
       //            ? _#field = #2 : throw '...'
       //        : #1;
       VariableDeclaration variable = new VariableDeclaration.forValue(
-          createVariableRead(useNewMethodInvocationEncoding,
-              needsPromotion: false)
-            ..fileOffset = fileOffset,
+          createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
           type: type)
         ..fileOffset = fileOffset;
-      return new ReturnStatement(new Let(
-          variable,
-          new ConditionalExpression(
-              new StaticInvocation(
-                  coreTypes.isSentinelMethod,
-                  new Arguments(<Expression>[
-                    new VariableGet(variable)..fileOffset = fileOffset
-                  ])
-                    ..fileOffset = fileOffset)
-                ..fileOffset = fileOffset,
-              new Let(
-                  temp,
-                  new ConditionalExpression(
-                      new StaticInvocation(
-                          coreTypes.isSentinelMethod,
-                          new Arguments(<Expression>[
-                            createVariableRead(useNewMethodInvocationEncoding,
-                                needsPromotion: false)
-                              ..fileOffset = fileOffset
-                          ])
-                            ..fileOffset = fileOffset)
-                        ..fileOffset = fileOffset,
-                      createVariableWrite(
-                          new VariableGet(temp)..fileOffset = fileOffset)
-                        ..fileOffset = fileOffset,
-                      exception,
-                      type)
-                    ..fileOffset = fileOffset),
-              new VariableGet(variable)..fileOffset = fileOffset,
-              type)
+      return new ReturnStatement(
+          new Let(
+              variable,
+              new ConditionalExpression(
+                  new StaticInvocation(
+                      coreTypes.isSentinelMethod,
+                      new Arguments(<Expression>[
+                        new VariableGet(variable)..fileOffset = fileOffset
+                      ])
+                        ..fileOffset = fileOffset)
+                    ..fileOffset = fileOffset,
+                  new Let(
+                      temp,
+                      new ConditionalExpression(
+                          new StaticInvocation(
+                              coreTypes.isSentinelMethod,
+                              new Arguments(<Expression>[
+                                createVariableRead(needsPromotion: false)
+                                  ..fileOffset = fileOffset
+                              ])
+                                ..fileOffset = fileOffset)
+                            ..fileOffset = fileOffset,
+                          createVariableWrite(
+                              new VariableGet(temp)..fileOffset = fileOffset)
+                            ..fileOffset = fileOffset,
+                          exception,
+                          type)
+                        ..fileOffset = fileOffset),
+                  new VariableGet(variable)..fileOffset = fileOffset,
+                  type)
+                ..fileOffset = fileOffset)
             ..fileOffset = fileOffset)
-        ..fileOffset = fileOffset)
         ..fileOffset = fileOffset;
     case IsSetEncoding.useNull:
       // Generate:
@@ -261,55 +232,33 @@
       //            ? _#field = #2 : throw '...'
       //        : #1;
       VariableDeclaration variable = new VariableDeclaration.forValue(
-          createVariableRead(useNewMethodInvocationEncoding,
-              needsPromotion: false)
-            ..fileOffset = fileOffset,
+          createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
           type: type.withDeclaredNullability(Nullability.nullable))
         ..fileOffset = fileOffset;
-      return new ReturnStatement(new Let(
-          variable,
-          new ConditionalExpression(
-              useNewMethodInvocationEncoding
-                  ? (new EqualsNull(
+      return new ReturnStatement(
+          new Let(
+              variable,
+              new ConditionalExpression(
+                  new EqualsNull(
                       new VariableGet(variable)..fileOffset = fileOffset)
-                    ..fileOffset = fileOffset)
-                  : new MethodInvocation(
-                      new VariableGet(variable)..fileOffset = fileOffset,
-                      equalsName,
-                      new Arguments(<Expression>[
-                        new NullLiteral()..fileOffset = fileOffset
-                      ])
-                        ..fileOffset = fileOffset)
-                ..fileOffset = fileOffset,
-              new Let(
-                  temp,
-                  new ConditionalExpression(
-                      useNewMethodInvocationEncoding
-                          ? (new EqualsNull(
-                              createVariableRead(useNewMethodInvocationEncoding,
-                                  needsPromotion: false)
+                    ..fileOffset = fileOffset,
+                  new Let(
+                      temp,
+                      new ConditionalExpression(
+                          new EqualsNull(
+                              createVariableRead(needsPromotion: false)
                                 ..fileOffset = fileOffset)
-                            ..fileOffset = fileOffset)
-                          : new MethodInvocation(
-                              createVariableRead(useNewMethodInvocationEncoding,
-                                  needsPromotion: false)
-                                ..fileOffset = fileOffset,
-                              equalsName,
-                              new Arguments(<Expression>[
-                                new NullLiteral()..fileOffset = fileOffset
-                              ])
-                                ..fileOffset = fileOffset)
-                        ..fileOffset = fileOffset,
-                      createVariableWrite(
-                          new VariableGet(temp)..fileOffset = fileOffset)
-                        ..fileOffset = fileOffset,
-                      exception,
-                      type)
-                    ..fileOffset = fileOffset),
-              new VariableGet(variable, type)..fileOffset = fileOffset,
-              type)
+                            ..fileOffset = fileOffset,
+                          createVariableWrite(
+                              new VariableGet(temp)..fileOffset = fileOffset)
+                            ..fileOffset = fileOffset,
+                          exception,
+                          type)
+                        ..fileOffset = fileOffset),
+                  new VariableGet(variable, type)..fileOffset = fileOffset,
+                  type)
+                ..fileOffset = fileOffset)
             ..fileOffset = fileOffset)
-        ..fileOffset = fileOffset)
         ..fileOffset = fileOffset;
   }
 }
@@ -317,13 +266,8 @@
 /// Creates the body for the synthesized getter used to encode the lowering
 /// of a late field or local without an initializer.
 Statement createGetterBodyWithoutInitializer(
-    CoreTypes coreTypes,
-    int fileOffset,
-    String name,
-    DartType type,
-    bool useNewMethodInvocationEncoding,
-    {required Expression createVariableRead(bool useNewMethodInvocationEncoding,
-        {bool needsPromotion}),
+    CoreTypes coreTypes, int fileOffset, String name, DartType type,
+    {required Expression createVariableRead({bool needsPromotion}),
     required Expression createIsSetRead(),
     required IsSetEncoding isSetEncoding,
     required bool forField}) {
@@ -349,8 +293,7 @@
       return new ReturnStatement(
           new ConditionalExpression(
               createIsSetRead()..fileOffset = fileOffset,
-              createVariableRead(useNewMethodInvocationEncoding,
-                  needsPromotion: type.isPotentiallyNonNullable)
+              createVariableRead(needsPromotion: type.isPotentiallyNonNullable)
                 ..fileOffset = fileOffset,
               exception,
               type)
@@ -361,8 +304,7 @@
       //
       //    return let # = _#field in isSentinel(#) ? throw '...' : #;
       VariableDeclaration variable = new VariableDeclaration.forValue(
-          createVariableRead(useNewMethodInvocationEncoding)
-            ..fileOffset = fileOffset,
+          createVariableRead()..fileOffset = fileOffset,
           type: type.withDeclaredNullability(Nullability.nullable))
         ..fileOffset = fileOffset;
       return new ReturnStatement(
@@ -387,30 +329,21 @@
       //
       //    return let # = _#field in # == null ? throw '...' : #;
       VariableDeclaration variable = new VariableDeclaration.forValue(
-          createVariableRead(useNewMethodInvocationEncoding)
-            ..fileOffset = fileOffset,
+          createVariableRead()..fileOffset = fileOffset,
           type: type.withDeclaredNullability(Nullability.nullable))
         ..fileOffset = fileOffset;
-      return new ReturnStatement(new Let(
-          variable,
-          new ConditionalExpression(
-              useNewMethodInvocationEncoding
-                  ? (new EqualsNull(
+      return new ReturnStatement(
+          new Let(
+              variable,
+              new ConditionalExpression(
+                  new EqualsNull(
                       new VariableGet(variable)..fileOffset = fileOffset)
-                    ..fileOffset = fileOffset)
-                  : new MethodInvocation(
-                      new VariableGet(variable)..fileOffset = fileOffset,
-                      equalsName,
-                      new Arguments(<Expression>[
-                        new NullLiteral()..fileOffset = fileOffset
-                      ])
-                        ..fileOffset = fileOffset)
-                ..fileOffset = fileOffset,
-              exception,
-              new VariableGet(variable, type)..fileOffset = fileOffset,
-              type)
+                    ..fileOffset = fileOffset,
+                  exception,
+                  new VariableGet(variable, type)..fileOffset = fileOffset,
+                  type)
+                ..fileOffset = fileOffset)
             ..fileOffset = fileOffset)
-        ..fileOffset = fileOffset)
         ..fileOffset = fileOffset;
   }
 }
@@ -464,15 +397,10 @@
 
 /// Creates the body for the synthesized setter used to encode the lowering
 /// of a final late field or local.
-Statement createSetterBodyFinal(
-    CoreTypes coreTypes,
-    int fileOffset,
-    String name,
-    VariableDeclaration parameter,
-    DartType type,
-    bool useNewMethodInvocationEncoding,
+Statement createSetterBodyFinal(CoreTypes coreTypes, int fileOffset,
+    String name, VariableDeclaration parameter, DartType type,
     {required bool shouldReturnValue,
-    required Expression createVariableRead(bool useNewMethodInvocationEncoding),
+    required Expression createVariableRead(),
     required Expression createVariableWrite(Expression value),
     required Expression createIsSetRead(),
     required Expression createIsSetWrite(Expression value),
@@ -536,10 +464,8 @@
       return new IfStatement(
         new StaticInvocation(
             coreTypes.isSentinelMethod,
-            new Arguments(<Expression>[
-              createVariableRead(useNewMethodInvocationEncoding)
-                ..fileOffset = fileOffset
-            ])
+            new Arguments(
+                <Expression>[createVariableRead()..fileOffset = fileOffset])
               ..fileOffset = fileOffset)
           ..fileOffset = fileOffset,
         createReturn(createVariableWrite(
@@ -556,18 +482,7 @@
       //      throw '...';
       //    }
       return new IfStatement(
-        useNewMethodInvocationEncoding
-            ? (new EqualsNull(
-                createVariableRead(useNewMethodInvocationEncoding)
-                  ..fileOffset = fileOffset)
-              ..fileOffset = fileOffset)
-            : new MethodInvocation(
-                createVariableRead(useNewMethodInvocationEncoding)
-                  ..fileOffset = fileOffset,
-                equalsName,
-                new Arguments(
-                    <Expression>[new NullLiteral()..fileOffset = fileOffset])
-                  ..fileOffset = fileOffset)
+        new EqualsNull(createVariableRead()..fileOffset = fileOffset)
           ..fileOffset = fileOffset,
         createReturn(createVariableWrite(
             new VariableGet(parameter)..fileOffset = fileOffset)
diff --git a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
index 265cee2..4f63d8b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
@@ -179,12 +179,11 @@
 }
 
 RedirectionTarget? getRedirectionTarget(Procedure member, EnsureLoaded helper) {
-  List<DartType> typeArguments = <DartType>[]..length =
-      member.function.typeParameters.length;
-  for (int i = 0; i < typeArguments.length; i++) {
-    typeArguments[i] = new TypeParameterType.withDefaultNullabilityForLibrary(
+  List<DartType> typeArguments = new List<DartType>.generate(
+      member.function.typeParameters.length, (int i) {
+    return new TypeParameterType.withDefaultNullabilityForLibrary(
         member.function.typeParameters[i], member.enclosingLibrary);
-  }
+  }, growable: true);
 
   // We use the [tortoise and hare algorithm]
   // (https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare) to
@@ -201,15 +200,15 @@
     Member nextTortoise = tortoiseBody!.target!;
     helper.ensureLoaded(nextTortoise);
     List<DartType>? nextTypeArguments = tortoiseBody.typeArguments;
-    if (nextTypeArguments == null) {
-      nextTypeArguments = <DartType>[];
-    }
-
-    Substitution sub = Substitution.fromPairs(
-        tortoise.function!.typeParameters, typeArguments);
-    typeArguments = <DartType>[]..length = nextTypeArguments.length;
-    for (int i = 0; i < typeArguments.length; i++) {
-      typeArguments[i] = sub.substituteType(nextTypeArguments[i]);
+    if (nextTypeArguments != null) {
+      Substitution sub = Substitution.fromPairs(
+          tortoise.function!.typeParameters, typeArguments);
+      typeArguments =
+          new List<DartType>.generate(nextTypeArguments.length, (int i) {
+        return sub.substituteType(nextTypeArguments[i]);
+      }, growable: true);
+    } else {
+      typeArguments = <DartType>[];
     }
 
     tortoise = nextTortoise;
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
index af26d1b..ed6516b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
@@ -46,7 +46,6 @@
   final Procedure _setAddAll;
   late final FunctionType _setAddAllFunctionType;
   final Procedure _setOf;
-  final Procedure _objectEquals;
   final Procedure _mapEntries;
   final Procedure _mapPut;
   late final FunctionType _mapPutFunctionType;
@@ -54,7 +53,6 @@
   final Field _mapEntryKey;
   final Field _mapEntryValue;
   final SourceLoaderDataForTesting? _dataForTesting;
-  final bool useNewMethodInvocationEncoding;
 
   /// Library that contains the transformed nodes.
   ///
@@ -83,8 +81,6 @@
         _setAddAll =
             _loader.coreTypes.index.getProcedure('dart:core', 'Set', 'addAll'),
         _setOf = _findSetFactory(_loader.coreTypes, 'of'),
-        _objectEquals =
-            _loader.coreTypes.index.getProcedure('dart:core', 'Object', '=='),
         _mapEntries = _loader.coreTypes.index
             .getProcedure('dart:core', 'Map', 'get:entries'),
         _mapPut =
@@ -95,9 +91,7 @@
             _loader.coreTypes.index.getField('dart:core', 'MapEntry', 'key'),
         _mapEntryValue =
             _loader.coreTypes.index.getField('dart:core', 'MapEntry', 'value'),
-        _dataForTesting = _loader.dataForTesting,
-        useNewMethodInvocationEncoding =
-            _loader.target.backendTarget.supportsNewMethodInvocationEncoding {
+        _dataForTesting = _loader.dataForTesting {
     _listAddFunctionType = _listAdd.getterType as FunctionType;
     _listAddAllFunctionType = _listAddAll.getterType as FunctionType;
     _setAddFunctionType = _setAdd.getterType as FunctionType;
@@ -908,24 +902,17 @@
     assert(argument != null);
     assert(argument.fileOffset != TreeNode.noOffset,
         "No fileOffset on ${argument}.");
-    if (useNewMethodInvocationEncoding) {
-      DartType functionType = Substitution.fromInterfaceType(receiverType)
-          .substituteType(isSet ? _setAddFunctionType : _listAddFunctionType);
-      if (!_currentLibrary!.isNonNullableByDefault) {
-        functionType = legacyErasure(functionType);
-      }
-      return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
-          new Name('add'), new Arguments([argument]),
-          functionType: functionType as FunctionType,
-          interfaceTarget: isSet ? _setAdd : _listAdd)
-        ..fileOffset = argument.fileOffset
-        ..isInvariant = true;
-    } else {
-      return new MethodInvocation(receiver, new Name('add'),
-          new Arguments([argument]), isSet ? _setAdd : _listAdd)
-        ..fileOffset = argument.fileOffset
-        ..isInvariant = true;
+    DartType functionType = Substitution.fromInterfaceType(receiverType)
+        .substituteType(isSet ? _setAddFunctionType : _listAddFunctionType);
+    if (!_currentLibrary!.isNonNullableByDefault) {
+      functionType = legacyErasure(functionType);
     }
+    return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
+        new Name('add'), new Arguments([argument]),
+        functionType: functionType as FunctionType,
+        interfaceTarget: isSet ? _setAdd : _listAdd)
+      ..fileOffset = argument.fileOffset
+      ..isInvariant = true;
   }
 
   Expression _createAddAll(Expression receiver, InterfaceType receiverType,
@@ -936,43 +923,26 @@
     assert(argument != null);
     assert(argument.fileOffset != TreeNode.noOffset,
         "No fileOffset on ${argument}.");
-    if (useNewMethodInvocationEncoding) {
-      DartType functionType = Substitution.fromInterfaceType(receiverType)
-          .substituteType(
-              isSet ? _setAddAllFunctionType : _listAddAllFunctionType);
-      if (!_currentLibrary!.isNonNullableByDefault) {
-        functionType = legacyErasure(functionType);
-      }
-      return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
-          new Name('addAll'), new Arguments([argument]),
-          functionType: functionType as FunctionType,
-          interfaceTarget: isSet ? _setAddAll : _listAddAll)
-        ..fileOffset = argument.fileOffset
-        ..isInvariant = true;
-    } else {
-      return new MethodInvocation(receiver, new Name('addAll'),
-          new Arguments([argument]), isSet ? _setAddAll : _listAddAll)
-        ..fileOffset = argument.fileOffset
-        ..isInvariant = true;
+    DartType functionType = Substitution.fromInterfaceType(receiverType)
+        .substituteType(
+            isSet ? _setAddAllFunctionType : _listAddAllFunctionType);
+    if (!_currentLibrary!.isNonNullableByDefault) {
+      functionType = legacyErasure(functionType);
     }
+    return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
+        new Name('addAll'), new Arguments([argument]),
+        functionType: functionType as FunctionType,
+        interfaceTarget: isSet ? _setAddAll : _listAddAll)
+      ..fileOffset = argument.fileOffset
+      ..isInvariant = true;
   }
 
   Expression _createEqualsNull(Expression expression, {bool notEquals: false}) {
     // ignore: unnecessary_null_comparison
     assert(expression != null);
     assert(expression.fileOffset != TreeNode.noOffset);
-    Expression check;
-    if (useNewMethodInvocationEncoding) {
-      check = new EqualsNull(expression)..fileOffset = expression.fileOffset;
-    } else {
-      check = new MethodInvocation(
-          expression,
-          new Name('=='),
-          new Arguments(
-              [new NullLiteral()..fileOffset = expression.fileOffset]),
-          _objectEquals)
-        ..fileOffset = expression.fileOffset;
-    }
+    Expression check = new EqualsNull(expression)
+      ..fileOffset = expression.fileOffset;
     if (notEquals) {
       check = new Not(check)..fileOffset = expression.fileOffset;
     }
@@ -984,23 +954,16 @@
     // ignore: unnecessary_null_comparison
     assert(fileOffset != null);
     assert(fileOffset != TreeNode.noOffset);
-    if (useNewMethodInvocationEncoding) {
-      DartType functionType = Substitution.fromInterfaceType(receiverType)
-          .substituteType(_mapPutFunctionType);
-      if (!_currentLibrary!.isNonNullableByDefault) {
-        functionType = legacyErasure(functionType);
-      }
-      return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
-          new Name('[]='), new Arguments([key, value]),
-          functionType: functionType as FunctionType, interfaceTarget: _mapPut)
-        ..fileOffset = fileOffset
-        ..isInvariant = true;
-    } else {
-      return new MethodInvocation(
-          receiver, new Name('[]='), new Arguments([key, value]), _mapPut)
-        ..fileOffset = fileOffset
-        ..isInvariant = true;
+    DartType functionType = Substitution.fromInterfaceType(receiverType)
+        .substituteType(_mapPutFunctionType);
+    if (!_currentLibrary!.isNonNullableByDefault) {
+      functionType = legacyErasure(functionType);
     }
+    return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
+        new Name('[]='), new Arguments([key, value]),
+        functionType: functionType as FunctionType, interfaceTarget: _mapPut)
+      ..fileOffset = fileOffset
+      ..isInvariant = true;
   }
 
   AsExpression _createImplicitAs(
@@ -1027,17 +990,12 @@
     // ignore: unnecessary_null_comparison
     assert(fileOffset != null);
     assert(fileOffset != TreeNode.noOffset);
-    if (useNewMethodInvocationEncoding) {
-      DartType resultType = Substitution.fromInterfaceType(entryType)
-          .substituteType(_mapEntryKey.type);
-      return new InstanceGet(
-          InstanceAccessKind.Instance, receiver, new Name('key'),
-          interfaceTarget: _mapEntryKey, resultType: resultType)
-        ..fileOffset = fileOffset;
-    } else {
-      return new PropertyGet(receiver, new Name('key'), _mapEntryKey)
-        ..fileOffset = fileOffset;
-    }
+    DartType resultType = Substitution.fromInterfaceType(entryType)
+        .substituteType(_mapEntryKey.type);
+    return new InstanceGet(
+        InstanceAccessKind.Instance, receiver, new Name('key'),
+        interfaceTarget: _mapEntryKey, resultType: resultType)
+      ..fileOffset = fileOffset;
   }
 
   Expression _createGetValue(
@@ -1045,17 +1003,12 @@
     // ignore: unnecessary_null_comparison
     assert(fileOffset != null);
     assert(fileOffset != TreeNode.noOffset);
-    if (useNewMethodInvocationEncoding) {
-      DartType resultType = Substitution.fromInterfaceType(entryType)
-          .substituteType(_mapEntryValue.type);
-      return new InstanceGet(
-          InstanceAccessKind.Instance, receiver, new Name('value'),
-          interfaceTarget: _mapEntryValue, resultType: resultType)
-        ..fileOffset = fileOffset;
-    } else {
-      return new PropertyGet(receiver, new Name('value'), _mapEntryValue)
-        ..fileOffset = fileOffset;
-    }
+    DartType resultType = Substitution.fromInterfaceType(entryType)
+        .substituteType(_mapEntryValue.type);
+    return new InstanceGet(
+        InstanceAccessKind.Instance, receiver, new Name('value'),
+        interfaceTarget: _mapEntryValue, resultType: resultType)
+      ..fileOffset = fileOffset;
   }
 
   Expression _createGetEntries(
@@ -1063,17 +1016,12 @@
     // ignore: unnecessary_null_comparison
     assert(fileOffset != null);
     assert(fileOffset != TreeNode.noOffset);
-    if (useNewMethodInvocationEncoding) {
-      DartType resultType = Substitution.fromInterfaceType(mapType)
-          .substituteType(_mapEntries.getterType);
-      return new InstanceGet(
-          InstanceAccessKind.Instance, receiver, new Name('entries'),
-          interfaceTarget: _mapEntries, resultType: resultType)
-        ..fileOffset = fileOffset;
-    } else {
-      return new PropertyGet(receiver, new Name('entries'), _mapEntries)
-        ..fileOffset = fileOffset;
-    }
+    DartType resultType = Substitution.fromInterfaceType(mapType)
+        .substituteType(_mapEntries.getterType);
+    return new InstanceGet(
+        InstanceAccessKind.Instance, receiver, new Name('entries'),
+        interfaceTarget: _mapEntries, resultType: resultType)
+      ..fileOffset = fileOffset;
   }
 
   ForStatement _createForStatement(
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart b/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
index 74246b0..4cab9fe 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
@@ -22,7 +22,6 @@
   final Procedure setFactory;
   final Procedure addMethod;
   late final FunctionType _addMethodFunctionType;
-  final bool useNewMethodInvocationEncoding;
 
   /// Library that contains the transformed nodes.
   ///
@@ -44,9 +43,7 @@
   SetLiteralTransformer(SourceLoader loader)
       : coreTypes = loader.coreTypes,
         setFactory = _findSetFactory(loader.coreTypes),
-        addMethod = _findAddMethod(loader.coreTypes),
-        useNewMethodInvocationEncoding =
-            loader.target.backendTarget.supportsNewMethodInvocationEncoding {
+        addMethod = _findAddMethod(loader.coreTypes) {
     _addMethodFunctionType = addMethod.getterType as FunctionType;
   }
 
@@ -65,25 +62,20 @@
     List<Statement> statements = [setVar];
     for (int i = 0; i < node.expressions.length; i++) {
       Expression entry = transform(node.expressions[i]);
-      Expression methodInvocation;
-      if (useNewMethodInvocationEncoding) {
-        DartType functionType = Substitution.fromInterfaceType(receiverType)
-            .substituteType(_addMethodFunctionType);
-        if (!_currentLibrary!.isNonNullableByDefault) {
-          functionType = legacyErasure(functionType);
-        }
-        methodInvocation = new InstanceInvocation(InstanceAccessKind.Instance,
-            new VariableGet(setVar), new Name("add"), new Arguments([entry]),
-            functionType: functionType as FunctionType,
-            interfaceTarget: addMethod)
-          ..fileOffset = entry.fileOffset
-          ..isInvariant = true;
-      } else {
-        methodInvocation = new MethodInvocation(new VariableGet(setVar),
-            new Name("add"), new Arguments([entry]), addMethod)
-          ..fileOffset = entry.fileOffset
-          ..isInvariant = true;
+      DartType functionType = Substitution.fromInterfaceType(receiverType)
+          .substituteType(_addMethodFunctionType);
+      if (!_currentLibrary!.isNonNullableByDefault) {
+        functionType = legacyErasure(functionType);
       }
+      Expression methodInvocation = new InstanceInvocation(
+          InstanceAccessKind.Instance,
+          new VariableGet(setVar),
+          new Name("add"),
+          new Arguments([entry]),
+          functionType: functionType as FunctionType,
+          interfaceTarget: addMethod)
+        ..fileOffset = entry.fileOffset
+        ..isInvariant = true;
       statements.add(new ExpressionStatement(methodInvocation)
         ..fileOffset = methodInvocation.fileOffset);
     }
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart b/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
index b5828a4..7f6631d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
@@ -11,6 +11,7 @@
 
 import '../builder/class_builder.dart';
 import '../builder/dynamic_type_declaration_builder.dart';
+import '../builder/fixed_type_builder.dart';
 import '../builder/formal_parameter_builder.dart';
 import '../builder/function_type_builder.dart';
 import '../builder/future_or_type_declaration_builder.dart';
@@ -39,7 +40,10 @@
 
   @override
   TypeBuilder visitInvalidType(InvalidType node) {
-    throw "Not implemented";
+    return new FixedTypeBuilder(
+        node,
+        /* fileUri = */ null,
+        /* charOffset = */ null);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
index aeb1696..8a23b53 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
@@ -361,7 +361,7 @@
   }
 
   void visitStaticTearOffConstant(StaticTearOffConstant node) {
-    Procedure procedure = node.procedure;
+    Procedure procedure = node.target;
     Class? classNode = procedure.enclosingClass;
     if (classNode != null) {
       result.add(nameForEntity(
@@ -375,8 +375,21 @@
   }
 
   void visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
-    Constructor constructor = node.constructor;
-    Class? classNode = constructor.enclosingClass;
+    Member constructor = node.target;
+    Class classNode = constructor.enclosingClass!;
+    result.add(nameForEntity(
+        classNode,
+        classNode.name,
+        classNode.enclosingLibrary.importUri,
+        classNode.enclosingLibrary.fileUri));
+    result.add(".");
+    result.add(constructor.name.text);
+  }
+
+  void visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node) {
+    Member constructor = node.target;
+    Class classNode = constructor.enclosingClass!;
     result.add(nameForEntity(
         classNode,
         classNode.name,
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index b24667f..a077ad7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -32,9 +32,12 @@
 
 import '../builder/fixed_type_builder.dart';
 import '../builder/formal_parameter_builder.dart';
+import '../builder/metadata_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_variable_builder.dart';
+import '../builder/unresolved_type.dart';
 import '../combinator.dart';
+import '../configuration.dart';
 import '../identifiers.dart';
 import '../source/source_library_builder.dart';
 import 'body_builder.dart';
@@ -159,6 +162,7 @@
 final Token dummyToken = new SyntheticToken(TokenType.AT, -1);
 final Identifier dummyIdentifier = new Identifier(dummyToken);
 final Combinator dummyCombinator = new Combinator(false, {}, -1, dummyUri);
+final MetadataBuilder dummyMetadataBuilder = new MetadataBuilder(dummyToken);
 final TypeBuilder dummyTypeBuilder =
     new FixedTypeBuilder(dummyDartType, dummyUri, -1);
 final FormalParameterBuilder dummyFormalParameterBuilder =
@@ -167,3 +171,6 @@
     new TypeVariableBuilder(TypeVariableBuilder.noNameSentinel, null, -1, null);
 final Label dummyLabel = new Label('', -1);
 final FieldInfo dummyFieldInfo = new FieldInfo('', -1, null, dummyToken, -1);
+final Configuration dummyConfiguration = new Configuration(-1, '', '', '');
+final UnresolvedType dummyUnresolvedType =
+    new UnresolvedType(dummyTypeBuilder, -1, dummyUri);
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index 363f618..7c313ec 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -283,7 +283,7 @@
     // the shape, but aren't of the RedirectingFactoryBody type.
     bool hasBody = isRedirectingFactory(node) ||
         RedirectingFactoryBody.hasRedirectingFactoryBodyShape(node);
-    bool hasFlag = node.isRedirectingFactoryConstructor;
+    bool hasFlag = node.isRedirectingFactory;
     if (hasBody != hasFlag) {
       String hasBodyString = hasBody ? "has" : "doesn't have";
       String hasFlagString = hasFlag ? "has" : "doesn't have";
@@ -291,7 +291,7 @@
           node,
           "Procedure '${node.name}' ${hasBodyString} a body "
           "of a redirecting factory, but ${hasFlagString} the "
-          "'isRedirectingFactoryConstructor' bit set.");
+          "'isRedirectingFactory' bit set.");
     }
 
     super.visitProcedure(node);
@@ -437,39 +437,6 @@
   }
 
   @override
-  void visitMethodInvocation(MethodInvocation node) {
-    if (target.supportsNewMethodInvocationEncoding) {
-      problem(
-          node,
-          "New method invocation encoding is supported, "
-          "but found a MethodInvocation.");
-    }
-    super.visitMethodInvocation(node);
-  }
-
-  @override
-  void visitPropertyGet(PropertyGet node) {
-    if (target.supportsNewMethodInvocationEncoding) {
-      problem(
-          node,
-          "New method invocation encoding is supported, "
-          "but found a PropertyGet.");
-    }
-    super.visitPropertyGet(node);
-  }
-
-  @override
-  void visitPropertySet(PropertySet node) {
-    if (target.supportsNewMethodInvocationEncoding) {
-      problem(
-          node,
-          "New method invocation encoding is supported, "
-          "but found a PropertySet.");
-    }
-    super.visitPropertySet(node);
-  }
-
-  @override
   void defaultTreeNode(TreeNode node) {
     enterTreeNode(node);
     super.defaultTreeNode(node);
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index 31aea33..7dedab8 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.dart
@@ -81,6 +81,15 @@
   final List<FormattedMessage> allComponentProblems = <FormattedMessage>[];
 
   final Set<String> seenMessages = new Set<String>();
+  bool _hasSeenError = false;
+
+  void resetSeenMessages() {
+    seenMessages.clear();
+    _hasSeenError = false;
+  }
+
+  /// Returns `true` if a compile time error has been reported.
+  bool get hasSeenError => _hasSeenError;
 
   LibraryBuilder? _coreLibrary;
   LibraryBuilder? typedDataLibrary;
@@ -362,6 +371,9 @@
 severity: $severity
 """;
     if (!seenMessages.add(trace)) return null;
+    if (message.code.severity == Severity.error) {
+      _hasSeenError = true;
+    }
     if (message.code.severity == Severity.context) {
       internalProblem(
           templateInternalProblemContextSeverity
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index 76daac6..34849e8 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -15,6 +15,7 @@
 import 'builder/type_variable_builder.dart';
 import 'kernel/body_builder.dart' show JumpTarget;
 import 'kernel/class_hierarchy_builder.dart' show ClassMember;
+import 'kernel/kernel_helper.dart';
 import 'util/helpers.dart' show DelayedActionPerformer;
 
 import 'fasta_codes.dart'
@@ -806,8 +807,11 @@
   ProcedureKind? get kind => null;
 
   @override
-  void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
+  void buildOutlineExpressions(
+      LibraryBuilder library,
+      CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     throw new UnsupportedError(
         'AmbiguousMemberBuilder.buildOutlineExpressions');
   }
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 88490a6..331d16b 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -339,7 +339,7 @@
     debugEvent("TopLevelMethod");
     Token bodyToken = pop() as Token;
     Object? name = pop();
-    Token metadata = pop() as Token;
+    Token? metadata = pop() as Token?;
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery) return;
 
@@ -509,7 +509,7 @@
     debugEvent("Import");
     Object? name = pop(NullValue.Prefix);
 
-    Token metadata = pop() as Token;
+    Token? metadata = pop() as Token?;
     checkEmpty(importKeyword.charOffset);
     if (name is ParserRecovery) return;
 
@@ -535,7 +535,7 @@
   void endExport(Token exportKeyword, Token semicolon) {
     debugEvent("Export");
 
-    Token metadata = pop() as Token;
+    Token? metadata = pop() as Token?;
     Library libraryNode = libraryBuilder.library;
     LibraryDependency dependency =
         libraryNode.dependencies[importExportDirectiveIndex++];
@@ -546,7 +546,7 @@
   void endPart(Token partKeyword, Token semicolon) {
     debugEvent("Part");
 
-    Token metadata = pop() as Token;
+    Token? metadata = pop() as Token?;
     Library libraryNode = libraryBuilder.library;
     if (libraryNode.parts.length > partDirectiveIndex) {
       // If partDirectiveIndex >= libraryNode.parts.length we are in a case of
@@ -588,7 +588,7 @@
     debugEvent("ClassFactoryMethod");
     Token bodyToken = pop() as Token;
     Object? name = pop();
-    Token metadata = pop() as Token;
+    Token? metadata = pop() as Token?;
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery || currentClassIsParserRecovery) return;
 
@@ -699,7 +699,7 @@
     // in handleNoFormalParameters rather than the supplied token.
     pop(); // bodyToken
     Object? name = pop();
-    Token metadata = pop() as Token;
+    Token? metadata = pop() as Token?;
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery || currentClassIsParserRecovery) return;
     FunctionBuilderImpl builder;
@@ -1054,6 +1054,9 @@
           ? ""
           : nameOrQualified as String;
     }
+    if (libraryBuilder.enableConstructorTearOffsInLibrary) {
+      suffix = suffix == "new" ? "" : suffix;
+    }
     declaration = currentClass!.constructors.local[suffix];
     declaration = handleDuplicatedName(declaration, token);
     checkBuilder(token, declaration, nameOrQualified);
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 4cc93c2..1cbd3d7 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -129,9 +129,7 @@
 
   List<String>? popIdentifierList(int count) {
     if (count == 0) return null;
-    List<String> list = new List<String>.filled(
-        count,
-        /* dummyValue = */ '');
+    List<String> list = new List<String>.filled(count, /* dummyValue = */ '');
     bool isParserRecovery = false;
     for (int i = count - 1; i >= 0; i--) {
       popCharOffset();
@@ -164,7 +162,8 @@
   @override
   void endMetadataStar(int count) {
     debugEvent("MetadataStar");
-    push(const FixedNullableList<MetadataBuilder>().pop(stack, count) ??
+    push(const FixedNullableList<MetadataBuilder>()
+            .popNonNullable(stack, count, dummyMetadataBuilder) ??
         NullValue.Metadata);
   }
 
@@ -261,7 +260,8 @@
   @override
   void endConditionalUris(int count) {
     debugEvent("EndConditionalUris");
-    push(const FixedNullableList<Configuration>().pop(stack, count) ??
+    push(const FixedNullableList<Configuration>()
+            .popNonNullable(stack, count, dummyConfiguration) ??
         NullValue.ConditionalUris);
   }
 
@@ -1371,7 +1371,8 @@
   @override
   void endTypeArguments(int count, Token beginToken, Token endToken) {
     debugEvent("TypeArguments");
-    push(const FixedNullableList<TypeBuilder>().pop(stack, count) ??
+    push(const FixedNullableList<TypeBuilder>()
+            .popNonNullable(stack, count, dummyTypeBuilder) ??
         NullValue.TypeArguments);
   }
 
@@ -1470,8 +1471,14 @@
     if (name is ParserRecovery) {
       push(name);
     } else {
-      push(libraryBuilder.addFormalParameter(metadata, modifiers, type,
-          name as String, thisKeyword != null, charOffset, initializerStart));
+      push(libraryBuilder.addFormalParameter(
+          metadata,
+          modifiers,
+          type,
+          name == null ? FormalParameterBuilder.noNameSentinel : name as String,
+          thisKeyword != null,
+          charOffset,
+          initializerStart));
     }
   }
 
@@ -1559,8 +1566,8 @@
       assert(formals.isNotEmpty);
       if (formals.length == 2) {
         // The name may be null for generalized function types.
-        // ignore: unnecessary_null_comparison
-        if (formals[0].name != null && formals[0].name == formals[1].name) {
+        if (formals[0].name != FormalParameterBuilder.noNameSentinel &&
+            formals[0].name == formals[1].name) {
           addProblem(
               templateDuplicatedParameterName.withArguments(formals[1].name),
               formals[1].charOffset,
@@ -1576,8 +1583,7 @@
         Map<String, FormalParameterBuilder> seenNames =
             <String, FormalParameterBuilder>{};
         for (FormalParameterBuilder formal in formals) {
-          // ignore: unnecessary_null_comparison
-          if (formal.name == null) continue;
+          if (formal.name == FormalParameterBuilder.noNameSentinel) continue;
           if (seenNames.containsKey(formal.name)) {
             addProblem(
                 templateDuplicatedParameterName.withArguments(formal.name),
@@ -1808,11 +1814,7 @@
     checkEmpty(beginToken.charOffset);
     if (fieldInfos == null) return;
     libraryBuilder.addFields(
-        metadata,
-        modifiers,
-        /* isTopLevel = */ true,
-        type,
-        fieldInfos);
+        metadata, modifiers, /* isTopLevel = */ true, type, fieldInfos);
   }
 
   @override
@@ -1873,11 +1875,7 @@
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
     if (fieldInfos == null) return;
     libraryBuilder.addFields(
-        metadata,
-        modifiers,
-        /* isTopLevel = */ false,
-        type,
-        fieldInfos);
+        metadata, modifiers, /* isTopLevel = */ false, type, fieldInfos);
   }
 
   List<FieldInfo>? popFieldInfos(int count) {
@@ -1887,7 +1885,7 @@
     bool isParserRecovery = false;
     for (int i = count - 1; i != -1; i--) {
       int charEndOffset = popCharOffset();
-      Token beforeLast = pop() as Token;
+      Token? beforeLast = pop() as Token?;
       Token? initializerTokenForInference = pop() as Token?;
       int charOffset = popCharOffset();
       Object? name = pop(NullValue.Identifier);
@@ -1919,7 +1917,8 @@
   void handleTypeVariablesDefined(Token token, int count) {
     debugEvent("TypeVariablesDefined");
     assert(count > 0);
-    push(const FixedNullableList<TypeVariableBuilder>().pop(stack, count) ??
+    push(const FixedNullableList<TypeVariableBuilder>()
+            .popNonNullable(stack, count, dummyTypeVariableBuilder) ??
         NullValue.TypeVariables);
   }
 
@@ -2232,13 +2231,15 @@
 
   @override
   void handleNewAsIdentifier(Token token) {
-    // TODO(johnniwinther, paulberry): disable this error when the
-    // "constructor-tearoffs" feature is enabled.
-    addProblem(
-        templateExperimentNotEnabled.withArguments('constructor-tearoffs',
-            libraryBuilder.enableConstructorTearOffsVersionInLibrary.toText()),
-        token.charOffset,
-        token.length);
+    if (!libraryBuilder.enableConstructorTearOffsInLibrary) {
+      addProblem(
+          templateExperimentNotEnabled.withArguments(
+              'constructor-tearoffs',
+              libraryBuilder.enableConstructorTearOffsVersionInLibrary
+                  .toText()),
+          token.charOffset,
+          token.length);
+    }
   }
 }
 
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 392acae..395a4d2 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
@@ -17,6 +17,7 @@
 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';
@@ -160,8 +161,8 @@
                 cls.addField(member);
               } else if (member is Constructor) {
                 cls.addConstructor(member);
-              } else if (member is RedirectingFactoryConstructor) {
-                cls.addRedirectingFactoryConstructor(member);
+              } else if (member is RedirectingFactory) {
+                cls.addRedirectingFactory(member);
               } else {
                 unhandled("${member.runtimeType}", "getMember",
                     member.fileOffset, member.fileUri);
@@ -528,7 +529,7 @@
         // Check procedures
         checkVarianceInFunction(
             builder.procedure, typeEnvironment, cls.typeParameters);
-        library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+        library.checkTypesInFunctionBuilder(builder, typeEnvironment);
       } else {
         assert(builder is DillFieldBuilder && builder.name == redirectingName,
             "Unexpected member: $builder.");
@@ -540,9 +541,9 @@
         library.checkTypesInConstructorBuilder(builder, typeEnvironment);
       } else if (builder is RedirectingFactoryBuilder) {
         library.checkTypesInRedirectingFactoryBuilder(builder, typeEnvironment);
-      } else if (builder is ProcedureBuilder) {
+      } else if (builder is SourceFactoryBuilder) {
         assert(builder.isFactory, "Unexpected constructor $builder.");
-        library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+        library.checkTypesInFunctionBuilder(builder, typeEnvironment);
       } else {
         assert(
             // This is a synthesized constructor.
@@ -828,19 +829,11 @@
         new Arguments.forwarded(procedure.function, library.library),
         procedure.fileOffset,
         /*isSuper=*/ false);
-    Expression result;
-    if (library
-        .loader.target.backendTarget.supportsNewMethodInvocationEncoding) {
-      result = new InstanceInvocation(InstanceAccessKind.Instance,
-          new ThisExpression(), noSuchMethodName, new Arguments([invocation]),
-          functionType: noSuchMethodInterface.getterType as FunctionType,
-          interfaceTarget: noSuchMethodInterface)
-        ..fileOffset = procedure.fileOffset;
-    } else {
-      result = new MethodInvocation(new ThisExpression(), noSuchMethodName,
-          new Arguments([invocation]), noSuchMethodInterface)
-        ..fileOffset = procedure.fileOffset;
-    }
+    Expression result = new InstanceInvocation(InstanceAccessKind.Instance,
+        new ThisExpression(), noSuchMethodName, new Arguments([invocation]),
+        functionType: noSuchMethodInterface.getterType as FunctionType,
+        interfaceTarget: noSuchMethodInterface)
+      ..fileOffset = procedure.fileOffset;
     if (procedure.function.returnType is! VoidType) {
       result = new AsExpression(result, procedure.function.returnType)
         ..isTypeError = true
@@ -859,7 +852,7 @@
     procedure.stubTarget = null;
   }
 
-  void _addRedirectingConstructor(ProcedureBuilder constructorBuilder,
+  void _addRedirectingConstructor(SourceFactoryBuilder constructorBuilder,
       SourceLibraryBuilder library, Reference? getterReference) {
     // Add a new synthetic field to this class for representing factory
     // constructors. This is used to support resolving such constructors in
@@ -893,7 +886,7 @@
     Field field = constructorsField.field;
     ListLiteral literal = field.initializer as ListLiteral;
     literal.expressions
-        .add(new StaticGet(constructorBuilder.procedure)..parent = literal);
+        .add(new StaticGet(constructorBuilder.member)..parent = literal);
   }
 
   @override
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 9adab49..5ffcb20 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
@@ -26,6 +26,8 @@
         noLength,
         templateExtensionMemberConflictsWithObjectMember;
 
+import '../kernel/kernel_helper.dart';
+
 import '../problems.dart';
 
 import '../scope.dart';
@@ -254,7 +256,7 @@
         library.checkTypesInField(builder, typeEnvironment);
       } else if (builder is ProcedureBuilder) {
         // Check procedures
-        library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+        library.checkTypesInFunctionBuilder(builder, typeEnvironment);
         if (builder.isGetter) {
           Builder? setterDeclaration =
               scope.lookupLocalMember(builder.name, setter: true);
@@ -273,7 +275,8 @@
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     MetadataBuilder.buildAnnotations(isPatch ? origin.extension : extension,
         metadata, library, this, null, fileUri);
     if (typeParameters != null) {
@@ -285,8 +288,8 @@
 
     void build(String ignore, Builder declaration) {
       MemberBuilder member = declaration as MemberBuilder;
-      member.buildOutlineExpressions(
-          library, coreTypes, delayedActionPerformers);
+      member.buildOutlineExpressions(library, coreTypes,
+          delayedActionPerformers, synthesizedFunctionNodes);
     }
 
     scope.forEach(build);
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 b9eed88..324a721 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
@@ -12,9 +12,6 @@
 import 'package:_fe_analyzer_shared/src/util/resolve_relative_uri.dart'
     show resolveRelativeUri;
 
-import 'package:front_end/src/fasta/dill/dill_library_builder.dart'
-    show DillLibraryBuilder;
-
 import 'package:kernel/ast.dart' hide Combinator, MapLiteralEntry;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -47,6 +44,7 @@
 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';
@@ -73,6 +71,8 @@
 
 import '../configuration.dart' show Configuration;
 
+import '../dill/dill_library_builder.dart' show DillLibraryBuilder;
+
 import '../export.dart' show Export;
 
 import '../fasta_codes.dart';
@@ -642,6 +642,9 @@
       prefix = name as String;
       suffix = null;
     }
+    if (enableConstructorTearOffsInLibrary) {
+      suffix = suffix == "new" ? "" : suffix;
+    }
     if (prefix == className) {
       return suffix ?? "";
     }
@@ -800,7 +803,7 @@
       if (startToken != null) {
         // Extract only the tokens for the initializer expression from the
         // token stream.
-        Token endToken = info.beforeLast;
+        Token endToken = info.beforeLast!;
         endToken.setNext(new Token.eof(endToken.next!.offset));
         new Token.eof(startToken.previous!.offset).setNext(startToken);
       }
@@ -2503,7 +2506,7 @@
             procedureName, _currentClassReferencesFromIndexed!.library))
         ?.reference;
 
-    ProcedureBuilder procedureBuilder;
+    SourceFactoryBuilder procedureBuilder;
     if (redirectionTarget != null) {
       procedureBuilder = new RedirectingFactoryBuilder(
           metadata,
@@ -2525,7 +2528,7 @@
           nativeMethodName,
           redirectionTarget);
     } else {
-      procedureBuilder = new SourceProcedureBuilder(
+      procedureBuilder = new SourceFactoryBuilder(
           metadata,
           staticMask | modifiers,
           returnType,
@@ -2535,18 +2538,14 @@
                   const <TypeVariableBuilder>[],
               factoryDeclaration),
           formals,
-          ProcedureKind.Factory,
           this,
           startCharOffset,
           charOffset,
           charOpenParenOffset,
           charEndOffset,
           reference,
-          /* tearOffReference = */ null,
           asyncModifier,
           procedureNameScheme,
-          isExtensionMember: false,
-          isInstanceMember: false,
           nativeMethodName: nativeMethodName);
     }
 
@@ -3272,7 +3271,7 @@
 
           declaration.constructors.forEach((String name, Builder member) {
             List<FormalParameterBuilder>? formals;
-            if (member is ProcedureBuilder) {
+            if (member is SourceFactoryBuilder) {
               assert(member.isFactory,
                   "Unexpected constructor member (${member.runtimeType}).");
               count += computeDefaultTypesForVariables(member.typeVariables,
@@ -3828,10 +3827,10 @@
     }
   }
 
-  void checkTypesInProcedureBuilder(
-      ProcedureBuilder procedureBuilder, TypeEnvironment typeEnvironment) {
-    checkBoundsInFunctionNode(procedureBuilder.procedure.function,
-        typeEnvironment, procedureBuilder.fileUri!);
+  void checkTypesInFunctionBuilder(
+      FunctionBuilder procedureBuilder, TypeEnvironment typeEnvironment) {
+    checkBoundsInFunctionNode(
+        procedureBuilder.function, typeEnvironment, procedureBuilder.fileUri!);
     if (procedureBuilder.formals != null &&
         !(procedureBuilder.isAbstract || procedureBuilder.isExternal)) {
       checkInitializersInFormals(procedureBuilder.formals!, typeEnvironment);
@@ -3850,7 +3849,7 @@
   void checkTypesInRedirectingFactoryBuilder(
       RedirectingFactoryBuilder redirectingFactoryBuilder,
       TypeEnvironment typeEnvironment) {
-    checkBoundsInFunctionNode(redirectingFactoryBuilder.procedure.function,
+    checkBoundsInFunctionNode(redirectingFactoryBuilder.function,
         typeEnvironment, redirectingFactoryBuilder.fileUri);
     // Default values are not required on redirecting factory constructors so
     // we don't call [checkInitializersInFormals].
@@ -4137,7 +4136,7 @@
       if (declaration is FieldBuilder) {
         checkTypesInField(declaration, typeEnvironment);
       } else if (declaration is ProcedureBuilder) {
-        checkTypesInProcedureBuilder(declaration, typeEnvironment);
+        checkTypesInFunctionBuilder(declaration, typeEnvironment);
         if (declaration.isGetter) {
           Builder? setterDeclaration =
               scope.lookupLocalMember(declaration.name, setter: true);
@@ -4235,6 +4234,24 @@
     }
     uncheckedTypedefTypes.clear();
   }
+
+  void installTypedefTearOffs() {
+    Iterator<Builder> iterator = this.iterator;
+    while (iterator.moveNext()) {
+      Builder? declaration = iterator.current;
+      while (declaration != null) {
+        if (declaration is SourceTypeAliasBuilder) {
+          declaration.buildTypedefTearOffs(this, (Procedure procedure) {
+            procedure.isStatic = true;
+            if (!declaration!.isPatch && !declaration.isDuplicate) {
+              library.addProcedure(procedure);
+            }
+          });
+        }
+        declaration = declaration.next;
+      }
+    }
+  }
 }
 
 // The kind of type parameter scope built by a [TypeParameterScopeBuilder]
@@ -4505,7 +4522,7 @@
   final String name;
   final int charOffset;
   final Token? initializerToken;
-  final Token beforeLast;
+  final Token? beforeLast;
   final int charEndOffset;
 
   const FieldInfo(this.name, this.charOffset, this.initializerToken,
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 51b2dd8..538d6cc 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -30,12 +30,14 @@
         AsyncMarker,
         Class,
         Component,
+        Constructor,
         DartType,
         Expression,
         FunctionNode,
         InterfaceType,
         Library,
         LibraryDependency,
+        Member,
         NeverType,
         Nullability,
         Procedure,
@@ -70,6 +72,7 @@
 
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
+import '../builder/constructor_builder.dart';
 import '../builder/dynamic_type_declaration_builder.dart';
 import '../builder/enum_builder.dart';
 import '../builder/extension_builder.dart';
@@ -89,17 +92,14 @@
 
 import '../fasta_codes.dart';
 
+import '../kernel/body_builder.dart' show BodyBuilder;
 import '../kernel/kernel_builder.dart'
     show ClassHierarchyBuilder, ClassMember, DelayedCheck;
-
+import '../kernel/kernel_helper.dart'
+    show SynthesizedFunctionNode, TypeDependency;
 import '../kernel/kernel_target.dart' show KernelTarget;
-
-import '../kernel/body_builder.dart' show BodyBuilder;
-
 import '../kernel/transform_collections.dart' show CollectionTransformer;
-
 import '../kernel/transform_set_literals.dart' show SetLiteralTransformer;
-
 import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
 
 import '../loader.dart' show Loader, untranslatableUriScheme;
@@ -109,20 +109,16 @@
 import '../source/stack_listener_impl.dart' show offsetForToken;
 
 import '../type_inference/type_inference_engine.dart';
-
 import '../type_inference/type_inferrer.dart';
 
 import '../util/helpers.dart';
 
 import 'diet_listener.dart' show DietListener;
-
 import 'diet_parser.dart' show DietParser;
-
 import 'outline_builder.dart' show OutlineBuilder;
-
 import 'source_class_builder.dart' show SourceClassBuilder;
-
 import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_type_alias_builder.dart';
 
 class SourceLoader extends Loader {
   /// The [FileSystem] which should be used to access files.
@@ -366,6 +362,15 @@
     hasInvalidNnbdModeLibrary = true;
   }
 
+  void registerConstructorToBeInferred(
+      Constructor constructor, ConstructorBuilder builder) {
+    _typeInferenceEngine!.toBeInferred[constructor] = builder;
+  }
+
+  void registerTypeDependency(Member member, TypeDependency typeDependency) {
+    _typeInferenceEngine!.typeDependencies[member] = typeDependency;
+  }
+
   @override
   Future<Null> buildOutlines() async {
     await super.buildOutlines();
@@ -718,6 +723,16 @@
     ticker.logMs("Resolved $count constructors");
   }
 
+  void installTypedefTearOffs() {
+    if (target.backendTarget.isTypedefTearOffLoweringEnabled) {
+      for (LibraryBuilder library in builders.values) {
+        if (library.loader == this && library is SourceLibraryBuilder) {
+          library.installTypedefTearOffs();
+        }
+      }
+    }
+  }
+
   void finishTypeVariables(ClassBuilder object, TypeBuilder dynamicType) {
     int count = 0;
     for (LibraryBuilder library in builders.values) {
@@ -1182,7 +1197,8 @@
     ticker.logMs("Checked mixin declaration applications");
   }
 
-  void buildOutlineExpressions(CoreTypes coreTypes) {
+  void buildOutlineExpressions(CoreTypes coreTypes,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     List<DelayedActionPerformer> delayedActionPerformers =
         <DelayedActionPerformer>[];
     for (LibraryBuilder library in builders.values) {
@@ -1192,17 +1208,17 @@
         while (iterator.moveNext()) {
           Builder declaration = iterator.current;
           if (declaration is ClassBuilder) {
-            declaration.buildOutlineExpressions(
-                library, coreTypes, delayedActionPerformers);
+            declaration.buildOutlineExpressions(library, coreTypes,
+                delayedActionPerformers, synthesizedFunctionNodes);
           } else if (declaration is ExtensionBuilder) {
-            declaration.buildOutlineExpressions(
-                library, coreTypes, delayedActionPerformers);
+            declaration.buildOutlineExpressions(library, coreTypes,
+                delayedActionPerformers, synthesizedFunctionNodes);
           } else if (declaration is MemberBuilder) {
-            declaration.buildOutlineExpressions(
-                library, coreTypes, delayedActionPerformers);
-          } else if (declaration is TypeAliasBuilder) {
-            declaration.buildOutlineExpressions(
-                library, coreTypes, delayedActionPerformers);
+            declaration.buildOutlineExpressions(library, coreTypes,
+                delayedActionPerformers, synthesizedFunctionNodes);
+          } else if (declaration is SourceTypeAliasBuilder) {
+            declaration.buildOutlineExpressions(library, coreTypes,
+                delayedActionPerformers, synthesizedFunctionNodes);
           } else {
             assert(
                 declaration is PrefixBuilder ||
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 ae4fbb9..60e717f 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
@@ -4,17 +4,8 @@
 
 library fasta.source_type_alias_builder;
 
-import 'package:kernel/ast.dart'
-    show
-        DartType,
-        DynamicType,
-        InvalidType,
-        TypeParameter,
-        TypeParameterType,
-        Typedef,
-        TypedefType,
-        VariableDeclaration,
-        getAsTypeArguments;
+import 'package:front_end/src/fasta/kernel/expression_generator_helper.dart';
+import 'package:kernel/ast.dart';
 
 import 'package:kernel/core_types.dart';
 
@@ -33,6 +24,7 @@
 import '../builder/formal_parameter_builder.dart';
 import '../builder/function_type_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_builder.dart';
@@ -40,6 +32,9 @@
 import '../builder/type_declaration_builder.dart';
 import '../builder/type_variable_builder.dart';
 
+import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/kernel_helper.dart';
+
 import '../util/helpers.dart';
 
 import 'source_library_builder.dart' show SourceLibraryBuilder;
@@ -54,6 +49,8 @@
 
   DartType? thisType;
 
+  Map<Name, Procedure>? tearOffs;
+
   SourceTypeAliasBuilder(
       List<MetadataBuilder>? metadata,
       String name,
@@ -253,11 +250,11 @@
         allowSuperBounded: false);
   }
 
-  @override
   void buildOutlineExpressions(
       SourceLibraryBuilder library,
       CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
+      List<DelayedActionPerformer> delayedActionPerformers,
+      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
     MetadataBuilder.buildAnnotations(
         typedef, metadata, library, null, null, fileUri);
     if (typeVariables != null) {
@@ -266,5 +263,45 @@
             library, null, null, coreTypes, delayedActionPerformers);
       }
     }
+    _tearOffDependencies?.forEach((Procedure tearOff, Member target) {
+      InterfaceType targetType = typedef.type as InterfaceType;
+      synthesizedFunctionNodes.add(new SynthesizedFunctionNode(
+          new Map<TypeParameter, DartType>.fromIterables(
+              target.enclosingClass!.typeParameters, targetType.typeArguments),
+          target.function!,
+          tearOff.function));
+    });
+  }
+
+  Map<Procedure, Member>? _tearOffDependencies;
+
+  void buildTypedefTearOffs(
+      SourceLibraryBuilder library, void Function(Procedure) f) {
+    TypeDeclarationBuilder? declaration = unaliasDeclaration(null);
+    if (declaration is ClassBuilder &&
+        typedef.typeParameters.isNotEmpty &&
+        !isProperRenameForClass(library.loader.typeEnvironment, typedef)) {
+      tearOffs = {};
+      _tearOffDependencies = {};
+      declaration
+          .forEachConstructor((String constructorName, MemberBuilder builder) {
+        Member? target = builder.invokeTarget;
+        if (target != null) {
+          if (target is Procedure && target.isRedirectingFactory) {
+            target = builder.readTarget!;
+          }
+          Name targetName =
+              new Name(constructorName, declaration.library.library);
+          Procedure tearOff = tearOffs![targetName] =
+              createTypedefTearOffProcedure(
+                  name, constructorName, library, fileUri, charOffset);
+          _tearOffDependencies![tearOff] = target;
+          InterfaceType targetType = typedef.type as InterfaceType;
+          buildTypedefTearOffProcedure(tearOff, target, declaration.cls,
+              typedef.typeParameters, targetType.typeArguments, library);
+          f(tearOff);
+        }
+      });
+    }
   }
 }
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 407fbfb..5ba0cfa 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,7 +3,6 @@
 // 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:front_end/src/fasta/kernel/internal_ast.dart';
 
 import 'package:kernel/ast.dart';
 
@@ -18,9 +17,10 @@
 import '../builder/constructor_builder.dart';
 
 import '../kernel/forest.dart';
-
+import '../kernel/internal_ast.dart';
 import '../kernel/kernel_builder.dart'
     show ClassHierarchyBuilder, ImplicitFieldType;
+import '../kernel/kernel_helper.dart';
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
@@ -128,6 +128,8 @@
   /// is used to report errors.
   final Map<Constructor, ConstructorBuilder> beingInferred = {};
 
+  final Map<Member, TypeDependency> typeDependencies = {};
+
   final Instrumentation? instrumentation;
 
   TypeInferenceEngine(this.instrumentation);
@@ -152,6 +154,10 @@
       builder.inferFormalTypes();
     }
     toBeInferred.clear();
+    for (TypeDependency typeDependency in typeDependencies.values) {
+      typeDependency.copyInferred();
+    }
+    typeDependencies.clear();
   }
 
   /// Gets ready to do top level type inference for the component having the
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 fe7c2c6..2bf3ff0 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
@@ -37,6 +37,7 @@
 import '../fasta_codes.dart';
 
 import '../kernel/class_hierarchy_builder.dart' show ClassMember;
+import '../kernel/kernel_helper.dart';
 import '../kernel/inference_visitor.dart';
 import '../kernel/internal_ast.dart';
 import '../kernel/invalid_type.dart';
@@ -226,7 +227,7 @@
                 assignedVariables)
             : new FlowAnalysis.legacy(
                 new TypeOperationsCfe(engine.typeSchemaEnvironment),
-                assignedVariables);
+                assignedVariables) {}
 
   CoreTypes get coreTypes => engine.coreTypes;
 
@@ -234,9 +235,6 @@
 
   NnbdMode get nnbdMode => library.loader.nnbdMode;
 
-  bool get useNewMethodInvocationEncoding =>
-      library.loader.target.backendTarget.supportsNewMethodInvocationEncoding;
-
   DartType get bottomType =>
       isNonNullableByDefault ? const NeverType.nonNullable() : const NullType();
 
@@ -357,6 +355,19 @@
     }
   }
 
+  /// Ensures that the type of [member] has been computed.
+  // TODO(johnniwinther): Expand this to handle lowerings.
+  void ensureMemberType(Member member) {
+    if (member is Constructor) {
+      inferConstructorParameterTypes(member);
+    }
+    TypeDependency? typeDependency = engine.typeDependencies.remove(member);
+    if (typeDependency != null) {
+      ensureMemberType(typeDependency.original);
+      typeDependency.copyInferred();
+    }
+  }
+
   @override
   void inferConstructorParameterTypes(Constructor target) {
     ConstructorBuilder? constructor = engine.beingInferred[target];
@@ -746,32 +757,19 @@
     VariableDeclaration t =
         new VariableDeclaration.forValue(expression, type: expressionType)
           ..fileOffset = fileOffset;
-    Expression nullCheck;
+
     // TODO(johnniwinther): Avoid null-check for non-nullable expressions.
-    if (useNewMethodInvocationEncoding) {
-      nullCheck = new EqualsNull(new VariableGet(t)..fileOffset = fileOffset)
-        ..fileOffset = fileOffset;
-    } else {
-      nullCheck = new MethodInvocation(
-          new VariableGet(t)..fileOffset = fileOffset,
-          equalsName,
-          new Arguments(
-              <Expression>[new NullLiteral()..fileOffset = fileOffset]))
-        ..fileOffset = fileOffset;
-    }
-    Expression tearOff;
+    Expression nullCheck =
+        new EqualsNull(new VariableGet(t)..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
+
     DartType tearoffType =
         getGetterTypeForMemberTarget(callMember, expressionType)
             .withDeclaredNullability(expressionType.nullability);
-    if (useNewMethodInvocationEncoding) {
-      tearOff = new InstanceTearOff(
-          InstanceAccessKind.Instance, new VariableGet(t), callName,
-          interfaceTarget: callMember as Procedure, resultType: tearoffType)
-        ..fileOffset = fileOffset;
-    } else {
-      tearOff = new PropertyGet(new VariableGet(t), callName, callMember)
-        ..fileOffset = fileOffset;
-    }
+    Expression tearOff = new InstanceTearOff(
+        InstanceAccessKind.Instance, new VariableGet(t), callName,
+        interfaceTarget: callMember as Procedure, resultType: tearoffType)
+      ..fileOffset = fileOffset;
     ConditionalExpression conditional = new ConditionalExpression(nullCheck,
         new NullLiteral()..fileOffset = fileOffset, tearOff, tearoffType);
     return new TypedTearoff(
@@ -2754,15 +2752,9 @@
         receiverType: const DynamicType(),
         isImplicitCall: isImplicitCall);
     assert(name != equalsName);
-    Expression expression;
-    if (useNewMethodInvocationEncoding) {
-      expression = new DynamicInvocation(
-          DynamicAccessKind.Dynamic, receiver, name, arguments)
-        ..fileOffset = fileOffset;
-    } else {
-      expression = new MethodInvocation(receiver, name, arguments)
-        ..fileOffset = fileOffset;
-    }
+    Expression expression = new DynamicInvocation(
+        DynamicAccessKind.Dynamic, receiver, name, arguments)
+      ..fileOffset = fileOffset;
     return createNullAwareExpressionInferenceResult(
         result.inferredType, result.applyResult(expression), nullAwareGuards);
   }
@@ -2785,15 +2777,9 @@
         receiverType: receiverType,
         isImplicitCall: isImplicitCall);
     assert(name != equalsName);
-    Expression expression;
-    if (useNewMethodInvocationEncoding) {
-      expression = new DynamicInvocation(
-          DynamicAccessKind.Never, receiver, name, arguments)
-        ..fileOffset = fileOffset;
-    } else {
-      expression = new MethodInvocation(receiver, name, arguments)
-        ..fileOffset = fileOffset;
-    }
+    Expression expression = new DynamicInvocation(
+        DynamicAccessKind.Never, receiver, name, arguments)
+      ..fileOffset = fileOffset;
     return createNullAwareExpressionInferenceResult(
         const NeverType.nonNullable(),
         result.applyResult(expression),
@@ -2971,52 +2957,39 @@
         isImplicitCall: isImplicitCall);
     Expression? expression;
     String? localName;
-    if (useNewMethodInvocationEncoding) {
-      DartType inferredFunctionType = result.functionType;
-      if (result.isInapplicable) {
-        // This was a function invocation whose arguments didn't match
-        // the parameters.
-        expression = new FunctionInvocation(
-            FunctionAccessKind.Inapplicable, receiver, arguments,
-            functionType: null)
-          ..fileOffset = fileOffset;
-      } else if (receiver is VariableGet) {
-        VariableDeclaration variable = receiver.variable;
-        TreeNode? parent = variable.parent;
-        if (parent is FunctionDeclaration) {
-          assert(!identical(inferredFunctionType, unknownFunction),
-              "Unknown function type for local function invocation.");
-          localName = variable.name!;
-          expression = new LocalFunctionInvocation(variable, arguments,
-              functionType: inferredFunctionType as FunctionType)
-            ..fileOffset = receiver.fileOffset;
-        }
-      }
-      expression ??= new FunctionInvocation(
-          target.isNullableCallFunction
-              ? FunctionAccessKind.Nullable
-              : (identical(inferredFunctionType, unknownFunction)
-                  ? FunctionAccessKind.Function
-                  : FunctionAccessKind.FunctionType),
-          receiver,
-          arguments,
-          functionType: identical(inferredFunctionType, unknownFunction)
-              ? null
-              : inferredFunctionType as FunctionType)
+
+    DartType inferredFunctionType = result.functionType;
+    if (result.isInapplicable) {
+      // This was a function invocation whose arguments didn't match
+      // the parameters.
+      expression = new FunctionInvocation(
+          FunctionAccessKind.Inapplicable, receiver, arguments,
+          functionType: null)
         ..fileOffset = fileOffset;
-    } else {
-      if (receiver is VariableGet) {
-        VariableDeclaration variable = receiver.variable;
-        TreeNode? parent = variable.parent;
-        if (parent is FunctionDeclaration) {
-          // This is a local function invocation. Use the name in bounds
-          // checking below.
-          localName = variable.name!;
-        }
+    } else if (receiver is VariableGet) {
+      VariableDeclaration variable = receiver.variable;
+      TreeNode? parent = variable.parent;
+      if (parent is FunctionDeclaration) {
+        assert(!identical(inferredFunctionType, unknownFunction),
+            "Unknown function type for local function invocation.");
+        localName = variable.name!;
+        expression = new LocalFunctionInvocation(variable, arguments,
+            functionType: inferredFunctionType as FunctionType)
+          ..fileOffset = receiver.fileOffset;
       }
-      expression = new MethodInvocation(receiver, callName, arguments)
-        ..fileOffset = fileOffset;
     }
+    expression ??= new FunctionInvocation(
+        target.isNullableCallFunction
+            ? FunctionAccessKind.Nullable
+            : (identical(inferredFunctionType, unknownFunction)
+                ? FunctionAccessKind.Function
+                : FunctionAccessKind.FunctionType),
+        receiver,
+        arguments,
+        functionType: identical(inferredFunctionType, unknownFunction)
+            ? null
+            : inferredFunctionType as FunctionType)
+      ..fileOffset = fileOffset;
 
     _checkBoundsInFunctionInvocation(
         declaredFunctionType, localName, arguments, fileOffset);
@@ -3131,51 +3104,45 @@
         isSpecialCasedTernaryOperator: isSpecialCasedTernaryOperator);
 
     Expression expression;
-    if (useNewMethodInvocationEncoding) {
-      DartType inferredFunctionType = result.functionType;
-      if (target.isDynamic) {
-        // This was an Object member invocation whose arguments didn't match
-        // the parameters.
-        expression = new DynamicInvocation(
-            DynamicAccessKind.Dynamic, receiver, methodName, arguments)
-          ..fileOffset = fileOffset;
-      } else if (result.isInapplicable) {
-        // This was a method invocation whose arguments didn't match
-        // the parameters.
-        expression = new InstanceInvocation(
-            InstanceAccessKind.Inapplicable, receiver, methodName, arguments,
-            functionType: _computeFunctionTypeForArguments(
-                arguments, const InvalidType()),
-            interfaceTarget: method!)
-          ..fileOffset = fileOffset;
-      } else {
-        assert(
-            inferredFunctionType is FunctionType &&
-                !identical(unknownFunction, inferredFunctionType),
-            "No function type found for $receiver.$methodName ($target) on "
-            "$receiverType");
-        InstanceAccessKind kind;
-        switch (target.kind) {
-          case ObjectAccessTargetKind.instanceMember:
-            kind = InstanceAccessKind.Instance;
-            break;
-          case ObjectAccessTargetKind.nullableInstanceMember:
-            kind = InstanceAccessKind.Nullable;
-            break;
-          case ObjectAccessTargetKind.objectMember:
-            kind = InstanceAccessKind.Object;
-            break;
-          default:
-            throw new UnsupportedError('Unexpected target kind $target');
-        }
-        expression = new InstanceInvocation(
-            kind, receiver, methodName, arguments,
-            functionType: inferredFunctionType as FunctionType,
-            interfaceTarget: method!)
-          ..fileOffset = fileOffset;
-      }
+    DartType inferredFunctionType = result.functionType;
+    if (target.isDynamic) {
+      // This was an Object member invocation whose arguments didn't match
+      // the parameters.
+      expression = new DynamicInvocation(
+          DynamicAccessKind.Dynamic, receiver, methodName, arguments)
+        ..fileOffset = fileOffset;
+    } else if (result.isInapplicable) {
+      // This was a method invocation whose arguments didn't match
+      // the parameters.
+      expression = new InstanceInvocation(
+          InstanceAccessKind.Inapplicable, receiver, methodName, arguments,
+          functionType:
+              _computeFunctionTypeForArguments(arguments, const InvalidType()),
+          interfaceTarget: method!)
+        ..fileOffset = fileOffset;
     } else {
-      expression = new MethodInvocation(receiver, methodName, arguments, method)
+      assert(
+          inferredFunctionType is FunctionType &&
+              !identical(unknownFunction, inferredFunctionType),
+          "No function type found for $receiver.$methodName ($target) on "
+          "$receiverType");
+      InstanceAccessKind kind;
+      switch (target.kind) {
+        case ObjectAccessTargetKind.instanceMember:
+          kind = InstanceAccessKind.Instance;
+          break;
+        case ObjectAccessTargetKind.nullableInstanceMember:
+          kind = InstanceAccessKind.Nullable;
+          break;
+        case ObjectAccessTargetKind.objectMember:
+          kind = InstanceAccessKind.Object;
+          break;
+        default:
+          throw new UnsupportedError('Unexpected target kind $target');
+      }
+      expression = new InstanceInvocation(kind, receiver, methodName, arguments,
+          functionType: inferredFunctionType as FunctionType,
+          interfaceTarget: method!)
         ..fileOffset = fileOffset;
     }
     Expression replacement;
@@ -3293,30 +3260,24 @@
     Name originalName = getter!.name;
     Expression originalReceiver = receiver;
     Member originalTarget = getter;
-    Expression originalPropertyGet;
-    if (useNewMethodInvocationEncoding) {
-      InstanceAccessKind kind;
-      switch (target.kind) {
-        case ObjectAccessTargetKind.instanceMember:
-          kind = InstanceAccessKind.Instance;
-          break;
-        case ObjectAccessTargetKind.nullableInstanceMember:
-          kind = InstanceAccessKind.Nullable;
-          break;
-        case ObjectAccessTargetKind.objectMember:
-          kind = InstanceAccessKind.Object;
-          break;
-        default:
-          throw new UnsupportedError('Unexpected target kind $target');
-      }
-      originalPropertyGet = new InstanceGet(
-          kind, originalReceiver, originalName,
-          resultType: calleeType, interfaceTarget: originalTarget)
-        ..fileOffset = fileOffset;
-    } else {
-      originalPropertyGet = new PropertyGet(receiver, getter.name, getter)
-        ..fileOffset = fileOffset;
+    InstanceAccessKind kind;
+    switch (target.kind) {
+      case ObjectAccessTargetKind.instanceMember:
+        kind = InstanceAccessKind.Instance;
+        break;
+      case ObjectAccessTargetKind.nullableInstanceMember:
+        kind = InstanceAccessKind.Nullable;
+        break;
+      case ObjectAccessTargetKind.objectMember:
+        kind = InstanceAccessKind.Object;
+        break;
+      default:
+        throw new UnsupportedError('Unexpected target kind $target');
     }
+    InstanceGet originalPropertyGet = new InstanceGet(
+        kind, originalReceiver, originalName,
+        resultType: calleeType, interfaceTarget: originalTarget)
+      ..fileOffset = fileOffset;
     Expression propertyGet = originalPropertyGet;
     if (calleeType is! DynamicType &&
         receiver is! ThisExpression &&
@@ -3381,45 +3342,29 @@
       // TODO(johnniwinther): Remove this when dart2js/ddc supports explicit
       //  getter calls.
       Expression nullAwareAction = invocationResult.nullAwareAction;
-      if (nullAwareAction is MethodInvocation &&
+      if (nullAwareAction is InstanceInvocation &&
           nullAwareAction.receiver == originalPropertyGet) {
         invocationResult = new ExpressionInferenceResult(
             invocationResult.inferredType,
-            new MethodInvocation(originalReceiver, originalName,
-                nullAwareAction.arguments, originalTarget)
-              ..fileOffset = nullAwareAction.fileOffset);
-      } else if (nullAwareAction is InstanceInvocation &&
-          nullAwareAction.receiver == originalPropertyGet) {
-        // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
-        // used and [originalPropertyGet] can be an [InstanceGet].
-        InstanceGet instanceGet = originalPropertyGet as InstanceGet;
-        invocationResult = new ExpressionInferenceResult(
-            invocationResult.inferredType,
-            new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
-                originalName, nullAwareAction.arguments,
+            new InstanceGetterInvocation(originalPropertyGet.kind,
+                originalReceiver, originalName, nullAwareAction.arguments,
                 interfaceTarget: originalTarget,
                 functionType: nullAwareAction.functionType)
               ..fileOffset = nullAwareAction.fileOffset);
       } else if (nullAwareAction is DynamicInvocation &&
           nullAwareAction.receiver == originalPropertyGet) {
-        // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
-        // used and [originalPropertyGet] can be an [InstanceGet].
-        InstanceGet instanceGet = originalPropertyGet as InstanceGet;
         invocationResult = new ExpressionInferenceResult(
             invocationResult.inferredType,
-            new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
-                originalName, nullAwareAction.arguments,
+            new InstanceGetterInvocation(originalPropertyGet.kind,
+                originalReceiver, originalName, nullAwareAction.arguments,
                 interfaceTarget: originalTarget, functionType: null)
               ..fileOffset = nullAwareAction.fileOffset);
       } else if (nullAwareAction is FunctionInvocation &&
           nullAwareAction.receiver == originalPropertyGet) {
-        // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
-        // used and [originalPropertyGet] can be an [InstanceGet].
-        InstanceGet instanceGet = originalPropertyGet as InstanceGet;
         invocationResult = new ExpressionInferenceResult(
             invocationResult.inferredType,
-            new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
-                originalName, nullAwareAction.arguments,
+            new InstanceGetterInvocation(originalPropertyGet.kind,
+                originalReceiver, originalName, nullAwareAction.arguments,
                 interfaceTarget: originalTarget,
                 functionType: nullAwareAction.functionType)
               ..fileOffset = nullAwareAction.fileOffset);
@@ -3497,31 +3442,24 @@
     Name originalName = field.name;
     Expression originalReceiver = receiver;
     Member originalTarget = field;
-    Expression originalPropertyGet;
-    if (useNewMethodInvocationEncoding) {
-      InstanceAccessKind kind;
-      switch (target.kind) {
-        case ObjectAccessTargetKind.instanceMember:
-          kind = InstanceAccessKind.Instance;
-          break;
-        case ObjectAccessTargetKind.nullableInstanceMember:
-          kind = InstanceAccessKind.Nullable;
-          break;
-        case ObjectAccessTargetKind.objectMember:
-          kind = InstanceAccessKind.Object;
-          break;
-        default:
-          throw new UnsupportedError('Unexpected target kind $target');
-      }
-      originalPropertyGet = new InstanceGet(
-          kind, originalReceiver, originalName,
-          resultType: calleeType, interfaceTarget: originalTarget)
-        ..fileOffset = fileOffset;
-    } else {
-      originalPropertyGet =
-          new PropertyGet(originalReceiver, originalName, originalTarget)
-            ..fileOffset = fileOffset;
+    InstanceAccessKind kind;
+    switch (target.kind) {
+      case ObjectAccessTargetKind.instanceMember:
+        kind = InstanceAccessKind.Instance;
+        break;
+      case ObjectAccessTargetKind.nullableInstanceMember:
+        kind = InstanceAccessKind.Nullable;
+        break;
+      case ObjectAccessTargetKind.objectMember:
+        kind = InstanceAccessKind.Object;
+        break;
+      default:
+        throw new UnsupportedError('Unexpected target kind $target');
     }
+    InstanceGet originalPropertyGet = new InstanceGet(
+        kind, originalReceiver, originalName,
+        resultType: calleeType, interfaceTarget: originalTarget)
+      ..fileOffset = fileOffset;
     flowAnalysis.propertyGet(originalPropertyGet, originalReceiver,
         originalName.text, originalTarget, calleeType);
     Expression propertyGet = originalPropertyGet;
@@ -3592,45 +3530,29 @@
       // TODO(johnniwinther): Remove this when dart2js/ddc supports explicit
       //  getter calls.
       Expression nullAwareAction = invocationResult.nullAwareAction;
-      if (nullAwareAction is MethodInvocation &&
+      if (nullAwareAction is InstanceInvocation &&
           nullAwareAction.receiver == originalPropertyGet) {
         invocationResult = new ExpressionInferenceResult(
             invocationResult.inferredType,
-            new MethodInvocation(originalReceiver, originalName,
-                nullAwareAction.arguments, originalTarget)
-              ..fileOffset = nullAwareAction.fileOffset);
-      } else if (nullAwareAction is InstanceInvocation &&
-          nullAwareAction.receiver == originalPropertyGet) {
-        // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
-        // used and [originalPropertyGet] can be an [InstanceGet].
-        InstanceGet instanceGet = originalPropertyGet as InstanceGet;
-        invocationResult = new ExpressionInferenceResult(
-            invocationResult.inferredType,
-            new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
-                originalName, nullAwareAction.arguments,
+            new InstanceGetterInvocation(originalPropertyGet.kind,
+                originalReceiver, originalName, nullAwareAction.arguments,
                 interfaceTarget: originalTarget,
                 functionType: nullAwareAction.functionType)
               ..fileOffset = nullAwareAction.fileOffset);
       } else if (nullAwareAction is DynamicInvocation &&
           nullAwareAction.receiver == originalPropertyGet) {
-        // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
-        // used and [originalPropertyGet] can be an [InstanceGet].
-        InstanceGet instanceGet = originalPropertyGet as InstanceGet;
         invocationResult = new ExpressionInferenceResult(
             invocationResult.inferredType,
-            new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
-                originalName, nullAwareAction.arguments,
+            new InstanceGetterInvocation(originalPropertyGet.kind,
+                originalReceiver, originalName, nullAwareAction.arguments,
                 interfaceTarget: originalTarget, functionType: null)
               ..fileOffset = nullAwareAction.fileOffset);
       } else if (nullAwareAction is FunctionInvocation &&
           nullAwareAction.receiver == originalPropertyGet) {
-        // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
-        // used and [originalPropertyGet] can be an [InstanceGet].
-        InstanceGet instanceGet = originalPropertyGet as InstanceGet;
         invocationResult = new ExpressionInferenceResult(
             invocationResult.inferredType,
-            new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
-                originalName, nullAwareAction.arguments,
+            new InstanceGetterInvocation(originalPropertyGet.kind,
+                originalReceiver, originalName, nullAwareAction.arguments,
                 interfaceTarget: originalTarget,
                 functionType: nullAwareAction.functionType)
               ..fileOffset = nullAwareAction.fileOffset);
@@ -4472,18 +4394,7 @@
   /// the interface target of the created method invocation.
   Expression createEqualsNull(
       int fileOffset, Expression left, Member equalsMember) {
-    if (useNewMethodInvocationEncoding) {
-      return new EqualsNull(left)..fileOffset = fileOffset;
-    } else {
-      return new MethodInvocation(
-          left,
-          equalsName,
-          new Arguments(
-              <Expression>[new NullLiteral()..fileOffset = fileOffset])
-            ..fileOffset = fileOffset)
-        ..fileOffset = fileOffset
-        ..interfaceTarget = equalsMember;
-    }
+    return new EqualsNull(left)..fileOffset = fileOffset;
   }
 }
 
diff --git a/pkg/front_end/lib/src/testing/id_extractor.dart b/pkg/front_end/lib/src/testing/id_extractor.dart
index 50cf52f..13229aa 100644
--- a/pkg/front_end/lib/src/testing/id_extractor.dart
+++ b/pkg/front_end/lib/src/testing/id_extractor.dart
@@ -208,24 +208,6 @@
   }
 
   @override
-  visitMethodInvocation(MethodInvocation node) {
-    TreeNode receiver = node.receiver;
-    if (receiver is VariableGet &&
-        receiver.variable.parent is FunctionDeclaration) {
-      // This is an invocation of a named local function.
-      computeForNode(node, createInvokeId(node.receiver));
-      node.arguments.accept(this);
-    } else if (node.name.text == '==' &&
-        receiver is VariableGet &&
-        receiver.variable.name == null) {
-      // This is a desugared `?.`.
-    } else {
-      _visitInvocation(node, node.name);
-      super.visitMethodInvocation(node);
-    }
-  }
-
-  @override
   visitDynamicInvocation(DynamicInvocation node) {
     _visitInvocation(node, node.name);
     super.visitDynamicInvocation(node);
@@ -278,12 +260,6 @@
   }
 
   @override
-  visitPropertyGet(PropertyGet node) {
-    computeForNode(node, computeDefaultNodeId(node));
-    super.visitPropertyGet(node);
-  }
-
-  @override
   visitDynamicGet(DynamicGet node) {
     computeForNode(node, computeDefaultNodeId(node));
     super.visitDynamicGet(node);
@@ -344,12 +320,6 @@
   }
 
   @override
-  visitPropertySet(PropertySet node) {
-    computeForNode(node, createUpdateId(node));
-    super.visitPropertySet(node);
-  }
-
-  @override
   visitDynamicSet(DynamicSet node) {
     computeForNode(node, createUpdateId(node));
     super.visitDynamicSet(node);
@@ -529,11 +499,8 @@
   visitThisExpression(ThisExpression node) {
     TreeNode parent = node.parent!;
     if (node.fileOffset == TreeNode.noOffset ||
-        (parent is PropertyGet ||
-                parent is InstanceGet ||
-                parent is PropertySet ||
+        (parent is InstanceGet ||
                 parent is InstanceSet ||
-                parent is MethodInvocation ||
                 parent is InstanceInvocation) &&
             parent.fileOffset == node.fileOffset) {
       // Skip implicit this expressions.
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index fafad3a..0067517 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -415,7 +415,12 @@
 
   void visitInstantiationConstant(InstantiationConstant node) {
     sb.write('Instantiation(');
-    sb.write(getMemberName(node.tearOffConstant.member));
+    Constant tearOffConstant = node.tearOffConstant;
+    if (tearOffConstant is TearOffConstant) {
+      sb.write(getMemberName(tearOffConstant.target));
+    } else {
+      visit(tearOffConstant);
+    }
     sb.write('<');
     typeToText.visitList(node.types);
     sb.write('>)');
@@ -423,7 +428,7 @@
 
   void visitTypedefTearOffConstant(TypedefTearOffConstant node) {
     sb.write('TypedefTearOff(');
-    sb.write(getMemberName(node.tearOffConstant.member));
+    sb.write(getMemberName(node.tearOffConstant.target));
     if (node.parameters.isNotEmpty) {
       sb.write('<');
       for (int i = 0; i < node.parameters.length; i++) {
@@ -451,13 +456,20 @@
 
   void visitStaticTearOffConstant(StaticTearOffConstant node) {
     sb.write('Function(');
-    sb.write(getMemberName(node.procedure));
+    sb.write(getMemberName(node.target));
     sb.write(')');
   }
 
   void visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
     sb.write('Constructor(');
-    sb.write(getMemberName(node.constructor));
+    sb.write(getMemberName(node.target));
+    sb.write(')');
+  }
+
+  void visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node) {
+    sb.write('RedirectingFactory(');
+    sb.write(getMemberName(node.target));
     sb.write(')');
   }
 
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index f6e79b9a..8eb1f8d 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -103,6 +103,10 @@
 ConstEvalDuplicateKey/example: Fail
 ConstEvalElementImplementsEqual/example: Fail
 ConstEvalExtension/example: Fail
+ConstEvalExternalConstructor/analyzerCode: Fail
+ConstEvalExternalConstructor/example: Fail
+ConstEvalExternalFactory/analyzerCode: Fail
+ConstEvalExternalFactory/example: Fail
 ConstEvalFailedAssertion/example: Fail
 ConstEvalFailedAssertionWithMessage/example: Fail
 ConstEvalFreeTypeParameter/analyzerCode: Fail
@@ -340,6 +344,7 @@
 FfiFieldNull/analyzerCode: Fail
 FfiLeafCallMustNotReturnHandle/analyzerCode: Fail
 FfiLeafCallMustNotTakeHandle/analyzerCode: Fail
+FfiNativeAnnotationMustAnnotateStatic/analyzerCode: Fail
 FfiNotStatic/analyzerCode: Fail
 FfiPackedAnnotation/analyzerCode: Fail
 FfiPackedAnnotationAlignment/analyzerCode: Fail
@@ -509,6 +514,8 @@
 JsInteropDartClassExtendsJSClass/example: Fail # Web compiler specific
 JsInteropEnclosingClassJSAnnotation/analyzerCode: Fail # Web compiler specific
 JsInteropEnclosingClassJSAnnotation/example: Fail # Web compiler specific
+JsInteropExternalExtensionMemberOnTypeInvalid/analyzerCode: Fail # Web compiler specific
+JsInteropExternalExtensionMemberOnTypeInvalid/example: Fail # Web compiler specific
 JsInteropExternalMemberNotJSAnnotated/analyzerCode: Fail # Web compiler specific
 JsInteropExternalMemberNotJSAnnotated/example: Fail # Web compiler specific
 JsInteropIndexNotSupported/analyzerCode: Fail # Web compiler specific
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 84ed8c2..e94eac1 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -219,6 +219,12 @@
   template: "Extension operations can't be used in constant expressions."
   analyzerCode: NOT_CONSTANT_EXPRESSION
 
+ConstEvalExternalConstructor:
+  template: "External constructors can't be evaluated in constant expressions."
+
+ConstEvalExternalFactory:
+  template: "External factory constructors can't be evaluated in constant expressions."
+
 ConstEvalUnevaluated:
   template: "Couldn't evaluate constant expression."
 
@@ -4537,6 +4543,11 @@
   template: "FFI leaf call must not have Handle return type."
   external: test/ffi_test.dart
 
+FfiNativeAnnotationMustAnnotateStatic:
+  # Used by dart:ffi
+  template: "FfiNative annotations can only be used on static functions."
+  external: test/ffi_test.dart
+
 SpreadTypeMismatch:
   template: "Unexpected type '#type' of a spread.  Expected 'dynamic' or an Iterable."
   script:
@@ -4903,6 +4914,10 @@
   template: "This is the enclosing class."
   severity: CONTEXT
 
+JsInteropExternalExtensionMemberOnTypeInvalid:
+  template: "JS interop or Native class required for 'external' extension members."
+  tip: "Try adding a JS interop annotation to the on type class of the extension."
+
 JsInteropExternalMemberNotJSAnnotated:
   template: "Only JS interop members may be 'external'."
   tip: "Try removing the 'external' keyword or adding a JS interop annotation."
diff --git a/pkg/front_end/test/comments_on_certain_arguments_tool.dart b/pkg/front_end/test/comments_on_certain_arguments_tool.dart
index 56ddf2e..4ad6562 100644
--- a/pkg/front_end/test/comments_on_certain_arguments_tool.dart
+++ b/pkg/front_end/test/comments_on_certain_arguments_tool.dart
@@ -181,13 +181,6 @@
     super.visitProcedure(node);
   }
 
-  void visitMethodInvocation(MethodInvocation node) {
-    super.visitMethodInvocation(node);
-    if (node.interfaceTargetReference?.node != null) {
-      note(node.interfaceTargetReference?.node, node.arguments, node);
-    }
-  }
-
   void visitSuperMethodInvocation(SuperMethodInvocation node) {
     super.visitSuperMethodInvocation(node);
     note(node.interfaceTargetReference.node, node.arguments, node);
@@ -226,8 +219,15 @@
       } else if (arguments.positional[i] is ListLiteral) {
         ListLiteral literal = arguments.positional[i];
         if (literal.expressions.isEmpty) wantComment = true;
-      } else if (arguments.positional[i] is MethodInvocation) {
-        MethodInvocation methodInvocation = arguments.positional[i];
+      } else if (arguments.positional[i] is InstanceInvocation) {
+        InstanceInvocation methodInvocation = arguments.positional[i];
+        if (methodInvocation.receiver is NullLiteral ||
+            methodInvocation.receiver is IntLiteral ||
+            methodInvocation.receiver is BoolLiteral) {
+          wantComment = true;
+        }
+      } else if (arguments.positional[i] is DynamicInvocation) {
+        DynamicInvocation methodInvocation = arguments.positional[i];
         if (methodInvocation.receiver is NullLiteral ||
             methodInvocation.receiver is IntLiteral ||
             methodInvocation.receiver is BoolLiteral) {
diff --git a/pkg/front_end/test/desugar_test.dart b/pkg/front_end/test/desugar_test.dart
index 7aa716d..f8078d1 100644
--- a/pkg/front_end/test/desugar_test.dart
+++ b/pkg/front_end/test/desugar_test.dart
@@ -67,7 +67,7 @@
   Expect.isTrue(
       member.kind == ir.ProcedureKind.Factory, "$member is not a factory");
   Expect.isTrue(api.isRedirectingFactory(member));
-  Expect.isTrue(member.isRedirectingFactoryConstructor);
+  Expect.isTrue(member.isRedirectingFactory);
 }
 
 const aSource = '''
diff --git a/pkg/front_end/test/generated_files_up_to_date_git_test.dart b/pkg/front_end/test/generated_files_up_to_date_git_test.dart
index 47f7548..0800570 100644
--- a/pkg/front_end/test/generated_files_up_to_date_git_test.dart
+++ b/pkg/front_end/test/generated_files_up_to_date_git_test.dart
@@ -13,16 +13,18 @@
     as generateDirectParserAstHelper;
 import "parser_test_listener_creator.dart" as generateParserTestListener;
 import "parser_test_parser_creator.dart" as generateParserTestParser;
+import '../tool/generate_ast_equivalence.dart' as generateAstEquivalence;
 import 'utils/io_utils.dart' show computeRepoDirUri;
 
 final Uri repoDir = computeRepoDirUri();
 
-main() {
+main() async {
   messages();
   experimentalFlags();
   directParserAstHelper();
   parserTestListener();
   parserTestParser();
+  await astEquivalence();
 }
 
 void parserTestParser() {
@@ -48,6 +50,14 @@
       "dart pkg/front_end/tool/_fasta/direct_parser_ast_helper_creator.dart");
 }
 
+Future<void> astEquivalence() async {
+  Uri generatedFile = generateAstEquivalence.computeEquivalenceUri(repoDir);
+  String generated =
+      await generateAstEquivalence.generateAstEquivalence(repoDir);
+  check(generated, generatedFile,
+      "dart pkg/front_end/tool/generate_ast_equivalence.dart");
+}
+
 void experimentalFlags() {
   {
     Uri generatedFile =
diff --git a/pkg/front_end/test/incremental_compiler_leak_test.dart b/pkg/front_end/test/incremental_compiler_leak_test.dart
index d304ccb..922866f 100644
--- a/pkg/front_end/test/incremental_compiler_leak_test.dart
+++ b/pkg/front_end/test/incremental_compiler_leak_test.dart
@@ -243,7 +243,7 @@
     "Field",
     "Library",
     "Procedure",
-    "RedirectingFactoryConstructor",
+    "RedirectingFactory",
     "Typedef",
   };
 
diff --git a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
index 1fb8ad1..4320981 100644
--- a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
@@ -13,7 +13,8 @@
 
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
 
-import 'package:kernel/kernel.dart' show Component;
+import 'package:kernel/ast.dart';
+import 'package:kernel/src/equivalence.dart';
 import 'package:kernel/target/targets.dart';
 
 import 'incremental_suite.dart'
@@ -93,7 +94,19 @@
     List<int> normalDillData = new File.fromUri(normalDill).readAsBytesSync();
     List<int> initializedDillData =
         new File.fromUri(fullDillFromInitialized).readAsBytesSync();
-    checkIsEqual(normalDillData, initializedDillData);
+
+    Component component1 = new Component();
+    new BinaryBuilder(normalDillData).readComponent(component1);
+
+    Component component2 = new Component();
+    new BinaryBuilder(initializedDillData).readComponent(component2);
+    EquivalenceResult result =
+        checkEquivalence(component1, component2, strategy: const Strategy());
+    Expect.isTrue(result.isEquivalent, result.toString());
+
+    // TODO(johnniwinther): Reenable this check when the discrepancies have been
+    // fixed.
+    //checkIsEqual(normalDillData, initializedDillData);
 
     // Also try without invalidating anything.
     stopwatch.reset();
@@ -110,3 +123,49 @@
     checkIsEqual(normalDillData, initializedDillData);
   }
 }
+
+class Strategy extends EquivalenceStrategy {
+  const Strategy();
+
+  @override
+  bool checkClass_procedures(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    // Check procedures as a set instead of a list to allow for reordering.
+    return visitor.checkSets(node.procedures.toSet(), other.procedures.toSet(),
+        visitor.matchNamedNodes, visitor.checkNodes, 'procedures');
+  }
+
+  bool _isMixinOrCloneReference(EquivalenceVisitor visitor, Reference a,
+      Reference b, String propertyName) {
+    if (a != null && b != null) {
+      ReferenceName thisName = ReferenceName.fromReference(a);
+      ReferenceName otherName = ReferenceName.fromReference(b);
+      if (thisName.kind == ReferenceNameKind.Member &&
+          otherName.kind == ReferenceNameKind.Member &&
+          thisName.memberName == otherName.memberName) {
+        String thisClassName = thisName.declarationName;
+        String otherClassName = otherName.declarationName;
+        if (thisClassName != null &&
+            otherClassName != null &&
+            thisClassName.contains('&${otherClassName}')) {
+          visitor.assumeReferences(a, b);
+        }
+      }
+    }
+    return visitor.checkReferences(a, b, propertyName);
+  }
+
+  @override
+  bool checkProcedure_stubTargetReference(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return _isMixinOrCloneReference(visitor, node.stubTargetReference,
+        other.stubTargetReference, 'stubTargetReference');
+  }
+
+  @override
+  bool checkInstanceGet_interfaceTargetReference(
+      EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+    return _isMixinOrCloneReference(visitor, node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+}
diff --git a/pkg/front_end/test/simple_stats.dart b/pkg/front_end/test/simple_stats.dart
index dd69a4e..6ffd5c5 100644
--- a/pkg/front_end/test/simple_stats.dart
+++ b/pkg/front_end/test/simple_stats.dart
@@ -2,14 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE.md file.
 
-// @dart = 2.9
-
 import 'dart:math' as math;
 
 class SimpleTTestStat {
   static TTestResult ttest<E extends num>(List<E> a, List<E> b) {
-    E aSum = a.reduce((value, element) => (value + element));
-    E bSum = b.reduce((value, element) => (value + element));
+    E aSum = a.reduce((value, element) => (value + element) as E);
+    E bSum = b.reduce((value, element) => (value + element) as E);
     int aCount = a.length;
     int bCount = b.length;
     double aMean = aSum / aCount;
@@ -37,7 +35,7 @@
   }
 
   static double variance<E extends num>(List<E> data) {
-    E sum = data.reduce((value, element) => (value + element));
+    E sum = data.reduce((value, element) => (value + element) as E);
     int count = data.length;
     double average = sum / count;
 
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 510170a..7cc2003 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -62,6 +62,7 @@
 askesc
 aspect
 aspx
+asserting
 assigning
 assigns
 association
@@ -142,7 +143,6 @@
 bslash
 buffered
 builder`s
-bulder
 bulk
 bump
 bypassing
@@ -168,6 +168,7 @@
 casts
 categorized
 ce
+ceil
 cfe
 ch
 channel
@@ -221,6 +222,7 @@
 combiner
 compared
 compares
+compilations
 completes
 complicating
 component's
@@ -298,6 +300,7 @@
 deepest
 deeply
 def
+defaulting
 degrades
 degree
 del
@@ -359,6 +362,7 @@
 dummy
 dupdate
 dyn
+dynamically
 e
 easy
 ecma
@@ -386,11 +390,14 @@
 enforced
 enforces
 enforcing
+enters
+engineered
 enumerates
 env
 eof
 eq
 equation
+equivalences
 erased
 erasure
 es
@@ -577,6 +584,9 @@
 indirection
 individual
 inequality
+inequivalence
+inequivalences
+inequivalent
 influence
 informative
 infos
@@ -601,6 +611,7 @@
 int8
 integrate
 intentionally
+interested
 interim
 interior
 interleaved
@@ -783,6 +794,7 @@
 nk
 nnbd
 node's
+nominality
 nonimplementation
 norm
 normalization
@@ -818,6 +830,7 @@
 ogham
 oked
 op
+opens
 opt
 optimizations
 opting
@@ -1017,7 +1030,9 @@
 remedy
 removal
 remover
+renames
 render
+reordered
 reparse
 repeating
 replacements
@@ -1032,6 +1047,7 @@
 residue
 resource
 respond
+restoring
 restriction
 resumed
 ret
@@ -1057,6 +1073,7 @@
 rs
 runnable
 s
+sand
 sanitizing
 saw
 say
@@ -1102,6 +1119,7 @@
 siblings
 sides
 sigmund
+signaling
 significant
 simplify
 singleton
@@ -1200,12 +1218,14 @@
 sw
 swapped
 sweep
+symbolic
 synchronously
 syncs
 synth
 t
 tagged
 tagger
+tagging
 tags
 tailor
 taking
@@ -1408,6 +1428,7 @@
 wiki
 wikipedia
 wind
+wise
 wiser
 with1
 wn
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 816ad78..0b93c1a 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -1179,6 +1179,7 @@
 fetch
 few
 fewer
+ffinative
 field
 field's
 fieldname
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index c241a42..150c716 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -45,6 +45,7 @@
 asserter
 assure
 asterisk
+atomic
 auth
 authority
 autobianchi
@@ -111,27 +112,44 @@
 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
 ca
 cafebabe
 calloc
 camel
 capitalized
+categorization
 causal
 cb
 cc
@@ -157,6 +175,10 @@
 class5b
 class5c
 class5d
+class7a
+class7b
+class8a
+class8b
 cloneable
 cm
 cmd
@@ -184,6 +206,7 @@
 confirm
 consecutive
 considering
+consist
 constrains
 consts
 contract
@@ -225,10 +248,12 @@
 dash
 dashes
 day
+days
 db
 ddart
 dds
 debugger
+declarative
 decrease
 decrements
 dectcem
@@ -262,6 +287,7 @@
 disallowed
 disconnect
 discovering
+discrepancies
 dispatcher
 dispose
 dist
@@ -293,10 +319,12 @@
 elegantly
 ell
 emethod
+enters
 entrypoint
 entrypoints
 eoo
 epoch
+equivalences
 erase
 erased
 err
@@ -322,19 +350,42 @@
 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
 fac
 faking
 falling
@@ -404,6 +455,14 @@
 fuzz
 fuzzing
 fx
+g1a
+g1b
+g1c
+g2a
+g2b
+g2c
+g3a
+g3b
 gallery
 gamma
 gave
@@ -421,6 +480,20 @@
 gtgt
 gulp
 gunk
+h1a
+h1b
+h1c
+h2a
+h2b
+h2c
+h3a
+h3b
+h4a
+h4b
+h5a
+h5b
+h6a
+h6b
 hackish
 hardly
 helper2
@@ -439,6 +512,9 @@
 hunk
 hurray
 i'm
+i2a
+i3a
+i3b
 ia
 ideal
 identification
@@ -469,6 +545,7 @@
 insufficient
 intdiv
 interactive
+interested
 internet
 interpolate
 introducer
@@ -601,6 +678,8 @@
 nil
 ninja
 noisy
+nominal
+nominality
 nondefault
 nonexisting
 noo
@@ -633,6 +712,7 @@
 pack
 paging
 paint
+parallax
 parameterized
 party
 pause
@@ -700,6 +780,8 @@
 redirections
 rediscover
 reducer
+reenable
+referential
 referring
 reflectee
 refusing
@@ -711,6 +793,7 @@
 reload
 remap
 remaps
+renames
 rendition
 reorder
 reordering
@@ -733,6 +816,7 @@
 rows
 runtimes
 rv
+sand
 saves
 scans
 scheduler
@@ -746,6 +830,7 @@
 selection
 semifuzz
 sensitive
+serves
 services
 setter1a
 setter1b
@@ -759,6 +844,7 @@
 shortest
 shot
 sigint
+signaling
 signalled
 sigwinch
 slashes
@@ -881,6 +967,8 @@
 verbatim
 versioned
 vf
+visitor0
+visitor1
 vp
 vt
 vte
@@ -894,6 +982,7 @@
 wherever
 whiskers
 wins
+wise
 wording
 workflow
 worlds
diff --git a/pkg/front_end/test/static_types/analysis_helper.dart b/pkg/front_end/test/static_types/analysis_helper.dart
index 3ae2d5b..2091112 100644
--- a/pkg/front_end/test/static_types/analysis_helper.dart
+++ b/pkg/front_end/test/static_types/analysis_helper.dart
@@ -282,33 +282,6 @@
   }
 
   @override
-  void visitPropertyGet(PropertyGet node) {
-    DartType receiverType = node.receiver.getStaticType(staticTypeContext);
-    if (receiverType is DynamicType && node.interfaceTarget == null) {
-      registerError(node, "Dynamic access of '${node.name}'.");
-    }
-    super.visitPropertyGet(node);
-  }
-
-  @override
-  void visitPropertySet(PropertySet node) {
-    DartType receiverType = node.receiver.getStaticType(staticTypeContext);
-    if (receiverType is DynamicType) {
-      registerError(node, "Dynamic update to '${node.name}'.");
-    }
-    super.visitPropertySet(node);
-  }
-
-  @override
-  void visitMethodInvocation(MethodInvocation node) {
-    DartType receiverType = node.receiver.getStaticType(staticTypeContext);
-    if (receiverType is DynamicType && node.interfaceTarget == null) {
-      registerError(node, "Dynamic invocation of '${node.name}'.");
-    }
-    super.visitMethodInvocation(node);
-  }
-
-  @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     if (checkReturnTypes && node.function.returnType is DynamicType) {
       registerError(node, "Dynamic return type");
diff --git a/pkg/front_end/test/text_representation/empty_reference_test.dart b/pkg/front_end/test/text_representation/empty_reference_test.dart
index a33bd6b..0e36da8 100644
--- a/pkg/front_end/test/text_representation/empty_reference_test.dart
+++ b/pkg/front_end/test/text_representation/empty_reference_test.dart
@@ -83,15 +83,15 @@
 }
 
 void testMembers() {
-  testExpression(new PropertyGet(new IntLiteral(0), new Name('foo')), '''
-0.foo''');
   testExpression(new StaticGet.byReference(null), '''
 <missing-member-reference>''');
 
   Reference unlinkedMemberName = new Reference();
   testExpression(
-      new PropertyGet.byReference(
-          new IntLiteral(0), new Name('foo'), unlinkedMemberName),
+      new InstanceGet.byReference(
+          InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+          interfaceTargetReference: unlinkedMemberName,
+          resultType: const DynamicType()),
       '''
 0.foo''');
   testExpression(new StaticGet.byReference(unlinkedMemberName), '''
@@ -100,8 +100,10 @@
   CanonicalName root = new CanonicalName.root();
   Reference rootReference = new Reference()..canonicalName = root;
   testExpression(
-      new PropertyGet.byReference(
-          new IntLiteral(0), new Name('foo'), rootReference),
+      new InstanceGet.byReference(
+          InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+          interfaceTargetReference: rootReference,
+          resultType: const DynamicType()),
       '''
 0.foo''');
   testExpression(new StaticGet.byReference(rootReference), '''
@@ -110,8 +112,10 @@
   CanonicalName library = root.getChild('library');
   Reference libraryReference = new Reference()..canonicalName = library;
   testExpression(
-      new PropertyGet.byReference(
-          new IntLiteral(0), new Name('foo'), libraryReference),
+      new InstanceGet.byReference(
+          InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+          interfaceTargetReference: libraryReference,
+          resultType: const DynamicType()),
       '''
 0.foo''');
   testExpression(new StaticGet.byReference(libraryReference), '''
@@ -121,8 +125,10 @@
   Reference topLevelMemberNameReference = new Reference()
     ..canonicalName = topLevelMemberName;
   testExpression(
-      new PropertyGet.byReference(
-          new IntLiteral(0), new Name('foo'), topLevelMemberNameReference),
+      new InstanceGet.byReference(
+          InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+          interfaceTargetReference: topLevelMemberNameReference,
+          resultType: const DynamicType()),
       '''
 0.foo''');
   testExpression(new StaticGet.byReference(topLevelMemberNameReference), '''
@@ -132,8 +138,10 @@
   CanonicalName className = library.getChild('Class');
   Reference classNameReference = new Reference()..canonicalName = className;
   testExpression(
-      new PropertyGet.byReference(
-          new IntLiteral(0), new Name('foo'), classNameReference),
+      new InstanceGet.byReference(
+          InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+          interfaceTargetReference: classNameReference,
+          resultType: const DynamicType()),
       '''
 0.foo''');
   testExpression(new StaticGet.byReference(classNameReference), '''
@@ -144,8 +152,10 @@
   Reference classMemberNameReference = new Reference()
     ..canonicalName = classMemberName;
   testExpression(
-      new PropertyGet.byReference(
-          new IntLiteral(0), new Name('foo'), classMemberNameReference),
+      new InstanceGet.byReference(
+          InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+          interfaceTargetReference: classMemberNameReference,
+          resultType: const DynamicType()),
       '''
 0.foo''');
   testExpression(new StaticGet.byReference(classMemberNameReference), '''
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 e1f4a5b..e483c41 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
@@ -44,6 +44,9 @@
   _testFunctionDeclarationImpl();
   _testIfNullExpression();
   _testIntLiterals();
+  _testInternalMethodInvocation();
+  _testInternalPropertyGet();
+  _testInternalPropertySet();
   _testExpressionInvocation();
   _testNamedFunctionExpressionJudgment();
   _testNullAwareMethodInvocation();
@@ -284,7 +287,7 @@
   testExpression(cascade, '''
 let final dynamic #0 = 0 in cascade {} => #0''');
 
-  cascade.addCascadeExpression(new PropertySet(
+  cascade.addCascadeExpression(new DynamicSet(DynamicAccessKind.Dynamic,
       new VariableGet(variable), new Name('foo'), new IntLiteral(1)));
   testExpression(cascade, '''
 let final dynamic #0 = 0 in cascade {
@@ -292,7 +295,7 @@
 } => #0''', limited: '''
 let final dynamic #0 = 0 in cascade { #0.foo = 1; } => #0''');
 
-  cascade.addCascadeExpression(new PropertySet(
+  cascade.addCascadeExpression(new DynamicSet(DynamicAccessKind.Dynamic,
       new VariableGet(variable), new Name('bar'), new IntLiteral(2)));
   testExpression(cascade, '''
 let final dynamic #0 = 0 in cascade {
@@ -372,6 +375,44 @@
   testExpression(new ShadowLargeIntLiteral('bar', TreeNode.noOffset), 'bar');
 }
 
+void _testInternalMethodInvocation() {
+  testExpression(
+      new MethodInvocation(
+          new IntLiteral(0), new Name('boz'), new ArgumentsImpl([])),
+      '''
+0.boz()''');
+  testExpression(
+      new MethodInvocation(
+          new IntLiteral(0),
+          new Name('boz'),
+          new ArgumentsImpl([
+            new IntLiteral(1)
+          ], types: [
+            const VoidType(),
+            const DynamicType()
+          ], named: [
+            new NamedExpression('foo', new IntLiteral(2)),
+            new NamedExpression('bar', new IntLiteral(3))
+          ])),
+      '''
+0.boz<void, dynamic>(1, foo: 2, bar: 3)''');
+}
+
+void _testInternalPropertyGet() {
+  testExpression(
+      new PropertyGet(new IntLiteral(0), new Name('boz')), '''
+0.boz''');
+}
+
+void _testInternalPropertySet() {
+  testExpression(
+      new PropertySet(
+          new IntLiteral(0), new Name('boz'), new IntLiteral(1),
+          forEffect: false, readOnlyReceiver: false),
+      '''
+0.boz = 1''');
+}
+
 void _testExpressionInvocation() {
   testExpression(
       new ExpressionInvocation(new IntLiteral(0), new ArgumentsImpl([])), '''
@@ -409,11 +450,17 @@
   testExpression(
       new NullAwareMethodInvocation(
           variable,
-          new MethodInvocation(new VariableGet(variable), new Name('foo'),
+          new DynamicInvocation(
+              DynamicAccessKind.Dynamic,
+              new VariableGet(variable),
+              new Name('foo'),
               new ArgumentsImpl([]))),
       '''
 0?.foo()''');
 
+  // TODO(johnniwinther): Add a test using InstanceInvocation instead of
+  // DynamicInvocation.
+
   // An unusual use of this node.
   testExpression(
       new NullAwareMethodInvocation(variable,
@@ -437,7 +484,10 @@
   testExpression(
       new NullAwarePropertyGet(
           variable,
-          new MethodInvocation(new VariableGet(variable), new Name('foo'),
+          new DynamicInvocation(
+              DynamicAccessKind.Dynamic,
+              new VariableGet(variable),
+              new Name('foo'),
               new ArgumentsImpl([]))),
       '''
 let final dynamic #0 = 0 in null-aware #0.foo()''');
@@ -450,15 +500,20 @@
   testExpression(
       new NullAwarePropertySet(
           variable,
-          new PropertySet(
-              new VariableGet(variable), new Name('foo'), new IntLiteral(1))),
+          new DynamicSet(DynamicAccessKind.Dynamic, new VariableGet(variable),
+              new Name('foo'), new IntLiteral(1))),
       '''
 0?.foo = 1''');
 
+  // TODO(johnniwinther): Add a test using InstanceSet instead of DynamicSet.
+
   testExpression(
       new NullAwarePropertySet(
           variable,
-          new MethodInvocation(new VariableGet(variable), new Name('foo'),
+          new DynamicInvocation(
+              DynamicAccessKind.Dynamic,
+              new VariableGet(variable),
+              new Name('foo'),
               new ArgumentsImpl([]))),
       '''
 let final dynamic #0 = 0 in null-aware #0.foo()''');
diff --git a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
index f92bdce..a821c4b 100644
--- a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
@@ -9,7 +9,10 @@
 static method main() → dynamic {
   core::List<dynamic> list = core::_GrowableList::•<dynamic>(0);
   if(list.{core::Iterable::isNotEmpty}{core::bool}) {
-    let dynamic #t1 = new mai::Class::•() in let dynamic #t2 = _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::Enum in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+    block {
+      new mai::Class::•();
+      _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::Enum;
+    } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
   }
 }
 
diff --git a/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect b/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
index 077bd72..0aaa3a0 100644
--- a/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
@@ -35,7 +35,10 @@
   #C3;
   core::List<self::UnusedEnum> list = core::_GrowableList::•<self::UnusedEnum>(0);
   if(list.{core::Iterable::isNotEmpty}{core::bool}) {
-    let dynamic #t2 = new mai::ConstClass::•() in let dynamic #t3 = _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::ConstEnum in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+    block {
+      new mai::ConstClass::•();
+      _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::ConstEnum;
+    } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
   }
 }
 
diff --git a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.expect
index e8c1280..7435151 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.expect
@@ -46,14 +46,14 @@
 extension Extension on core::int {
 }
 static method test() → dynamic {
-  self::ConcreteClass::•;
+  #C1;
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:14:17: Error: Constructors on abstract classes can't be torn off.
   AbstractClass.new; // error
                 ^^^";
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:15:9: Error: Getter not found: 'new'.
   Mixin.new; // error
         ^^^";
-  self::NamedMixinApplication::•;
+  #C2;
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:17:33: Error: Constructors on abstract classes can't be torn off.
   AbstractNamedMixinApplication.new; // error
                                 ^^^";
@@ -62,3 +62,8 @@
             ^^^";
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::ConcreteClass::•
+  #C2 = constructor-tearoff self::NamedMixinApplication::•
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.transformed.expect
index b86fac8..2b7289e 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.transformed.expect
@@ -46,14 +46,14 @@
 extension Extension on core::int {
 }
 static method test() → dynamic {
-  self::ConcreteClass::•;
+  #C1;
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:14:17: Error: Constructors on abstract classes can't be torn off.
   AbstractClass.new; // error
                 ^^^";
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:15:9: Error: Getter not found: 'new'.
   Mixin.new; // error
         ^^^";
-  self::NamedMixinApplication::•;
+  #C2;
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:17:33: Error: Constructors on abstract classes can't be torn off.
   AbstractNamedMixinApplication.new; // error
                                 ^^^";
@@ -62,3 +62,8 @@
             ^^^";
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::ConcreteClass::•
+  #C2 = constructor-tearoff self::NamedMixinApplication::•
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.expect
index e8c1280..7435151 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.expect
@@ -46,14 +46,14 @@
 extension Extension on core::int {
 }
 static method test() → dynamic {
-  self::ConcreteClass::•;
+  #C1;
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:14:17: Error: Constructors on abstract classes can't be torn off.
   AbstractClass.new; // error
                 ^^^";
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:15:9: Error: Getter not found: 'new'.
   Mixin.new; // error
         ^^^";
-  self::NamedMixinApplication::•;
+  #C2;
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:17:33: Error: Constructors on abstract classes can't be torn off.
   AbstractNamedMixinApplication.new; // error
                                 ^^^";
@@ -62,3 +62,8 @@
             ^^^";
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::ConcreteClass::•
+  #C2 = constructor-tearoff self::NamedMixinApplication::•
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.transformed.expect
index b86fac8..2b7289e 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.transformed.expect
@@ -46,14 +46,14 @@
 extension Extension on core::int {
 }
 static method test() → dynamic {
-  self::ConcreteClass::•;
+  #C1;
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:14:17: Error: Constructors on abstract classes can't be torn off.
   AbstractClass.new; // error
                 ^^^";
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:15:9: Error: Getter not found: 'new'.
   Mixin.new; // error
         ^^^";
-  self::NamedMixinApplication::•;
+  #C2;
   invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:17:33: Error: Constructors on abstract classes can't be torn off.
   AbstractNamedMixinApplication.new; // error
                                 ^^^";
@@ -62,3 +62,8 @@
             ^^^";
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::ConcreteClass::•
+  #C2 = constructor-tearoff self::NamedMixinApplication::•
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart
index 6d8b22b..8650911 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart
@@ -5,5 +5,10 @@
 T func<T>(T value) => value;
 var funcValue = func;
 int Function(int) f = funcValue.call; // Disallowed!
+int Function(int) g = funcValue.call<int>; // Disallowed!
+
+test(Function f) {
+  int Function(int) g = f.call<int>; // Disallowed!
+}
 
 main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect
index 2d0b3bf..fe25279 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect
@@ -6,6 +6,12 @@
 // int Function(int) f = funcValue.call; // Disallowed!
 //                                 ^
 //
+// pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:11:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Function'.
+//  - 'Function' is from 'dart:core'.
+// Try changing the operand or remove the type arguments.
+//   int Function(int) g = f.call<int>; // Disallowed!
+//                               ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -13,10 +19,18 @@
 static field (core::int) → core::int f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
 int Function(int) f = funcValue.call; // Disallowed!
                                 ^" in self::funcValue.call as{TypeError,ForNonNullableByDefault} (core::int) → core::int;
+static field (core::int) → core::int g = self::funcValue.call<core::int>;
 static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
   return value;
+static method test(core::Function f) → dynamic {
+  (core::int) → core::int g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:11:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Function'.
+ - 'Function' is from 'dart:core'.
+Try changing the operand or remove the type arguments.
+  int Function(int) g = f.call<int>; // Disallowed!
+                              ^";
+}
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::func
+  #C1 = static-tearoff self::func
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect
index 2d0b3bf..bdc66d1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect
@@ -18,5 +18,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::func
+  #C1 = static-tearoff self::func
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect
index 26c075f..6488494 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect
@@ -1,4 +1,6 @@
 T func<T>(T value) => value;
 var funcValue = func;
 int Function(int) f = funcValue.call;
+int Function(int) g = funcValue.call<int>;
+test(Function f) {}
 main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect
index 2d0b3bf..fe25279 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect
@@ -6,6 +6,12 @@
 // int Function(int) f = funcValue.call; // Disallowed!
 //                                 ^
 //
+// pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:11:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Function'.
+//  - 'Function' is from 'dart:core'.
+// Try changing the operand or remove the type arguments.
+//   int Function(int) g = f.call<int>; // Disallowed!
+//                               ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -13,10 +19,18 @@
 static field (core::int) → core::int f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
 int Function(int) f = funcValue.call; // Disallowed!
                                 ^" in self::funcValue.call as{TypeError,ForNonNullableByDefault} (core::int) → core::int;
+static field (core::int) → core::int g = self::funcValue.call<core::int>;
 static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
   return value;
+static method test(core::Function f) → dynamic {
+  (core::int) → core::int g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:11:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Function'.
+ - 'Function' is from 'dart:core'.
+Try changing the operand or remove the type arguments.
+  int Function(int) g = f.call<int>; // Disallowed!
+                              ^";
+}
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::func
+  #C1 = static-tearoff self::func
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect
index cce6eb8..fc89fd2 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect
@@ -4,7 +4,10 @@
 
 static field <T extends core::Object? = dynamic>(T%) → T% funcValue;
 static field (core::int) → core::int f;
+static field (core::int) → core::int g;
 static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
   ;
+static method test(core::Function f) → dynamic
+  ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect
index 2d0b3bf..bdc66d1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect
@@ -18,5 +18,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::func
+  #C1 = static-tearoff self::func
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart
new file mode 100644
index 0000000..e832879f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.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.
+
+class A<T> {
+  A();
+  factory A.fact() => new A();
+  factory A.redirect() = A;
+}
+
+typedef B<T> = A<T>;
+typedef C<T> = A<int>;
+
+const a = A.new;
+const b = A<int>.new;
+const c = A.fact;
+const d = A<int>.fact;
+const e = A.redirect;
+const f = A<int>.redirect;
+const g = B.new;
+const h = B<int>.new;
+const i = B.fact;
+const j = B<int>.fact;
+const k = B.redirect;
+const l = B<int>.redirect;
+const m = C.new;
+const n = C<int>.new;
+const o = C.fact;
+const p = C<int>.fact;
+const q = C.redirect;
+const r = C<int>.redirect;
+
+main() {
+  var a = A.new;
+  var b = A<int>.new;
+  var c = A.fact;
+  var d = A<int>.fact;
+  var e = A.redirect;
+  var f = A<int>.redirect;
+  var g = B.new;
+  var h = B<int>.new;
+  var i = B.fact;
+  var j = B<int>.fact;
+  var k = B.redirect;
+  var l = B<int>.redirect;
+  var m = C.new;
+  var n = C<int>.new;
+  var o = C.fact;
+  var p = C<int>.fact;
+  var q = C.redirect;
+  var r = C<int>.redirect;
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.expect
new file mode 100644
index 0000000..cfec78a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+  <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+  () → self::A<core::int> b = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+  () → self::A<core::int> d = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+  () → self::A<core::int> f = #C6;
+  <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+  () → self::A<core::int> h = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+  () → self::A<core::int> j = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+  () → self::A<core::int> l = #C6;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+  () → self::A<core::int> n = #C2;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+  () → self::A<core::int> p = #C4;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+  () → self::A<core::int> r = #C6;
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int>
+  #C3 = static-tearoff self::A::fact
+  #C4 = instantiation self::A::fact <core::int>
+  #C5 = redirecting-factory-tearoff self::A::redirect
+  #C6 = instantiation self::A::redirect <core::int>
+  #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+  #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+  #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..d84286f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+  <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+  () → self::A<core::int> b = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+  () → self::A<core::int> d = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+  () → self::A<core::int> f = #C6;
+  <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+  () → self::A<core::int> h = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+  () → self::A<core::int> j = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+  () → self::A<core::int> l = #C6;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+  () → self::A<core::int> n = #C2;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+  () → self::A<core::int> p = #C4;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+  () → self::A<core::int> r = #C6;
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int>
+  #C3 = static-tearoff self::A::fact
+  #C4 = instantiation self::A::fact <core::int>
+  #C5 = redirecting-factory-tearoff self::A::redirect
+  #C6 = instantiation self::A::redirect <core::int>
+  #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+  #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+  #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..a4b6c13
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.textual_outline.expect
@@ -0,0 +1,26 @@
+class A<T> {
+  A();
+  factory A.fact() => new A();
+  factory A.redirect() = A;
+}
+typedef B<T> = A<T>;
+typedef C<T> = A<int>;
+const a = A.new;
+const b = A<int>.new;
+const c = A.fact;
+const d = A<int>.fact;
+const e = A.redirect;
+const f = A<int>.redirect;
+const g = B.new;
+const h = B<int>.new;
+const i = B.fact;
+const j = B<int>.fact;
+const k = B.redirect;
+const l = B<int>.redirect;
+const m = C.new;
+const n = C<int>.new;
+const o = C.fact;
+const p = C<int>.fact;
+const q = C.redirect;
+const r = C<int>.redirect;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.expect
new file mode 100644
index 0000000..7412c43
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+  <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+  () → self::A<core::int> b = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+  () → self::A<core::int> d = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+  () → self::A<core::int> f = #C6;
+  <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+  () → self::A<core::int> h = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+  () → self::A<core::int> j = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+  () → self::A<core::int> l = #C6;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+  () → self::A<core::int> n = #C2;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+  () → self::A<core::int> p = #C4;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+  () → self::A<core::int> r = #C6;
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int*>
+  #C3 = static-tearoff self::A::fact
+  #C4 = instantiation self::A::fact <core::int*>
+  #C5 = redirecting-factory-tearoff self::A::redirect
+  #C6 = instantiation self::A::redirect <core::int*>
+  #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+  #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+  #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..b93adae
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect
@@ -0,0 +1,57 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    ;
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    ;
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = self::A::•;
+static const field () → self::A<core::int> b = self::A::•<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = self::A::fact;
+static const field () → self::A<core::int> d = self::A::fact<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = self::A::redirect;
+static const field () → self::A<core::int> f = self::A::redirect<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = self::A::•;
+static const field () → self::A<core::int> h = self::A::•<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = self::A::fact;
+static const field () → self::A<core::int> j = self::A::fact<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = self::A::redirect;
+static const field () → self::A<core::int> l = self::A::redirect<core::int>;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = <unrelated T extends core::Object? = dynamic>.(self::A::•<core::int>);
+static const field () → self::A<core::int> n = self::A::•<core::int>;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = <unrelated T extends core::Object? = dynamic>.(self::A::fact<core::int>);
+static const field () → self::A<core::int> p = self::A::fact<core::int>;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = <unrelated T extends core::Object? = dynamic>.(self::A::redirect<core::int>);
+static const field () → self::A<core::int> r = self::A::redirect<core::int>;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///const_tear_off.dart:14:11 -> ConstructorTearOffConstant(A.)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:15:11 -> InstantiationConstant(A.<int*>)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///const_tear_off.dart:16:11 -> StaticTearOffConstant(A.fact)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:17:11 -> InstantiationConstant(A.fact<int*>)
+Evaluated: RedirectingFactoryTearOff @ org-dartlang-testcase:///const_tear_off.dart:18:11 -> RedirectingFactoryTearOffConstant(A.redirect)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:19:11 -> InstantiationConstant(A.redirect<int*>)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///const_tear_off.dart:20:11 -> ConstructorTearOffConstant(A.)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:21:11 -> InstantiationConstant(A.<int*>)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///const_tear_off.dart:22:11 -> StaticTearOffConstant(A.fact)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:23:11 -> InstantiationConstant(A.fact<int*>)
+Evaluated: RedirectingFactoryTearOff @ org-dartlang-testcase:///const_tear_off.dart:24:11 -> RedirectingFactoryTearOffConstant(A.redirect)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:25:11 -> InstantiationConstant(A.redirect<int*>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:26:11 -> TypedefTearOffConstant(<T>A.<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:27:11 -> InstantiationConstant(A.<int*>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:28:11 -> TypedefTearOffConstant(<T>A.fact<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:29:11 -> InstantiationConstant(A.fact<int*>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:30:11 -> TypedefTearOffConstant(<T>A.redirect<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:31:11 -> InstantiationConstant(A.redirect<int*>)
+Extra constant evaluation: evaluated: 23, effectively constant: 18
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..0a0394c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+  <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+  () → self::A<core::int> b = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+  () → self::A<core::int> d = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+  () → self::A<core::int> f = #C6;
+  <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+  () → self::A<core::int> h = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+  () → self::A<core::int> j = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+  () → self::A<core::int> l = #C6;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+  () → self::A<core::int> n = #C2;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+  () → self::A<core::int> p = #C4;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+  () → self::A<core::int> r = #C6;
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int*>
+  #C3 = static-tearoff self::A::fact
+  #C4 = instantiation self::A::fact <core::int*>
+  #C5 = redirecting-factory-tearoff self::A::redirect
+  #C6 = instantiation self::A::redirect <core::int*>
+  #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+  #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+  #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart
new file mode 100644
index 0000000..50c03ac
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart
@@ -0,0 +1,10 @@
+// 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.
+
+test1(dynamic x) => x.foo<int>; // Error.
+test2(Never x) => x.foo<int>; // Error.
+test3(dynamic x) => x.toString<int>; // Error.
+test4(Never x) => x.toString<int>; // Error.
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.expect
new file mode 100644
index 0000000..ee9aed5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+// Try changing the operand or remove the type arguments.
+// test1(dynamic x) => x.foo<int>; // Error.
+//                          ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test2(Never x) => x.foo<int>; // Error.
+//                        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+// Try changing the operand or remove the type arguments.
+// test3(dynamic x) => x.toString<int>; // Error.
+//                               ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test4(Never x) => x.toString<int>; // Error.
+//                             ^
+//
+import self as self;
+
+static method test1(dynamic x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+Try changing the operand or remove the type arguments.
+test1(dynamic x) => x.foo<int>; // Error.
+                         ^";
+static method test2(Never x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test2(Never x) => x.foo<int>; // Error.
+                       ^";
+static method test3(dynamic x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+Try changing the operand or remove the type arguments.
+test3(dynamic x) => x.toString<int>; // Error.
+                              ^";
+static method test4(Never x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test4(Never x) => x.toString<int>; // Error.
+                            ^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.transformed.expect
new file mode 100644
index 0000000..ee9aed5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.transformed.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+// Try changing the operand or remove the type arguments.
+// test1(dynamic x) => x.foo<int>; // Error.
+//                          ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test2(Never x) => x.foo<int>; // Error.
+//                        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+// Try changing the operand or remove the type arguments.
+// test3(dynamic x) => x.toString<int>; // Error.
+//                               ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test4(Never x) => x.toString<int>; // Error.
+//                             ^
+//
+import self as self;
+
+static method test1(dynamic x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+Try changing the operand or remove the type arguments.
+test1(dynamic x) => x.foo<int>; // Error.
+                         ^";
+static method test2(Never x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test2(Never x) => x.foo<int>; // Error.
+                       ^";
+static method test3(dynamic x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+Try changing the operand or remove the type arguments.
+test3(dynamic x) => x.toString<int>; // Error.
+                              ^";
+static method test4(Never x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test4(Never x) => x.toString<int>; // Error.
+                            ^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.textual_outline.expect
new file mode 100644
index 0000000..8143249
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+test1(dynamic x) => x.foo<int>;
+test2(Never x) => x.foo<int>;
+test3(dynamic x) => x.toString<int>;
+test4(Never x) => x.toString<int>;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.expect
new file mode 100644
index 0000000..ee9aed5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+// Try changing the operand or remove the type arguments.
+// test1(dynamic x) => x.foo<int>; // Error.
+//                          ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test2(Never x) => x.foo<int>; // Error.
+//                        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+// Try changing the operand or remove the type arguments.
+// test3(dynamic x) => x.toString<int>; // Error.
+//                               ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test4(Never x) => x.toString<int>; // Error.
+//                             ^
+//
+import self as self;
+
+static method test1(dynamic x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+Try changing the operand or remove the type arguments.
+test1(dynamic x) => x.foo<int>; // Error.
+                         ^";
+static method test2(Never x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test2(Never x) => x.foo<int>; // Error.
+                       ^";
+static method test3(dynamic x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+Try changing the operand or remove the type arguments.
+test3(dynamic x) => x.toString<int>; // Error.
+                              ^";
+static method test4(Never x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test4(Never x) => x.toString<int>; // Error.
+                            ^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.outline.expect
new file mode 100644
index 0000000..a0dbfbd
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.outline.expect
@@ -0,0 +1,13 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method test1(dynamic x) → dynamic
+  ;
+static method test2(Never x) → dynamic
+  ;
+static method test3(dynamic x) → dynamic
+  ;
+static method test4(Never x) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.transformed.expect
new file mode 100644
index 0000000..ee9aed5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.transformed.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+// Try changing the operand or remove the type arguments.
+// test1(dynamic x) => x.foo<int>; // Error.
+//                          ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test2(Never x) => x.foo<int>; // Error.
+//                        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+// Try changing the operand or remove the type arguments.
+// test3(dynamic x) => x.toString<int>; // Error.
+//                               ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test4(Never x) => x.toString<int>; // Error.
+//                             ^
+//
+import self as self;
+
+static method test1(dynamic x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+Try changing the operand or remove the type arguments.
+test1(dynamic x) => x.foo<int>; // Error.
+                         ^";
+static method test2(Never x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test2(Never x) => x.foo<int>; // Error.
+                       ^";
+static method test3(dynamic x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+Try changing the operand or remove the type arguments.
+test3(dynamic x) => x.toString<int>; // Error.
+                              ^";
+static method test4(Never x) → dynamic
+  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test4(Never x) => x.toString<int>; // Error.
+                            ^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect
index efd5a53..ceaf4af 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect
@@ -92,12 +92,12 @@
 }
 
 constants  {
-  #C1 = tearoff self::C::stat
-  #C2 = partial-instantiation self::C::stat <core::int>
-  #C3 = tearoff self::M::mstat
-  #C4 = partial-instantiation self::M::mstat <core::int>
-  #C5 = tearoff self::Ext|estat
-  #C6 = partial-instantiation self::Ext|estat <core::int>
+  #C1 = static-tearoff self::C::stat
+  #C2 = instantiation self::C::stat <core::int>
+  #C3 = static-tearoff self::M::mstat
+  #C4 = instantiation self::M::mstat <core::int>
+  #C5 = static-tearoff self::Ext|estat
+  #C6 = instantiation self::Ext|estat <core::int>
   #C7 = TypeLiteralConstant(core::List<core::int>)
   #C8 = TypeLiteralConstant(core::List<core::List<core::int>>)
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect
index ba6e6f0..aa394b3 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect
@@ -100,12 +100,12 @@
 }
 
 constants  {
-  #C1 = tearoff self::C::stat
-  #C2 = partial-instantiation self::C::stat <core::int>
-  #C3 = tearoff self::M::mstat
-  #C4 = partial-instantiation self::M::mstat <core::int>
-  #C5 = tearoff self::Ext|estat
-  #C6 = partial-instantiation self::Ext|estat <core::int>
+  #C1 = static-tearoff self::C::stat
+  #C2 = instantiation self::C::stat <core::int>
+  #C3 = static-tearoff self::M::mstat
+  #C4 = instantiation self::M::mstat <core::int>
+  #C5 = static-tearoff self::Ext|estat
+  #C6 = instantiation self::Ext|estat <core::int>
   #C7 = TypeLiteralConstant(core::List<core::int>)
   #C8 = TypeLiteralConstant(core::List<core::List<core::int>>)
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect
index 70f8b63..ea4ceb1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect
@@ -92,12 +92,12 @@
 }
 
 constants  {
-  #C1 = tearoff self::C::stat
-  #C2 = partial-instantiation self::C::stat <core::int*>
-  #C3 = tearoff self::M::mstat
-  #C4 = partial-instantiation self::M::mstat <core::int*>
-  #C5 = tearoff self::Ext|estat
-  #C6 = partial-instantiation self::Ext|estat <core::int*>
+  #C1 = static-tearoff self::C::stat
+  #C2 = instantiation self::C::stat <core::int*>
+  #C3 = static-tearoff self::M::mstat
+  #C4 = instantiation self::M::mstat <core::int*>
+  #C5 = static-tearoff self::Ext|estat
+  #C6 = instantiation self::Ext|estat <core::int*>
   #C7 = TypeLiteralConstant(core::List<core::int*>*)
   #C8 = TypeLiteralConstant(core::List<core::List<core::int*>*>*)
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect
index 217f0b6..fc6c975 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect
@@ -100,12 +100,12 @@
 }
 
 constants  {
-  #C1 = tearoff self::C::stat
-  #C2 = partial-instantiation self::C::stat <core::int*>
-  #C3 = tearoff self::M::mstat
-  #C4 = partial-instantiation self::M::mstat <core::int*>
-  #C5 = tearoff self::Ext|estat
-  #C6 = partial-instantiation self::Ext|estat <core::int*>
+  #C1 = static-tearoff self::C::stat
+  #C2 = instantiation self::C::stat <core::int*>
+  #C3 = static-tearoff self::M::mstat
+  #C4 = instantiation self::M::mstat <core::int*>
+  #C5 = static-tearoff self::Ext|estat
+  #C6 = instantiation self::Ext|estat <core::int*>
   #C7 = TypeLiteralConstant(core::List<core::int*>*)
   #C8 = TypeLiteralConstant(core::List<core::List<core::int*>*>*)
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect
index 7d47228..630fe40 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect
@@ -105,8 +105,8 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = partial-instantiation self::id <core::int>
-  #C3 = tearoff self::boundedMethod
-  #C4 = partial-instantiation self::boundedMethod <core::String>
+  #C1 = static-tearoff self::id
+  #C2 = instantiation self::id <core::int>
+  #C3 = static-tearoff self::boundedMethod
+  #C4 = instantiation self::boundedMethod <core::String>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect
index 7d47228..630fe40 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect
@@ -105,8 +105,8 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = partial-instantiation self::id <core::int>
-  #C3 = tearoff self::boundedMethod
-  #C4 = partial-instantiation self::boundedMethod <core::String>
+  #C1 = static-tearoff self::id
+  #C2 = instantiation self::id <core::int>
+  #C3 = static-tearoff self::boundedMethod
+  #C4 = instantiation self::boundedMethod <core::String>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect
index c32e295..2e9d2db 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect
@@ -105,8 +105,8 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = partial-instantiation self::id <core::int*>
-  #C3 = tearoff self::boundedMethod
-  #C4 = partial-instantiation self::boundedMethod <core::String*>
+  #C1 = static-tearoff self::id
+  #C2 = instantiation self::id <core::int*>
+  #C3 = static-tearoff self::boundedMethod
+  #C4 = instantiation self::boundedMethod <core::String*>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect
index c32e295..2e9d2db 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect
@@ -105,8 +105,8 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = partial-instantiation self::id <core::int*>
-  #C3 = tearoff self::boundedMethod
-  #C4 = partial-instantiation self::boundedMethod <core::String*>
+  #C1 = static-tearoff self::id
+  #C2 = instantiation self::id <core::int*>
+  #C3 = static-tearoff self::boundedMethod
+  #C4 = instantiation self::boundedMethod <core::String*>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart
new file mode 100644
index 0000000..fe45034
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.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.
+
+class A {
+  A.new();
+}
+
+class B {
+  B();
+}
+
+class C {
+  C();
+  C.new(); // Error.
+}
+
+class D {
+  D.new();
+  D(); // Error.
+}
+
+class E1 {
+  E1._();
+  E1();
+  factory E1.new() => E1._(); // Error.
+}
+
+class E2 {
+  E2._();
+  factory E2.new() => E2._(); // Error.
+  E2();
+}
+
+class E3 {
+  E3._();
+  E3();
+  factory E3.new() = E3._; // Error.
+}
+
+class E4 {
+  E4._();
+  factory E4.new() = E4._;
+  E4(); // Error.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.expect
new file mode 100644
index 0000000..331bcc5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.expect
@@ -0,0 +1,101 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:15:3: Error: 'C' is already declared in this scope.
+//   C.new(); // Error.
+//   ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:14:3: Context: Previous declaration of 'C'.
+//   C();
+//   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:20:3: Error: 'D' is already declared in this scope.
+//   D(); // Error.
+//   ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:19:3: Context: Previous declaration of 'D'.
+//   D.new();
+//   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:26:11: Error: 'E1' is already declared in this scope.
+//   factory E1.new() => E1._(); // Error.
+//           ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:25:3: Context: Previous declaration of 'E1'.
+//   E1();
+//   ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:32:3: Error: 'E2' is already declared in this scope.
+//   E2();
+//   ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:31:11: Context: Previous declaration of 'E2'.
+//   factory E2.new() => E2._(); // Error.
+//           ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:38:11: Error: 'E3' is already declared in this scope.
+//   factory E3.new() = E3._; // Error.
+//           ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:37:3: Context: Previous declaration of 'E3'.
+//   E3();
+//   ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:44:3: Error: 'E4' is already declared in this scope.
+//   E4(); // Error.
+//   ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:43:11: Context: Previous declaration of 'E4'.
+//   factory E4.new() = E4._;
+//           ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object {
+  constructor •() → self::D
+    : super core::Object::•()
+    ;
+}
+class E1 extends core::Object {
+  constructor _() → self::E1
+    : super core::Object::•()
+    ;
+  constructor •() → self::E1
+    : super core::Object::•()
+    ;
+}
+class E2 extends core::Object {
+  constructor _() → self::E2
+    : super core::Object::•()
+    ;
+  static factory •() → self::E2
+    return new self::E2::_();
+}
+class E3 extends core::Object {
+  constructor _() → self::E3
+    : super core::Object::•()
+    ;
+  constructor •() → self::E3
+    : super core::Object::•()
+    ;
+}
+class E4 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::E4::•]/*isLegacy*/;
+  constructor _() → self::E4
+    : super core::Object::•()
+    ;
+  static factory •() → self::E4
+    let dynamic #redirecting_factory = self::E4::_ in invalid-expression;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.transformed.expect
new file mode 100644
index 0000000..fdbc0b6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.transformed.expect
@@ -0,0 +1,101 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:15:3: Error: 'C' is already declared in this scope.
+//   C.new(); // Error.
+//   ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:14:3: Context: Previous declaration of 'C'.
+//   C();
+//   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:20:3: Error: 'D' is already declared in this scope.
+//   D(); // Error.
+//   ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:19:3: Context: Previous declaration of 'D'.
+//   D.new();
+//   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:26:11: Error: 'E1' is already declared in this scope.
+//   factory E1.new() => E1._(); // Error.
+//           ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:25:3: Context: Previous declaration of 'E1'.
+//   E1();
+//   ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:32:3: Error: 'E2' is already declared in this scope.
+//   E2();
+//   ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:31:11: Context: Previous declaration of 'E2'.
+//   factory E2.new() => E2._(); // Error.
+//           ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:38:11: Error: 'E3' is already declared in this scope.
+//   factory E3.new() = E3._; // Error.
+//           ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:37:3: Context: Previous declaration of 'E3'.
+//   E3();
+//   ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:44:3: Error: 'E4' is already declared in this scope.
+//   E4(); // Error.
+//   ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:43:11: Context: Previous declaration of 'E4'.
+//   factory E4.new() = E4._;
+//           ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object {
+  constructor •() → self::D
+    : super core::Object::•()
+    ;
+}
+class E1 extends core::Object {
+  constructor _() → self::E1
+    : super core::Object::•()
+    ;
+  constructor •() → self::E1
+    : super core::Object::•()
+    ;
+}
+class E2 extends core::Object {
+  constructor _() → self::E2
+    : super core::Object::•()
+    ;
+  static factory •() → self::E2
+    return new self::E2::_();
+}
+class E3 extends core::Object {
+  constructor _() → self::E3
+    : super core::Object::•()
+    ;
+  constructor •() → self::E3
+    : super core::Object::•()
+    ;
+}
+class E4 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::E4::•]/*isLegacy*/;
+  constructor _() → self::E4
+    : super core::Object::•()
+    ;
+  static factory •() → self::E4
+    let Never #redirecting_factory = self::E4::_ in invalid-expression;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.textual_outline.expect
new file mode 100644
index 0000000..d6ac347
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.textual_outline.expect
@@ -0,0 +1,35 @@
+class A {
+  A.new();
+}
+class B {
+  B();
+}
+class C {
+  C();
+  C.new();
+}
+class D {
+  D.new();
+  D();
+}
+class E1 {
+  E1._();
+  E1();
+  factory E1.new() => E1._();
+}
+class E2 {
+  E2._();
+  factory E2.new() => E2._();
+  E2();
+}
+class E3 {
+  E3._();
+  E3();
+  factory E3.new() = E3._;
+}
+class E4 {
+  E4._();
+  factory E4.new() = E4._;
+  E4();
+}
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.expect
new file mode 100644
index 0000000..331bcc5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.expect
@@ -0,0 +1,101 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:15:3: Error: 'C' is already declared in this scope.
+//   C.new(); // Error.
+//   ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:14:3: Context: Previous declaration of 'C'.
+//   C();
+//   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:20:3: Error: 'D' is already declared in this scope.
+//   D(); // Error.
+//   ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:19:3: Context: Previous declaration of 'D'.
+//   D.new();
+//   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:26:11: Error: 'E1' is already declared in this scope.
+//   factory E1.new() => E1._(); // Error.
+//           ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:25:3: Context: Previous declaration of 'E1'.
+//   E1();
+//   ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:32:3: Error: 'E2' is already declared in this scope.
+//   E2();
+//   ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:31:11: Context: Previous declaration of 'E2'.
+//   factory E2.new() => E2._(); // Error.
+//           ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:38:11: Error: 'E3' is already declared in this scope.
+//   factory E3.new() = E3._; // Error.
+//           ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:37:3: Context: Previous declaration of 'E3'.
+//   E3();
+//   ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:44:3: Error: 'E4' is already declared in this scope.
+//   E4(); // Error.
+//   ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:43:11: Context: Previous declaration of 'E4'.
+//   factory E4.new() = E4._;
+//           ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object {
+  constructor •() → self::D
+    : super core::Object::•()
+    ;
+}
+class E1 extends core::Object {
+  constructor _() → self::E1
+    : super core::Object::•()
+    ;
+  constructor •() → self::E1
+    : super core::Object::•()
+    ;
+}
+class E2 extends core::Object {
+  constructor _() → self::E2
+    : super core::Object::•()
+    ;
+  static factory •() → self::E2
+    return new self::E2::_();
+}
+class E3 extends core::Object {
+  constructor _() → self::E3
+    : super core::Object::•()
+    ;
+  constructor •() → self::E3
+    : super core::Object::•()
+    ;
+}
+class E4 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::E4::•]/*isLegacy*/;
+  constructor _() → self::E4
+    : super core::Object::•()
+    ;
+  static factory •() → self::E4
+    let dynamic #redirecting_factory = self::E4::_ in invalid-expression;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.outline.expect
new file mode 100644
index 0000000..34ae47c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.outline.expect
@@ -0,0 +1,92 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:15:3: Error: 'C' is already declared in this scope.
+//   C.new(); // Error.
+//   ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:14:3: Context: Previous declaration of 'C'.
+//   C();
+//   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:20:3: Error: 'D' is already declared in this scope.
+//   D(); // Error.
+//   ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:19:3: Context: Previous declaration of 'D'.
+//   D.new();
+//   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:26:11: Error: 'E1' is already declared in this scope.
+//   factory E1.new() => E1._(); // Error.
+//           ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:25:3: Context: Previous declaration of 'E1'.
+//   E1();
+//   ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:32:3: Error: 'E2' is already declared in this scope.
+//   E2();
+//   ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:31:11: Context: Previous declaration of 'E2'.
+//   factory E2.new() => E2._(); // Error.
+//           ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:38:11: Error: 'E3' is already declared in this scope.
+//   factory E3.new() = E3._; // Error.
+//           ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:37:3: Context: Previous declaration of 'E3'.
+//   E3();
+//   ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:44:3: Error: 'E4' is already declared in this scope.
+//   E4(); // Error.
+//   ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:43:11: Context: Previous declaration of 'E4'.
+//   factory E4.new() = E4._;
+//           ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → self::A
+    ;
+}
+class B extends core::Object {
+  constructor •() → self::B
+    ;
+}
+class C extends core::Object {
+  constructor •() → self::C
+    ;
+}
+class D extends core::Object {
+  constructor •() → self::D
+    ;
+}
+class E1 extends core::Object {
+  constructor _() → self::E1
+    ;
+  constructor •() → self::E1
+    ;
+}
+class E2 extends core::Object {
+  constructor _() → self::E2
+    ;
+  static factory •() → self::E2
+    ;
+}
+class E3 extends core::Object {
+  constructor _() → self::E3
+    ;
+  constructor •() → self::E3
+    ;
+}
+class E4 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::E4::•]/*isLegacy*/;
+  constructor _() → self::E4
+    ;
+  static factory •() → self::E4
+    let dynamic #redirecting_factory = self::E4::_ in invalid-expression;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.transformed.expect
new file mode 100644
index 0000000..fdbc0b6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.transformed.expect
@@ -0,0 +1,101 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:15:3: Error: 'C' is already declared in this scope.
+//   C.new(); // Error.
+//   ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:14:3: Context: Previous declaration of 'C'.
+//   C();
+//   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:20:3: Error: 'D' is already declared in this scope.
+//   D(); // Error.
+//   ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:19:3: Context: Previous declaration of 'D'.
+//   D.new();
+//   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:26:11: Error: 'E1' is already declared in this scope.
+//   factory E1.new() => E1._(); // Error.
+//           ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:25:3: Context: Previous declaration of 'E1'.
+//   E1();
+//   ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:32:3: Error: 'E2' is already declared in this scope.
+//   E2();
+//   ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:31:11: Context: Previous declaration of 'E2'.
+//   factory E2.new() => E2._(); // Error.
+//           ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:38:11: Error: 'E3' is already declared in this scope.
+//   factory E3.new() = E3._; // Error.
+//           ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:37:3: Context: Previous declaration of 'E3'.
+//   E3();
+//   ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:44:3: Error: 'E4' is already declared in this scope.
+//   E4(); // Error.
+//   ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:43:11: Context: Previous declaration of 'E4'.
+//   factory E4.new() = E4._;
+//           ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object {
+  constructor •() → self::D
+    : super core::Object::•()
+    ;
+}
+class E1 extends core::Object {
+  constructor _() → self::E1
+    : super core::Object::•()
+    ;
+  constructor •() → self::E1
+    : super core::Object::•()
+    ;
+}
+class E2 extends core::Object {
+  constructor _() → self::E2
+    : super core::Object::•()
+    ;
+  static factory •() → self::E2
+    return new self::E2::_();
+}
+class E3 extends core::Object {
+  constructor _() → self::E3
+    : super core::Object::•()
+    ;
+  constructor •() → self::E3
+    : super core::Object::•()
+    ;
+}
+class E4 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::E4::•]/*isLegacy*/;
+  constructor _() → self::E4
+    : super core::Object::•()
+    ;
+  static factory •() → self::E4
+    let Never #redirecting_factory = self::E4::_ in invalid-expression;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.expect
index 3ac9d56..fdd4fb7 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.expect
@@ -4,14 +4,14 @@
 //
 // pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-//  - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+//  - 'X/*1*/' is from 'unknown'.
 //  - 'X/*2*/' is from 'unknown'.
 // A<X> Function<X>(X) test2() => A.foo2; // Error.
 //                                ^
 //
 // pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-//  - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+//  - 'X/*1*/' is from 'unknown'.
 //  - 'X/*2*/' is from 'unknown'.
 // A<X> Function<X>(X) test3() => A.new; // Error.
 //                                ^
@@ -68,26 +68,26 @@
     return new self::A::•<self::A::bar1::X%>();
 }
 static method test1() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
-  return self::A::foo1;
+  return #C1;
 static method test2() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test2() => A.foo2; // Error.
-                               ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C2) as{TypeError,ForNonNullableByDefault} Never;
 static method test3() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test3() => A.new; // Error.
-                               ^" in self::A::• as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C3) as{TypeError,ForNonNullableByDefault} Never;
 static method test4() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:15:32: Error: A value of type 'A<int> Function()' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test4() => A<int>.new; // Error.
-                               ^" in (self::A::•<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C4) as{TypeError,ForNonNullableByDefault} Never;
 static method test5() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:16:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -97,7 +97,7 @@
   return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:17:32: Error: A value of type 'A<int> Function(int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test6() => A<int>.foo1; // Error.
-                               ^" in (self::A::foo1<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C5) as{TypeError,ForNonNullableByDefault} Never;
 static method test7() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:18:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -107,23 +107,34 @@
   return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:19:32: Error: A value of type 'A<int> Function(int, int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test8() => A<int>.foo2; // Error.
-                               ^" in (self::A::foo2<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C6) as{TypeError,ForNonNullableByDefault} Never;
 static method test9() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:20:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
 A<X> Function<X>(X) test9() => A<int, String>.foo2; // Error.
                                ^";
 static method test10() → <X extends core::Object? = dynamic>() → self::A<X%>
-  return self::A::bar1;
+  return #C7;
 static method test11() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:22:33: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
  - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test11() => A.bar1; // Error.
-                                ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} Never;
+                                ^" in (#C7) as{TypeError,ForNonNullableByDefault} Never;
 static method test12() → () → self::A<core::int>
-  return self::A::bar1<core::int>;
+  return #C8;
 static method test13() → () → self::A<core::int>
-  return self::A::bar1<core::int>;
+  return #C8;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo1
+  #C2 = constructor-tearoff self::A::foo2
+  #C3 = constructor-tearoff self::A::•
+  #C4 = instantiation self::A::• <core::int>
+  #C5 = instantiation self::A::foo1 <core::int>
+  #C6 = instantiation self::A::foo2 <core::int>
+  #C7 = static-tearoff self::A::bar1
+  #C8 = instantiation self::A::bar1 <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.transformed.expect
index 3ac9d56..fdd4fb7 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.transformed.expect
@@ -4,14 +4,14 @@
 //
 // pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-//  - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+//  - 'X/*1*/' is from 'unknown'.
 //  - 'X/*2*/' is from 'unknown'.
 // A<X> Function<X>(X) test2() => A.foo2; // Error.
 //                                ^
 //
 // pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-//  - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+//  - 'X/*1*/' is from 'unknown'.
 //  - 'X/*2*/' is from 'unknown'.
 // A<X> Function<X>(X) test3() => A.new; // Error.
 //                                ^
@@ -68,26 +68,26 @@
     return new self::A::•<self::A::bar1::X%>();
 }
 static method test1() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
-  return self::A::foo1;
+  return #C1;
 static method test2() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test2() => A.foo2; // Error.
-                               ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C2) as{TypeError,ForNonNullableByDefault} Never;
 static method test3() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test3() => A.new; // Error.
-                               ^" in self::A::• as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C3) as{TypeError,ForNonNullableByDefault} Never;
 static method test4() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:15:32: Error: A value of type 'A<int> Function()' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test4() => A<int>.new; // Error.
-                               ^" in (self::A::•<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C4) as{TypeError,ForNonNullableByDefault} Never;
 static method test5() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:16:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -97,7 +97,7 @@
   return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:17:32: Error: A value of type 'A<int> Function(int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test6() => A<int>.foo1; // Error.
-                               ^" in (self::A::foo1<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C5) as{TypeError,ForNonNullableByDefault} Never;
 static method test7() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:18:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -107,23 +107,34 @@
   return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:19:32: Error: A value of type 'A<int> Function(int, int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test8() => A<int>.foo2; // Error.
-                               ^" in (self::A::foo2<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C6) as{TypeError,ForNonNullableByDefault} Never;
 static method test9() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:20:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
 A<X> Function<X>(X) test9() => A<int, String>.foo2; // Error.
                                ^";
 static method test10() → <X extends core::Object? = dynamic>() → self::A<X%>
-  return self::A::bar1;
+  return #C7;
 static method test11() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:22:33: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
  - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test11() => A.bar1; // Error.
-                                ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} Never;
+                                ^" in (#C7) as{TypeError,ForNonNullableByDefault} Never;
 static method test12() → () → self::A<core::int>
-  return self::A::bar1<core::int>;
+  return #C8;
 static method test13() → () → self::A<core::int>
-  return self::A::bar1<core::int>;
+  return #C8;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo1
+  #C2 = constructor-tearoff self::A::foo2
+  #C3 = constructor-tearoff self::A::•
+  #C4 = instantiation self::A::• <core::int>
+  #C5 = instantiation self::A::foo1 <core::int>
+  #C6 = instantiation self::A::foo2 <core::int>
+  #C7 = static-tearoff self::A::bar1
+  #C8 = instantiation self::A::bar1 <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.expect
index 3ac9d56..b0da904 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.expect
@@ -4,14 +4,14 @@
 //
 // pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-//  - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+//  - 'X/*1*/' is from 'unknown'.
 //  - 'X/*2*/' is from 'unknown'.
 // A<X> Function<X>(X) test2() => A.foo2; // Error.
 //                                ^
 //
 // pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-//  - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+//  - 'X/*1*/' is from 'unknown'.
 //  - 'X/*2*/' is from 'unknown'.
 // A<X> Function<X>(X) test3() => A.new; // Error.
 //                                ^
@@ -68,26 +68,26 @@
     return new self::A::•<self::A::bar1::X%>();
 }
 static method test1() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
-  return self::A::foo1;
+  return #C1;
 static method test2() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test2() => A.foo2; // Error.
-                               ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C2) as{TypeError,ForNonNullableByDefault} Never;
 static method test3() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test3() => A.new; // Error.
-                               ^" in self::A::• as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C3) as{TypeError,ForNonNullableByDefault} Never;
 static method test4() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:15:32: Error: A value of type 'A<int> Function()' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test4() => A<int>.new; // Error.
-                               ^" in (self::A::•<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C4) as{TypeError,ForNonNullableByDefault} Never;
 static method test5() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:16:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -97,7 +97,7 @@
   return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:17:32: Error: A value of type 'A<int> Function(int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test6() => A<int>.foo1; // Error.
-                               ^" in (self::A::foo1<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C5) as{TypeError,ForNonNullableByDefault} Never;
 static method test7() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:18:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -107,23 +107,34 @@
   return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:19:32: Error: A value of type 'A<int> Function(int, int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test8() => A<int>.foo2; // Error.
-                               ^" in (self::A::foo2<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C6) as{TypeError,ForNonNullableByDefault} Never;
 static method test9() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:20:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
 A<X> Function<X>(X) test9() => A<int, String>.foo2; // Error.
                                ^";
 static method test10() → <X extends core::Object? = dynamic>() → self::A<X%>
-  return self::A::bar1;
+  return #C7;
 static method test11() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:22:33: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
  - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test11() => A.bar1; // Error.
-                                ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} Never;
+                                ^" in (#C7) as{TypeError,ForNonNullableByDefault} Never;
 static method test12() → () → self::A<core::int>
-  return self::A::bar1<core::int>;
+  return #C8;
 static method test13() → () → self::A<core::int>
-  return self::A::bar1<core::int>;
+  return #C8;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo1
+  #C2 = constructor-tearoff self::A::foo2
+  #C3 = constructor-tearoff self::A::•
+  #C4 = instantiation self::A::• <core::int*>
+  #C5 = instantiation self::A::foo1 <core::int*>
+  #C6 = instantiation self::A::foo2 <core::int*>
+  #C7 = static-tearoff self::A::bar1
+  #C8 = instantiation self::A::bar1 <core::int*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.transformed.expect
index 3ac9d56..b0da904 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.transformed.expect
@@ -4,14 +4,14 @@
 //
 // pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-//  - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+//  - 'X/*1*/' is from 'unknown'.
 //  - 'X/*2*/' is from 'unknown'.
 // A<X> Function<X>(X) test2() => A.foo2; // Error.
 //                                ^
 //
 // pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-//  - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+//  - 'X/*1*/' is from 'unknown'.
 //  - 'X/*2*/' is from 'unknown'.
 // A<X> Function<X>(X) test3() => A.new; // Error.
 //                                ^
@@ -68,26 +68,26 @@
     return new self::A::•<self::A::bar1::X%>();
 }
 static method test1() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
-  return self::A::foo1;
+  return #C1;
 static method test2() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test2() => A.foo2; // Error.
-                               ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C2) as{TypeError,ForNonNullableByDefault} Never;
 static method test3() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test3() => A.new; // Error.
-                               ^" in self::A::• as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C3) as{TypeError,ForNonNullableByDefault} Never;
 static method test4() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:15:32: Error: A value of type 'A<int> Function()' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test4() => A<int>.new; // Error.
-                               ^" in (self::A::•<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C4) as{TypeError,ForNonNullableByDefault} Never;
 static method test5() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:16:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -97,7 +97,7 @@
   return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:17:32: Error: A value of type 'A<int> Function(int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test6() => A<int>.foo1; // Error.
-                               ^" in (self::A::foo1<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C5) as{TypeError,ForNonNullableByDefault} Never;
 static method test7() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:18:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -107,23 +107,34 @@
   return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:19:32: Error: A value of type 'A<int> Function(int, int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
 A<X> Function<X>(X) test8() => A<int>.foo2; // Error.
-                               ^" in (self::A::foo2<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+                               ^" in (#C6) as{TypeError,ForNonNullableByDefault} Never;
 static method test9() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:20:32: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
 A<X> Function<X>(X) test9() => A<int, String>.foo2; // Error.
                                ^";
 static method test10() → <X extends core::Object? = dynamic>() → self::A<X%>
-  return self::A::bar1;
+  return #C7;
 static method test11() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
   return let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:22:33: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
  - 'X/*1*/' is from 'unknown'.
  - 'X/*2*/' is from 'unknown'.
 A<X> Function<X>(X) test11() => A.bar1; // Error.
-                                ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} Never;
+                                ^" in (#C7) as{TypeError,ForNonNullableByDefault} Never;
 static method test12() → () → self::A<core::int>
-  return self::A::bar1<core::int>;
+  return #C8;
 static method test13() → () → self::A<core::int>
-  return self::A::bar1<core::int>;
+  return #C8;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo1
+  #C2 = constructor-tearoff self::A::foo2
+  #C3 = constructor-tearoff self::A::•
+  #C4 = instantiation self::A::• <core::int*>
+  #C5 = instantiation self::A::foo1 <core::int*>
+  #C6 = instantiation self::A::foo2 <core::int*>
+  #C7 = static-tearoff self::A::bar1
+  #C8 = instantiation self::A::bar1 <core::int*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart
index b668e20..ad3a27c 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart
@@ -19,4 +19,17 @@
 testNewExtraArgs() => A<int, String>.new; // Error.
 testBarExtraArgs() => A<int, String>.bar; // Error.
 
+method() {
+  var foo = A.foo; // Ok.
+  var fooArgs = A<int>.foo; // Ok.
+  var _new = A.new; // Ok.
+  var newArgs  = A<int>.new; // Ok.
+  var bar = A.bar; // Ok.
+  var barArgs = A<int>.bar; // Ok.
+
+  var fooExtraArgs = A<int, String>.foo; // Error.
+  var newExtraArgs = A<int, String>.new; // Error.
+  var barExtraArgs = A<int, String>.bar; // Error.
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.expect
index b9ace2c..8aa8628 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.expect
@@ -17,6 +17,21 @@
 // testBarExtraArgs() => A<int, String>.bar; // Error.
 //                       ^
 //
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var fooExtraArgs = A<int, String>.foo; // Error.
+//                      ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var newExtraArgs = A<int, String>.new; // Error.
+//                      ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var barExtraArgs = A<int, String>.bar; // Error.
+//                      ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -29,17 +44,17 @@
     return new self::A::•<self::A::bar::X%>();
 }
 static method testFoo() → dynamic
-  return self::A::foo;
+  return #C1;
 static method testFooArgs() → dynamic
-  return self::A::foo<core::int>;
+  return #C2;
 static method testNew() → dynamic
-  return self::A::•;
+  return #C3;
 static method testNewArgs() → dynamic
-  return self::A::•<core::int>;
+  return #C4;
 static method testBar() → dynamic
-  return self::A::bar;
+  return #C5;
 static method testBarArgs() → dynamic
-  return self::A::bar<core::int>;
+  return #C6;
 static method testFooExtraArgs() → dynamic
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:18:23: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -55,4 +70,33 @@
 Try removing the extra type arguments.
 testBarExtraArgs() => A<int, String>.bar; // Error.
                       ^";
+static method method() → dynamic {
+  <X extends core::Object? = dynamic>() → self::A<X%> foo = #C1;
+  () → self::A<core::int> fooArgs = #C2;
+  <X extends core::Object? = dynamic>() → self::A<X%> _new = #C3;
+  () → self::A<core::int> newArgs = #C4;
+  <X extends core::Object? = dynamic>() → self::A<X%> bar = #C5;
+  () → self::A<core::int> barArgs = #C6;
+  invalid-type fooExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var fooExtraArgs = A<int, String>.foo; // Error.
+                     ^";
+  invalid-type newExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var newExtraArgs = A<int, String>.new; // Error.
+                     ^";
+  invalid-type barExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var barExtraArgs = A<int, String>.bar; // Error.
+                     ^";
+}
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = instantiation self::A::foo <core::int>
+  #C3 = constructor-tearoff self::A::•
+  #C4 = instantiation self::A::• <core::int>
+  #C5 = static-tearoff self::A::bar
+  #C6 = instantiation self::A::bar <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.transformed.expect
index b9ace2c..8aa8628 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.transformed.expect
@@ -17,6 +17,21 @@
 // testBarExtraArgs() => A<int, String>.bar; // Error.
 //                       ^
 //
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var fooExtraArgs = A<int, String>.foo; // Error.
+//                      ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var newExtraArgs = A<int, String>.new; // Error.
+//                      ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var barExtraArgs = A<int, String>.bar; // Error.
+//                      ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -29,17 +44,17 @@
     return new self::A::•<self::A::bar::X%>();
 }
 static method testFoo() → dynamic
-  return self::A::foo;
+  return #C1;
 static method testFooArgs() → dynamic
-  return self::A::foo<core::int>;
+  return #C2;
 static method testNew() → dynamic
-  return self::A::•;
+  return #C3;
 static method testNewArgs() → dynamic
-  return self::A::•<core::int>;
+  return #C4;
 static method testBar() → dynamic
-  return self::A::bar;
+  return #C5;
 static method testBarArgs() → dynamic
-  return self::A::bar<core::int>;
+  return #C6;
 static method testFooExtraArgs() → dynamic
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:18:23: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -55,4 +70,33 @@
 Try removing the extra type arguments.
 testBarExtraArgs() => A<int, String>.bar; // Error.
                       ^";
+static method method() → dynamic {
+  <X extends core::Object? = dynamic>() → self::A<X%> foo = #C1;
+  () → self::A<core::int> fooArgs = #C2;
+  <X extends core::Object? = dynamic>() → self::A<X%> _new = #C3;
+  () → self::A<core::int> newArgs = #C4;
+  <X extends core::Object? = dynamic>() → self::A<X%> bar = #C5;
+  () → self::A<core::int> barArgs = #C6;
+  invalid-type fooExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var fooExtraArgs = A<int, String>.foo; // Error.
+                     ^";
+  invalid-type newExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var newExtraArgs = A<int, String>.new; // Error.
+                     ^";
+  invalid-type barExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var barExtraArgs = A<int, String>.bar; // Error.
+                     ^";
+}
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = instantiation self::A::foo <core::int>
+  #C3 = constructor-tearoff self::A::•
+  #C4 = instantiation self::A::• <core::int>
+  #C5 = static-tearoff self::A::bar
+  #C6 = instantiation self::A::bar <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.textual_outline.expect
index 4b026de..a5d04bf 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.textual_outline.expect
@@ -12,4 +12,5 @@
 testFooExtraArgs() => A<int, String>.foo;
 testNewExtraArgs() => A<int, String>.new;
 testBarExtraArgs() => A<int, String>.bar;
+method() {}
 main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.expect
index b9ace2c..c49c929 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.expect
@@ -17,6 +17,21 @@
 // testBarExtraArgs() => A<int, String>.bar; // Error.
 //                       ^
 //
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var fooExtraArgs = A<int, String>.foo; // Error.
+//                      ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var newExtraArgs = A<int, String>.new; // Error.
+//                      ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var barExtraArgs = A<int, String>.bar; // Error.
+//                      ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -29,17 +44,17 @@
     return new self::A::•<self::A::bar::X%>();
 }
 static method testFoo() → dynamic
-  return self::A::foo;
+  return #C1;
 static method testFooArgs() → dynamic
-  return self::A::foo<core::int>;
+  return #C2;
 static method testNew() → dynamic
-  return self::A::•;
+  return #C3;
 static method testNewArgs() → dynamic
-  return self::A::•<core::int>;
+  return #C4;
 static method testBar() → dynamic
-  return self::A::bar;
+  return #C5;
 static method testBarArgs() → dynamic
-  return self::A::bar<core::int>;
+  return #C6;
 static method testFooExtraArgs() → dynamic
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:18:23: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -55,4 +70,33 @@
 Try removing the extra type arguments.
 testBarExtraArgs() => A<int, String>.bar; // Error.
                       ^";
+static method method() → dynamic {
+  <X extends core::Object? = dynamic>() → self::A<X%> foo = #C1;
+  () → self::A<core::int> fooArgs = #C2;
+  <X extends core::Object? = dynamic>() → self::A<X%> _new = #C3;
+  () → self::A<core::int> newArgs = #C4;
+  <X extends core::Object? = dynamic>() → self::A<X%> bar = #C5;
+  () → self::A<core::int> barArgs = #C6;
+  invalid-type fooExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var fooExtraArgs = A<int, String>.foo; // Error.
+                     ^";
+  invalid-type newExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var newExtraArgs = A<int, String>.new; // Error.
+                     ^";
+  invalid-type barExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var barExtraArgs = A<int, String>.bar; // Error.
+                     ^";
+}
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = instantiation self::A::foo <core::int*>
+  #C3 = constructor-tearoff self::A::•
+  #C4 = instantiation self::A::• <core::int*>
+  #C5 = static-tearoff self::A::bar
+  #C6 = instantiation self::A::bar <core::int*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.outline.expect
index e5848bc..928b5e1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.outline.expect
@@ -28,5 +28,7 @@
   ;
 static method testBarExtraArgs() → dynamic
   ;
+static method method() → dynamic
+  ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.transformed.expect
index b9ace2c..c49c929 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.transformed.expect
@@ -17,6 +17,21 @@
 // testBarExtraArgs() => A<int, String>.bar; // Error.
 //                       ^
 //
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var fooExtraArgs = A<int, String>.foo; // Error.
+//                      ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var newExtraArgs = A<int, String>.new; // Error.
+//                      ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+//   var barExtraArgs = A<int, String>.bar; // Error.
+//                      ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -29,17 +44,17 @@
     return new self::A::•<self::A::bar::X%>();
 }
 static method testFoo() → dynamic
-  return self::A::foo;
+  return #C1;
 static method testFooArgs() → dynamic
-  return self::A::foo<core::int>;
+  return #C2;
 static method testNew() → dynamic
-  return self::A::•;
+  return #C3;
 static method testNewArgs() → dynamic
-  return self::A::•<core::int>;
+  return #C4;
 static method testBar() → dynamic
-  return self::A::bar;
+  return #C5;
 static method testBarArgs() → dynamic
-  return self::A::bar<core::int>;
+  return #C6;
 static method testFooExtraArgs() → dynamic
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:18:23: Error: Too many type arguments: 1 allowed, but 2 found.
 Try removing the extra type arguments.
@@ -55,4 +70,33 @@
 Try removing the extra type arguments.
 testBarExtraArgs() => A<int, String>.bar; // Error.
                       ^";
+static method method() → dynamic {
+  <X extends core::Object? = dynamic>() → self::A<X%> foo = #C1;
+  () → self::A<core::int> fooArgs = #C2;
+  <X extends core::Object? = dynamic>() → self::A<X%> _new = #C3;
+  () → self::A<core::int> newArgs = #C4;
+  <X extends core::Object? = dynamic>() → self::A<X%> bar = #C5;
+  () → self::A<core::int> barArgs = #C6;
+  invalid-type fooExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var fooExtraArgs = A<int, String>.foo; // Error.
+                     ^";
+  invalid-type newExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var newExtraArgs = A<int, String>.new; // Error.
+                     ^";
+  invalid-type barExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+  var barExtraArgs = A<int, String>.bar; // Error.
+                     ^";
+}
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = instantiation self::A::foo <core::int*>
+  #C3 = constructor-tearoff self::A::•
+  #C4 = instantiation self::A::• <core::int*>
+  #C5 = static-tearoff self::A::bar
+  #C6 = instantiation self::A::bar <core::int*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect
index 8df289d3..5edad1d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect
@@ -46,7 +46,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = partial-instantiation self::id <core::int>
-  #C3 = partial-instantiation self::id <core::String>
+  #C1 = static-tearoff self::id
+  #C2 = instantiation self::id <core::int>
+  #C3 = instantiation self::id <core::String>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect
index 3afa4cf..f2e9fea 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect
@@ -46,9 +46,9 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = partial-instantiation self::id <core::int>
-  #C3 = partial-instantiation self::id <core::String>
+  #C1 = static-tearoff self::id
+  #C2 = instantiation self::id <core::int>
+  #C3 = instantiation self::id <core::String>
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect
index c33a355..7061d34 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect
@@ -46,7 +46,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = partial-instantiation self::id <core::int*>
-  #C3 = partial-instantiation self::id <core::String*>
+  #C1 = static-tearoff self::id
+  #C2 = instantiation self::id <core::int*>
+  #C3 = instantiation self::id <core::String*>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
index 9cdfa3c..8923c73 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
@@ -46,9 +46,9 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = partial-instantiation self::id <core::int*>
-  #C3 = partial-instantiation self::id <core::String*>
+  #C1 = static-tearoff self::id
+  #C2 = instantiation self::id <core::int*>
+  #C3 = instantiation self::id <core::String*>
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart
new file mode 100644
index 0000000..1750b68
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart
@@ -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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+  print('inSoundMode: $inSoundMode');
+  testInferred();
+}
+
+class Class1 {
+  int field;
+
+  Class1(this.field);
+}
+
+abstract class Interface2 {
+  int get field;
+}
+
+class Class2 implements Interface2 {
+  final field;
+
+  Class2(this.field);
+}
+
+var Class1_new = Class1.new;
+var Class2_new = Class2.new;
+
+testInferred() {
+  var f1a = Class1.new;
+  expect(true, f1a is Class1 Function(int));
+  expect(false, f1a is Class1 Function(String));
+  var c1a = f1a(0);
+  expect(true, c1a is Class1);
+  () {
+    f1a(''); // error
+  };
+
+  dynamic f1b = Class1.new;
+  var c1b = f1b(0);
+  expect(true, c1b is Class1);
+  throws(() => f1b(''));
+
+  var f2a = Class2.new;
+  expect(true, f2a is Class2 Function(int));
+  expect(false, f2a is Class2 Function(String));
+  var c2a = f2a(0);
+  expect(true, c2a is Class2);
+  () {
+    f2a(''); // error
+  };
+
+  dynamic f2b = Class2.new;
+  var c2b = f2b(0);
+  expect(true, c2b is Class2);
+  throws(() => f2b(''));
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.expect
new file mode 100644
index 0000000..e2692d7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.expect
@@ -0,0 +1,93 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+//     f1a(''); // error
+//         ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+//     f2a(''); // error
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int field;
+  constructor •(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+}
+abstract class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  abstract get field() → core::int;
+}
+class Class2 extends core::Object implements self::Interface2 {
+  final field core::int field;
+  constructor •(core::int field) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testInferred();
+}
+static method testInferred() → dynamic {
+  (core::int) → self::Class1 f1a = #C1;
+  self::expect(true, f1a is{ForNonNullableByDefault} (core::int) → self::Class1);
+  self::expect(false, f1a is{ForNonNullableByDefault} (core::String) → self::Class1);
+  self::Class1 c1a = f1a(0){(core::int) → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  () → Null {
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(''); // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
+  };
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call(0);
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::throws(() → dynamic => f1b{dynamic}.call(""));
+  (core::int) → self::Class2 f2a = #C2;
+  self::expect(true, f2a is{ForNonNullableByDefault} (core::int) → self::Class2);
+  self::expect(false, f2a is{ForNonNullableByDefault} (core::String) → self::Class2);
+  self::Class2 c2a = f2a(0){(core::int) → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  () → Null {
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(''); // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
+  };
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call(0);
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::throws(() → dynamic => f2b{dynamic}.call(""));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = constructor-tearoff self::Class1::•
+  #C2 = constructor-tearoff self::Class2::•
+  #C3 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..6a6db60
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,93 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+//     f1a(''); // error
+//         ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+//     f2a(''); // error
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int field;
+  constructor •(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+}
+abstract class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  abstract get field() → core::int;
+}
+class Class2 extends core::Object implements self::Interface2 {
+  final field core::int field;
+  constructor •(core::int field) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testInferred();
+}
+static method testInferred() → dynamic {
+  (core::int) → self::Class1 f1a = #C1;
+  self::expect(true, f1a is{ForNonNullableByDefault} (core::int) → self::Class1);
+  self::expect(false, f1a is{ForNonNullableByDefault} (core::String) → self::Class1);
+  self::Class1 c1a = f1a(0){(core::int) → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  () → Null {
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(''); // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
+  };
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call(0);
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::throws(() → dynamic => f1b{dynamic}.call(""));
+  (core::int) → self::Class2 f2a = #C2;
+  self::expect(true, f2a is{ForNonNullableByDefault} (core::int) → self::Class2);
+  self::expect(false, f2a is{ForNonNullableByDefault} (core::String) → self::Class2);
+  self::Class2 c2a = f2a(0){(core::int) → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  () → Null {
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(''); // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
+  };
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call(0);
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::throws(() → dynamic => f2b{dynamic}.call(""));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = constructor-tearoff self::Class1::•
+  #C2 = constructor-tearoff self::Class2::•
+  #C3 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..94115d1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.textual_outline.expect
@@ -0,0 +1,18 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+class Class1 {
+  int field;
+  Class1(this.field);
+}
+abstract class Interface2 {
+  int get field;
+}
+class Class2 implements Interface2 {
+  final field;
+  Class2(this.field);
+}
+var Class1_new = Class1.new;
+var Class2_new = Class2.new;
+testInferred() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.expect
new file mode 100644
index 0000000..e2692d7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.expect
@@ -0,0 +1,93 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+//     f1a(''); // error
+//         ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+//     f2a(''); // error
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int field;
+  constructor •(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+}
+abstract class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  abstract get field() → core::int;
+}
+class Class2 extends core::Object implements self::Interface2 {
+  final field core::int field;
+  constructor •(core::int field) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testInferred();
+}
+static method testInferred() → dynamic {
+  (core::int) → self::Class1 f1a = #C1;
+  self::expect(true, f1a is{ForNonNullableByDefault} (core::int) → self::Class1);
+  self::expect(false, f1a is{ForNonNullableByDefault} (core::String) → self::Class1);
+  self::Class1 c1a = f1a(0){(core::int) → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  () → Null {
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(''); // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
+  };
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call(0);
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::throws(() → dynamic => f1b{dynamic}.call(""));
+  (core::int) → self::Class2 f2a = #C2;
+  self::expect(true, f2a is{ForNonNullableByDefault} (core::int) → self::Class2);
+  self::expect(false, f2a is{ForNonNullableByDefault} (core::String) → self::Class2);
+  self::Class2 c2a = f2a(0){(core::int) → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  () → Null {
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(''); // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
+  };
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call(0);
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::throws(() → dynamic => f2b{dynamic}.call(""));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = constructor-tearoff self::Class1::•
+  #C2 = constructor-tearoff self::Class2::•
+  #C3 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..73a2bca
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.outline.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int field;
+  constructor •(core::int field) → self::Class1
+    ;
+}
+abstract class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    ;
+  abstract get field() → core::int;
+}
+class Class2 extends core::Object implements self::Interface2 {
+  final field core::int field;
+  constructor •(core::int field) → self::Class2
+    ;
+}
+static final field core::bool inSoundMode;
+static field (core::int) → self::Class1 Class1_new;
+static field (core::int) → self::Class2 Class2_new;
+static method main() → dynamic
+  ;
+static method testInferred() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..6a6db60
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,93 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+//     f1a(''); // error
+//         ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+//     f2a(''); // error
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int field;
+  constructor •(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+}
+abstract class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  abstract get field() → core::int;
+}
+class Class2 extends core::Object implements self::Interface2 {
+  final field core::int field;
+  constructor •(core::int field) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testInferred();
+}
+static method testInferred() → dynamic {
+  (core::int) → self::Class1 f1a = #C1;
+  self::expect(true, f1a is{ForNonNullableByDefault} (core::int) → self::Class1);
+  self::expect(false, f1a is{ForNonNullableByDefault} (core::String) → self::Class1);
+  self::Class1 c1a = f1a(0){(core::int) → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  () → Null {
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(''); // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
+  };
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call(0);
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::throws(() → dynamic => f1b{dynamic}.call(""));
+  (core::int) → self::Class2 f2a = #C2;
+  self::expect(true, f2a is{ForNonNullableByDefault} (core::int) → self::Class2);
+  self::expect(false, f2a is{ForNonNullableByDefault} (core::String) → self::Class2);
+  self::Class2 c2a = f2a(0){(core::int) → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  () → Null {
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(''); // error
+        ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
+  };
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call(0);
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::throws(() → dynamic => f2b{dynamic}.call(""));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = constructor-tearoff self::Class1::•
+  #C2 = constructor-tearoff self::Class2::•
+  #C3 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart
new file mode 100644
index 0000000..601da2a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart
@@ -0,0 +1,73 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+class A<T> {}
+
+typedef F<X extends num> = A<X>;
+typedef G<Y> = A<int>;
+typedef H<X, Y> = A<X>;
+
+const f1a = A<int>.new;
+const f1b = F<int>.new;
+const A<int> Function() f1c = F.new;
+
+const g1a = A<int>.new;
+const g1b = G<String>.new;
+const A<int> Function() g1c = G.new;
+
+const h1a = A<int>.new;
+const h1b = H<int, String>.new;
+const A<int> Function() h1c = H.new;
+
+main() {
+  test<int>();
+
+  identical(f1a, f1b);
+  identical(f1a, f1c);
+
+  identical(g1a, g1b);
+  identical(g1a, g1c);
+
+  identical(h1a, h1b);
+  identical(h1a, h1c);
+}
+
+test<T extends num>() {
+  var f2a = A<T>.new;
+  var f2b = F<T>.new;
+  A<T> Function() f2c = F.new;
+
+  var g2a = A<int>.new;
+  var g2b = G<T>.new;
+  A<int> Function() g2c = G.new;
+
+  var h2a = A<T>.new;
+  var h2b = H<T, String>.new;
+  A<T> Function() h2c = H.new;
+
+  // TODO(johnniwinther): Enable these if structural equality is supported at
+  // runtime.
+  /*expect(f1a, f2a);
+  expect(f2a, f2b);
+  expect(f2a, f2c);*/
+
+  expect(g1a, g2a);
+  expect(g2a, g2b);
+  if (inSoundMode) {
+    // In weak mode type arguments of constants are weakened.
+    expect(g2a, g2c);
+  }
+
+  // TODO(johnniwinther): Enable these if structural equality is supported at
+  // runtime.
+  /*expect(h1a, h2a);
+  expect(h2a, h2b);
+  expect(h2a, h2c);*/
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.expect
new file mode 100644
index 0000000..ce055a4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.expect
@@ -0,0 +1,56 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C2;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+  self::test<core::int>();
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+  () → self::A<self::test::T> f2a = #C1<self::test::T>;
+  () → self::A<self::test::T> f2b = #C1<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<core::int> g2a = #C2;
+  () → self::A<core::int> g2b = #C2;
+  () → self::A<core::int> g2c = #C2;
+  () → self::A<self::test::T> h2a = #C1<self::test::T>;
+  () → self::A<self::test::T> h2b = #C1<self::test::T>;
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
+  self::expect(#C2, g2a);
+  self::expect(g2a, g2b);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.transformed.expect
new file mode 100644
index 0000000..0f0953f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.transformed.expect
@@ -0,0 +1,65 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C2;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+  self::test<core::int>();
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+  () → self::A<self::test::T> f2a = #C1<self::test::T>;
+  () → self::A<self::test::T> f2b = #C1<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<core::int> g2a = #C2;
+  () → self::A<core::int> g2b = #C2;
+  () → self::A<core::int> g2c = #C2;
+  () → self::A<self::test::T> h2a = #C1<self::test::T>;
+  () → self::A<self::test::T> h2b = #C1<self::test::T>;
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
+  self::expect(#C2, g2a);
+  self::expect(g2a, g2b);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:28:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:31:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:34:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:35:3 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 33, effectively constant: 6
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.textual_outline.expect
new file mode 100644
index 0000000..71dbef8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.textual_outline.expect
@@ -0,0 +1,17 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+class A<T> {}
+typedef F<X extends num> = A<X>;
+typedef G<Y> = A<int>;
+typedef H<X, Y> = A<X>;
+const f1a = A<int>.new;
+const f1b = F<int>.new;
+const A<int> Function() f1c = F.new;
+const g1a = A<int>.new;
+const g1b = G<String>.new;
+const A<int> Function() g1c = G.new;
+const h1a = A<int>.new;
+const h1b = H<int, String>.new;
+const A<int> Function() h1c = H.new;
+main() {}
+test<T extends num>() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.expect
new file mode 100644
index 0000000..7f08054
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.expect
@@ -0,0 +1,57 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C3;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+  self::test<core::int>();
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C3);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+  () → self::A<self::test::T> f2a = #C1<self::test::T>;
+  () → self::A<self::test::T> f2b = #C1<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<core::int> g2a = #C2;
+  () → self::A<core::int> g2b = #C2;
+  () → self::A<core::int> g2c = #C3;
+  () → self::A<self::test::T> h2a = #C1<self::test::T>;
+  () → self::A<self::test::T> h2b = #C1<self::test::T>;
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
+  self::expect(#C2, g2a);
+  self::expect(g2a, g2b);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int*>
+  #C3 = instantiation self::A::• <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.outline.expect
new file mode 100644
index 0000000..54daed1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.outline.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
+    ;
+}
+static final field core::bool inSoundMode;
+static const field () → self::A<core::int> f1a = self::A::•<core::int>;
+static const field () → self::A<core::int> f1b = self::A::•<core::int>;
+static const field () → self::A<core::int> f1c = <X extends core::num>.(self::A::•<X>)<core::int>;
+static const field () → self::A<core::int> g1a = self::A::•<core::int>;
+static const field () → self::A<core::int> g1b = self::A::•<core::int>;
+static const field () → self::A<core::int> g1c = <unrelated Y extends core::Object? = dynamic>.(self::A::•<core::int>)<dynamic>;
+static const field () → self::A<core::int> h1a = self::A::•<core::int>;
+static const field () → self::A<core::int> h1b = self::A::•<core::int>;
+static const field () → self::A<core::int> h1c = <X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>.(self::A::•<X%>)<core::int, dynamic>;
+static method main() → dynamic
+  ;
+static method test<T extends core::num>() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:13:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:14:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:15:31 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:17:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:18:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:19:31 -> InstantiationConstant(A.<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:21:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:22:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:23:31 -> InstantiationConstant(A.<int*>)
+Extra constant evaluation: evaluated: 9, effectively constant: 9
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.transformed.expect
new file mode 100644
index 0000000..4b8f00e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.transformed.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C3;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+  self::test<core::int>();
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C3);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+  () → self::A<self::test::T> f2a = #C1<self::test::T>;
+  () → self::A<self::test::T> f2b = #C1<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<core::int> g2a = #C2;
+  () → self::A<core::int> g2b = #C2;
+  () → self::A<core::int> g2c = #C3;
+  () → self::A<self::test::T> h2a = #C1<self::test::T>;
+  () → self::A<self::test::T> h2b = #C1<self::test::T>;
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
+  self::expect(#C2, g2a);
+  self::expect(g2a, g2b);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int*>
+  #C3 = instantiation self::A::• <core::int>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:28:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:31:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:34:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:35:3 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 33, effectively constant: 6
diff --git a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.expect
index 33ffc2b..547e506 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.expect
@@ -7,18 +7,12 @@
 // Try specifying type arguments explicitly so that they conform to the bounds.
 // A<dynamic> Function(String) test5() => A.foo; // Error.
 //                                        ^
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
-// class A<X extends num> {
-//         ^
 //
 // pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
 // Try specifying type arguments explicitly so that they conform to the bounds.
 // A<dynamic> Function(String) test6() => A.new; // Error.
 //                                        ^
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
-// class A<X extends num> {
-//         ^
 //
 // pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:23:41: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
@@ -38,27 +32,42 @@
     return new self::A::•<self::A::bar::X>(x);
 }
 static method test1() → (core::num) → self::A<core::num>
-  return self::A::foo<core::num>;
+  return #C2;
 static method test2() → (core::int) → self::A<core::int>
-  return self::A::foo<core::int>;
+  return #C3;
 static method test3() → (core::num) → self::A<core::num>
-  return self::A::•<core::num>;
+  return #C5;
 static method test4() → (core::int) → self::A<core::int>
-  return self::A::•<core::int>;
+  return #C6;
 static method test5() → (core::String) → self::A<dynamic>
-  return self::A::foo<core::String>;
+  return #C7;
 static method test6() → (core::String) → self::A<dynamic>
-  return self::A::•<core::String>;
+  return #C8;
 static method test7() → (core::num) → self::A<dynamic>
-  return self::A::foo<core::num>;
+  return #C2;
 static method test8() → (core::num) → self::A<dynamic>
-  return self::A::•<core::num>;
+  return #C5;
 static method test9() → (core::num) → self::A<core::num>
-  return self::A::bar<core::num>;
+  return #C10;
 static method test10() → (core::int) → self::A<core::int>
-  return self::A::bar<core::int>;
+  return #C11;
 static method test11() → (core::String) → self::A<dynamic>
-  return self::A::bar<core::String>;
+  return #C12;
 static method test12() → (core::num) → self::A<dynamic>
-  return self::A::bar<core::num>;
+  return #C10;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = instantiation self::A::foo <core::num>
+  #C3 = instantiation self::A::foo <core::int>
+  #C4 = constructor-tearoff self::A::•
+  #C5 = instantiation self::A::• <core::num>
+  #C6 = instantiation self::A::• <core::int>
+  #C7 = instantiation self::A::foo <core::String>
+  #C8 = instantiation self::A::• <core::String>
+  #C9 = static-tearoff self::A::bar
+  #C10 = instantiation self::A::bar <core::num>
+  #C11 = instantiation self::A::bar <core::int>
+  #C12 = instantiation self::A::bar <core::String>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.transformed.expect
index 3bcaa2b..547e506 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.transformed.expect
@@ -2,37 +2,23 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:10:35: Error: Getter not found: 'foo'.
-// A<num> Function(num) test1() => A.foo; // Ok.
-//                                   ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:11:35: Error: Getter not found: 'foo'.
-// A<int> Function(int) test2() => A.foo; // Ok.
-//                                   ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:12:35: Error: Getter not found: 'new'.
-// A<num> Function(num) test3() => A.new; // Ok.
-//                                   ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:13:35: Error: Getter not found: 'new'.
-// A<int> Function(int) test4() => A.new; // Ok.
-//                                   ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:15:42: Error: Getter not found: 'foo'.
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+//  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
 // A<dynamic> Function(String) test5() => A.foo; // Error.
-//                                          ^^^
+//                                        ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:42: Error: Getter not found: 'new'.
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+//  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
 // A<dynamic> Function(String) test6() => A.new; // Error.
-//                                          ^^^
+//                                        ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:44: Error: Getter not found: 'foo'.
-// A<dynamic> Function(num) test7() => A<num>.foo; // Error.
-//                                            ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:18:44: Error: Getter not found: 'new'.
-// A<dynamic> Function(num) test8() => A<num>.new; // Error.
-//                                            ^^^
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:23:41: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+//  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// A<dynamic> Function(String) test11() => A.bar; // Error.
+//                                         ^
 //
 import self as self;
 import "dart:core" as core;
@@ -42,37 +28,46 @@
     : super core::Object::•() {}
   constructor •(self::A::X x) → self::A<self::A::X>
     : super core::Object::•() {}
+  static factory bar<X extends core::num>(self::A::bar::X x) → self::A<self::A::bar::X>
+    return new self::A::•<self::A::bar::X>(x);
 }
 static method test1() → (core::num) → self::A<core::num>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:10:35: Error: Getter not found: 'foo'.
-A<num> Function(num) test1() => A.foo; // Ok.
-                                  ^^^";
+  return #C2;
 static method test2() → (core::int) → self::A<core::int>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:11:35: Error: Getter not found: 'foo'.
-A<int> Function(int) test2() => A.foo; // Ok.
-                                  ^^^";
+  return #C3;
 static method test3() → (core::num) → self::A<core::num>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:12:35: Error: Getter not found: 'new'.
-A<num> Function(num) test3() => A.new; // Ok.
-                                  ^^^";
+  return #C5;
 static method test4() → (core::int) → self::A<core::int>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:13:35: Error: Getter not found: 'new'.
-A<int> Function(int) test4() => A.new; // Ok.
-                                  ^^^";
+  return #C6;
 static method test5() → (core::String) → self::A<dynamic>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:15:42: Error: Getter not found: 'foo'.
-A<dynamic> Function(String) test5() => A.foo; // Error.
-                                         ^^^";
+  return #C7;
 static method test6() → (core::String) → self::A<dynamic>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:42: Error: Getter not found: 'new'.
-A<dynamic> Function(String) test6() => A.new; // Error.
-                                         ^^^";
+  return #C8;
 static method test7() → (core::num) → self::A<dynamic>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:44: Error: Getter not found: 'foo'.
-A<dynamic> Function(num) test7() => A<num>.foo; // Error.
-                                           ^^^";
+  return #C2;
 static method test8() → (core::num) → self::A<dynamic>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:18:44: Error: Getter not found: 'new'.
-A<dynamic> Function(num) test8() => A<num>.new; // Error.
-                                           ^^^";
+  return #C5;
+static method test9() → (core::num) → self::A<core::num>
+  return #C10;
+static method test10() → (core::int) → self::A<core::int>
+  return #C11;
+static method test11() → (core::String) → self::A<dynamic>
+  return #C12;
+static method test12() → (core::num) → self::A<dynamic>
+  return #C10;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = instantiation self::A::foo <core::num>
+  #C3 = instantiation self::A::foo <core::int>
+  #C4 = constructor-tearoff self::A::•
+  #C5 = instantiation self::A::• <core::num>
+  #C6 = instantiation self::A::• <core::int>
+  #C7 = instantiation self::A::foo <core::String>
+  #C8 = instantiation self::A::• <core::String>
+  #C9 = static-tearoff self::A::bar
+  #C10 = instantiation self::A::bar <core::num>
+  #C11 = instantiation self::A::bar <core::int>
+  #C12 = instantiation self::A::bar <core::String>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.expect
index 33ffc2b..8f0ed57 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.expect
@@ -7,18 +7,12 @@
 // Try specifying type arguments explicitly so that they conform to the bounds.
 // A<dynamic> Function(String) test5() => A.foo; // Error.
 //                                        ^
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
-// class A<X extends num> {
-//         ^
 //
 // pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
 // Try specifying type arguments explicitly so that they conform to the bounds.
 // A<dynamic> Function(String) test6() => A.new; // Error.
 //                                        ^
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
-// class A<X extends num> {
-//         ^
 //
 // pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:23:41: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
 //  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
@@ -38,27 +32,42 @@
     return new self::A::•<self::A::bar::X>(x);
 }
 static method test1() → (core::num) → self::A<core::num>
-  return self::A::foo<core::num>;
+  return #C2;
 static method test2() → (core::int) → self::A<core::int>
-  return self::A::foo<core::int>;
+  return #C3;
 static method test3() → (core::num) → self::A<core::num>
-  return self::A::•<core::num>;
+  return #C5;
 static method test4() → (core::int) → self::A<core::int>
-  return self::A::•<core::int>;
+  return #C6;
 static method test5() → (core::String) → self::A<dynamic>
-  return self::A::foo<core::String>;
+  return #C7;
 static method test6() → (core::String) → self::A<dynamic>
-  return self::A::•<core::String>;
+  return #C8;
 static method test7() → (core::num) → self::A<dynamic>
-  return self::A::foo<core::num>;
+  return #C2;
 static method test8() → (core::num) → self::A<dynamic>
-  return self::A::•<core::num>;
+  return #C5;
 static method test9() → (core::num) → self::A<core::num>
-  return self::A::bar<core::num>;
+  return #C10;
 static method test10() → (core::int) → self::A<core::int>
-  return self::A::bar<core::int>;
+  return #C11;
 static method test11() → (core::String) → self::A<dynamic>
-  return self::A::bar<core::String>;
+  return #C12;
 static method test12() → (core::num) → self::A<dynamic>
-  return self::A::bar<core::num>;
+  return #C10;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = instantiation self::A::foo <core::num*>
+  #C3 = instantiation self::A::foo <core::int*>
+  #C4 = constructor-tearoff self::A::•
+  #C5 = instantiation self::A::• <core::num*>
+  #C6 = instantiation self::A::• <core::int*>
+  #C7 = instantiation self::A::foo <core::String*>
+  #C8 = instantiation self::A::• <core::String*>
+  #C9 = static-tearoff self::A::bar
+  #C10 = instantiation self::A::bar <core::num*>
+  #C11 = instantiation self::A::bar <core::int*>
+  #C12 = instantiation self::A::bar <core::String*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.transformed.expect
index 3bcaa2b..8f0ed57 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.transformed.expect
@@ -2,37 +2,23 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:10:35: Error: Getter not found: 'foo'.
-// A<num> Function(num) test1() => A.foo; // Ok.
-//                                   ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:11:35: Error: Getter not found: 'foo'.
-// A<int> Function(int) test2() => A.foo; // Ok.
-//                                   ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:12:35: Error: Getter not found: 'new'.
-// A<num> Function(num) test3() => A.new; // Ok.
-//                                   ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:13:35: Error: Getter not found: 'new'.
-// A<int> Function(int) test4() => A.new; // Ok.
-//                                   ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:15:42: Error: Getter not found: 'foo'.
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+//  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
 // A<dynamic> Function(String) test5() => A.foo; // Error.
-//                                          ^^^
+//                                        ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:42: Error: Getter not found: 'new'.
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+//  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
 // A<dynamic> Function(String) test6() => A.new; // Error.
-//                                          ^^^
+//                                        ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:44: Error: Getter not found: 'foo'.
-// A<dynamic> Function(num) test7() => A<num>.foo; // Error.
-//                                            ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:18:44: Error: Getter not found: 'new'.
-// A<dynamic> Function(num) test8() => A<num>.new; // Error.
-//                                            ^^^
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:23:41: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+//  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// A<dynamic> Function(String) test11() => A.bar; // Error.
+//                                         ^
 //
 import self as self;
 import "dart:core" as core;
@@ -42,37 +28,46 @@
     : super core::Object::•() {}
   constructor •(self::A::X x) → self::A<self::A::X>
     : super core::Object::•() {}
+  static factory bar<X extends core::num>(self::A::bar::X x) → self::A<self::A::bar::X>
+    return new self::A::•<self::A::bar::X>(x);
 }
 static method test1() → (core::num) → self::A<core::num>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:10:35: Error: Getter not found: 'foo'.
-A<num> Function(num) test1() => A.foo; // Ok.
-                                  ^^^";
+  return #C2;
 static method test2() → (core::int) → self::A<core::int>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:11:35: Error: Getter not found: 'foo'.
-A<int> Function(int) test2() => A.foo; // Ok.
-                                  ^^^";
+  return #C3;
 static method test3() → (core::num) → self::A<core::num>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:12:35: Error: Getter not found: 'new'.
-A<num> Function(num) test3() => A.new; // Ok.
-                                  ^^^";
+  return #C5;
 static method test4() → (core::int) → self::A<core::int>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:13:35: Error: Getter not found: 'new'.
-A<int> Function(int) test4() => A.new; // Ok.
-                                  ^^^";
+  return #C6;
 static method test5() → (core::String) → self::A<dynamic>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:15:42: Error: Getter not found: 'foo'.
-A<dynamic> Function(String) test5() => A.foo; // Error.
-                                         ^^^";
+  return #C7;
 static method test6() → (core::String) → self::A<dynamic>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:42: Error: Getter not found: 'new'.
-A<dynamic> Function(String) test6() => A.new; // Error.
-                                         ^^^";
+  return #C8;
 static method test7() → (core::num) → self::A<dynamic>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:44: Error: Getter not found: 'foo'.
-A<dynamic> Function(num) test7() => A<num>.foo; // Error.
-                                           ^^^";
+  return #C2;
 static method test8() → (core::num) → self::A<dynamic>
-  return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:18:44: Error: Getter not found: 'new'.
-A<dynamic> Function(num) test8() => A<num>.new; // Error.
-                                           ^^^";
+  return #C5;
+static method test9() → (core::num) → self::A<core::num>
+  return #C10;
+static method test10() → (core::int) → self::A<core::int>
+  return #C11;
+static method test11() → (core::String) → self::A<dynamic>
+  return #C12;
+static method test12() → (core::num) → self::A<dynamic>
+  return #C10;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = instantiation self::A::foo <core::num*>
+  #C3 = instantiation self::A::foo <core::int*>
+  #C4 = constructor-tearoff self::A::•
+  #C5 = instantiation self::A::• <core::num*>
+  #C6 = instantiation self::A::• <core::int*>
+  #C7 = instantiation self::A::foo <core::String*>
+  #C8 = instantiation self::A::• <core::String*>
+  #C9 = static-tearoff self::A::bar
+  #C10 = instantiation self::A::bar <core::num*>
+  #C11 = instantiation self::A::bar <core::int*>
+  #C12 = instantiation self::A::bar <core::String*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.expect
index ecc6126..2dac5ed 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.expect
@@ -220,11 +220,11 @@
 
 constants  {
   #C1 = null
-  #C2 = tearoff self::Class1::_#new#tearOff
-  #C3 = tearoff self::Class2::_#named#tearOff
-  #C4 = tearoff self::Class3::_#new#tearOff
-  #C5 = tearoff self::Class4::_#new#tearOff
-  #C6 = tearoff self::Class5::_#new#tearOff
-  #C7 = tearoff self::Class6::_#new#tearOff
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
   #C8 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.transformed.expect
index 49aa5ce..67d30a7 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.transformed.expect
@@ -220,11 +220,11 @@
 
 constants  {
   #C1 = null
-  #C2 = tearoff self::Class1::_#new#tearOff
-  #C3 = tearoff self::Class2::_#named#tearOff
-  #C4 = tearoff self::Class3::_#new#tearOff
-  #C5 = tearoff self::Class4::_#new#tearOff
-  #C6 = tearoff self::Class5::_#new#tearOff
-  #C7 = tearoff self::Class6::_#new#tearOff
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
   #C8 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.expect
index ecc6126..2dac5ed 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.expect
@@ -220,11 +220,11 @@
 
 constants  {
   #C1 = null
-  #C2 = tearoff self::Class1::_#new#tearOff
-  #C3 = tearoff self::Class2::_#named#tearOff
-  #C4 = tearoff self::Class3::_#new#tearOff
-  #C5 = tearoff self::Class4::_#new#tearOff
-  #C6 = tearoff self::Class5::_#new#tearOff
-  #C7 = tearoff self::Class6::_#new#tearOff
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
   #C8 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.transformed.expect
index 49aa5ce..67d30a7 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.transformed.expect
@@ -220,11 +220,11 @@
 
 constants  {
   #C1 = null
-  #C2 = tearoff self::Class1::_#new#tearOff
-  #C3 = tearoff self::Class2::_#named#tearOff
-  #C4 = tearoff self::Class3::_#new#tearOff
-  #C5 = tearoff self::Class4::_#new#tearOff
-  #C6 = tearoff self::Class5::_#new#tearOff
-  #C7 = tearoff self::Class6::_#new#tearOff
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
   #C8 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart
index 80b72e45..dda860c 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart
@@ -15,6 +15,12 @@
   Class1([this.field = 42]);
 }
 
+class Class2 {
+  final int field;
+
+  Class2({this.field: 42});
+}
+
 void testDefaultValues() {
   var f1a = Class1.new;
   var c1a = f1a();
@@ -31,6 +37,22 @@
   var c1d = f1b(87);
   expect(87, c1d.field);
   throws(() => f1b(42, 87));
+
+  var f2a = Class2.new;
+  var c2a = f2a();
+  expect(42, c2a.field);
+  var c2b = f2a(field: 87);
+  expect(87, c2b.field);
+  () {
+    f2a(87); // error
+  };
+
+  dynamic f2b = Class2.new;
+  var c2c = f2b();
+  expect(42, c2c.field);
+  var c2d = f2b(field: 87);
+  expect(87, c2d.field);
+  throws(() => f2b(87));
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.expect
index 9c7ebb5..066aa724 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.expect
@@ -2,11 +2,16 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
 // Try removing the extra positional arguments.
 //     f1a(42, 87); // error
 //        ^
 //
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -18,6 +23,14 @@
   static method _#new#tearOff([core::int field = #C1]) → self::Class1
     return new self::Class1::•(field);
 }
+class Class2 extends core::Object {
+  final field core::int field;
+  constructor •({core::int field = #C1}) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::•(field: field);
+}
 static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
@@ -30,7 +43,7 @@
   self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
   self::expect(87, c1b.{self::Class1::field}{core::int});
   () → Null {
-    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
 Try removing the extra positional arguments.
     f1a(42, 87); // error
        ^" in f1a{<inapplicable>}.(42, 87);
@@ -41,12 +54,29 @@
   dynamic c1d = f1b{dynamic}.call(87);
   self::expect(87, c1d{dynamic}.field);
   self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C3;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
     throw "Expected ${expected}, actual ${actual}";
 }
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
   try {
     f(){() → dynamic};
   }
@@ -62,6 +92,7 @@
 
 constants  {
   #C1 = 42
-  #C2 = tearoff self::Class1::_#new#tearOff
-  #C3 = false
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#new#tearOff
+  #C4 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.transformed.expect
index dfe46c0..c76d239 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.transformed.expect
@@ -2,11 +2,16 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
 // Try removing the extra positional arguments.
 //     f1a(42, 87); // error
 //        ^
 //
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -18,6 +23,14 @@
   static method _#new#tearOff([core::int field = #C1]) → self::Class1
     return new self::Class1::•(field);
 }
+class Class2 extends core::Object {
+  final field core::int field;
+  constructor •({core::int field = #C1}) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::•(field: field);
+}
 static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
@@ -30,7 +43,7 @@
   self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
   self::expect(87, c1b.{self::Class1::field}{core::int});
   () → Null {
-    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
 Try removing the extra positional arguments.
     f1a(42, 87); // error
        ^" in f1a{<inapplicable>}.(42, 87);
@@ -41,12 +54,29 @@
   dynamic c1d = f1b{dynamic}.call(87);
   self::expect(87, c1d{dynamic}.field);
   self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C3;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
     throw "Expected ${expected}, actual ${actual}";
 }
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
   try {
     f(){() → dynamic};
   }
@@ -62,6 +92,7 @@
 
 constants  {
   #C1 = 42
-  #C2 = tearoff self::Class1::_#new#tearOff
-  #C3 = false
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#new#tearOff
+  #C4 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline.expect
index cd95744..8aff8da 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline.expect
@@ -6,6 +6,11 @@
   Class1([this.field = 42]);
 }
 
+class Class2 {
+  final int field;
+  Class2({this.field: 42});
+}
+
 void testDefaultValues() {}
 expect(expected, actual) {}
 throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline_modelled.expect
index 0426153..ecb692c 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline_modelled.expect
@@ -3,6 +3,11 @@
   final int field;
 }
 
+class Class2 {
+  Class2({this.field: 42});
+  final int field;
+}
+
 expect(expected, actual) {}
 final bool inSoundMode = <int?>[] is! List<int>;
 main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.expect
index 9c7ebb5..066aa724 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.expect
@@ -2,11 +2,16 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
 // Try removing the extra positional arguments.
 //     f1a(42, 87); // error
 //        ^
 //
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -18,6 +23,14 @@
   static method _#new#tearOff([core::int field = #C1]) → self::Class1
     return new self::Class1::•(field);
 }
+class Class2 extends core::Object {
+  final field core::int field;
+  constructor •({core::int field = #C1}) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::•(field: field);
+}
 static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
@@ -30,7 +43,7 @@
   self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
   self::expect(87, c1b.{self::Class1::field}{core::int});
   () → Null {
-    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
 Try removing the extra positional arguments.
     f1a(42, 87); // error
        ^" in f1a{<inapplicable>}.(42, 87);
@@ -41,12 +54,29 @@
   dynamic c1d = f1b{dynamic}.call(87);
   self::expect(87, c1d{dynamic}.field);
   self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C3;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
     throw "Expected ${expected}, actual ${actual}";
 }
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
   try {
     f(){() → dynamic};
   }
@@ -62,6 +92,7 @@
 
 constants  {
   #C1 = 42
-  #C2 = tearoff self::Class1::_#new#tearOff
-  #C3 = false
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#new#tearOff
+  #C4 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.outline.expect
index 7554ec1..128018d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.outline.expect
@@ -9,6 +9,13 @@
   static method _#new#tearOff([core::int field]) → self::Class1
     return new self::Class1::•(field);
 }
+class Class2 extends core::Object {
+  final field core::int field;
+  constructor •({core::int field}) → self::Class2
+    ;
+  static method _#new#tearOff({core::int field}) → self::Class2
+    return new self::Class2::•(field: field);
+}
 static final field core::bool inSoundMode;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.transformed.expect
index dfe46c0..c76d239 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.transformed.expect
@@ -2,11 +2,16 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
 // Try removing the extra positional arguments.
 //     f1a(42, 87); // error
 //        ^
 //
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -18,6 +23,14 @@
   static method _#new#tearOff([core::int field = #C1]) → self::Class1
     return new self::Class1::•(field);
 }
+class Class2 extends core::Object {
+  final field core::int field;
+  constructor •({core::int field = #C1}) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::•(field: field);
+}
 static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
@@ -30,7 +43,7 @@
   self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
   self::expect(87, c1b.{self::Class1::field}{core::int});
   () → Null {
-    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
 Try removing the extra positional arguments.
     f1a(42, 87); // error
        ^" in f1a{<inapplicable>}.(42, 87);
@@ -41,12 +54,29 @@
   dynamic c1d = f1b{dynamic}.call(87);
   self::expect(87, c1d{dynamic}.field);
   self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C3;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
     throw "Expected ${expected}, actual ${actual}";
 }
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
   try {
     f(){() → dynamic};
   }
@@ -62,6 +92,7 @@
 
 constants  {
   #C1 = 42
-  #C2 = tearoff self::Class1::_#new#tearOff
-  #C3 = false
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#new#tearOff
+  #C4 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart
new file mode 100644
index 0000000..d268773
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart
@@ -0,0 +1,7 @@
+// 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.
+
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect
new file mode 100644
index 0000000..007285e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = static-tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect
new file mode 100644
index 0000000..007285e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = static-tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect
new file mode 100644
index 0000000..428e3bc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..428e3bc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect
new file mode 100644
index 0000000..007285e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = static-tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect
new file mode 100644
index 0000000..90a7e36
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic
+  ;
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect
new file mode 100644
index 0000000..007285e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = static-tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart
new file mode 100644
index 0000000..042cb62
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.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.
+
+part of 'constructor_tear_off_uri.dart';
+
+test() {
+  Class Function(int) f = Class.new;
+}
+
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+
+class Class {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart
new file mode 100644
index 0000000..9c6ef02
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart
@@ -0,0 +1,163 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+  print('inSoundMode: $inSoundMode');
+  testNoArgs();
+  testArgs();
+}
+
+class Class1 {
+  Class1._();
+  factory Class1() => new Class1._();
+}
+
+class Class2 {
+  Class2._();
+  factory Class2.named() => new Class2._();
+}
+
+testNoArgs() {
+  var f1a = Class1.new;
+  var c1a = f1a();
+  expect(true, c1a is Class1);
+
+  dynamic f1b = Class1.new;
+  var c1b = f1b();
+  expect(true, c1b is Class1);
+
+  expect(true, identical(f1a, f1b));
+
+  var f2a = Class2.named;
+  var c2a = f2a();
+  expect(true, c2a is Class2);
+
+  dynamic f2b = Class2.named;
+  var c2b = f2b();
+  expect(true, c2b is Class2);
+
+  expect(true, identical(f2a, f2b));
+}
+
+class Class3 {
+  final int field;
+
+  Class3._(this.field);
+  factory Class3(int field) => new Class3._(field);
+}
+
+class Class4 {
+  final int? field;
+
+  Class4._([this.field]);
+  factory Class4([int? field]) => new Class4._(field);
+}
+
+class Class5 {
+  final int field1;
+  final int? field2;
+
+  Class5._(this.field1, [this.field2]);
+  factory Class5(int field1, [int? field2]) => new Class5._(field1, field2);
+}
+
+class Class6 {
+  final int field1;
+  final int? field2;
+  final int field3;
+
+  Class6._(this.field1, {this.field2, required this.field3});
+  factory Class6(int field1, {int? field2, required int field3}) =>
+      new Class6._(field1, field2: field2, field3: field3);
+}
+
+testArgs() {
+  var f3a = Class3.new;
+  var c3a = f3a(42);
+  expect(42, c3a.field);
+  () {
+    f3a(); // error
+    f3a(42, 87); // error
+  };
+
+  dynamic f3b = Class3.new;
+  var c3b = f3b(87);
+  expect(87, c3b.field);
+  throws(() => f3b());
+  throws(() => f3b(42, 87));
+
+  var f4a = Class4.new;
+  var c4a = f4a();
+  expect(null, c4a.field);
+  var c4b = f4a(42);
+  expect(42, c4b.field);
+  () {
+    f4a(42, 87); // error
+  };
+  dynamic f4b = Class4.new;
+  throws(() => f4b(42, 87));
+
+
+  var f5a = Class5.new;
+  var c5a = f5a(42);
+  expect(42, c5a.field1);
+  expect(null, c5a.field2);
+  var c5b = f5a(87, 42);
+  expect(87, c5b.field1);
+  expect(42, c5b.field2);
+  () {
+    f5a(); // error
+    f5a(42, 87, 123); // error
+  };
+  dynamic f5b = Class5.new;
+  throws(() => f5b());
+  throws(() => f5b(42, 87, 123));
+
+  var f6a = Class6.new;
+  var c6a = f6a(42, field3: 87);
+  expect(42, c6a.field1);
+  expect(null, c6a.field2);
+  expect(87, c6a.field3);
+  () {
+    f6a(); // error
+    f6a(42); // error
+    f6a(42, 87); // error
+    f6a(field1: 87, field2: 87); // error
+  };
+
+  var c6b = f6a(42, field2: 123, field3: 87);
+  expect(42, c6b.field1);
+  expect(123, c6b.field2);
+  expect(87, c6b.field3);
+
+  var c6c = f6a(87, field3: 42, field2: 123);
+  expect(87, c6c.field1);
+  expect(123, c6c.field2);
+  expect(42, c6c.field3);
+
+  dynamic f6b = Class6.new;
+  throws(() => f6b());
+  throws(() => f6b(42), inSoundModeOnly: true);
+  throws(() => f6b(42, 87), inSoundModeOnly: true);
+  throws(() => f6b(field1: 87, field2: 87));
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..7c14634
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.expect
@@ -0,0 +1,254 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class1
+    return new self::Class1::_();
+  static factory •() → self::Class1
+    return new self::Class1::_();
+  static method _#new#tearOff() → self::Class1
+    return self::Class1::•();
+}
+class Class2 extends core::Object {
+  constructor _() → self::Class2
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class2
+    return new self::Class2::_();
+  static factory named() → self::Class2
+    return new self::Class2::_();
+  static method _#named#tearOff() → self::Class2
+    return self::Class2::named();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static factory •(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static method _#new#tearOff(core::int field) → self::Class3
+    return self::Class3::•(field);
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static factory •([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+    return self::Class4::•(field);
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return self::Class5::•(field1, field2);
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return self::Class6::•(field1, field2: field2, field3: field3);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
+  #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..ebe5432
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,254 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class1
+    return new self::Class1::_();
+  static factory •() → self::Class1
+    return new self::Class1::_();
+  static method _#new#tearOff() → self::Class1
+    return self::Class1::•();
+}
+class Class2 extends core::Object {
+  constructor _() → self::Class2
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class2
+    return new self::Class2::_();
+  static factory named() → self::Class2
+    return new self::Class2::_();
+  static method _#named#tearOff() → self::Class2
+    return self::Class2::named();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static factory •(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static method _#new#tearOff(core::int field) → self::Class3
+    return self::Class3::•(field);
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static factory •([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+    return self::Class4::•(field);
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return self::Class5::•(field1, field2);
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return self::Class6::•(field1, field2: field2, field3: field3);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
+  #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..e4d0e54
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,46 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+  Class1._();
+  factory Class1() => new Class1._();
+}
+
+class Class2 {
+  Class2._();
+  factory Class2.named() => new Class2._();
+}
+
+testNoArgs() {}
+
+class Class3 {
+  final int field;
+  Class3._(this.field);
+  factory Class3(int field) => new Class3._(field);
+}
+
+class Class4 {
+  final int? field;
+  Class4._([this.field]);
+  factory Class4([int? field]) => new Class4._(field);
+}
+
+class Class5 {
+  final int field1;
+  final int? field2;
+  Class5._(this.field1, [this.field2]);
+  factory Class5(int field1, [int? field2]) => new Class5._(field1, field2);
+}
+
+class Class6 {
+  final int field1;
+  final int? field2;
+  final int field3;
+  Class6._(this.field1, {this.field2, required this.field3});
+  factory Class6(int field1, {int? field2, required int field3}) =>
+      new Class6._(field1, field2: field2, field3: field3);
+}
+
+testArgs() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0e60ce8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,44 @@
+class Class1 {
+  Class1._();
+  factory Class1() => new Class1._();
+}
+
+class Class2 {
+  Class2._();
+  factory Class2.named() => new Class2._();
+}
+
+class Class3 {
+  Class3._(this.field);
+  factory Class3(int field) => new Class3._(field);
+  final int field;
+}
+
+class Class4 {
+  Class4._([this.field]);
+  factory Class4([int? field]) => new Class4._(field);
+  final int? field;
+}
+
+class Class5 {
+  Class5._(this.field1, [this.field2]);
+  factory Class5(int field1, [int? field2]) => new Class5._(field1, field2);
+  final int? field2;
+  final int field1;
+}
+
+class Class6 {
+  Class6._(this.field1, {this.field2, required this.field3});
+  factory Class6(int field1, {int? field2, required int field3}) =>
+      new Class6._(field1, field2: field2, field3: field3);
+  final int? field2;
+  final int field1;
+  final int field3;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testArgs() {}
+testNoArgs() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..7c14634
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.expect
@@ -0,0 +1,254 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class1
+    return new self::Class1::_();
+  static factory •() → self::Class1
+    return new self::Class1::_();
+  static method _#new#tearOff() → self::Class1
+    return self::Class1::•();
+}
+class Class2 extends core::Object {
+  constructor _() → self::Class2
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class2
+    return new self::Class2::_();
+  static factory named() → self::Class2
+    return new self::Class2::_();
+  static method _#named#tearOff() → self::Class2
+    return self::Class2::named();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static factory •(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static method _#new#tearOff(core::int field) → self::Class3
+    return self::Class3::•(field);
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static factory •([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+    return self::Class4::•(field);
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return self::Class5::•(field1, field2);
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return self::Class6::•(field1, field2: field2, field3: field3);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
+  #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..5366579f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  constructor _() → self::Class1
+    ;
+  static method _#_#tearOff() → self::Class1
+    return new self::Class1::_();
+  static factory •() → self::Class1
+    ;
+  static method _#new#tearOff() → self::Class1
+    return self::Class1::•();
+}
+class Class2 extends core::Object {
+  constructor _() → self::Class2
+    ;
+  static method _#_#tearOff() → self::Class2
+    return new self::Class2::_();
+  static factory named() → self::Class2
+    ;
+  static method _#named#tearOff() → self::Class2
+    return self::Class2::named();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class3
+    ;
+  static method _#_#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static factory •(core::int field) → self::Class3
+    ;
+  static method _#new#tearOff(core::int field) → self::Class3
+    return self::Class3::•(field);
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  constructor _([core::int? field]) → self::Class4
+    ;
+  static method _#_#tearOff([core::int? field]) → self::Class4
+    return new self::Class4::_(field);
+  static factory •([core::int? field]) → self::Class4
+    ;
+  static method _#new#tearOff([core::int? field]) → self::Class4
+    return self::Class4::•(field);
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  constructor _(core::int field1, [core::int? field2]) → self::Class5
+    ;
+  static method _#_#tearOff(core::int field1, [core::int? field2]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static factory •(core::int field1, [core::int? field2]) → self::Class5
+    ;
+  static method _#new#tearOff(core::int field1, [core::int? field2]) → self::Class5
+    return self::Class5::•(field1, field2);
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  constructor _(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+    ;
+  static method _#_#tearOff(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static factory •(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+    ;
+  static method _#new#tearOff(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+    return self::Class6::•(field1, field2: field2, field3: field3);
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+  ;
+static method testNoArgs() → dynamic
+  ;
+static method testArgs() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..ebe5432
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,254 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class1
+    return new self::Class1::_();
+  static factory •() → self::Class1
+    return new self::Class1::_();
+  static method _#new#tearOff() → self::Class1
+    return self::Class1::•();
+}
+class Class2 extends core::Object {
+  constructor _() → self::Class2
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class2
+    return new self::Class2::_();
+  static factory named() → self::Class2
+    return new self::Class2::_();
+  static method _#named#tearOff() → self::Class2
+    return self::Class2::named();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static factory •(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static method _#new#tearOff(core::int field) → self::Class3
+    return self::Class3::•(field);
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static factory •([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+    return self::Class4::•(field);
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return self::Class5::•(field1, field2);
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return self::Class6::•(field1, field2: field2, field3: field3);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
+  #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart
new file mode 100644
index 0000000..f966b5b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+  print('inSoundMode: $inSoundMode');
+  testDefaultValues();
+}
+
+class Class1 {
+  final int field;
+
+  Class1._(this.field);
+  factory Class1([int field = 42]) => new Class1._(field);
+}
+
+class Class2 {
+  final int field;
+
+  Class2._(this.field);
+  factory Class2({int field: 42}) => new Class2._(field);
+}
+
+void testDefaultValues() {
+  var f1a = Class1.new;
+  var c1a = f1a();
+  expect(42, c1a.field);
+  var c1b = f1a(87);
+  expect(87, c1b.field);
+  () {
+    f1a(42, 87); // error
+  };
+
+  dynamic f1b = Class1.new;
+  var c1c = f1b();
+  expect(42, c1c.field);
+  var c1d = f1b(87);
+  expect(87, c1d.field);
+  throws(() => f1b(42, 87));
+
+  var f2a = Class2.new;
+  var c2a = f2a();
+  expect(42, c2a.field);
+  var c2b = f2a(field: 87);
+  expect(87, c2b.field);
+  () {
+    f2a(87); // error
+  };
+
+  dynamic f2b = Class2.new;
+  var c2c = f2b();
+  expect(42, c2c.field);
+  var c2d = f2b(field: 87);
+  expect(87, c2d.field);
+  throws(() => f2b(87));
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.expect
new file mode 100644
index 0000000..bcc5942
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class1
+    return new self::Class1::_(field);
+  static factory •([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+  static method _#new#tearOff([core::int field = #C1]) → self::Class1
+    return self::Class1::•(field);
+}
+class Class2 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class2
+    return new self::Class2::_(field);
+  static factory •({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field);
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return self::Class2::•(field: field);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+  ([core::int]) → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+  self::expect(42, c1a.{self::Class1::field}{core::int});
+  self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+  self::expect(87, c1b.{self::Class1::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1a(42, 87); // error
+       ^" in f1a{<inapplicable>}.(42, 87);
+  };
+  dynamic f1b = #C2;
+  dynamic c1c = f1b{dynamic}.call();
+  self::expect(42, c1c{dynamic}.field);
+  dynamic c1d = f1b{dynamic}.call(87);
+  self::expect(87, c1d{dynamic}.field);
+  self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C3;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 42
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#new#tearOff
+  #C4 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..db9b0fa
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.transformed.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class1
+    return new self::Class1::_(field);
+  static factory •([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+  static method _#new#tearOff([core::int field = #C1]) → self::Class1
+    return self::Class1::•(field);
+}
+class Class2 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class2
+    return new self::Class2::_(field);
+  static factory •({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field);
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return self::Class2::•(field: field);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+  ([core::int]) → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+  self::expect(42, c1a.{self::Class1::field}{core::int});
+  self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+  self::expect(87, c1b.{self::Class1::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1a(42, 87); // error
+       ^" in f1a{<inapplicable>}.(42, 87);
+  };
+  dynamic f1b = #C2;
+  dynamic c1c = f1b{dynamic}.call();
+  self::expect(42, c1c{dynamic}.field);
+  dynamic c1d = f1b{dynamic}.call(87);
+  self::expect(87, c1d{dynamic}.field);
+  self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C3;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 42
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#new#tearOff
+  #C4 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline.expect
new file mode 100644
index 0000000..99a80f2
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline.expect
@@ -0,0 +1,18 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+  final int field;
+  Class1._(this.field);
+  factory Class1([int field = 42]) => new Class1._(field);
+}
+
+class Class2 {
+  final int field;
+  Class2._(this.field);
+  factory Class2({int field: 42}) => new Class2._(field);
+}
+
+void testDefaultValues() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4f18568
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class Class1 {
+  Class1._(this.field);
+  factory Class1([int field = 42]) => new Class1._(field);
+  final int field;
+}
+
+class Class2 {
+  Class2._(this.field);
+  factory Class2({int field: 42}) => new Class2._(field);
+  final int field;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
+void testDefaultValues() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.expect
new file mode 100644
index 0000000..bcc5942
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class1
+    return new self::Class1::_(field);
+  static factory •([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+  static method _#new#tearOff([core::int field = #C1]) → self::Class1
+    return self::Class1::•(field);
+}
+class Class2 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class2
+    return new self::Class2::_(field);
+  static factory •({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field);
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return self::Class2::•(field: field);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+  ([core::int]) → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+  self::expect(42, c1a.{self::Class1::field}{core::int});
+  self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+  self::expect(87, c1b.{self::Class1::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1a(42, 87); // error
+       ^" in f1a{<inapplicable>}.(42, 87);
+  };
+  dynamic f1b = #C2;
+  dynamic c1c = f1b{dynamic}.call();
+  self::expect(42, c1c{dynamic}.field);
+  dynamic c1d = f1b{dynamic}.call(87);
+  self::expect(87, c1d{dynamic}.field);
+  self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C3;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 42
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#new#tearOff
+  #C4 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.outline.expect
new file mode 100644
index 0000000..da300f3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.outline.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class1
+    ;
+  static method _#_#tearOff(core::int field) → self::Class1
+    return new self::Class1::_(field);
+  static factory •([core::int field]) → self::Class1
+    ;
+  static method _#new#tearOff([core::int field]) → self::Class1
+    return self::Class1::•(field);
+}
+class Class2 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class2
+    ;
+  static method _#_#tearOff(core::int field) → self::Class2
+    return new self::Class2::_(field);
+  static factory •({core::int field}) → self::Class2
+    ;
+  static method _#new#tearOff({core::int field}) → self::Class2
+    return self::Class2::•(field: field);
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+  ;
+static method testDefaultValues() → void
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.transformed.expect
new file mode 100644
index 0000000..db9b0fa
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.transformed.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class1
+    return new self::Class1::_(field);
+  static factory •([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+  static method _#new#tearOff([core::int field = #C1]) → self::Class1
+    return self::Class1::•(field);
+}
+class Class2 extends core::Object {
+  final field core::int field;
+  constructor _(core::int field) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class2
+    return new self::Class2::_(field);
+  static factory •({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field);
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return self::Class2::•(field: field);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+  ([core::int]) → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+  self::expect(42, c1a.{self::Class1::field}{core::int});
+  self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+  self::expect(87, c1b.{self::Class1::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1a(42, 87); // error
+       ^" in f1a{<inapplicable>}.(42, 87);
+  };
+  dynamic f1b = #C2;
+  dynamic c1c = f1b{dynamic}.call();
+  self::expect(42, c1c{dynamic}.field);
+  dynamic c1d = f1b{dynamic}.call(87);
+  self::expect(87, c1d{dynamic}.field);
+  self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C3;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 42
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#new#tearOff
+  #C4 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart
new file mode 100644
index 0000000..ff03d6e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart
@@ -0,0 +1,142 @@
+// 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 'main_lib.dart';
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+  var f1a = Class1.new;
+  var c1a = f1a();
+  expect(true, c1a is Class1);
+
+  dynamic f1b = Class1.new;
+  var c1b = f1b();
+  expect(true, c1b is Class1);
+
+  expect(true, identical(f1a, f1b));
+
+  var f2a = Class2.named;
+  var c2a = f2a();
+  expect(true, c2a is Class2);
+
+  dynamic f2b = Class2.named;
+  var c2b = f2b();
+  expect(true, c2b is Class2);
+
+  expect(true, identical(f2a, f2b));
+
+  var f2c = Class2.redirect;
+  var c2c = f2c();
+  expect(true, c2c is Class2);
+
+  dynamic f2d = Class2.redirect;
+  var c2d = f2d();
+  expect(true, c2d is Class2);
+
+  expect(true, identical(f2c, f2d));
+
+  var f3a = Class3.new;
+  var c3a = f3a(42);
+  expect(42, c3a.field);
+  () {
+    f3a(); // error
+    f3a(42, 87); // error
+  };
+
+  dynamic f3b = Class3.new;
+  var c3b = f3b(87);
+  expect(87, c3b.field);
+  throws(() => f3b());
+  throws(() => f3b(42, 87));
+
+  var f4a = Class4.new;
+  var c4a = f4a();
+  expect(true, c4a is Class4<dynamic>);
+  expect(false, c4a is Class4<int>);
+  var c4b = f4a<int>();
+  expect(true, c4b is Class4<int>);
+  expect(false, c4b is Class4<String>);
+  () {
+    f4a<int, String>(); // error
+  };
+
+  var f4b = f4a<int>;
+  var c4c = f4b();
+  expect(true, c4c is Class4<int>);
+  expect(false, c4c is Class4<String>);
+  () {
+    f4b<int>(); // error
+  };
+
+  dynamic f4c = Class4.new;
+  var c4d = f4c();
+  expect(true, c4d is Class4<dynamic>);
+  expect(false, c4d is Class4<int>);
+  throws(() => f4c<int, String>());
+
+  var f4d = Class4.redirect;
+  var c4e = f4d();
+  expect(true, c4e is Class4<dynamic>);
+  expect(false, c4e is Class4<int>);
+  var c4f = f4d<int>();
+  expect(true, c4f is Class4<int>);
+  expect(false, c4f is Class4<String>);
+  () {
+    f4d<int, String>(); // error
+  };
+
+  var f4e = f4d<int>;
+  var c4g = f4e();
+  expect(true, c4g is Class4<int>);
+  expect(false, c4g is Class4<String>);
+  () {
+    f4e<int>(); // error
+  };
+
+  dynamic f4f = Class4.redirect;
+  var c4h = f4f();
+  expect(true, c4h is Class4<dynamic>);
+  expect(false, c4h is Class4<int>);
+  throws(() => f4f<int, String>());
+
+  var f5a = Class5.new;
+  var c5a = f5a();
+  expect(true, c5a is Class5<num>);
+  expect(false, c5a is Class5<int>);
+  var c5b = f5a<int>();
+  expect(true, c5b is Class5<int>);
+  expect(false, c5b is Class5<double>);
+  () {
+    f5a<String>(); // error
+    f5a<int, String>(); // error
+  };
+
+  dynamic f5b = Class5.new;
+  var c5c = f5b();
+  expect(true, c5c is Class5<num>);
+  expect(false, c5c is Class5<int>);
+  var c5d = f5b<int>();
+  expect(true, c5d is Class5<int>);
+  expect(false, c5d is Class5<double>);
+  throws(() => f5b<String>());
+  throws(() => f5b<int, String>());
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.expect
new file mode 100644
index 0000000..1806fdc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.expect
@@ -0,0 +1,246 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+//     f4a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+//     f4b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+//     f4d<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+//     f4e<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:112:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+//     f5a<int, String>(); // error
+//        ^
+//
+import self as self;
+import "main_lib.dart" as mai;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  () → mai::Class1 f1a = #C1;
+  mai::Class1 c1a = f1a(){() → mai::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} mai::Class1);
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} mai::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → mai::Class2 f2a = #C2;
+  mai::Class2 c2a = f2a(){() → mai::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} mai::Class2);
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} mai::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+  () → mai::Class2 f2c = #C3;
+  mai::Class2 c2c = f2c(){() → mai::Class2};
+  self::expect(true, c2c is{ForNonNullableByDefault} mai::Class2);
+  dynamic f2d = #C3;
+  dynamic c2d = f2d{dynamic}.call();
+  self::expect(true, c2d is{ForNonNullableByDefault} mai::Class2);
+  self::expect(true, core::identical(f2c, f2d));
+  (core::int) → mai::Class3 f3a = #C4;
+  mai::Class3 c3a = f3a(42){(core::int) → mai::Class3};
+  self::expect(42, c3a.{mai::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  <T extends core::Object? = dynamic>() → mai::Class4<T%> f4a = #C5;
+  mai::Class4<dynamic> c4a = f4a<dynamic>(){() → mai::Class4<dynamic>};
+  self::expect(true, c4a is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4a is{ForNonNullableByDefault} mai::Class4<core::int>);
+  mai::Class4<core::int> c4b = f4a<core::int>(){() → mai::Class4<core::int>};
+  self::expect(true, c4b is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4b is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+    f4a<int, String>(); // error
+       ^" in f4a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → mai::Class4<core::int> f4b = f4a<core::int>;
+  mai::Class4<core::int> c4c = f4b(){() → mai::Class4<core::int>};
+  self::expect(true, c4c is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4c is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+    f4b<int>(); // error
+       ^" in f4b{<inapplicable>}.<core::int>();
+  };
+  dynamic f4c = #C5;
+  dynamic c4d = f4c{dynamic}.call();
+  self::expect(true, c4d is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4d is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::throws(() → dynamic => f4c{dynamic}.call<core::int, core::String>());
+  <T extends core::Object? = dynamic>() → mai::Class4<T%> f4d = #C6;
+  mai::Class4<dynamic> c4e = f4d<dynamic>(){() → mai::Class4<dynamic>};
+  self::expect(true, c4e is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4e is{ForNonNullableByDefault} mai::Class4<core::int>);
+  mai::Class4<core::int> c4f = f4d<core::int>(){() → mai::Class4<core::int>};
+  self::expect(true, c4f is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4f is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+    f4d<int, String>(); // error
+       ^" in f4d{<inapplicable>}.<core::int, core::String>();
+  };
+  () → mai::Class4<core::int> f4e = f4d<core::int>;
+  mai::Class4<core::int> c4g = f4e(){() → mai::Class4<core::int>};
+  self::expect(true, c4g is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4g is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+    f4e<int>(); // error
+       ^" in f4e{<inapplicable>}.<core::int>();
+  };
+  dynamic f4f = #C6;
+  dynamic c4h = f4f{dynamic}.call();
+  self::expect(true, c4h is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4h is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::throws(() → dynamic => f4f{dynamic}.call<core::int, core::String>());
+  <T extends core::num>() → mai::Class5<T> f5a = #C7;
+  mai::Class5<core::num> c5a = f5a<core::num>(){() → mai::Class5<core::num>};
+  self::expect(true, c5a is{ForNonNullableByDefault} mai::Class5<core::num>);
+  self::expect(false, c5a is{ForNonNullableByDefault} mai::Class5<core::int>);
+  mai::Class5<core::int> c5b = f5a<core::int>(){() → mai::Class5<core::int>};
+  self::expect(true, c5b is{ForNonNullableByDefault} mai::Class5<core::int>);
+  self::expect(false, c5b is{ForNonNullableByDefault} mai::Class5<core::double>);
+  () → Null {
+    f5a<core::String>(){() → mai::Class5<core::String>};
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+    f5a<int, String>(); // error
+       ^" in f5a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f5b = #C7;
+  dynamic c5c = f5b{dynamic}.call();
+  self::expect(true, c5c is{ForNonNullableByDefault} mai::Class5<core::num>);
+  self::expect(false, c5c is{ForNonNullableByDefault} mai::Class5<core::int>);
+  dynamic c5d = f5b{dynamic}.call<core::int>();
+  self::expect(true, c5d is{ForNonNullableByDefault} mai::Class5<core::int>);
+  self::expect(false, c5d is{ForNonNullableByDefault} mai::Class5<core::double>);
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::int, core::String>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → mai::Class1
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → mai::Class1
+    return new mai::Class1::•();
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::Class2::redirect]/*isLegacy*/;
+  constructor named() → mai::Class2
+    : super core::Object::•()
+    ;
+  static method _#named#tearOff() → mai::Class2
+    return new mai::Class2::named();
+  static factory redirect() → mai::Class2
+    let dynamic #redirecting_factory = mai::Class2::named in invalid-expression;
+  static method _#redirect#tearOff() → mai::Class2
+    return new mai::Class2::named();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  constructor •(core::int field) → mai::Class3
+    : mai::Class3::field = field, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field) → mai::Class3
+    return new mai::Class3::•(field);
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::Class4::redirect]/*isLegacy*/;
+  constructor _() → mai::Class4<mai::Class4::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#_#tearOff::T%>
+    return new mai::Class4::_<mai::Class4::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::•::T%>
+    return new mai::Class4::_<mai::Class4::•::T%>();
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#new#tearOff::T%>
+    return mai::Class4::•<mai::Class4::_#new#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::redirect::T%>
+    let dynamic #redirecting_factory = mai::Class4::_ in let mai::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#redirect#tearOff::T%>
+    return new mai::Class4::_<mai::Class4::_#redirect#tearOff::T%>();
+}
+class Class5<T extends core::num> extends core::Object {
+  constructor _() → mai::Class5<mai::Class5::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#_#tearOff::T>
+    return new mai::Class5::_<mai::Class5::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → mai::Class5<mai::Class5::•::T>
+    return new mai::Class5::_<mai::Class5::•::T>();
+  static method _#new#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#new#tearOff::T>
+    return mai::Class5::•<mai::Class5::_#new#tearOff::T>();
+}
+
+constants  {
+  #C1 = static-tearoff mai::Class1::_#new#tearOff
+  #C2 = static-tearoff mai::Class2::_#named#tearOff
+  #C3 = static-tearoff mai::Class2::_#redirect#tearOff
+  #C4 = static-tearoff mai::Class3::_#new#tearOff
+  #C5 = static-tearoff mai::Class4::_#new#tearOff
+  #C6 = static-tearoff mai::Class4::_#redirect#tearOff
+  #C7 = static-tearoff mai::Class5::_#new#tearOff
+  #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..9edd33a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.transformed.expect
@@ -0,0 +1,246 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+//     f4a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+//     f4b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+//     f4d<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+//     f4e<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:112:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+//     f5a<int, String>(); // error
+//        ^
+//
+import self as self;
+import "main_lib.dart" as mai;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  () → mai::Class1 f1a = #C1;
+  mai::Class1 c1a = f1a(){() → mai::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} mai::Class1);
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} mai::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → mai::Class2 f2a = #C2;
+  mai::Class2 c2a = f2a(){() → mai::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} mai::Class2);
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} mai::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+  () → mai::Class2 f2c = #C3;
+  mai::Class2 c2c = f2c(){() → mai::Class2};
+  self::expect(true, c2c is{ForNonNullableByDefault} mai::Class2);
+  dynamic f2d = #C3;
+  dynamic c2d = f2d{dynamic}.call();
+  self::expect(true, c2d is{ForNonNullableByDefault} mai::Class2);
+  self::expect(true, core::identical(f2c, f2d));
+  (core::int) → mai::Class3 f3a = #C4;
+  mai::Class3 c3a = f3a(42){(core::int) → mai::Class3};
+  self::expect(42, c3a.{mai::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  <T extends core::Object? = dynamic>() → mai::Class4<T%> f4a = #C5;
+  mai::Class4<dynamic> c4a = f4a<dynamic>(){() → mai::Class4<dynamic>};
+  self::expect(true, c4a is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4a is{ForNonNullableByDefault} mai::Class4<core::int>);
+  mai::Class4<core::int> c4b = f4a<core::int>(){() → mai::Class4<core::int>};
+  self::expect(true, c4b is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4b is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+    f4a<int, String>(); // error
+       ^" in f4a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → mai::Class4<core::int> f4b = f4a<core::int>;
+  mai::Class4<core::int> c4c = f4b(){() → mai::Class4<core::int>};
+  self::expect(true, c4c is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4c is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+    f4b<int>(); // error
+       ^" in f4b{<inapplicable>}.<core::int>();
+  };
+  dynamic f4c = #C5;
+  dynamic c4d = f4c{dynamic}.call();
+  self::expect(true, c4d is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4d is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::throws(() → dynamic => f4c{dynamic}.call<core::int, core::String>());
+  <T extends core::Object? = dynamic>() → mai::Class4<T%> f4d = #C6;
+  mai::Class4<dynamic> c4e = f4d<dynamic>(){() → mai::Class4<dynamic>};
+  self::expect(true, c4e is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4e is{ForNonNullableByDefault} mai::Class4<core::int>);
+  mai::Class4<core::int> c4f = f4d<core::int>(){() → mai::Class4<core::int>};
+  self::expect(true, c4f is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4f is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+    f4d<int, String>(); // error
+       ^" in f4d{<inapplicable>}.<core::int, core::String>();
+  };
+  () → mai::Class4<core::int> f4e = f4d<core::int>;
+  mai::Class4<core::int> c4g = f4e(){() → mai::Class4<core::int>};
+  self::expect(true, c4g is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4g is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+    f4e<int>(); // error
+       ^" in f4e{<inapplicable>}.<core::int>();
+  };
+  dynamic f4f = #C6;
+  dynamic c4h = f4f{dynamic}.call();
+  self::expect(true, c4h is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4h is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::throws(() → dynamic => f4f{dynamic}.call<core::int, core::String>());
+  <T extends core::num>() → mai::Class5<T> f5a = #C7;
+  mai::Class5<core::num> c5a = f5a<core::num>(){() → mai::Class5<core::num>};
+  self::expect(true, c5a is{ForNonNullableByDefault} mai::Class5<core::num>);
+  self::expect(false, c5a is{ForNonNullableByDefault} mai::Class5<core::int>);
+  mai::Class5<core::int> c5b = f5a<core::int>(){() → mai::Class5<core::int>};
+  self::expect(true, c5b is{ForNonNullableByDefault} mai::Class5<core::int>);
+  self::expect(false, c5b is{ForNonNullableByDefault} mai::Class5<core::double>);
+  () → Null {
+    f5a<core::String>(){() → mai::Class5<core::String>};
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+    f5a<int, String>(); // error
+       ^" in f5a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f5b = #C7;
+  dynamic c5c = f5b{dynamic}.call();
+  self::expect(true, c5c is{ForNonNullableByDefault} mai::Class5<core::num>);
+  self::expect(false, c5c is{ForNonNullableByDefault} mai::Class5<core::int>);
+  dynamic c5d = f5b{dynamic}.call<core::int>();
+  self::expect(true, c5d is{ForNonNullableByDefault} mai::Class5<core::int>);
+  self::expect(false, c5d is{ForNonNullableByDefault} mai::Class5<core::double>);
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::int, core::String>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → mai::Class1
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → mai::Class1
+    return new mai::Class1::•();
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::Class2::redirect]/*isLegacy*/;
+  constructor named() → mai::Class2
+    : super core::Object::•()
+    ;
+  static method _#named#tearOff() → mai::Class2
+    return new mai::Class2::named();
+  static factory redirect() → mai::Class2
+    let Never #redirecting_factory = mai::Class2::named in invalid-expression;
+  static method _#redirect#tearOff() → mai::Class2
+    return new mai::Class2::named();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  constructor •(core::int field) → mai::Class3
+    : mai::Class3::field = field, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field) → mai::Class3
+    return new mai::Class3::•(field);
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::Class4::redirect]/*isLegacy*/;
+  constructor _() → mai::Class4<mai::Class4::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#_#tearOff::T%>
+    return new mai::Class4::_<mai::Class4::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::•::T%>
+    return new mai::Class4::_<mai::Class4::•::T%>();
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#new#tearOff::T%>
+    return mai::Class4::•<mai::Class4::_#new#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::redirect::T%>
+    let Never #redirecting_factory = mai::Class4::_ in let mai::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#redirect#tearOff::T%>
+    return new mai::Class4::_<mai::Class4::_#redirect#tearOff::T%>();
+}
+class Class5<T extends core::num> extends core::Object {
+  constructor _() → mai::Class5<mai::Class5::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#_#tearOff::T>
+    return new mai::Class5::_<mai::Class5::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → mai::Class5<mai::Class5::•::T>
+    return new mai::Class5::_<mai::Class5::•::T>();
+  static method _#new#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#new#tearOff::T>
+    return mai::Class5::•<mai::Class5::_#new#tearOff::T>();
+}
+
+constants  {
+  #C1 = static-tearoff mai::Class1::_#new#tearOff
+  #C2 = static-tearoff mai::Class2::_#named#tearOff
+  #C3 = static-tearoff mai::Class2::_#redirect#tearOff
+  #C4 = static-tearoff mai::Class3::_#new#tearOff
+  #C5 = static-tearoff mai::Class4::_#new#tearOff
+  #C6 = static-tearoff mai::Class4::_#redirect#tearOff
+  #C7 = static-tearoff mai::Class5::_#new#tearOff
+  #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline.expect
new file mode 100644
index 0000000..4166ca7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+import 'main_lib.dart';
+
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..26f0c41
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+import 'main_lib.dart';
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.expect
new file mode 100644
index 0000000..1806fdc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.expect
@@ -0,0 +1,246 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+//     f4a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+//     f4b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+//     f4d<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+//     f4e<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:112:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+//     f5a<int, String>(); // error
+//        ^
+//
+import self as self;
+import "main_lib.dart" as mai;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  () → mai::Class1 f1a = #C1;
+  mai::Class1 c1a = f1a(){() → mai::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} mai::Class1);
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} mai::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → mai::Class2 f2a = #C2;
+  mai::Class2 c2a = f2a(){() → mai::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} mai::Class2);
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} mai::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+  () → mai::Class2 f2c = #C3;
+  mai::Class2 c2c = f2c(){() → mai::Class2};
+  self::expect(true, c2c is{ForNonNullableByDefault} mai::Class2);
+  dynamic f2d = #C3;
+  dynamic c2d = f2d{dynamic}.call();
+  self::expect(true, c2d is{ForNonNullableByDefault} mai::Class2);
+  self::expect(true, core::identical(f2c, f2d));
+  (core::int) → mai::Class3 f3a = #C4;
+  mai::Class3 c3a = f3a(42){(core::int) → mai::Class3};
+  self::expect(42, c3a.{mai::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  <T extends core::Object? = dynamic>() → mai::Class4<T%> f4a = #C5;
+  mai::Class4<dynamic> c4a = f4a<dynamic>(){() → mai::Class4<dynamic>};
+  self::expect(true, c4a is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4a is{ForNonNullableByDefault} mai::Class4<core::int>);
+  mai::Class4<core::int> c4b = f4a<core::int>(){() → mai::Class4<core::int>};
+  self::expect(true, c4b is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4b is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+    f4a<int, String>(); // error
+       ^" in f4a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → mai::Class4<core::int> f4b = f4a<core::int>;
+  mai::Class4<core::int> c4c = f4b(){() → mai::Class4<core::int>};
+  self::expect(true, c4c is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4c is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+    f4b<int>(); // error
+       ^" in f4b{<inapplicable>}.<core::int>();
+  };
+  dynamic f4c = #C5;
+  dynamic c4d = f4c{dynamic}.call();
+  self::expect(true, c4d is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4d is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::throws(() → dynamic => f4c{dynamic}.call<core::int, core::String>());
+  <T extends core::Object? = dynamic>() → mai::Class4<T%> f4d = #C6;
+  mai::Class4<dynamic> c4e = f4d<dynamic>(){() → mai::Class4<dynamic>};
+  self::expect(true, c4e is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4e is{ForNonNullableByDefault} mai::Class4<core::int>);
+  mai::Class4<core::int> c4f = f4d<core::int>(){() → mai::Class4<core::int>};
+  self::expect(true, c4f is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4f is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+    f4d<int, String>(); // error
+       ^" in f4d{<inapplicable>}.<core::int, core::String>();
+  };
+  () → mai::Class4<core::int> f4e = f4d<core::int>;
+  mai::Class4<core::int> c4g = f4e(){() → mai::Class4<core::int>};
+  self::expect(true, c4g is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4g is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+    f4e<int>(); // error
+       ^" in f4e{<inapplicable>}.<core::int>();
+  };
+  dynamic f4f = #C6;
+  dynamic c4h = f4f{dynamic}.call();
+  self::expect(true, c4h is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4h is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::throws(() → dynamic => f4f{dynamic}.call<core::int, core::String>());
+  <T extends core::num>() → mai::Class5<T> f5a = #C7;
+  mai::Class5<core::num> c5a = f5a<core::num>(){() → mai::Class5<core::num>};
+  self::expect(true, c5a is{ForNonNullableByDefault} mai::Class5<core::num>);
+  self::expect(false, c5a is{ForNonNullableByDefault} mai::Class5<core::int>);
+  mai::Class5<core::int> c5b = f5a<core::int>(){() → mai::Class5<core::int>};
+  self::expect(true, c5b is{ForNonNullableByDefault} mai::Class5<core::int>);
+  self::expect(false, c5b is{ForNonNullableByDefault} mai::Class5<core::double>);
+  () → Null {
+    f5a<core::String>(){() → mai::Class5<core::String>};
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+    f5a<int, String>(); // error
+       ^" in f5a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f5b = #C7;
+  dynamic c5c = f5b{dynamic}.call();
+  self::expect(true, c5c is{ForNonNullableByDefault} mai::Class5<core::num>);
+  self::expect(false, c5c is{ForNonNullableByDefault} mai::Class5<core::int>);
+  dynamic c5d = f5b{dynamic}.call<core::int>();
+  self::expect(true, c5d is{ForNonNullableByDefault} mai::Class5<core::int>);
+  self::expect(false, c5d is{ForNonNullableByDefault} mai::Class5<core::double>);
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::int, core::String>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → mai::Class1
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → mai::Class1
+    return new mai::Class1::•();
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::Class2::redirect]/*isLegacy*/;
+  constructor named() → mai::Class2
+    : super core::Object::•()
+    ;
+  static method _#named#tearOff() → mai::Class2
+    return new mai::Class2::named();
+  static factory redirect() → mai::Class2
+    let dynamic #redirecting_factory = mai::Class2::named in invalid-expression;
+  static method _#redirect#tearOff() → mai::Class2
+    return new mai::Class2::named();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  constructor •(core::int field) → mai::Class3
+    : mai::Class3::field = field, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field) → mai::Class3
+    return new mai::Class3::•(field);
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::Class4::redirect]/*isLegacy*/;
+  constructor _() → mai::Class4<mai::Class4::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#_#tearOff::T%>
+    return new mai::Class4::_<mai::Class4::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::•::T%>
+    return new mai::Class4::_<mai::Class4::•::T%>();
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#new#tearOff::T%>
+    return mai::Class4::•<mai::Class4::_#new#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::redirect::T%>
+    let dynamic #redirecting_factory = mai::Class4::_ in let mai::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#redirect#tearOff::T%>
+    return new mai::Class4::_<mai::Class4::_#redirect#tearOff::T%>();
+}
+class Class5<T extends core::num> extends core::Object {
+  constructor _() → mai::Class5<mai::Class5::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#_#tearOff::T>
+    return new mai::Class5::_<mai::Class5::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → mai::Class5<mai::Class5::•::T>
+    return new mai::Class5::_<mai::Class5::•::T>();
+  static method _#new#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#new#tearOff::T>
+    return mai::Class5::•<mai::Class5::_#new#tearOff::T>();
+}
+
+constants  {
+  #C1 = static-tearoff mai::Class1::_#new#tearOff
+  #C2 = static-tearoff mai::Class2::_#named#tearOff
+  #C3 = static-tearoff mai::Class2::_#redirect#tearOff
+  #C4 = static-tearoff mai::Class3::_#new#tearOff
+  #C5 = static-tearoff mai::Class4::_#new#tearOff
+  #C6 = static-tearoff mai::Class4::_#redirect#tearOff
+  #C7 = static-tearoff mai::Class5::_#new#tearOff
+  #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.outline.expect
new file mode 100644
index 0000000..a682b15
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.outline.expect
@@ -0,0 +1,67 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+static final field core::bool inSoundMode;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → self2::Class1
+    ;
+  static method _#new#tearOff() → self2::Class1
+    return new self2::Class1::•();
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self2::Class2::redirect]/*isLegacy*/;
+  constructor named() → self2::Class2
+    ;
+  static method _#named#tearOff() → self2::Class2
+    return new self2::Class2::named();
+  static factory redirect() → self2::Class2
+    let dynamic #redirecting_factory = self2::Class2::named in invalid-expression;
+  static method _#redirect#tearOff() → self2::Class2
+    return new self2::Class2::named();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  constructor •(core::int field) → self2::Class3
+    ;
+  static method _#new#tearOff(core::int field) → self2::Class3
+    return new self2::Class3::•(field);
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self2::Class4::redirect]/*isLegacy*/;
+  constructor _() → self2::Class4<self2::Class4::T%>
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self2::Class4<self2::Class4::_#_#tearOff::T%>
+    return new self2::Class4::_<self2::Class4::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self2::Class4<self2::Class4::•::T%>
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self2::Class4<self2::Class4::_#new#tearOff::T%>
+    return self2::Class4::•<self2::Class4::_#new#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self2::Class4<self2::Class4::redirect::T%>
+    let dynamic #redirecting_factory = self2::Class4::_ in let self2::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self2::Class4<self2::Class4::_#redirect#tearOff::T%>
+    return new self2::Class4::_<self2::Class4::_#redirect#tearOff::T%>();
+}
+class Class5<T extends core::num> extends core::Object {
+  constructor _() → self2::Class5<self2::Class5::T>
+    ;
+  static method _#_#tearOff<T extends core::num>() → self2::Class5<self2::Class5::_#_#tearOff::T>
+    return new self2::Class5::_<self2::Class5::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self2::Class5<self2::Class5::•::T>
+    ;
+  static method _#new#tearOff<T extends core::num>() → self2::Class5<self2::Class5::_#new#tearOff::T>
+    return self2::Class5::•<self2::Class5::_#new#tearOff::T>();
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..9edd33a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.transformed.expect
@@ -0,0 +1,246 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+//     f4a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+//     f4b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+//     f4d<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+//     f4e<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:112:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+//     f5a<int, String>(); // error
+//        ^
+//
+import self as self;
+import "main_lib.dart" as mai;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  () → mai::Class1 f1a = #C1;
+  mai::Class1 c1a = f1a(){() → mai::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} mai::Class1);
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} mai::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → mai::Class2 f2a = #C2;
+  mai::Class2 c2a = f2a(){() → mai::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} mai::Class2);
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} mai::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+  () → mai::Class2 f2c = #C3;
+  mai::Class2 c2c = f2c(){() → mai::Class2};
+  self::expect(true, c2c is{ForNonNullableByDefault} mai::Class2);
+  dynamic f2d = #C3;
+  dynamic c2d = f2d{dynamic}.call();
+  self::expect(true, c2d is{ForNonNullableByDefault} mai::Class2);
+  self::expect(true, core::identical(f2c, f2d));
+  (core::int) → mai::Class3 f3a = #C4;
+  mai::Class3 c3a = f3a(42){(core::int) → mai::Class3};
+  self::expect(42, c3a.{mai::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  <T extends core::Object? = dynamic>() → mai::Class4<T%> f4a = #C5;
+  mai::Class4<dynamic> c4a = f4a<dynamic>(){() → mai::Class4<dynamic>};
+  self::expect(true, c4a is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4a is{ForNonNullableByDefault} mai::Class4<core::int>);
+  mai::Class4<core::int> c4b = f4a<core::int>(){() → mai::Class4<core::int>};
+  self::expect(true, c4b is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4b is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+    f4a<int, String>(); // error
+       ^" in f4a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → mai::Class4<core::int> f4b = f4a<core::int>;
+  mai::Class4<core::int> c4c = f4b(){() → mai::Class4<core::int>};
+  self::expect(true, c4c is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4c is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+    f4b<int>(); // error
+       ^" in f4b{<inapplicable>}.<core::int>();
+  };
+  dynamic f4c = #C5;
+  dynamic c4d = f4c{dynamic}.call();
+  self::expect(true, c4d is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4d is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::throws(() → dynamic => f4c{dynamic}.call<core::int, core::String>());
+  <T extends core::Object? = dynamic>() → mai::Class4<T%> f4d = #C6;
+  mai::Class4<dynamic> c4e = f4d<dynamic>(){() → mai::Class4<dynamic>};
+  self::expect(true, c4e is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4e is{ForNonNullableByDefault} mai::Class4<core::int>);
+  mai::Class4<core::int> c4f = f4d<core::int>(){() → mai::Class4<core::int>};
+  self::expect(true, c4f is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4f is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+    f4d<int, String>(); // error
+       ^" in f4d{<inapplicable>}.<core::int, core::String>();
+  };
+  () → mai::Class4<core::int> f4e = f4d<core::int>;
+  mai::Class4<core::int> c4g = f4e(){() → mai::Class4<core::int>};
+  self::expect(true, c4g is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::expect(false, c4g is{ForNonNullableByDefault} mai::Class4<core::String>);
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+    f4e<int>(); // error
+       ^" in f4e{<inapplicable>}.<core::int>();
+  };
+  dynamic f4f = #C6;
+  dynamic c4h = f4f{dynamic}.call();
+  self::expect(true, c4h is{ForNonNullableByDefault} mai::Class4<dynamic>);
+  self::expect(false, c4h is{ForNonNullableByDefault} mai::Class4<core::int>);
+  self::throws(() → dynamic => f4f{dynamic}.call<core::int, core::String>());
+  <T extends core::num>() → mai::Class5<T> f5a = #C7;
+  mai::Class5<core::num> c5a = f5a<core::num>(){() → mai::Class5<core::num>};
+  self::expect(true, c5a is{ForNonNullableByDefault} mai::Class5<core::num>);
+  self::expect(false, c5a is{ForNonNullableByDefault} mai::Class5<core::int>);
+  mai::Class5<core::int> c5b = f5a<core::int>(){() → mai::Class5<core::int>};
+  self::expect(true, c5b is{ForNonNullableByDefault} mai::Class5<core::int>);
+  self::expect(false, c5b is{ForNonNullableByDefault} mai::Class5<core::double>);
+  () → Null {
+    f5a<core::String>(){() → mai::Class5<core::String>};
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+    f5a<int, String>(); // error
+       ^" in f5a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f5b = #C7;
+  dynamic c5c = f5b{dynamic}.call();
+  self::expect(true, c5c is{ForNonNullableByDefault} mai::Class5<core::num>);
+  self::expect(false, c5c is{ForNonNullableByDefault} mai::Class5<core::int>);
+  dynamic c5d = f5b{dynamic}.call<core::int>();
+  self::expect(true, c5d is{ForNonNullableByDefault} mai::Class5<core::int>);
+  self::expect(false, c5d is{ForNonNullableByDefault} mai::Class5<core::double>);
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::int, core::String>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → mai::Class1
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → mai::Class1
+    return new mai::Class1::•();
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::Class2::redirect]/*isLegacy*/;
+  constructor named() → mai::Class2
+    : super core::Object::•()
+    ;
+  static method _#named#tearOff() → mai::Class2
+    return new mai::Class2::named();
+  static factory redirect() → mai::Class2
+    let Never #redirecting_factory = mai::Class2::named in invalid-expression;
+  static method _#redirect#tearOff() → mai::Class2
+    return new mai::Class2::named();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  constructor •(core::int field) → mai::Class3
+    : mai::Class3::field = field, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field) → mai::Class3
+    return new mai::Class3::•(field);
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::Class4::redirect]/*isLegacy*/;
+  constructor _() → mai::Class4<mai::Class4::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#_#tearOff::T%>
+    return new mai::Class4::_<mai::Class4::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::•::T%>
+    return new mai::Class4::_<mai::Class4::•::T%>();
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#new#tearOff::T%>
+    return mai::Class4::•<mai::Class4::_#new#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::redirect::T%>
+    let Never #redirecting_factory = mai::Class4::_ in let mai::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#redirect#tearOff::T%>
+    return new mai::Class4::_<mai::Class4::_#redirect#tearOff::T%>();
+}
+class Class5<T extends core::num> extends core::Object {
+  constructor _() → mai::Class5<mai::Class5::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#_#tearOff::T>
+    return new mai::Class5::_<mai::Class5::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → mai::Class5<mai::Class5::•::T>
+    return new mai::Class5::_<mai::Class5::•::T>();
+  static method _#new#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#new#tearOff::T>
+    return mai::Class5::•<mai::Class5::_#new#tearOff::T>();
+}
+
+constants  {
+  #C1 = static-tearoff mai::Class1::_#new#tearOff
+  #C2 = static-tearoff mai::Class2::_#named#tearOff
+  #C3 = static-tearoff mai::Class2::_#redirect#tearOff
+  #C4 = static-tearoff mai::Class3::_#new#tearOff
+  #C5 = static-tearoff mai::Class4::_#new#tearOff
+  #C6 = static-tearoff mai::Class4::_#redirect#tearOff
+  #C7 = static-tearoff mai::Class5::_#new#tearOff
+  #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main_lib.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main_lib.dart
new file mode 100644
index 0000000..eed7823
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main_lib.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.
+
+class Class1 {}
+
+class Class2 {
+  Class2.named();
+  factory Class2.redirect() = Class2.named;
+}
+
+class Class3 {
+  final int field;
+
+  Class3(this.field);
+}
+
+class Class4<T> {
+  Class4._();
+  factory Class4() => new Class4<T>._();
+  factory Class4.redirect() = Class4._;
+}
+
+class Class5<T extends num> {
+  Class5._();
+  factory Class5() => new Class5<T>._();
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/test.options b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/test.options
new file mode 100644
index 0000000..bfe6dc8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/test.options
@@ -0,0 +1 @@
+main_lib.dart
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.expect
index d686ae7..1802229 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.expect
@@ -172,9 +172,9 @@
 }
 
 constants  {
-  #C1 = tearoff self::Class1::_#new#tearOff
-  #C2 = tearoff self::Class2::_#new#tearOff
-  #C3 = tearoff self::Class3::_#new#tearOff
-  #C4 = tearoff self::Class4::_#new#tearOff
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
   #C5 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.transformed.expect
index d58a81e..d13da4b 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.transformed.expect
@@ -172,9 +172,9 @@
 }
 
 constants  {
-  #C1 = tearoff self::Class1::_#new#tearOff
-  #C2 = tearoff self::Class2::_#new#tearOff
-  #C3 = tearoff self::Class3::_#new#tearOff
-  #C4 = tearoff self::Class4::_#new#tearOff
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
   #C5 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.expect
index d686ae7..1802229 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.expect
@@ -172,9 +172,9 @@
 }
 
 constants  {
-  #C1 = tearoff self::Class1::_#new#tearOff
-  #C2 = tearoff self::Class2::_#new#tearOff
-  #C3 = tearoff self::Class3::_#new#tearOff
-  #C4 = tearoff self::Class4::_#new#tearOff
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
   #C5 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.transformed.expect
index d58a81e..d13da4b 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.transformed.expect
@@ -172,9 +172,9 @@
 }
 
 constants  {
-  #C1 = tearoff self::Class1::_#new#tearOff
-  #C2 = tearoff self::Class2::_#new#tearOff
-  #C3 = tearoff self::Class3::_#new#tearOff
-  #C4 = tearoff self::Class4::_#new#tearOff
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
   #C5 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart
new file mode 100644
index 0000000..a8d167a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart
@@ -0,0 +1,134 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+  print('inSoundMode: $inSoundMode');
+  testGeneric();
+  testBounded();
+}
+
+class Class1<T> {
+  Class1._();
+  factory Class1() => new Class1<T>._();
+}
+
+testGeneric() {
+  var f1a = Class1.new;
+  var c1a = f1a();
+  expect(true, c1a is Class1<dynamic>);
+  expect(false, c1a is Class1<int>);
+  var c1b = f1a<int>();
+  expect(true, c1b is Class1<int>);
+  expect(false, c1b is Class1<String>);
+  () {
+    f1a<int, String>(); // error
+  };
+
+  var f1b = f1a<int>;
+  var c1c = f1b();
+  expect(true, c1c is Class1<int>);
+  expect(false, c1c is Class1<String>);
+  () {
+    f1b<int>(); // error
+  };
+
+  dynamic f1c = Class1.new;
+  var c1d = f1c();
+  expect(true, c1a is Class1<dynamic>);
+  expect(false, c1a is Class1<int>);
+  throws(() => f1c<int, String>());
+}
+
+class Class2<T extends num> {
+  Class2._();
+  factory Class2() => new Class2<T>._();
+}
+
+class Class3<T extends S, S> {
+  Class3._();
+  factory Class3() => new Class3<T, S>._();
+}
+
+class Class4<T extends Class4<T>> {
+  Class4._();
+  factory Class4() => new Class4<T>._();
+}
+
+class Class4int extends Class4<Class4int> {
+  Class4int._() : super._();
+  factory Class4int() => new Class4int._();
+}
+
+testBounded() {
+  var f2a = Class2.new;
+  var c2a = f2a();
+  expect(true, c2a is Class2<num>);
+  expect(false, c2a is Class2<int>);
+  var c2b = f2a<int>();
+  expect(true, c2b is Class2<int>);
+  expect(false, c2b is Class2<double>);
+  () {
+    f2a<String>(); // error
+    f2a<int, String>(); // error
+  };
+
+  dynamic f2b = Class2.new;
+  var c2c = f2b();
+  expect(true, c2c is Class2<num>);
+  expect(false, c2c is Class2<int>);
+  var c2d = f2b<int>();
+  expect(true, c2d is Class2<int>);
+  expect(false, c2d is Class2<double>);
+  throws(() => f2b<String>());
+  throws(() => f2b<int, String>());
+
+  var f3a = Class3.new;
+  var c3a = f3a();
+  expect(true, c3a is Class3<dynamic, dynamic>);
+  expect(false, c3a is Class3<int, num>);
+  var c3b = f3a<int, num>();
+  expect(true, c3b is Class3<int, num>);
+  expect(false, c3b is Class3<double, num>);
+  () {
+    f3a<num, int>(); // error
+  };
+
+  dynamic f3b = Class3.new;
+  var c3c = f3b();
+  expect(true, c3c is Class3<dynamic, dynamic>);
+  expect(false, c3c is Class3<int, num>);
+  var c3d = f3b<int, num>();
+  expect(true, c3d is Class3<int, num>);
+  expect(false, c3d is Class3<double, num>);
+  throws(() => f3b<num, int>());
+
+  var f4a = Class4.new;
+  () {
+    var c4a = f4a(); // error
+  };
+
+  dynamic f4b = Class4.new;
+  throws(() => f4b());
+  var c4b = f4b<Class4int>();
+  expect(true, c4b is Class4<Class4int>);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..eae54df
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.expect
@@ -0,0 +1,200 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+//     f1a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+//     f1b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+//     f2a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f3a<num, int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+//  - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart'.
+//  - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//     var c4a = f4a(); // error
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+  constructor _() → self::Class1<self::Class1::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+    return new self::Class1::_<self::Class1::•::T%>();
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+    return self::Class1::•<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+  constructor _() → self::Class2<self::Class2::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+    return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+    return new self::Class2::_<self::Class2::•::T>();
+  static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+    return self::Class2::•<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+  constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+  static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+    return new self::Class3::_<self::Class3::•::T%, self::Class3::•::S%>();
+  static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+    return self::Class3::•<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+  constructor _() → self::Class4<self::Class4::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+    return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+  static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+    return new self::Class4::_<self::Class4::•::T>();
+  static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+    return self::Class4::•<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+  constructor _() → self::Class4int
+    : super self::Class4::_()
+    ;
+  static method _#_#tearOff() → self::Class4int
+    return new self::Class4int::_();
+  static factory •() → self::Class4int
+    return new self::Class4int::_();
+  static method _#new#tearOff() → self::Class4int
+    return self::Class4int::•();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testGeneric();
+  self::testBounded();
+}
+static method testGeneric() → dynamic {
+  <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+  self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+    f1a<int, String>(); // error
+       ^" in f1a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → self::Class1<core::int> f1b = f1a<core::int>;
+  self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+  self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+    f1b<int>(); // error
+       ^" in f1b{<inapplicable>}.<core::int>();
+  };
+  dynamic f1c = #C1;
+  dynamic c1d = f1c{dynamic}.call();
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+  <T extends core::num>() → self::Class2<T> f2a = #C2;
+  self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+  () → Null {
+    f2a<core::String>(){() → self::Class2<core::String>};
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+    f2a<int, String>(); // error
+       ^" in f2a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f2b = #C2;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+  dynamic c2d = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+  <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+  self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+  self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  () → Null {
+    f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+  };
+  dynamic f3b = #C3;
+  dynamic c3c = f3b{dynamic}.call();
+  self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+  self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+  <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+  () → Null {
+    self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+  };
+  dynamic f4b = #C4;
+  self::throws(() → dynamic => f4b{dynamic}.call());
+  dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+  self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..552fe7e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,200 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+//     f1a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+//     f1b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+//     f2a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f3a<num, int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+//  - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart'.
+//  - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//     var c4a = f4a(); // error
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+  constructor _() → self::Class1<self::Class1::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+    return new self::Class1::_<self::Class1::•::T%>();
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+    return self::Class1::•<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+  constructor _() → self::Class2<self::Class2::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+    return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+    return new self::Class2::_<self::Class2::•::T>();
+  static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+    return self::Class2::•<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+  constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+  static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+    return new self::Class3::_<self::Class3::•::T%, self::Class3::•::S%>();
+  static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+    return self::Class3::•<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+  constructor _() → self::Class4<self::Class4::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+    return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+  static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+    return new self::Class4::_<self::Class4::•::T>();
+  static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+    return self::Class4::•<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+  constructor _() → self::Class4int
+    : super self::Class4::_()
+    ;
+  static method _#_#tearOff() → self::Class4int
+    return new self::Class4int::_();
+  static factory •() → self::Class4int
+    return new self::Class4int::_();
+  static method _#new#tearOff() → self::Class4int
+    return self::Class4int::•();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testGeneric();
+  self::testBounded();
+}
+static method testGeneric() → dynamic {
+  <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+  self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+    f1a<int, String>(); // error
+       ^" in f1a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → self::Class1<core::int> f1b = f1a<core::int>;
+  self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+  self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+    f1b<int>(); // error
+       ^" in f1b{<inapplicable>}.<core::int>();
+  };
+  dynamic f1c = #C1;
+  dynamic c1d = f1c{dynamic}.call();
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+  <T extends core::num>() → self::Class2<T> f2a = #C2;
+  self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+  () → Null {
+    f2a<core::String>(){() → self::Class2<core::String>};
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+    f2a<int, String>(); // error
+       ^" in f2a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f2b = #C2;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+  dynamic c2d = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+  <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+  self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+  self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  () → Null {
+    f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+  };
+  dynamic f3b = #C3;
+  dynamic c3c = f3b{dynamic}.call();
+  self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+  self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+  <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+  () → Null {
+    self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+  };
+  dynamic f4b = #C4;
+  self::throws(() → dynamic => f4b{dynamic}.call());
+  dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+  self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..b692fbf
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,33 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1<T> {
+  Class1._();
+  factory Class1() => new Class1<T>._();
+}
+
+testGeneric() {}
+
+class Class2<T extends num> {
+  Class2._();
+  factory Class2() => new Class2<T>._();
+}
+
+class Class3<T extends S, S> {
+  Class3._();
+  factory Class3() => new Class3<T, S>._();
+}
+
+class Class4<T extends Class4<T>> {
+  Class4._();
+  factory Class4() => new Class4<T>._();
+}
+
+class Class4int extends Class4<Class4int> {
+  Class4int._() : super._();
+  factory Class4int() => new Class4int._();
+}
+
+testBounded() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c82d489
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,31 @@
+class Class1<T> {
+  Class1._();
+  factory Class1() => new Class1<T>._();
+}
+
+class Class2<T extends num> {
+  Class2._();
+  factory Class2() => new Class2<T>._();
+}
+
+class Class3<T extends S, S> {
+  Class3._();
+  factory Class3() => new Class3<T, S>._();
+}
+
+class Class4<T extends Class4<T>> {
+  Class4._();
+  factory Class4() => new Class4<T>._();
+}
+
+class Class4int extends Class4<Class4int> {
+  Class4int._() : super._();
+  factory Class4int() => new Class4int._();
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testBounded() {}
+testGeneric() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..eae54df
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.expect
@@ -0,0 +1,200 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+//     f1a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+//     f1b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+//     f2a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f3a<num, int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+//  - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart'.
+//  - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//     var c4a = f4a(); // error
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+  constructor _() → self::Class1<self::Class1::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+    return new self::Class1::_<self::Class1::•::T%>();
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+    return self::Class1::•<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+  constructor _() → self::Class2<self::Class2::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+    return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+    return new self::Class2::_<self::Class2::•::T>();
+  static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+    return self::Class2::•<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+  constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+  static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+    return new self::Class3::_<self::Class3::•::T%, self::Class3::•::S%>();
+  static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+    return self::Class3::•<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+  constructor _() → self::Class4<self::Class4::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+    return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+  static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+    return new self::Class4::_<self::Class4::•::T>();
+  static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+    return self::Class4::•<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+  constructor _() → self::Class4int
+    : super self::Class4::_()
+    ;
+  static method _#_#tearOff() → self::Class4int
+    return new self::Class4int::_();
+  static factory •() → self::Class4int
+    return new self::Class4int::_();
+  static method _#new#tearOff() → self::Class4int
+    return self::Class4int::•();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testGeneric();
+  self::testBounded();
+}
+static method testGeneric() → dynamic {
+  <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+  self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+    f1a<int, String>(); // error
+       ^" in f1a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → self::Class1<core::int> f1b = f1a<core::int>;
+  self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+  self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+    f1b<int>(); // error
+       ^" in f1b{<inapplicable>}.<core::int>();
+  };
+  dynamic f1c = #C1;
+  dynamic c1d = f1c{dynamic}.call();
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+  <T extends core::num>() → self::Class2<T> f2a = #C2;
+  self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+  () → Null {
+    f2a<core::String>(){() → self::Class2<core::String>};
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+    f2a<int, String>(); // error
+       ^" in f2a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f2b = #C2;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+  dynamic c2d = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+  <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+  self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+  self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  () → Null {
+    f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+  };
+  dynamic f3b = #C3;
+  dynamic c3c = f3b{dynamic}.call();
+  self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+  self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+  <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+  () → Null {
+    self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+  };
+  dynamic f4b = #C4;
+  self::throws(() → dynamic => f4b{dynamic}.call());
+  dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+  self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..6216fd6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,65 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+  constructor _() → self::Class1<self::Class1::T%>
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+    return self::Class1::•<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+  constructor _() → self::Class2<self::Class2::T>
+    ;
+  static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+    return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+    ;
+  static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+    return self::Class2::•<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+  constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+    ;
+  static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+  static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+    ;
+  static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+    return self::Class3::•<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+  constructor _() → self::Class4<self::Class4::T>
+    ;
+  static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+    return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+  static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+    ;
+  static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+    return self::Class4::•<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+  constructor _() → self::Class4int
+    ;
+  static method _#_#tearOff() → self::Class4int
+    return new self::Class4int::_();
+  static factory •() → self::Class4int
+    ;
+  static method _#new#tearOff() → self::Class4int
+    return self::Class4int::•();
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+  ;
+static method testGeneric() → dynamic
+  ;
+static method testBounded() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..552fe7e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,200 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+//     f1a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+//     f1b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+//     f2a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f3a<num, int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+//  - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart'.
+//  - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//     var c4a = f4a(); // error
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+  constructor _() → self::Class1<self::Class1::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+    return new self::Class1::_<self::Class1::•::T%>();
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+    return self::Class1::•<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+  constructor _() → self::Class2<self::Class2::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+    return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+    return new self::Class2::_<self::Class2::•::T>();
+  static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+    return self::Class2::•<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+  constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+  static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+    return new self::Class3::_<self::Class3::•::T%, self::Class3::•::S%>();
+  static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+    return self::Class3::•<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+  constructor _() → self::Class4<self::Class4::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+    return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+  static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+    return new self::Class4::_<self::Class4::•::T>();
+  static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+    return self::Class4::•<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+  constructor _() → self::Class4int
+    : super self::Class4::_()
+    ;
+  static method _#_#tearOff() → self::Class4int
+    return new self::Class4int::_();
+  static factory •() → self::Class4int
+    return new self::Class4int::_();
+  static method _#new#tearOff() → self::Class4int
+    return self::Class4int::•();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testGeneric();
+  self::testBounded();
+}
+static method testGeneric() → dynamic {
+  <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+  self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+    f1a<int, String>(); // error
+       ^" in f1a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → self::Class1<core::int> f1b = f1a<core::int>;
+  self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+  self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+    f1b<int>(); // error
+       ^" in f1b{<inapplicable>}.<core::int>();
+  };
+  dynamic f1c = #C1;
+  dynamic c1d = f1c{dynamic}.call();
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+  <T extends core::num>() → self::Class2<T> f2a = #C2;
+  self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+  () → Null {
+    f2a<core::String>(){() → self::Class2<core::String>};
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+    f2a<int, String>(); // error
+       ^" in f2a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f2b = #C2;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+  dynamic c2d = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+  <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+  self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+  self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  () → Null {
+    f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+  };
+  dynamic f3b = #C3;
+  dynamic c3c = f3b{dynamic}.call();
+  self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+  self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+  <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+  () → Null {
+    self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+  };
+  dynamic f4b = #C4;
+  self::throws(() → dynamic => f4b{dynamic}.call());
+  dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+  self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart
new file mode 100644
index 0000000..302f380
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart
@@ -0,0 +1,134 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+  print('inSoundMode: $inSoundMode');
+  testGeneric();
+  testBounded();
+}
+
+class Class1<T> {
+  Class1._();
+  factory Class1() = Class1<T>._;
+}
+
+testGeneric() {
+  var f1a = Class1.new;
+  var c1a = f1a();
+  expect(true, c1a is Class1<dynamic>);
+  expect(false, c1a is Class1<int>);
+  var c1b = f1a<int>();
+  expect(true, c1b is Class1<int>);
+  expect(false, c1b is Class1<String>);
+  () {
+    f1a<int, String>(); // error
+  };
+
+  var f1b = f1a<int>;
+  var c1c = f1b();
+  expect(true, c1c is Class1<int>);
+  expect(false, c1c is Class1<String>);
+  () {
+    f1b<int>(); // error
+  };
+
+  dynamic f1c = Class1.new;
+  var c1d = f1c();
+  expect(true, c1a is Class1<dynamic>);
+  expect(false, c1a is Class1<int>);
+  throws(() => f1c<int, String>());
+}
+
+class Class2<T extends num> {
+  Class2._();
+  factory Class2() = Class2<T>._;
+}
+
+class Class3<T extends S, S> {
+  Class3._();
+  factory Class3() = Class3<T, S>._;
+}
+
+class Class4<T extends Class4<T>> {
+  Class4._();
+  factory Class4() = Class4<T>._;
+}
+
+class Class4int extends Class4<Class4int> {
+  Class4int._() : super._();
+  factory Class4int() = Class4int._;
+}
+
+testBounded() {
+  var f2a = Class2.new;
+  var c2a = f2a();
+  expect(true, c2a is Class2<num>);
+  expect(false, c2a is Class2<int>);
+  var c2b = f2a<int>();
+  expect(true, c2b is Class2<int>);
+  expect(false, c2b is Class2<double>);
+  () {
+    f2a<String>(); // error
+    f2a<int, String>(); // error
+  };
+
+  dynamic f2b = Class2.new;
+  var c2c = f2b();
+  expect(true, c2c is Class2<num>);
+  expect(false, c2c is Class2<int>);
+  var c2d = f2b<int>();
+  expect(true, c2d is Class2<int>);
+  expect(false, c2d is Class2<double>);
+  throws(() => f2b<String>());
+  throws(() => f2b<int, String>());
+
+  var f3a = Class3.new;
+  var c3a = f3a();
+  expect(true, c3a is Class3<dynamic, dynamic>);
+  expect(false, c3a is Class3<int, num>);
+  var c3b = f3a<int, num>();
+  expect(true, c3b is Class3<int, num>);
+  expect(false, c3b is Class3<double, num>);
+  () {
+    f3a<num, int>(); // error
+  };
+
+  dynamic f3b = Class3.new;
+  var c3c = f3b();
+  expect(true, c3c is Class3<dynamic, dynamic>);
+  expect(false, c3c is Class3<int, num>);
+  var c3d = f3b<int, num>();
+  expect(true, c3d is Class3<int, num>);
+  expect(false, c3d is Class3<double, num>);
+  throws(() => f3b<num, int>());
+
+  var f4a = Class4.new;
+  () {
+    var c4a = f4a(); // error
+  };
+
+  dynamic f4b = Class4.new;
+  throws(() => f4b());
+  var c4b = f4b<Class4int>();
+  expect(true, c4b is Class4<Class4int>);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..14303b7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.expect
@@ -0,0 +1,205 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+//     f1a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+//     f1b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+//     f2a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f3a<num, int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+//  - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart'.
+//  - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//     var c4a = f4a(); // error
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1<self::Class1::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+    let dynamic #redirecting_factory = self::Class1::_ in let self::Class1::•::T% #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+  constructor _() → self::Class2<self::Class2::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+    return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+    let dynamic #redirecting_factory = self::Class2::_ in let self::Class2::•::T #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+    return new self::Class2::_<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+  static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+    let dynamic #redirecting_factory = self::Class3::_ in let self::Class3::•::T% #typeArg0 = null in let self::Class3::•::S% #typeArg1 = null in invalid-expression;
+  static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _() → self::Class4<self::Class4::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+    return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+  static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+    let dynamic #redirecting_factory = self::Class4::_ in let self::Class4::•::T #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+    return new self::Class4::_<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+  static final field dynamic _redirecting# = <dynamic>[self::Class4int::•]/*isLegacy*/;
+  constructor _() → self::Class4int
+    : super self::Class4::_()
+    ;
+  static method _#_#tearOff() → self::Class4int
+    return new self::Class4int::_();
+  static factory •() → self::Class4int
+    let dynamic #redirecting_factory = self::Class4int::_ in invalid-expression;
+  static method _#new#tearOff() → self::Class4int
+    return new self::Class4int::_();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testGeneric();
+  self::testBounded();
+}
+static method testGeneric() → dynamic {
+  <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+  self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+    f1a<int, String>(); // error
+       ^" in f1a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → self::Class1<core::int> f1b = f1a<core::int>;
+  self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+  self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+    f1b<int>(); // error
+       ^" in f1b{<inapplicable>}.<core::int>();
+  };
+  dynamic f1c = #C1;
+  dynamic c1d = f1c{dynamic}.call();
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+  <T extends core::num>() → self::Class2<T> f2a = #C2;
+  self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+  () → Null {
+    f2a<core::String>(){() → self::Class2<core::String>};
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+    f2a<int, String>(); // error
+       ^" in f2a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f2b = #C2;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+  dynamic c2d = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+  <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+  self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+  self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  () → Null {
+    f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+  };
+  dynamic f3b = #C3;
+  dynamic c3c = f3b{dynamic}.call();
+  self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+  self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+  <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+  () → Null {
+    self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+  };
+  dynamic f4b = #C4;
+  self::throws(() → dynamic => f4b{dynamic}.call());
+  dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+  self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..2ede93c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,205 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+//     f1a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+//     f1b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+//     f2a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f3a<num, int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+//  - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart'.
+//  - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//     var c4a = f4a(); // error
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1<self::Class1::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+    let Never #redirecting_factory = self::Class1::_ in let self::Class1::•::T% #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+  constructor _() → self::Class2<self::Class2::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+    return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+    let Never #redirecting_factory = self::Class2::_ in let self::Class2::•::T #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+    return new self::Class2::_<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+  static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+    let Never #redirecting_factory = self::Class3::_ in let self::Class3::•::T% #typeArg0 = null in let self::Class3::•::S% #typeArg1 = null in invalid-expression;
+  static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _() → self::Class4<self::Class4::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+    return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+  static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+    let Never #redirecting_factory = self::Class4::_ in let self::Class4::•::T #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+    return new self::Class4::_<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+  static final field dynamic _redirecting# = <dynamic>[self::Class4int::•]/*isLegacy*/;
+  constructor _() → self::Class4int
+    : super self::Class4::_()
+    ;
+  static method _#_#tearOff() → self::Class4int
+    return new self::Class4int::_();
+  static factory •() → self::Class4int
+    let Never #redirecting_factory = self::Class4int::_ in invalid-expression;
+  static method _#new#tearOff() → self::Class4int
+    return new self::Class4int::_();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testGeneric();
+  self::testBounded();
+}
+static method testGeneric() → dynamic {
+  <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+  self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+    f1a<int, String>(); // error
+       ^" in f1a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → self::Class1<core::int> f1b = f1a<core::int>;
+  self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+  self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+    f1b<int>(); // error
+       ^" in f1b{<inapplicable>}.<core::int>();
+  };
+  dynamic f1c = #C1;
+  dynamic c1d = f1c{dynamic}.call();
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+  <T extends core::num>() → self::Class2<T> f2a = #C2;
+  self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+  () → Null {
+    f2a<core::String>(){() → self::Class2<core::String>};
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+    f2a<int, String>(); // error
+       ^" in f2a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f2b = #C2;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+  dynamic c2d = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+  <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+  self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+  self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  () → Null {
+    f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+  };
+  dynamic f3b = #C3;
+  dynamic c3c = f3b{dynamic}.call();
+  self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+  self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+  <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+  () → Null {
+    self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+  };
+  dynamic f4b = #C4;
+  self::throws(() → dynamic => f4b{dynamic}.call());
+  dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+  self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..ad86735
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,33 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1<T> {
+  Class1._();
+  factory Class1() = Class1<T>._;
+}
+
+testGeneric() {}
+
+class Class2<T extends num> {
+  Class2._();
+  factory Class2() = Class2<T>._;
+}
+
+class Class3<T extends S, S> {
+  Class3._();
+  factory Class3() = Class3<T, S>._;
+}
+
+class Class4<T extends Class4<T>> {
+  Class4._();
+  factory Class4() = Class4<T>._;
+}
+
+class Class4int extends Class4<Class4int> {
+  Class4int._() : super._();
+  factory Class4int() = Class4int._;
+}
+
+testBounded() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..24223f7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,31 @@
+class Class1<T> {
+  Class1._();
+  factory Class1() = Class1<T>._;
+}
+
+class Class2<T extends num> {
+  Class2._();
+  factory Class2() = Class2<T>._;
+}
+
+class Class3<T extends S, S> {
+  Class3._();
+  factory Class3() = Class3<T, S>._;
+}
+
+class Class4<T extends Class4<T>> {
+  Class4._();
+  factory Class4() = Class4<T>._;
+}
+
+class Class4int extends Class4<Class4int> {
+  Class4int._() : super._();
+  factory Class4int() = Class4int._;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testBounded() {}
+testGeneric() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..14303b7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.expect
@@ -0,0 +1,205 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+//     f1a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+//     f1b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+//     f2a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f3a<num, int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+//  - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart'.
+//  - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//     var c4a = f4a(); // error
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1<self::Class1::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+    let dynamic #redirecting_factory = self::Class1::_ in let self::Class1::•::T% #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+  constructor _() → self::Class2<self::Class2::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+    return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+    let dynamic #redirecting_factory = self::Class2::_ in let self::Class2::•::T #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+    return new self::Class2::_<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+  static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+    let dynamic #redirecting_factory = self::Class3::_ in let self::Class3::•::T% #typeArg0 = null in let self::Class3::•::S% #typeArg1 = null in invalid-expression;
+  static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _() → self::Class4<self::Class4::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+    return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+  static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+    let dynamic #redirecting_factory = self::Class4::_ in let self::Class4::•::T #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+    return new self::Class4::_<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+  static final field dynamic _redirecting# = <dynamic>[self::Class4int::•]/*isLegacy*/;
+  constructor _() → self::Class4int
+    : super self::Class4::_()
+    ;
+  static method _#_#tearOff() → self::Class4int
+    return new self::Class4int::_();
+  static factory •() → self::Class4int
+    let dynamic #redirecting_factory = self::Class4int::_ in invalid-expression;
+  static method _#new#tearOff() → self::Class4int
+    return new self::Class4int::_();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testGeneric();
+  self::testBounded();
+}
+static method testGeneric() → dynamic {
+  <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+  self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+    f1a<int, String>(); // error
+       ^" in f1a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → self::Class1<core::int> f1b = f1a<core::int>;
+  self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+  self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+    f1b<int>(); // error
+       ^" in f1b{<inapplicable>}.<core::int>();
+  };
+  dynamic f1c = #C1;
+  dynamic c1d = f1c{dynamic}.call();
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+  <T extends core::num>() → self::Class2<T> f2a = #C2;
+  self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+  () → Null {
+    f2a<core::String>(){() → self::Class2<core::String>};
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+    f2a<int, String>(); // error
+       ^" in f2a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f2b = #C2;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+  dynamic c2d = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+  <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+  self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+  self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  () → Null {
+    f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+  };
+  dynamic f3b = #C3;
+  dynamic c3c = f3b{dynamic}.call();
+  self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+  self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+  <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+  () → Null {
+    self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+  };
+  dynamic f4b = #C4;
+  self::throws(() → dynamic => f4b{dynamic}.call());
+  dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+  self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..26553e6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,70 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1<self::Class1::T%>
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+    let dynamic #redirecting_factory = self::Class1::_ in let self::Class1::•::T% #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+  constructor _() → self::Class2<self::Class2::T>
+    ;
+  static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+    return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+    let dynamic #redirecting_factory = self::Class2::_ in let self::Class2::•::T #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+    return new self::Class2::_<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+    ;
+  static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+  static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+    let dynamic #redirecting_factory = self::Class3::_ in let self::Class3::•::T% #typeArg0 = null in let self::Class3::•::S% #typeArg1 = null in invalid-expression;
+  static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _() → self::Class4<self::Class4::T>
+    ;
+  static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+    return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+  static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+    let dynamic #redirecting_factory = self::Class4::_ in let self::Class4::•::T #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+    return new self::Class4::_<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+  static final field dynamic _redirecting# = <dynamic>[self::Class4int::•]/*isLegacy*/;
+  constructor _() → self::Class4int
+    ;
+  static method _#_#tearOff() → self::Class4int
+    return new self::Class4int::_();
+  static factory •() → self::Class4int
+    let dynamic #redirecting_factory = self::Class4int::_ in invalid-expression;
+  static method _#new#tearOff() → self::Class4int
+    return new self::Class4int::_();
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+  ;
+static method testGeneric() → dynamic
+  ;
+static method testBounded() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..2ede93c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,205 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+//     f1a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+//     f1b<int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+//     f2a<int, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f3a<num, int>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+//  - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart'.
+//  - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//     var c4a = f4a(); // error
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1<self::Class1::T%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+  static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+    let Never #redirecting_factory = self::Class1::_ in let self::Class1::•::T% #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+    return new self::Class1::_<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+  constructor _() → self::Class2<self::Class2::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+    return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+  static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+    let Never #redirecting_factory = self::Class2::_ in let self::Class2::•::T #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+    return new self::Class2::_<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+  static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+    let Never #redirecting_factory = self::Class3::_ in let self::Class3::•::T% #typeArg0 = null in let self::Class3::•::S% #typeArg1 = null in invalid-expression;
+  static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+    return new self::Class3::_<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _() → self::Class4<self::Class4::T>
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+    return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+  static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+    let Never #redirecting_factory = self::Class4::_ in let self::Class4::•::T #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+    return new self::Class4::_<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+  static final field dynamic _redirecting# = <dynamic>[self::Class4int::•]/*isLegacy*/;
+  constructor _() → self::Class4int
+    : super self::Class4::_()
+    ;
+  static method _#_#tearOff() → self::Class4int
+    return new self::Class4int::_();
+  static factory •() → self::Class4int
+    let Never #redirecting_factory = self::Class4int::_ in invalid-expression;
+  static method _#new#tearOff() → self::Class4int
+    return new self::Class4int::_();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testGeneric();
+  self::testBounded();
+}
+static method testGeneric() → dynamic {
+  <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+  self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+    f1a<int, String>(); // error
+       ^" in f1a{<inapplicable>}.<core::int, core::String>();
+  };
+  () → self::Class1<core::int> f1b = f1a<core::int>;
+  self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+  self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+    f1b<int>(); // error
+       ^" in f1b{<inapplicable>}.<core::int>();
+  };
+  dynamic f1c = #C1;
+  dynamic c1d = f1c{dynamic}.call();
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+  self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+  self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+  <T extends core::num>() → self::Class2<T> f2a = #C2;
+  self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+  () → Null {
+    f2a<core::String>(){() → self::Class2<core::String>};
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+    f2a<int, String>(); // error
+       ^" in f2a{<inapplicable>}.<core::int, core::String>();
+  };
+  dynamic f2b = #C2;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+  self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+  dynamic c2d = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+  self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+  <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+  self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+  self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  () → Null {
+    f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+  };
+  dynamic f3b = #C3;
+  dynamic c3c = f3b{dynamic}.call();
+  self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+  self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+  self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+  <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+  () → Null {
+    self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+  };
+  dynamic f4b = #C4;
+  self::throws(() → dynamic => f4b{dynamic}.call());
+  dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+  self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
+  #C3 = static-tearoff self::Class3::_#new#tearOff
+  #C4 = static-tearoff self::Class4::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart
index fc8cba1..1750b68 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart
@@ -25,6 +25,9 @@
   Class2(this.field);
 }
 
+var Class1_new = Class1.new;
+var Class2_new = Class2.new;
+
 testInferred() {
   var f1a = Class1.new;
   expect(true, f1a is Class1 Function(int));
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect
index edd7977..fa85f71 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f1a(''); // error
 //         ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f2a(''); // error
 //         ^
 //
@@ -36,6 +36,8 @@
     return new self::Class2::•(field);
 }
 static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
   self::testInferred();
@@ -47,7 +49,7 @@
   self::Class1 c1a = f1a(0){(core::int) → self::Class1};
   self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
   () → Null {
-    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f1a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
   };
@@ -61,7 +63,7 @@
   self::Class2 c2a = f2a(0){(core::int) → self::Class2};
   self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
   () → Null {
-    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f2a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
   };
@@ -89,7 +91,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::Class1::_#new#tearOff
-  #C2 = tearoff self::Class2::_#new#tearOff
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
   #C3 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect
index 9297490..2664cf0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f1a(''); // error
 //         ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f2a(''); // error
 //         ^
 //
@@ -36,6 +36,8 @@
     return new self::Class2::•(field);
 }
 static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
   self::testInferred();
@@ -47,7 +49,7 @@
   self::Class1 c1a = f1a(0){(core::int) → self::Class1};
   self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
   () → Null {
-    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f1a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
   };
@@ -61,7 +63,7 @@
   self::Class2 c2a = f2a(0){(core::int) → self::Class2};
   self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
   () → Null {
-    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f2a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
   };
@@ -89,7 +91,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::Class1::_#new#tearOff
-  #C2 = tearoff self::Class2::_#new#tearOff
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
   #C3 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.textual_outline.expect
index 9e086db..94115d1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.textual_outline.expect
@@ -1,20 +1,18 @@
 final bool inSoundMode = <int?>[] is! List<int>;
 main() {}
-
 class Class1 {
   int field;
   Class1(this.field);
 }
-
 abstract class Interface2 {
   int get field;
 }
-
 class Class2 implements Interface2 {
   final field;
   Class2(this.field);
 }
-
+var Class1_new = Class1.new;
+var Class2_new = Class2.new;
 testInferred() {}
 expect(expected, actual) {}
 throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect
index edd7977..fa85f71 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f1a(''); // error
 //         ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f2a(''); // error
 //         ^
 //
@@ -36,6 +36,8 @@
     return new self::Class2::•(field);
 }
 static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
   self::testInferred();
@@ -47,7 +49,7 @@
   self::Class1 c1a = f1a(0){(core::int) → self::Class1};
   self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
   () → Null {
-    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f1a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
   };
@@ -61,7 +63,7 @@
   self::Class2 c2a = f2a(0){(core::int) → self::Class2};
   self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
   () → Null {
-    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f2a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
   };
@@ -89,7 +91,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::Class1::_#new#tearOff
-  #C2 = tearoff self::Class2::_#new#tearOff
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
   #C3 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect
index 802525c..cc60ae4 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect
@@ -22,6 +22,8 @@
     return new self::Class2::•(field);
 }
 static final field core::bool inSoundMode;
+static field (core::int) → self::Class1 Class1_new;
+static field (core::int) → self::Class2 Class2_new;
 static method main() → dynamic
   ;
 static method testInferred() → dynamic
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect
index 9297490..2664cf0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f1a(''); // error
 //         ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
 //     f2a(''); // error
 //         ^
 //
@@ -36,6 +36,8 @@
     return new self::Class2::•(field);
 }
 static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
 static method main() → dynamic {
   core::print("inSoundMode: ${self::inSoundMode}");
   self::testInferred();
@@ -47,7 +49,7 @@
   self::Class1 c1a = f1a(0){(core::int) → self::Class1};
   self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
   () → Null {
-    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f1a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
   };
@@ -61,7 +63,7 @@
   self::Class2 c2a = f2a(0){(core::int) → self::Class2};
   self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
   () → Null {
-    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+    f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
     f2a(''); // error
         ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
   };
@@ -89,7 +91,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::Class1::_#new#tearOff
-  #C2 = tearoff self::Class2::_#new#tearOff
+  #C1 = static-tearoff self::Class1::_#new#tearOff
+  #C2 = static-tearoff self::Class2::_#new#tearOff
   #C3 = false
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart
new file mode 100644
index 0000000..36599bd
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart
@@ -0,0 +1,103 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+class A<T> {
+  A();
+  factory A.fact() => new A<T>();
+  factory A.redirect() = A<T>;
+}
+
+typedef F<X extends num> = A<X>;
+typedef G<Y> = A<int>;
+typedef H<X, Y> = A<X>;
+
+const f1a = A<int>.new;
+const f1b = F<int>.new;
+const A<int> Function() f1c = F.new;
+const f1d = A<int>.fact;
+const f1e = F<int>.fact;
+const A<int> Function() f1f = F.fact;
+const f1g = A<int>.redirect;
+const f1h = F<int>.redirect;
+const A<int> Function() f1i = F.redirect;
+
+const g1a = A<int>.new;
+const g1b = G<String>.new;
+const A<int> Function() g1c = G.new;
+
+const h1a = A<int>.new;
+const h1b = H<int, String>.new;
+const A<int> Function() h1c = H.new;
+
+main() {
+  test<int>();
+
+  identical(f1a, f1b);
+  identical(f1a, f1c);
+
+  identical(f1d, f1e);
+  identical(f1d, f1f);
+
+  identical(f1g, f1h);
+  identical(f1g, f1i);
+
+  identical(g1a, g1b);
+  identical(g1a, g1c);
+
+  identical(h1a, h1b);
+  identical(h1a, h1c);
+}
+
+test<T extends num>() {
+  var f2a = A<T>.new;
+  var f2b = F<T>.new;
+  A<T> Function() f2c = F.new;
+  var f2d = A<T>.fact;
+  var f2e = F<T>.fact;
+  A<T> Function() f2f = F.fact;
+  var f2g = A<T>.redirect;
+  var f2h = F<T>.redirect;
+  A<T> Function() f2i = F.redirect;
+
+  var g2a = A<int>.new;
+  var g2b = G<T>.new;
+  A<int> Function() g2c = G.new;
+
+  var h2a = A<T>.new;
+  var h2b = H<T, String>.new;
+  A<T> Function() h2c = H.new;
+
+  // TODO(johnniwinther): Enable these if structural equality is supported at
+  // runtime.
+  /*expect(f1a, f2a);
+  expect(f2a, f2b);
+  expect(f2a, f2c);
+
+  expect(f1d, f2d);
+  expect(f2d, f2e);
+  expect(f2d, f2f);
+
+  expect(f1g, f2g);
+  expect(f2g, f2h);
+  expect(f2g, f2i);*/
+
+  expect(g1a, g2a);
+  expect(g2a, g2b);
+  if (inSoundMode) {
+    // In weak mode type arguments of constants are weakened.
+    expect(g2a, g2c);
+  }
+
+  // TODO(johnniwinther): Enable these if structural equality is supported at
+  // runtime.
+  /*expect(h1a, h2a);
+  expect(h2a, h2b);
+  expect(h2a, h2c);*/
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.expect
new file mode 100644
index 0000000..9277874
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.expect
@@ -0,0 +1,105 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+    return new self::A::•<self::A::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+    return self::A::fact<self::A::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+    return new self::A::•<self::A::_#redirect#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> f1d = #C4;
+static const field () → self::A<core::int> f1e = #C4;
+static const field () → self::A<core::int> f1f = #C4;
+static const field () → self::A<core::int> f1g = #C6;
+static const field () → self::A<core::int> f1h = #C6;
+static const field () → self::A<core::int> f1i = #C6;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C2;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+  self::test<core::int>();
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C4, #C4);
+  core::identical(#C4, #C4);
+  core::identical(#C6, #C6);
+  core::identical(#C6, #C6);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+  () → self::A<self::test::T> f2a = #C1<self::test::T>;
+  () → self::A<self::test::T> f2b = #C1<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<self::test::T> f2d = #C3<self::test::T>;
+  () → self::A<self::test::T> f2e = #C3<self::test::T>;
+  () → self::A<self::test::T> f2f = #C3<self::test::T>;
+  () → self::A<self::test::T> f2g = #C5<self::test::T>;
+  () → self::A<self::test::T> f2h = #C5<self::test::T>;
+  () → self::A<self::test::T> f2i = #C5<self::test::T>;
+  () → self::A<core::int> g2a = #C2;
+  () → self::A<core::int> g2b = #C2;
+  () → self::A<core::int> g2c = #C2;
+  () → self::A<self::test::T> h2a = #C1<self::test::T>;
+  () → self::A<self::test::T> h2b = #C1<self::test::T>;
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
+  self::expect(#C2, g2a);
+  self::expect(g2a, g2b);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
+  return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+  return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+  return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
+static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::_#redirect#tearOff<core::int>();
+static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
+  return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+  return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+  return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = instantiation self::A::_#new#tearOff <core::int>
+  #C3 = static-tearoff self::A::_#fact#tearOff
+  #C4 = instantiation self::A::_#fact#tearOff <core::int>
+  #C5 = static-tearoff self::A::_#redirect#tearOff
+  #C6 = instantiation self::A::_#redirect#tearOff <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.transformed.expect
new file mode 100644
index 0000000..bfa45c0
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.transformed.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+    return new self::A::•<self::A::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+    return self::A::fact<self::A::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+    return new self::A::•<self::A::_#redirect#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> f1d = #C4;
+static const field () → self::A<core::int> f1e = #C4;
+static const field () → self::A<core::int> f1f = #C4;
+static const field () → self::A<core::int> f1g = #C6;
+static const field () → self::A<core::int> f1h = #C6;
+static const field () → self::A<core::int> f1i = #C6;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C2;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+  self::test<core::int>();
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C4, #C4);
+  core::identical(#C4, #C4);
+  core::identical(#C6, #C6);
+  core::identical(#C6, #C6);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+  () → self::A<self::test::T> f2a = #C1<self::test::T>;
+  () → self::A<self::test::T> f2b = #C1<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<self::test::T> f2d = #C3<self::test::T>;
+  () → self::A<self::test::T> f2e = #C3<self::test::T>;
+  () → self::A<self::test::T> f2f = #C3<self::test::T>;
+  () → self::A<self::test::T> f2g = #C5<self::test::T>;
+  () → self::A<self::test::T> f2h = #C5<self::test::T>;
+  () → self::A<self::test::T> f2i = #C5<self::test::T>;
+  () → self::A<core::int> g2a = #C2;
+  () → self::A<core::int> g2b = #C2;
+  () → self::A<core::int> g2c = #C2;
+  () → self::A<self::test::T> h2a = #C1<self::test::T>;
+  () → self::A<self::test::T> h2b = #C1<self::test::T>;
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
+  self::expect(#C2, g2a);
+  self::expect(g2a, g2b);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
+  return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+  return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+  return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
+static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::_#redirect#tearOff<core::int>();
+static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
+  return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+  return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+  return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = instantiation self::A::_#new#tearOff <core::int>
+  #C3 = static-tearoff self::A::_#fact#tearOff
+  #C4 = instantiation self::A::_#fact#tearOff <core::int>
+  #C5 = static-tearoff self::A::_#redirect#tearOff
+  #C6 = instantiation self::A::_#redirect#tearOff <core::int>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:38:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:39:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:41:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:42:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:44:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:45:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:47:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:48:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:50:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:51:3 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 61, effectively constant: 10
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.textual_outline.expect
new file mode 100644
index 0000000..8731bf4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.textual_outline.expect
@@ -0,0 +1,27 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+class A<T> {
+  A();
+  factory A.fact() => new A<T>();
+  factory A.redirect() = A<T>;
+}
+typedef F<X extends num> = A<X>;
+typedef G<Y> = A<int>;
+typedef H<X, Y> = A<X>;
+const f1a = A<int>.new;
+const f1b = F<int>.new;
+const A<int> Function() f1c = F.new;
+const f1d = A<int>.fact;
+const f1e = F<int>.fact;
+const A<int> Function() f1f = F.fact;
+const f1g = A<int>.redirect;
+const f1h = F<int>.redirect;
+const A<int> Function() f1i = F.redirect;
+const g1a = A<int>.new;
+const g1b = G<String>.new;
+const A<int> Function() g1c = G.new;
+const h1a = A<int>.new;
+const h1b = H<int, String>.new;
+const A<int> Function() h1c = H.new;
+main() {}
+test<T extends num>() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.expect
new file mode 100644
index 0000000..8e0844f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.expect
@@ -0,0 +1,108 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+    return new self::A::•<self::A::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+    return self::A::fact<self::A::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+    return new self::A::•<self::A::_#redirect#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C3;
+static const field () → self::A<core::int> f1d = #C5;
+static const field () → self::A<core::int> f1e = #C5;
+static const field () → self::A<core::int> f1f = #C6;
+static const field () → self::A<core::int> f1g = #C8;
+static const field () → self::A<core::int> f1h = #C8;
+static const field () → self::A<core::int> f1i = #C9;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C3;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C3;
+static method main() → dynamic {
+  self::test<core::int>();
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C3);
+  core::identical(#C5, #C5);
+  core::identical(#C5, #C6);
+  core::identical(#C8, #C8);
+  core::identical(#C8, #C9);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C3);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C3);
+}
+static method test<T extends core::num>() → dynamic {
+  () → self::A<self::test::T> f2a = #C1<self::test::T>;
+  () → self::A<self::test::T> f2b = #C1<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<self::test::T> f2d = #C4<self::test::T>;
+  () → self::A<self::test::T> f2e = #C4<self::test::T>;
+  () → self::A<self::test::T> f2f = #C4<self::test::T>;
+  () → self::A<self::test::T> f2g = #C7<self::test::T>;
+  () → self::A<self::test::T> f2h = #C7<self::test::T>;
+  () → self::A<self::test::T> f2i = #C7<self::test::T>;
+  () → self::A<core::int> g2a = #C2;
+  () → self::A<core::int> g2b = #C2;
+  () → self::A<core::int> g2c = #C3;
+  () → self::A<self::test::T> h2a = #C1<self::test::T>;
+  () → self::A<self::test::T> h2b = #C1<self::test::T>;
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
+  self::expect(#C2, g2a);
+  self::expect(g2a, g2b);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
+  return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+  return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+  return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
+static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::_#redirect#tearOff<core::int>();
+static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
+  return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+  return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+  return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = instantiation self::A::_#new#tearOff <core::int*>
+  #C3 = instantiation self::A::_#new#tearOff <core::int>
+  #C4 = static-tearoff self::A::_#fact#tearOff
+  #C5 = instantiation self::A::_#fact#tearOff <core::int*>
+  #C6 = instantiation self::A::_#fact#tearOff <core::int>
+  #C7 = static-tearoff self::A::_#redirect#tearOff
+  #C8 = instantiation self::A::_#redirect#tearOff <core::int*>
+  #C9 = instantiation self::A::_#redirect#tearOff <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.outline.expect
new file mode 100644
index 0000000..e433d37
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.outline.expect
@@ -0,0 +1,81 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+    return new self::A::•<self::A::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    ;
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+    return self::A::fact<self::A::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+    return new self::A::•<self::A::_#redirect#tearOff::T%>();
+}
+static final field core::bool inSoundMode;
+static const field () → self::A<core::int> f1a = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> f1b = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> f1c = self::_#F#new#tearOff<core::int>;
+static const field () → self::A<core::int> f1d = self::A::_#fact#tearOff<core::int>;
+static const field () → self::A<core::int> f1e = self::A::_#fact#tearOff<core::int>;
+static const field () → self::A<core::int> f1f = self::_#F#fact#tearOff<core::int>;
+static const field () → self::A<core::int> f1g = self::A::_#redirect#tearOff<core::int>;
+static const field () → self::A<core::int> f1h = self::A::_#redirect#tearOff<core::int>;
+static const field () → self::A<core::int> f1i = self::_#F#redirect#tearOff<core::int>;
+static const field () → self::A<core::int> g1a = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> g1b = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> g1c = self::_#G#new#tearOff<dynamic>;
+static const field () → self::A<core::int> h1a = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> h1b = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> h1c = self::_#H#new#tearOff<core::int, dynamic>;
+static method main() → dynamic
+  ;
+static method test<T extends core::num>() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
+  return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+  return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+  return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
+static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::_#redirect#tearOff<core::int>();
+static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
+  return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+  return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+  return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
+
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:17:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:18:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:19:31 -> InstantiationConstant(A._#new#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:20:13 -> InstantiationConstant(A._#fact#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:21:13 -> InstantiationConstant(A._#fact#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:22:31 -> InstantiationConstant(A._#fact#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:23:13 -> InstantiationConstant(A._#redirect#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:24:13 -> InstantiationConstant(A._#redirect#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:25:31 -> InstantiationConstant(A._#redirect#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:27:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:28:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:31 -> InstantiationConstant(A._#new#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:31:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:33:31 -> InstantiationConstant(A._#new#tearOff<int>)
+Extra constant evaluation: evaluated: 32, effectively constant: 15
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.transformed.expect
new file mode 100644
index 0000000..0b3ac45
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.transformed.expect
@@ -0,0 +1,121 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+    return new self::A::•<self::A::_#new#tearOff::T%>();
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+    return self::A::fact<self::A::_#fact#tearOff::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+    return new self::A::•<self::A::_#redirect#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C3;
+static const field () → self::A<core::int> f1d = #C5;
+static const field () → self::A<core::int> f1e = #C5;
+static const field () → self::A<core::int> f1f = #C6;
+static const field () → self::A<core::int> f1g = #C8;
+static const field () → self::A<core::int> f1h = #C8;
+static const field () → self::A<core::int> f1i = #C9;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C3;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C3;
+static method main() → dynamic {
+  self::test<core::int>();
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C3);
+  core::identical(#C5, #C5);
+  core::identical(#C5, #C6);
+  core::identical(#C8, #C8);
+  core::identical(#C8, #C9);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C3);
+  core::identical(#C2, #C2);
+  core::identical(#C2, #C3);
+}
+static method test<T extends core::num>() → dynamic {
+  () → self::A<self::test::T> f2a = #C1<self::test::T>;
+  () → self::A<self::test::T> f2b = #C1<self::test::T>;
+  () → self::A<self::test::T> f2c = #C1<self::test::T>;
+  () → self::A<self::test::T> f2d = #C4<self::test::T>;
+  () → self::A<self::test::T> f2e = #C4<self::test::T>;
+  () → self::A<self::test::T> f2f = #C4<self::test::T>;
+  () → self::A<self::test::T> f2g = #C7<self::test::T>;
+  () → self::A<self::test::T> f2h = #C7<self::test::T>;
+  () → self::A<self::test::T> f2i = #C7<self::test::T>;
+  () → self::A<core::int> g2a = #C2;
+  () → self::A<core::int> g2b = #C2;
+  () → self::A<core::int> g2c = #C3;
+  () → self::A<self::test::T> h2a = #C1<self::test::T>;
+  () → self::A<self::test::T> h2b = #C1<self::test::T>;
+  () → self::A<self::test::T> h2c = #C1<self::test::T>;
+  self::expect(#C2, g2a);
+  self::expect(g2a, g2b);
+  if(self::inSoundMode) {
+    self::expect(g2a, g2c);
+  }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
+  return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+  return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+  return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
+static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+  return self::A::_#redirect#tearOff<core::int>();
+static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
+  return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+  return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+  return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = instantiation self::A::_#new#tearOff <core::int*>
+  #C3 = instantiation self::A::_#new#tearOff <core::int>
+  #C4 = static-tearoff self::A::_#fact#tearOff
+  #C5 = instantiation self::A::_#fact#tearOff <core::int*>
+  #C6 = instantiation self::A::_#fact#tearOff <core::int>
+  #C7 = static-tearoff self::A::_#redirect#tearOff
+  #C8 = instantiation self::A::_#redirect#tearOff <core::int*>
+  #C9 = instantiation self::A::_#redirect#tearOff <core::int>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:38:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:39:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:41:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:42:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:44:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:45:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:47:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:48:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:50:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:51:3 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 61, effectively constant: 10
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart
new file mode 100644
index 0000000..e923b7a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart
@@ -0,0 +1,33 @@
+// 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.
+
+var A_new = A.new;
+var B_new = B.new;
+var F_new = F.new;
+var G_new = G.new;
+
+class A {
+  int field1 = 0;
+
+  A(this.field1);
+  A.named(this.field1);
+}
+
+class B<T> implements A {
+  var field1;
+  T field2;
+
+  B(this.field1, this.field2);
+  B.named(this.field1, this.field2);
+}
+
+typedef F<T> = A;
+typedef G<T extends num> = B;
+
+var A_named = A.named;
+var B_named = B<int>.named;
+var F_named = F.named;
+var G_named = G<int>.named;
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.expect
new file mode 100644
index 0000000..d952a09
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+  field core::int field1 = 0;
+  constructor •(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  constructor named(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field1) → self::A
+    return new self::A::•(field1);
+  static method _#named#tearOff(core::int field1) → self::A
+    return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+  field core::int field1;
+  generic-covariant-impl field self::B::T% field2;
+  constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+  static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+    return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::named<dynamic>(field1, field2);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = static-tearoff self::_#F#new#tearOff
+  #C4 = static-tearoff self::_#G#new#tearOff
+  #C5 = static-tearoff self::A::_#named#tearOff
+  #C6 = static-tearoff self::B::_#named#tearOff
+  #C7 = instantiation self::B::_#named#tearOff <core::int>
+  #C8 = static-tearoff self::_#F#named#tearOff
+  #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..d952a09
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+  field core::int field1 = 0;
+  constructor •(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  constructor named(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field1) → self::A
+    return new self::A::•(field1);
+  static method _#named#tearOff(core::int field1) → self::A
+    return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+  field core::int field1;
+  generic-covariant-impl field self::B::T% field2;
+  constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+  static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+    return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::named<dynamic>(field1, field2);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = static-tearoff self::_#F#new#tearOff
+  #C4 = static-tearoff self::_#G#new#tearOff
+  #C5 = static-tearoff self::A::_#named#tearOff
+  #C6 = static-tearoff self::B::_#named#tearOff
+  #C7 = instantiation self::B::_#named#tearOff <core::int>
+  #C8 = static-tearoff self::_#F#named#tearOff
+  #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..12bef00
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+var A_new = A.new;
+var B_new = B.new;
+var F_new = F.new;
+var G_new = G.new;
+class A {
+  int field1 = 0;
+  A(this.field1);
+  A.named(this.field1);
+}
+class B<T> implements A {
+  var field1;
+  T field2;
+  B(this.field1, this.field2);
+  B.named(this.field1, this.field2);
+}
+typedef F<T> = A;
+typedef G<T extends num> = B;
+var A_named = A.named;
+var B_named = B<int>.named;
+var F_named = F.named;
+var G_named = G<int>.named;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.expect
new file mode 100644
index 0000000..9294ac3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+  field core::int field1 = 0;
+  constructor •(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  constructor named(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field1) → self::A
+    return new self::A::•(field1);
+  static method _#named#tearOff(core::int field1) → self::A
+    return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+  field core::int field1;
+  generic-covariant-impl field self::B::T% field2;
+  constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+  static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+    return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::named<dynamic>(field1, field2);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = static-tearoff self::_#F#new#tearOff
+  #C4 = static-tearoff self::_#G#new#tearOff
+  #C5 = static-tearoff self::A::_#named#tearOff
+  #C6 = static-tearoff self::B::_#named#tearOff
+  #C7 = instantiation self::B::_#named#tearOff <core::int*>
+  #C8 = static-tearoff self::_#F#named#tearOff
+  #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..c32ee60
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.outline.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+  field core::int field1;
+  constructor •(core::int field1) → self::A
+    ;
+  constructor named(core::int field1) → self::A
+    ;
+  static method _#new#tearOff(core::int field1) → self::A
+    return new self::A::•(field1);
+  static method _#named#tearOff(core::int field1) → self::A
+    return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+  field core::int field1;
+  generic-covariant-impl field self::B::T% field2;
+  constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    ;
+  constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+  static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+    return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new;
+static field (core::int) → self::A A_named;
+static field (core::int, core::int) → self::B<core::int> B_named;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named;
+static field (core::int, dynamic) → self::B<dynamic> G_named;
+static method main() → dynamic
+  ;
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::named<dynamic>(field1, field2);
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..9294ac3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+  field core::int field1 = 0;
+  constructor •(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  constructor named(core::int field1) → self::A
+    : self::A::field1 = field1, super core::Object::•()
+    ;
+  static method _#new#tearOff(core::int field1) → self::A
+    return new self::A::•(field1);
+  static method _#named#tearOff(core::int field1) → self::A
+    return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+  field core::int field1;
+  generic-covariant-impl field self::B::T% field2;
+  constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+  static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+    return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+  return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+  return new self::B::named<dynamic>(field1, field2);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = static-tearoff self::_#F#new#tearOff
+  #C4 = static-tearoff self::_#G#new#tearOff
+  #C5 = static-tearoff self::A::_#named#tearOff
+  #C6 = static-tearoff self::B::_#named#tearOff
+  #C7 = instantiation self::B::_#named#tearOff <core::int*>
+  #C8 = static-tearoff self::_#F#named#tearOff
+  #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart
new file mode 100644
index 0000000..ed7af3d1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart
@@ -0,0 +1,14 @@
+// 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 {
+  Class._();
+  static Class constructor() => new Class._();
+  static Class Function() field = () => new Class._();
+
+  factory Class.a() = Class.nonexisting;
+  factory Class.b() = Class.constructor;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.expect
new file mode 100644
index 0000000..d55e231
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:10:23: Error: Redirection constructor target not found: 'Class.nonexisting'
+//   factory Class.a() = Class.nonexisting;
+//                       ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:11:23: Error: Redirection constructor target not found: 'Class.constructor'
+//   factory Class.b() = Class.constructor;
+//                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  static field () → self::Class field = () → self::Class => new self::Class::_();
+  static final field dynamic _redirecting# = <dynamic>[self::Class::a, self::Class::b]/*isLegacy*/;
+  constructor _() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class
+    return new self::Class::_();
+  static method constructor() → self::Class
+    return new self::Class::_();
+  static factory a() → self::Class
+    let dynamic #redirecting_factory = "Class.nonexisting" in invalid-expression;
+  static method _#a#tearOff() → self::Class;
+  static factory b() → self::Class
+    let dynamic #redirecting_factory = "Class.constructor" in invalid-expression;
+  static method _#b#tearOff() → self::Class;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.transformed.expect
new file mode 100644
index 0000000..fe5e039
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:10:23: Error: Redirection constructor target not found: 'Class.nonexisting'
+//   factory Class.a() = Class.nonexisting;
+//                       ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:11:23: Error: Redirection constructor target not found: 'Class.constructor'
+//   factory Class.b() = Class.constructor;
+//                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  static field () → self::Class field = () → self::Class => new self::Class::_();
+  static final field dynamic _redirecting# = <dynamic>[self::Class::a, self::Class::b]/*isLegacy*/;
+  constructor _() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class
+    return new self::Class::_();
+  static method constructor() → self::Class
+    return new self::Class::_();
+  static factory a() → self::Class
+    let core::String* #redirecting_factory = "Class.nonexisting" in invalid-expression;
+  static method _#a#tearOff() → self::Class;
+  static factory b() → self::Class
+    let core::String* #redirecting_factory = "Class.constructor" in invalid-expression;
+  static method _#b#tearOff() → self::Class;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline.expect
new file mode 100644
index 0000000..1dc9515
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+class Class {
+  Class._();
+  static Class constructor() => new Class._();
+  static Class Function() field = () => new Class._();
+  factory Class.a() = Class.nonexisting;
+  factory Class.b() = Class.constructor;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f765ff19
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Class {
+  Class._();
+  factory Class.a() = Class.nonexisting;
+  factory Class.b() = Class.constructor;
+  static Class Function() field = () => new Class._();
+  static Class constructor() => new Class._();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.expect
new file mode 100644
index 0000000..d55e231
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:10:23: Error: Redirection constructor target not found: 'Class.nonexisting'
+//   factory Class.a() = Class.nonexisting;
+//                       ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:11:23: Error: Redirection constructor target not found: 'Class.constructor'
+//   factory Class.b() = Class.constructor;
+//                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  static field () → self::Class field = () → self::Class => new self::Class::_();
+  static final field dynamic _redirecting# = <dynamic>[self::Class::a, self::Class::b]/*isLegacy*/;
+  constructor _() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class
+    return new self::Class::_();
+  static method constructor() → self::Class
+    return new self::Class::_();
+  static factory a() → self::Class
+    let dynamic #redirecting_factory = "Class.nonexisting" in invalid-expression;
+  static method _#a#tearOff() → self::Class;
+  static factory b() → self::Class
+    let dynamic #redirecting_factory = "Class.constructor" in invalid-expression;
+  static method _#b#tearOff() → self::Class;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.outline.expect
new file mode 100644
index 0000000..7a6886a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:10:23: Error: Redirection constructor target not found: 'Class.nonexisting'
+//   factory Class.a() = Class.nonexisting;
+//                       ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:11:23: Error: Redirection constructor target not found: 'Class.constructor'
+//   factory Class.b() = Class.constructor;
+//                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  static field () → self::Class field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class::a, self::Class::b]/*isLegacy*/;
+  constructor _() → self::Class
+    ;
+  static method _#_#tearOff() → self::Class
+    return new self::Class::_();
+  static method constructor() → self::Class
+    ;
+  static factory a() → self::Class
+    let dynamic #redirecting_factory = "Class.nonexisting" in invalid-expression;
+  static method _#a#tearOff() → self::Class;
+  static factory b() → self::Class
+    let dynamic #redirecting_factory = "Class.constructor" in invalid-expression;
+  static method _#b#tearOff() → self::Class;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.transformed.expect
new file mode 100644
index 0000000..fe5e039
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:10:23: Error: Redirection constructor target not found: 'Class.nonexisting'
+//   factory Class.a() = Class.nonexisting;
+//                       ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:11:23: Error: Redirection constructor target not found: 'Class.constructor'
+//   factory Class.b() = Class.constructor;
+//                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  static field () → self::Class field = () → self::Class => new self::Class::_();
+  static final field dynamic _redirecting# = <dynamic>[self::Class::a, self::Class::b]/*isLegacy*/;
+  constructor _() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class
+    return new self::Class::_();
+  static method constructor() → self::Class
+    return new self::Class::_();
+  static factory a() → self::Class
+    let core::String* #redirecting_factory = "Class.nonexisting" in invalid-expression;
+  static method _#a#tearOff() → self::Class;
+  static factory b() → self::Class
+    let core::String* #redirecting_factory = "Class.constructor" in invalid-expression;
+  static method _#b#tearOff() → self::Class;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart
new file mode 100644
index 0000000..1cbbc8e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart
@@ -0,0 +1,62 @@
+// 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 A {}
+
+class B<T> {}
+
+class C<X, Y> {}
+
+class D<X extends num> {}
+
+typedef F = A;
+
+typedef G0 = B;
+typedef G1 = B<int>;
+typedef G2<T> = B<T>;
+typedef G3<T extends num> = B<T>;
+
+typedef H0 = C;
+typedef H1 = C<int, String>;
+typedef H2<T> = C<int, T>;
+typedef H3<T, S> = C<T, S>;
+typedef H4<T, S> = C<S, T>;
+typedef H5<T extends num, S> = C<T, S>;
+typedef H6<T, S extends num> = C<T, S>;
+
+typedef I0 = D;
+typedef I1 = D<num>;
+typedef I2<T extends num> = D<T>;
+typedef I3<T extends int> = D<T>;
+
+main() {
+  var f = F.new;
+
+  var g0 = G0.new;
+  var g1 = G1.new;
+  var g2a = G2.new;
+  var g2b = G2<int>.new;
+  var g3a = G3.new;
+  var g3b = G3<int>.new;
+
+  var h0 = H0.new;
+  var h1 = H1.new;
+  var h2a = H2.new;
+  var h2b = H2<int>.new;
+  var h3a = H3.new;
+  var h3b = H3<int, String>.new;
+  var h4a = H4.new;
+  var h4b = H4<int, String>.new;
+  var h5a = H5.new;
+  var h5b = H5<int, String>.new;
+  var h6a = H6.new;
+  var h6b = H6<String, int>.new;
+
+  var i0 = I0.new;
+  var i1 = I1.new;
+  var i2a = I2.new;
+  var i2b = I2<int>.new;
+  var i3a = I3.new;
+  var i3b = I3<int>.new;
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.expect
new file mode 100644
index 0000000..b6e38f4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.expect
@@ -0,0 +1,108 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = self::A;
+typedef G0 = self::B<dynamic>;
+typedef G1 = self::B<core::int>;
+typedef G2<T extends core::Object? = dynamic> = self::B<T%>;
+typedef G3<T extends core::num> = self::B<T>;
+typedef H0 = self::C<dynamic, dynamic>;
+typedef H1 = self::C<core::int, core::String>;
+typedef H2<T extends core::Object? = dynamic> = self::C<core::int, T%>;
+typedef H3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<T%, S%>;
+typedef H4<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<S%, T%>;
+typedef H5<T extends core::num, S extends core::Object? = dynamic> = self::C<T, S%>;
+typedef H6<T extends core::Object? = dynamic, S extends core::num> = self::C<T%, S>;
+typedef I0 = self::D<core::num>;
+typedef I1 = self::D<core::num>;
+typedef I2<T extends core::num> = self::D<T>;
+typedef I3<T extends core::int> = self::D<T>;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::A
+    return new self::A::•();
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>();
+}
+class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%, self::C::Y%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>
+    return new self::C::•<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>();
+}
+class D<X extends core::num> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<X extends core::num>() → self::D<self::D::_#new#tearOff::X>
+    return new self::D::•<self::D::_#new#tearOff::X>();
+}
+static method main() → dynamic {
+  () → self::A f = #C1;
+  () → self::B<dynamic> g0 = #C3;
+  () → self::B<core::int> g1 = #C4;
+  <T extends core::Object? = dynamic>() → self::B<T%> g2a = #C2;
+  () → self::B<core::int> g2b = #C4;
+  <T extends core::num>() → self::B<T> g3a = #C5;
+  () → self::B<core::int> g3b = #C4;
+  () → self::C<dynamic, dynamic> h0 = #C7;
+  () → self::C<core::int, core::String> h1 = #C8;
+  <T extends core::Object? = dynamic>() → self::C<core::int, T%> h2a = #C9;
+  () → self::C<core::int, core::int> h2b = #C10;
+  <X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<X%, Y%> h3a = #C6;
+  () → self::C<core::int, core::String> h3b = #C8;
+  <T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<S%, T%> h4a = #C11;
+  () → self::C<core::String, core::int> h4b = #C12;
+  <T extends core::num, S extends core::Object? = dynamic>() → self::C<T, S%> h5a = #C13;
+  () → self::C<core::int, core::String> h5b = #C8;
+  <T extends core::Object? = dynamic, S extends core::num>() → self::C<T%, S> h6a = #C14;
+  () → self::C<core::String, core::int> h6b = #C12;
+  () → self::D<core::num> i0 = #C16;
+  () → self::D<core::num> i1 = #C16;
+  <X extends core::num>() → self::D<X> i2a = #C15;
+  () → self::D<core::int> i2b = #C17;
+  <T extends core::int>() → self::D<T> i3a = #C18;
+  () → self::D<core::int> i3b = #C17;
+}
+static method _#G3#new#tearOff<T extends core::num>() → self::B<self::_#G3#new#tearOff::T>
+  return new self::B::•<self::_#G3#new#tearOff::T>();
+static method _#H2#new#tearOff<T extends core::Object? = dynamic>() → self::C<core::int, self::_#H2#new#tearOff::T%>
+  return new self::C::•<core::int, self::_#H2#new#tearOff::T%>();
+static method _#H4#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>
+  return new self::C::•<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>();
+static method _#H5#new#tearOff<T extends core::num, S extends core::Object? = dynamic>() → self::C<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>
+  return new self::C::•<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>();
+static method _#H6#new#tearOff<T extends core::Object? = dynamic, S extends core::num>() → self::C<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>
+  return new self::C::•<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>();
+static method _#I3#new#tearOff<T extends core::int>() → self::D<self::_#I3#new#tearOff::T>
+  return new self::D::•<self::_#I3#new#tearOff::T>();
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = instantiation self::B::_#new#tearOff <dynamic>
+  #C4 = instantiation self::B::_#new#tearOff <core::int>
+  #C5 = static-tearoff self::_#G3#new#tearOff
+  #C6 = static-tearoff self::C::_#new#tearOff
+  #C7 = instantiation self::C::_#new#tearOff <dynamic, dynamic>
+  #C8 = instantiation self::C::_#new#tearOff <core::int, core::String>
+  #C9 = static-tearoff self::_#H2#new#tearOff
+  #C10 = instantiation self::C::_#new#tearOff <core::int, core::int>
+  #C11 = static-tearoff self::_#H4#new#tearOff
+  #C12 = instantiation self::C::_#new#tearOff <core::String, core::int>
+  #C13 = static-tearoff self::_#H5#new#tearOff
+  #C14 = static-tearoff self::_#H6#new#tearOff
+  #C15 = static-tearoff self::D::_#new#tearOff
+  #C16 = instantiation self::D::_#new#tearOff <core::num>
+  #C17 = instantiation self::D::_#new#tearOff <core::int>
+  #C18 = static-tearoff self::_#I3#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.transformed.expect
new file mode 100644
index 0000000..b6e38f4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.transformed.expect
@@ -0,0 +1,108 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = self::A;
+typedef G0 = self::B<dynamic>;
+typedef G1 = self::B<core::int>;
+typedef G2<T extends core::Object? = dynamic> = self::B<T%>;
+typedef G3<T extends core::num> = self::B<T>;
+typedef H0 = self::C<dynamic, dynamic>;
+typedef H1 = self::C<core::int, core::String>;
+typedef H2<T extends core::Object? = dynamic> = self::C<core::int, T%>;
+typedef H3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<T%, S%>;
+typedef H4<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<S%, T%>;
+typedef H5<T extends core::num, S extends core::Object? = dynamic> = self::C<T, S%>;
+typedef H6<T extends core::Object? = dynamic, S extends core::num> = self::C<T%, S>;
+typedef I0 = self::D<core::num>;
+typedef I1 = self::D<core::num>;
+typedef I2<T extends core::num> = self::D<T>;
+typedef I3<T extends core::int> = self::D<T>;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::A
+    return new self::A::•();
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>();
+}
+class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%, self::C::Y%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>
+    return new self::C::•<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>();
+}
+class D<X extends core::num> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<X extends core::num>() → self::D<self::D::_#new#tearOff::X>
+    return new self::D::•<self::D::_#new#tearOff::X>();
+}
+static method main() → dynamic {
+  () → self::A f = #C1;
+  () → self::B<dynamic> g0 = #C3;
+  () → self::B<core::int> g1 = #C4;
+  <T extends core::Object? = dynamic>() → self::B<T%> g2a = #C2;
+  () → self::B<core::int> g2b = #C4;
+  <T extends core::num>() → self::B<T> g3a = #C5;
+  () → self::B<core::int> g3b = #C4;
+  () → self::C<dynamic, dynamic> h0 = #C7;
+  () → self::C<core::int, core::String> h1 = #C8;
+  <T extends core::Object? = dynamic>() → self::C<core::int, T%> h2a = #C9;
+  () → self::C<core::int, core::int> h2b = #C10;
+  <X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<X%, Y%> h3a = #C6;
+  () → self::C<core::int, core::String> h3b = #C8;
+  <T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<S%, T%> h4a = #C11;
+  () → self::C<core::String, core::int> h4b = #C12;
+  <T extends core::num, S extends core::Object? = dynamic>() → self::C<T, S%> h5a = #C13;
+  () → self::C<core::int, core::String> h5b = #C8;
+  <T extends core::Object? = dynamic, S extends core::num>() → self::C<T%, S> h6a = #C14;
+  () → self::C<core::String, core::int> h6b = #C12;
+  () → self::D<core::num> i0 = #C16;
+  () → self::D<core::num> i1 = #C16;
+  <X extends core::num>() → self::D<X> i2a = #C15;
+  () → self::D<core::int> i2b = #C17;
+  <T extends core::int>() → self::D<T> i3a = #C18;
+  () → self::D<core::int> i3b = #C17;
+}
+static method _#G3#new#tearOff<T extends core::num>() → self::B<self::_#G3#new#tearOff::T>
+  return new self::B::•<self::_#G3#new#tearOff::T>();
+static method _#H2#new#tearOff<T extends core::Object? = dynamic>() → self::C<core::int, self::_#H2#new#tearOff::T%>
+  return new self::C::•<core::int, self::_#H2#new#tearOff::T%>();
+static method _#H4#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>
+  return new self::C::•<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>();
+static method _#H5#new#tearOff<T extends core::num, S extends core::Object? = dynamic>() → self::C<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>
+  return new self::C::•<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>();
+static method _#H6#new#tearOff<T extends core::Object? = dynamic, S extends core::num>() → self::C<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>
+  return new self::C::•<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>();
+static method _#I3#new#tearOff<T extends core::int>() → self::D<self::_#I3#new#tearOff::T>
+  return new self::D::•<self::_#I3#new#tearOff::T>();
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = instantiation self::B::_#new#tearOff <dynamic>
+  #C4 = instantiation self::B::_#new#tearOff <core::int>
+  #C5 = static-tearoff self::_#G3#new#tearOff
+  #C6 = static-tearoff self::C::_#new#tearOff
+  #C7 = instantiation self::C::_#new#tearOff <dynamic, dynamic>
+  #C8 = instantiation self::C::_#new#tearOff <core::int, core::String>
+  #C9 = static-tearoff self::_#H2#new#tearOff
+  #C10 = instantiation self::C::_#new#tearOff <core::int, core::int>
+  #C11 = static-tearoff self::_#H4#new#tearOff
+  #C12 = instantiation self::C::_#new#tearOff <core::String, core::int>
+  #C13 = static-tearoff self::_#H5#new#tearOff
+  #C14 = static-tearoff self::_#H6#new#tearOff
+  #C15 = static-tearoff self::D::_#new#tearOff
+  #C16 = instantiation self::D::_#new#tearOff <core::num>
+  #C17 = instantiation self::D::_#new#tearOff <core::int>
+  #C18 = static-tearoff self::_#I3#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline.expect
new file mode 100644
index 0000000..9a7c825
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline.expect
@@ -0,0 +1,25 @@
+class A {}
+
+class B<T> {}
+
+class C<X, Y> {}
+
+class D<X extends num> {}
+
+typedef F = A;
+typedef G0 = B;
+typedef G1 = B<int>;
+typedef G2<T> = B<T>;
+typedef G3<T extends num> = B<T>;
+typedef H0 = C;
+typedef H1 = C<int, String>;
+typedef H2<T> = C<int, T>;
+typedef H3<T, S> = C<T, S>;
+typedef H4<T, S> = C<S, T>;
+typedef H5<T extends num, S> = C<T, S>;
+typedef H6<T, S extends num> = C<T, S>;
+typedef I0 = D;
+typedef I1 = D<num>;
+typedef I2<T extends num> = D<T>;
+typedef I3<T extends int> = D<T>;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f5f173a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+class A {}
+
+class B<T> {}
+
+class C<X, Y> {}
+
+class D<X extends num> {}
+
+main() {}
+typedef F = A;
+typedef G0 = B;
+typedef G1 = B<int>;
+typedef G2<T> = B<T>;
+typedef G3<T extends num> = B<T>;
+typedef H0 = C;
+typedef H1 = C<int, String>;
+typedef H2<T> = C<int, T>;
+typedef H3<T, S> = C<T, S>;
+typedef H4<T, S> = C<S, T>;
+typedef H5<T extends num, S> = C<T, S>;
+typedef H6<T, S extends num> = C<T, S>;
+typedef I0 = D;
+typedef I1 = D<num>;
+typedef I2<T extends num> = D<T>;
+typedef I3<T extends int> = D<T>;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.expect
new file mode 100644
index 0000000..2d72357
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.expect
@@ -0,0 +1,108 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = self::A;
+typedef G0 = self::B<dynamic>;
+typedef G1 = self::B<core::int>;
+typedef G2<T extends core::Object? = dynamic> = self::B<T%>;
+typedef G3<T extends core::num> = self::B<T>;
+typedef H0 = self::C<dynamic, dynamic>;
+typedef H1 = self::C<core::int, core::String>;
+typedef H2<T extends core::Object? = dynamic> = self::C<core::int, T%>;
+typedef H3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<T%, S%>;
+typedef H4<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<S%, T%>;
+typedef H5<T extends core::num, S extends core::Object? = dynamic> = self::C<T, S%>;
+typedef H6<T extends core::Object? = dynamic, S extends core::num> = self::C<T%, S>;
+typedef I0 = self::D<core::num>;
+typedef I1 = self::D<core::num>;
+typedef I2<T extends core::num> = self::D<T>;
+typedef I3<T extends core::int> = self::D<T>;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::A
+    return new self::A::•();
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>();
+}
+class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%, self::C::Y%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>
+    return new self::C::•<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>();
+}
+class D<X extends core::num> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<X extends core::num>() → self::D<self::D::_#new#tearOff::X>
+    return new self::D::•<self::D::_#new#tearOff::X>();
+}
+static method main() → dynamic {
+  () → self::A f = #C1;
+  () → self::B<dynamic> g0 = #C3;
+  () → self::B<core::int> g1 = #C4;
+  <T extends core::Object? = dynamic>() → self::B<T%> g2a = #C2;
+  () → self::B<core::int> g2b = #C4;
+  <T extends core::num>() → self::B<T> g3a = #C5;
+  () → self::B<core::int> g3b = #C4;
+  () → self::C<dynamic, dynamic> h0 = #C7;
+  () → self::C<core::int, core::String> h1 = #C8;
+  <T extends core::Object? = dynamic>() → self::C<core::int, T%> h2a = #C9;
+  () → self::C<core::int, core::int> h2b = #C10;
+  <X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<X%, Y%> h3a = #C6;
+  () → self::C<core::int, core::String> h3b = #C8;
+  <T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<S%, T%> h4a = #C11;
+  () → self::C<core::String, core::int> h4b = #C12;
+  <T extends core::num, S extends core::Object? = dynamic>() → self::C<T, S%> h5a = #C13;
+  () → self::C<core::int, core::String> h5b = #C8;
+  <T extends core::Object? = dynamic, S extends core::num>() → self::C<T%, S> h6a = #C14;
+  () → self::C<core::String, core::int> h6b = #C12;
+  () → self::D<core::num> i0 = #C16;
+  () → self::D<core::num> i1 = #C16;
+  <X extends core::num>() → self::D<X> i2a = #C15;
+  () → self::D<core::int> i2b = #C17;
+  <T extends core::int>() → self::D<T> i3a = #C18;
+  () → self::D<core::int> i3b = #C17;
+}
+static method _#G3#new#tearOff<T extends core::num>() → self::B<self::_#G3#new#tearOff::T>
+  return new self::B::•<self::_#G3#new#tearOff::T>();
+static method _#H2#new#tearOff<T extends core::Object? = dynamic>() → self::C<core::int, self::_#H2#new#tearOff::T%>
+  return new self::C::•<core::int, self::_#H2#new#tearOff::T%>();
+static method _#H4#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>
+  return new self::C::•<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>();
+static method _#H5#new#tearOff<T extends core::num, S extends core::Object? = dynamic>() → self::C<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>
+  return new self::C::•<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>();
+static method _#H6#new#tearOff<T extends core::Object? = dynamic, S extends core::num>() → self::C<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>
+  return new self::C::•<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>();
+static method _#I3#new#tearOff<T extends core::int>() → self::D<self::_#I3#new#tearOff::T>
+  return new self::D::•<self::_#I3#new#tearOff::T>();
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = instantiation self::B::_#new#tearOff <dynamic>
+  #C4 = instantiation self::B::_#new#tearOff <core::int*>
+  #C5 = static-tearoff self::_#G3#new#tearOff
+  #C6 = static-tearoff self::C::_#new#tearOff
+  #C7 = instantiation self::C::_#new#tearOff <dynamic, dynamic>
+  #C8 = instantiation self::C::_#new#tearOff <core::int*, core::String*>
+  #C9 = static-tearoff self::_#H2#new#tearOff
+  #C10 = instantiation self::C::_#new#tearOff <core::int*, core::int*>
+  #C11 = static-tearoff self::_#H4#new#tearOff
+  #C12 = instantiation self::C::_#new#tearOff <core::String*, core::int*>
+  #C13 = static-tearoff self::_#H5#new#tearOff
+  #C14 = static-tearoff self::_#H6#new#tearOff
+  #C15 = static-tearoff self::D::_#new#tearOff
+  #C16 = instantiation self::D::_#new#tearOff <core::num*>
+  #C17 = instantiation self::D::_#new#tearOff <core::int*>
+  #C18 = static-tearoff self::_#I3#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.outline.expect
new file mode 100644
index 0000000..3dbbebd
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.outline.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = self::A;
+typedef G0 = self::B<dynamic>;
+typedef G1 = self::B<core::int>;
+typedef G2<T extends core::Object? = dynamic> = self::B<T%>;
+typedef G3<T extends core::num> = self::B<T>;
+typedef H0 = self::C<dynamic, dynamic>;
+typedef H1 = self::C<core::int, core::String>;
+typedef H2<T extends core::Object? = dynamic> = self::C<core::int, T%>;
+typedef H3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<T%, S%>;
+typedef H4<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<S%, T%>;
+typedef H5<T extends core::num, S extends core::Object? = dynamic> = self::C<T, S%>;
+typedef H6<T extends core::Object? = dynamic, S extends core::num> = self::C<T%, S>;
+typedef I0 = self::D<core::num>;
+typedef I1 = self::D<core::num>;
+typedef I2<T extends core::num> = self::D<T>;
+typedef I3<T extends core::int> = self::D<T>;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  static method _#new#tearOff() → self::A
+    return new self::A::•();
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T%>
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>();
+}
+class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%, self::C::Y%>
+    ;
+  static method _#new#tearOff<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>
+    return new self::C::•<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>();
+}
+class D<X extends core::num> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X>
+    ;
+  static method _#new#tearOff<X extends core::num>() → self::D<self::D::_#new#tearOff::X>
+    return new self::D::•<self::D::_#new#tearOff::X>();
+}
+static method main() → dynamic
+  ;
+static method _#G3#new#tearOff<T extends core::num>() → self::B<self::_#G3#new#tearOff::T>
+  return new self::B::•<self::_#G3#new#tearOff::T>();
+static method _#H2#new#tearOff<T extends core::Object? = dynamic>() → self::C<core::int, self::_#H2#new#tearOff::T%>
+  return new self::C::•<core::int, self::_#H2#new#tearOff::T%>();
+static method _#H4#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>
+  return new self::C::•<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>();
+static method _#H5#new#tearOff<T extends core::num, S extends core::Object? = dynamic>() → self::C<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>
+  return new self::C::•<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>();
+static method _#H6#new#tearOff<T extends core::Object? = dynamic, S extends core::num>() → self::C<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>
+  return new self::C::•<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>();
+static method _#I3#new#tearOff<T extends core::int>() → self::D<self::_#I3#new#tearOff::T>
+  return new self::D::•<self::_#I3#new#tearOff::T>();
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.transformed.expect
new file mode 100644
index 0000000..2d72357
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.transformed.expect
@@ -0,0 +1,108 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = self::A;
+typedef G0 = self::B<dynamic>;
+typedef G1 = self::B<core::int>;
+typedef G2<T extends core::Object? = dynamic> = self::B<T%>;
+typedef G3<T extends core::num> = self::B<T>;
+typedef H0 = self::C<dynamic, dynamic>;
+typedef H1 = self::C<core::int, core::String>;
+typedef H2<T extends core::Object? = dynamic> = self::C<core::int, T%>;
+typedef H3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<T%, S%>;
+typedef H4<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<S%, T%>;
+typedef H5<T extends core::num, S extends core::Object? = dynamic> = self::C<T, S%>;
+typedef H6<T extends core::Object? = dynamic, S extends core::num> = self::C<T%, S>;
+typedef I0 = self::D<core::num>;
+typedef I1 = self::D<core::num>;
+typedef I2<T extends core::num> = self::D<T>;
+typedef I3<T extends core::int> = self::D<T>;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::A
+    return new self::A::•();
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>
+    return new self::B::•<self::B::_#new#tearOff::T%>();
+}
+class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%, self::C::Y%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>
+    return new self::C::•<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>();
+}
+class D<X extends core::num> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<X extends core::num>() → self::D<self::D::_#new#tearOff::X>
+    return new self::D::•<self::D::_#new#tearOff::X>();
+}
+static method main() → dynamic {
+  () → self::A f = #C1;
+  () → self::B<dynamic> g0 = #C3;
+  () → self::B<core::int> g1 = #C4;
+  <T extends core::Object? = dynamic>() → self::B<T%> g2a = #C2;
+  () → self::B<core::int> g2b = #C4;
+  <T extends core::num>() → self::B<T> g3a = #C5;
+  () → self::B<core::int> g3b = #C4;
+  () → self::C<dynamic, dynamic> h0 = #C7;
+  () → self::C<core::int, core::String> h1 = #C8;
+  <T extends core::Object? = dynamic>() → self::C<core::int, T%> h2a = #C9;
+  () → self::C<core::int, core::int> h2b = #C10;
+  <X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<X%, Y%> h3a = #C6;
+  () → self::C<core::int, core::String> h3b = #C8;
+  <T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<S%, T%> h4a = #C11;
+  () → self::C<core::String, core::int> h4b = #C12;
+  <T extends core::num, S extends core::Object? = dynamic>() → self::C<T, S%> h5a = #C13;
+  () → self::C<core::int, core::String> h5b = #C8;
+  <T extends core::Object? = dynamic, S extends core::num>() → self::C<T%, S> h6a = #C14;
+  () → self::C<core::String, core::int> h6b = #C12;
+  () → self::D<core::num> i0 = #C16;
+  () → self::D<core::num> i1 = #C16;
+  <X extends core::num>() → self::D<X> i2a = #C15;
+  () → self::D<core::int> i2b = #C17;
+  <T extends core::int>() → self::D<T> i3a = #C18;
+  () → self::D<core::int> i3b = #C17;
+}
+static method _#G3#new#tearOff<T extends core::num>() → self::B<self::_#G3#new#tearOff::T>
+  return new self::B::•<self::_#G3#new#tearOff::T>();
+static method _#H2#new#tearOff<T extends core::Object? = dynamic>() → self::C<core::int, self::_#H2#new#tearOff::T%>
+  return new self::C::•<core::int, self::_#H2#new#tearOff::T%>();
+static method _#H4#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>
+  return new self::C::•<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>();
+static method _#H5#new#tearOff<T extends core::num, S extends core::Object? = dynamic>() → self::C<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>
+  return new self::C::•<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>();
+static method _#H6#new#tearOff<T extends core::Object? = dynamic, S extends core::num>() → self::C<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>
+  return new self::C::•<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>();
+static method _#I3#new#tearOff<T extends core::int>() → self::D<self::_#I3#new#tearOff::T>
+  return new self::D::•<self::_#I3#new#tearOff::T>();
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::B::_#new#tearOff
+  #C3 = instantiation self::B::_#new#tearOff <dynamic>
+  #C4 = instantiation self::B::_#new#tearOff <core::int*>
+  #C5 = static-tearoff self::_#G3#new#tearOff
+  #C6 = static-tearoff self::C::_#new#tearOff
+  #C7 = instantiation self::C::_#new#tearOff <dynamic, dynamic>
+  #C8 = instantiation self::C::_#new#tearOff <core::int*, core::String*>
+  #C9 = static-tearoff self::_#H2#new#tearOff
+  #C10 = instantiation self::C::_#new#tearOff <core::int*, core::int*>
+  #C11 = static-tearoff self::_#H4#new#tearOff
+  #C12 = instantiation self::C::_#new#tearOff <core::String*, core::int*>
+  #C13 = static-tearoff self::_#H5#new#tearOff
+  #C14 = static-tearoff self::_#H6#new#tearOff
+  #C15 = static-tearoff self::D::_#new#tearOff
+  #C16 = instantiation self::D::_#new#tearOff <core::num*>
+  #C17 = instantiation self::D::_#new#tearOff <core::int*>
+  #C18 = static-tearoff self::_#I3#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart
new file mode 100644
index 0000000..765da64
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart
@@ -0,0 +1,194 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+  print('inSoundMode: $inSoundMode');
+  testNoArgs();
+  testArgs();
+}
+
+class Class1 {
+  Class1._();
+  factory Class1() = Class1._;
+}
+
+class Class2 {
+    Class2.__();
+    factory Class2._() => Class2.__();
+    factory Class2.named() = Class2._;
+}
+
+testNoArgs() {
+  var f1a = Class1.new;
+  var c1a = f1a();
+  expect(true, c1a is Class1);
+
+  dynamic f1b = Class1.new;
+  var c1b = f1b();
+  expect(true, c1b is Class1);
+
+  expect(true, identical(f1a, f1b));
+
+  var f2a = Class2.named;
+  var c2a = f2a();
+  expect(true, c2a is Class2);
+
+  dynamic f2b = Class2.named;
+  var c2b = f2b();
+  expect(true, c2b is Class2);
+
+  expect(true, identical(f2a, f2b));
+}
+
+class Class3 {
+  final int field;
+
+  Class3._(this.field);
+  factory Class3(int field) = Class3._;
+}
+
+class Class4 {
+  final int? field;
+
+  Class4._([this.field]);
+  factory Class4([int? field]) = Class4._;
+}
+
+class Class5 {
+  final int field1;
+  final int? field2;
+
+  Class5._(this.field1, [this.field2]);
+  factory Class5(int field1, [int? field2]) = Class5._;
+}
+
+class Class6 {
+  final int field1;
+  final int? field2;
+  final int field3;
+
+  Class6._(this.field1, {this.field2, required this.field3});
+  factory Class6(int field1, {int? field2, required int field3}) =
+      Class6._;
+}
+
+class Class7a implements Class7b {
+  Class7a();
+}
+
+class Class7b {
+  factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+  Class8a();
+}
+
+class Class8b<T> {
+  factory Class8b() = Class8a<T>;
+}
+
+testArgs() {
+  var f3a = Class3.new;
+  var c3a = f3a(42);
+  expect(42, c3a.field);
+  () {
+    f3a(); // error
+    f3a(42, 87); // error
+  };
+
+  dynamic f3b = Class3.new;
+  var c3b = f3b(87);
+  expect(87, c3b.field);
+  throws(() => f3b());
+  throws(() => f3b(42, 87));
+
+  var f4a = Class4.new;
+  var c4a = f4a();
+  expect(null, c4a.field);
+  var c4b = f4a(42);
+  expect(42, c4b.field);
+  () {
+    f4a(42, 87); // error
+  };
+  dynamic f4b = Class4.new;
+  throws(() => f4b(42, 87));
+
+
+  var f5a = Class5.new;
+  var c5a = f5a(42);
+  expect(42, c5a.field1);
+  expect(null, c5a.field2);
+  var c5b = f5a(87, 42);
+  expect(87, c5b.field1);
+  expect(42, c5b.field2);
+  () {
+    f5a(); // error
+    f5a(42, 87, 123); // error
+  };
+  dynamic f5b = Class5.new;
+  throws(() => f5b());
+  throws(() => f5b(42, 87, 123));
+
+  var f6a = Class6.new;
+  var c6a = f6a(42, field3: 87);
+  expect(42, c6a.field1);
+  expect(null, c6a.field2);
+  expect(87, c6a.field3);
+  () {
+    f6a(); // error
+    f6a(42); // error
+    f6a(42, 87); // error
+    f6a(field1: 87, field2: 87); // error
+  };
+
+  var c6b = f6a(42, field2: 123, field3: 87);
+  expect(42, c6b.field1);
+  expect(123, c6b.field2);
+  expect(87, c6b.field3);
+
+  var c6c = f6a(87, field3: 42, field2: 123);
+  expect(87, c6c.field1);
+  expect(123, c6c.field2);
+  expect(42, c6c.field3);
+
+  dynamic f6b = Class6.new;
+  throws(() => f6b());
+  throws(() => f6b(42), inSoundModeOnly: true);
+  throws(() => f6b(42, 87), inSoundModeOnly: true);
+  throws(() => f6b(field1: 87, field2: 87));
+
+  var f7a = Class7b.new;
+  var c7a = f7a();
+  expect(true, c7a is Class7a);
+  expect(true, c7a is Class7b);
+
+  var f8a = Class8b.new;
+  var c8a = f8a();
+  expect(true, c8a is Class8a);
+  expect(true, c8a is Class8b);
+  var c8b = f8a<int>();
+  expect(true, c8b is Class8a<int>);
+  expect(true, c8b is Class8b<int>);
+  expect(false, c8b is Class8b<String>);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..a115126
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.expect
@@ -0,0 +1,306 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class1
+    return new self::Class1::_();
+  static factory •() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+  static method _#new#tearOff() → self::Class1
+    return new self::Class1::_();
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+  constructor __() → self::Class2
+    : super core::Object::•()
+    ;
+  static method _#__#tearOff() → self::Class2
+    return new self::Class2::__();
+  static factory _() → self::Class2
+    return new self::Class2::__();
+  static method _#_#tearOff() → self::Class2
+    return self::Class2::_();
+  static factory named() → self::Class2
+    let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+  static method _#named#tearOff() → self::Class2
+    return self::Class2::_();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static factory •(core::int field) → self::Class3
+    let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+  static method _#new#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static factory •([core::int? field = #C1]) → self::Class4
+    let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+  static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+  static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+  static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+}
+class Class7a extends core::Object implements self::Class7b {
+  constructor •() → self::Class7a
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class7a
+    return new self::Class7a::•();
+}
+class Class7b extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+  static factory •() → self::Class7b
+    let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+  static method _#new#tearOff() → self::Class7b
+    return new self::Class7a::•();
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+  constructor •() → self::Class8a<self::Class8a::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
+    return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+  static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+    let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
+    return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+  () → self::Class7b f7a = #C8;
+  self::Class7b c7a = f7a(){() → self::Class7b};
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+  <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+  self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+  self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+  self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
+  #C8 = static-tearoff self::Class7b::_#new#tearOff
+  #C9 = static-tearoff self::Class8b::_#new#tearOff
+  #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..02a4614
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,306 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class1
+    return new self::Class1::_();
+  static factory •() → self::Class1
+    let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+  static method _#new#tearOff() → self::Class1
+    return new self::Class1::_();
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+  constructor __() → self::Class2
+    : super core::Object::•()
+    ;
+  static method _#__#tearOff() → self::Class2
+    return new self::Class2::__();
+  static factory _() → self::Class2
+    return new self::Class2::__();
+  static method _#_#tearOff() → self::Class2
+    return self::Class2::_();
+  static factory named() → self::Class2
+    let () → self::Class2 #redirecting_factory = self::Class2::_ in invalid-expression;
+  static method _#named#tearOff() → self::Class2
+    return self::Class2::_();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static factory •(core::int field) → self::Class3
+    let Never #redirecting_factory = self::Class3::_ in invalid-expression;
+  static method _#new#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static factory •([core::int? field = #C1]) → self::Class4
+    let Never #redirecting_factory = self::Class4::_ in invalid-expression;
+  static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    let Never #redirecting_factory = self::Class5::_ in invalid-expression;
+  static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    let Never #redirecting_factory = self::Class6::_ in invalid-expression;
+  static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+}
+class Class7a extends core::Object implements self::Class7b {
+  constructor •() → self::Class7a
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class7a
+    return new self::Class7a::•();
+}
+class Class7b extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+  static factory •() → self::Class7b
+    let Never #redirecting_factory = self::Class7a::• in invalid-expression;
+  static method _#new#tearOff() → self::Class7b
+    return new self::Class7a::•();
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+  constructor •() → self::Class8a<self::Class8a::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
+    return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+  static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+    let Never #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
+    return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+  () → self::Class7b f7a = #C8;
+  self::Class7b c7a = f7a(){() → self::Class7b};
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+  <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+  self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+  self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+  self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
+  #C8 = static-tearoff self::Class7b::_#new#tearOff
+  #C9 = static-tearoff self::Class8b::_#new#tearOff
+  #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..2fa25d6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,62 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+  Class1._();
+  factory Class1() = Class1._;
+}
+
+class Class2 {
+  Class2.__();
+  factory Class2._() => Class2.__();
+  factory Class2.named() = Class2._;
+}
+
+testNoArgs() {}
+
+class Class3 {
+  final int field;
+  Class3._(this.field);
+  factory Class3(int field) = Class3._;
+}
+
+class Class4 {
+  final int? field;
+  Class4._([this.field]);
+  factory Class4([int? field]) = Class4._;
+}
+
+class Class5 {
+  final int field1;
+  final int? field2;
+  Class5._(this.field1, [this.field2]);
+  factory Class5(int field1, [int? field2]) = Class5._;
+}
+
+class Class6 {
+  final int field1;
+  final int? field2;
+  final int field3;
+  Class6._(this.field1, {this.field2, required this.field3});
+  factory Class6(int field1, {int? field2, required int field3}) = Class6._;
+}
+
+class Class7a implements Class7b {
+  Class7a();
+}
+
+class Class7b {
+  factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+  Class8a();
+}
+
+class Class8b<T> {
+  factory Class8b() = Class8a<T>;
+}
+
+testArgs() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0500e74
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,60 @@
+class Class1 {
+  Class1._();
+  factory Class1() = Class1._;
+}
+
+class Class2 {
+  Class2.__();
+  factory Class2._() => Class2.__();
+  factory Class2.named() = Class2._;
+}
+
+class Class3 {
+  Class3._(this.field);
+  factory Class3(int field) = Class3._;
+  final int field;
+}
+
+class Class4 {
+  Class4._([this.field]);
+  factory Class4([int? field]) = Class4._;
+  final int? field;
+}
+
+class Class5 {
+  Class5._(this.field1, [this.field2]);
+  factory Class5(int field1, [int? field2]) = Class5._;
+  final int? field2;
+  final int field1;
+}
+
+class Class6 {
+  Class6._(this.field1, {this.field2, required this.field3});
+  factory Class6(int field1, {int? field2, required int field3}) = Class6._;
+  final int? field2;
+  final int field1;
+  final int field3;
+}
+
+class Class7a implements Class7b {
+  Class7a();
+}
+
+class Class7b {
+  factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+  Class8a();
+}
+
+class Class8b<T> {
+  factory Class8b() = Class8a<T>;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testArgs() {}
+testNoArgs() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..a115126
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.expect
@@ -0,0 +1,306 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class1
+    return new self::Class1::_();
+  static factory •() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+  static method _#new#tearOff() → self::Class1
+    return new self::Class1::_();
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+  constructor __() → self::Class2
+    : super core::Object::•()
+    ;
+  static method _#__#tearOff() → self::Class2
+    return new self::Class2::__();
+  static factory _() → self::Class2
+    return new self::Class2::__();
+  static method _#_#tearOff() → self::Class2
+    return self::Class2::_();
+  static factory named() → self::Class2
+    let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+  static method _#named#tearOff() → self::Class2
+    return self::Class2::_();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static factory •(core::int field) → self::Class3
+    let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+  static method _#new#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static factory •([core::int? field = #C1]) → self::Class4
+    let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+  static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+  static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+  static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+}
+class Class7a extends core::Object implements self::Class7b {
+  constructor •() → self::Class7a
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class7a
+    return new self::Class7a::•();
+}
+class Class7b extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+  static factory •() → self::Class7b
+    let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+  static method _#new#tearOff() → self::Class7b
+    return new self::Class7a::•();
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+  constructor •() → self::Class8a<self::Class8a::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
+    return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+  static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+    let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
+    return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+  () → self::Class7b f7a = #C8;
+  self::Class7b c7a = f7a(){() → self::Class7b};
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+  <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+  self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+  self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+  self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
+  #C8 = static-tearoff self::Class7b::_#new#tearOff
+  #C9 = static-tearoff self::Class8b::_#new#tearOff
+  #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..0067daa
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    ;
+  static method _#_#tearOff() → self::Class1
+    return new self::Class1::_();
+  static factory •() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+  static method _#new#tearOff() → self::Class1
+    return new self::Class1::_();
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+  constructor __() → self::Class2
+    ;
+  static method _#__#tearOff() → self::Class2
+    return new self::Class2::__();
+  static factory _() → self::Class2
+    ;
+  static method _#_#tearOff() → self::Class2
+    return self::Class2::_();
+  static factory named() → self::Class2
+    let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+  static method _#named#tearOff() → self::Class2
+    return self::Class2::_();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _(core::int field) → self::Class3
+    ;
+  static method _#_#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static factory •(core::int field) → self::Class3
+    let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+  static method _#new#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _([core::int? field]) → self::Class4
+    ;
+  static method _#_#tearOff([core::int? field]) → self::Class4
+    return new self::Class4::_(field);
+  static factory •([core::int? field]) → self::Class4
+    let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+  static method _#new#tearOff([core::int? field]) → self::Class4
+    return new self::Class4::_(field);
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+  constructor _(core::int field1, [core::int? field2]) → self::Class5
+    ;
+  static method _#_#tearOff(core::int field1, [core::int? field2]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static factory •(core::int field1, [core::int? field2]) → self::Class5
+    let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+  static method _#new#tearOff(core::int field1, [core::int? field2]) → self::Class5
+    return new self::Class5::_(field1, field2);
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+  constructor _(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+    ;
+  static method _#_#tearOff(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static factory •(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+    let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+  static method _#new#tearOff(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+}
+class Class7a extends core::Object implements self::Class7b {
+  constructor •() → self::Class7a
+    ;
+  static method _#new#tearOff() → self::Class7a
+    return new self::Class7a::•();
+}
+class Class7b extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+  static factory •() → self::Class7b
+    let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+  static method _#new#tearOff() → self::Class7b
+    return new self::Class7a::•();
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+  constructor •() → self::Class8a<self::Class8a::T%>
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
+    return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+  static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+    let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
+    return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+  ;
+static method testNoArgs() → dynamic
+  ;
+static method testArgs() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..02a4614
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,306 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static method _#_#tearOff() → self::Class1
+    return new self::Class1::_();
+  static factory •() → self::Class1
+    let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+  static method _#new#tearOff() → self::Class1
+    return new self::Class1::_();
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+  constructor __() → self::Class2
+    : super core::Object::•()
+    ;
+  static method _#__#tearOff() → self::Class2
+    return new self::Class2::__();
+  static factory _() → self::Class2
+    return new self::Class2::__();
+  static method _#_#tearOff() → self::Class2
+    return self::Class2::_();
+  static factory named() → self::Class2
+    let () → self::Class2 #redirecting_factory = self::Class2::_ in invalid-expression;
+  static method _#named#tearOff() → self::Class2
+    return self::Class2::_();
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+  static factory •(core::int field) → self::Class3
+    let Never #redirecting_factory = self::Class3::_ in invalid-expression;
+  static method _#new#tearOff(core::int field) → self::Class3
+    return new self::Class3::_(field);
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+  static factory •([core::int? field = #C1]) → self::Class4
+    let Never #redirecting_factory = self::Class4::_ in invalid-expression;
+  static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+    return new self::Class4::_(field);
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    let Never #redirecting_factory = self::Class5::_ in invalid-expression;
+  static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    return new self::Class5::_(field1, field2);
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    let Never #redirecting_factory = self::Class6::_ in invalid-expression;
+  static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    return new self::Class6::_(field1, field2: field2, field3: field3);
+}
+class Class7a extends core::Object implements self::Class7b {
+  constructor •() → self::Class7a
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class7a
+    return new self::Class7a::•();
+}
+class Class7b extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+  static factory •() → self::Class7b
+    let Never #redirecting_factory = self::Class7a::• in invalid-expression;
+  static method _#new#tearOff() → self::Class7b
+    return new self::Class7a::•();
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+  constructor •() → self::Class8a<self::Class8a::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
+    return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+  static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+    let Never #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
+    return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+  () → self::Class7b f7a = #C8;
+  self::Class7b c7a = f7a(){() → self::Class7b};
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+  <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+  self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+  self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+  self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = static-tearoff self::Class1::_#new#tearOff
+  #C3 = static-tearoff self::Class2::_#named#tearOff
+  #C4 = static-tearoff self::Class3::_#new#tearOff
+  #C5 = static-tearoff self::Class4::_#new#tearOff
+  #C6 = static-tearoff self::Class5::_#new#tearOff
+  #C7 = static-tearoff self::Class6::_#new#tearOff
+  #C8 = static-tearoff self::Class7b::_#new#tearOff
+  #C9 = static-tearoff self::Class8b::_#new#tearOff
+  #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart
new file mode 100644
index 0000000..ef380c5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+  print('inSoundMode: $inSoundMode');
+  testDefaultValues();
+}
+
+class Class1 {
+  final int field;
+
+  Class1._([this.field = 42]);
+  factory Class1([int field]) = Class1._;
+}
+
+class Class2 {
+  final int field;
+
+  Class2._({this.field: 42});
+  factory Class2({int field}) = Class2._;
+}
+
+void testDefaultValues() {
+  var f1a = Class1.new;
+  var c1a = f1a();
+  expect(42, c1a.field);
+  var c1b = f1a(87);
+  expect(87, c1b.field);
+  () {
+    f1a(42, 87); // error
+  };
+
+  dynamic f1b = Class1.new;
+  var c1c = f1b();
+  expect(42, c1c.field);
+  var c1d = f1b(87);
+  expect(87, c1d.field);
+  throws(() => f1b(42, 87));
+
+  var f2a = Class2.new;
+  var c2a = f2a();
+  expect(42, c2a.field);
+  var c2b = f2a(field: 87);
+  expect(87, c2b.field);
+  () {
+    f2a(87); // error
+  };
+
+  dynamic f2b = Class2.new;
+  var c2c = f2b();
+  expect(42, c2c.field);
+  var c2d = f2b(field: 87);
+  expect(87, c2d.field);
+  throws(() => f2b(87));
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.expect
new file mode 100644
index 0000000..873e7a9
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _([core::int field = #C1]) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+  static factory •([core::int field = #C2]) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+  static method _#new#tearOff([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+}
+class Class2 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+  constructor _({core::int field = #C1}) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field: field);
+  static factory •({core::int field = #C2}) → self::Class2
+    let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field: field);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+  ([core::int]) → self::Class1 f1a = #C3;
+  self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+  self::expect(42, c1a.{self::Class1::field}{core::int});
+  self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+  self::expect(87, c1b.{self::Class1::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1a(42, 87); // error
+       ^" in f1a{<inapplicable>}.(42, 87);
+  };
+  dynamic f1b = #C3;
+  dynamic c1c = f1b{dynamic}.call();
+  self::expect(42, c1c{dynamic}.field);
+  dynamic c1d = f1b{dynamic}.call(87);
+  self::expect(87, c1d{dynamic}.field);
+  self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C4;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C4;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 42
+  #C2 = null
+  #C3 = static-tearoff self::Class1::_#new#tearOff
+  #C4 = static-tearoff self::Class2::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..fe92fac
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.transformed.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _([core::int field = #C1]) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+  static factory •([core::int field = #C2]) → self::Class1
+    let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+  static method _#new#tearOff([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+}
+class Class2 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+  constructor _({core::int field = #C1}) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field: field);
+  static factory •({core::int field = #C2}) → self::Class2
+    let Never #redirecting_factory = self::Class2::_ in invalid-expression;
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field: field);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+  ([core::int]) → self::Class1 f1a = #C3;
+  self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+  self::expect(42, c1a.{self::Class1::field}{core::int});
+  self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+  self::expect(87, c1b.{self::Class1::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1a(42, 87); // error
+       ^" in f1a{<inapplicable>}.(42, 87);
+  };
+  dynamic f1b = #C3;
+  dynamic c1c = f1b{dynamic}.call();
+  self::expect(42, c1c{dynamic}.field);
+  dynamic c1d = f1b{dynamic}.call(87);
+  self::expect(87, c1d{dynamic}.field);
+  self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C4;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C4;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 42
+  #C2 = null
+  #C3 = static-tearoff self::Class1::_#new#tearOff
+  #C4 = static-tearoff self::Class2::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline.expect
new file mode 100644
index 0000000..1194776
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline.expect
@@ -0,0 +1,18 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+  final int field;
+  Class1._([this.field = 42]);
+  factory Class1([int field]) = Class1._;
+}
+
+class Class2 {
+  final int field;
+  Class2._({this.field: 42});
+  factory Class2({int field}) = Class2._;
+}
+
+void testDefaultValues() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c51e203
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class Class1 {
+  Class1._([this.field = 42]);
+  factory Class1([int field]) = Class1._;
+  final int field;
+}
+
+class Class2 {
+  Class2._({this.field: 42});
+  factory Class2({int field}) = Class2._;
+  final int field;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
+void testDefaultValues() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.expect
new file mode 100644
index 0000000..873e7a9
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _([core::int field = #C1]) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+  static factory •([core::int field = #C2]) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+  static method _#new#tearOff([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+}
+class Class2 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+  constructor _({core::int field = #C1}) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field: field);
+  static factory •({core::int field = #C2}) → self::Class2
+    let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field: field);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+  ([core::int]) → self::Class1 f1a = #C3;
+  self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+  self::expect(42, c1a.{self::Class1::field}{core::int});
+  self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+  self::expect(87, c1b.{self::Class1::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1a(42, 87); // error
+       ^" in f1a{<inapplicable>}.(42, 87);
+  };
+  dynamic f1b = #C3;
+  dynamic c1c = f1b{dynamic}.call();
+  self::expect(42, c1c{dynamic}.field);
+  dynamic c1d = f1b{dynamic}.call(87);
+  self::expect(87, c1d{dynamic}.field);
+  self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C4;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C4;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 42
+  #C2 = null
+  #C3 = static-tearoff self::Class1::_#new#tearOff
+  #C4 = static-tearoff self::Class2::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.outline.expect
new file mode 100644
index 0000000..e6fbbd5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.outline.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _([core::int field]) → self::Class1
+    ;
+  static method _#_#tearOff([core::int field]) → self::Class1
+    return new self::Class1::_(field);
+  static factory •([core::int field]) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+  static method _#new#tearOff([core::int field]) → self::Class1
+    return new self::Class1::_(field);
+}
+class Class2 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+  constructor _({core::int field}) → self::Class2
+    ;
+  static method _#_#tearOff({core::int field}) → self::Class2
+    return new self::Class2::_(field: field);
+  static factory •({core::int field}) → self::Class2
+    let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+  static method _#new#tearOff({core::int field}) → self::Class2
+    return new self::Class2::_(field: field);
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+  ;
+static method testDefaultValues() → void
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.transformed.expect
new file mode 100644
index 0000000..fe92fac
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.transformed.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _([core::int field = #C1]) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+  static factory •([core::int field = #C2]) → self::Class1
+    let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+  static method _#new#tearOff([core::int field = #C1]) → self::Class1
+    return new self::Class1::_(field);
+}
+class Class2 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+  constructor _({core::int field = #C1}) → self::Class2
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  static method _#_#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field: field);
+  static factory •({core::int field = #C2}) → self::Class2
+    let Never #redirecting_factory = self::Class2::_ in invalid-expression;
+  static method _#new#tearOff({core::int field = #C1}) → self::Class2
+    return new self::Class2::_(field: field);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+  ([core::int]) → self::Class1 f1a = #C3;
+  self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+  self::expect(42, c1a.{self::Class1::field}{core::int});
+  self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+  self::expect(87, c1b.{self::Class1::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1a(42, 87); // error
+       ^" in f1a{<inapplicable>}.(42, 87);
+  };
+  dynamic f1b = #C3;
+  dynamic c1c = f1b{dynamic}.call();
+  self::expect(42, c1c{dynamic}.field);
+  dynamic c1d = f1b{dynamic}.call(87);
+  self::expect(87, c1d{dynamic}.field);
+  self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+  ({field: core::int}) → self::Class2 f2a = #C4;
+  self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+  self::expect(42, c2a.{self::Class2::field}{core::int});
+  self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+  self::expect(87, c2b.{self::Class2::field}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(87); // error
+       ^" in f2a{<inapplicable>}.(87);
+  };
+  dynamic f2b = #C4;
+  dynamic c2c = f2b{dynamic}.call();
+  self::expect(42, c2c{dynamic}.field);
+  dynamic c2d = f2b{dynamic}.call(field: 87);
+  self::expect(87, c2d{dynamic}.field);
+  self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 42
+  #C2 = null
+  #C3 = static-tearoff self::Class1::_#new#tearOff
+  #C4 = static-tearoff self::Class2::_#new#tearOff
+  #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart
new file mode 100644
index 0000000..605ae05
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart
@@ -0,0 +1,152 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+  print('inSoundMode: $inSoundMode');
+  testDefaultValues();
+}
+
+class Class1 {
+  final int field1;
+  final int field2;
+
+  Class1.positional([this.field1 = 1, this.field2 = 2]);
+
+  factory Class1.redirectPositionalSame([int field1, int field2]) =
+      Class1.positional;
+
+  factory Class1.redirectPositionalFewer1([int field1]) = Class1.positional;
+
+  factory Class1.redirectPositionalFewer2() = Class1.positional;
+
+  Class1.named({this.field1 = 1, this.field2 = 2});
+
+  factory Class1.redirectNamedSame({int field1, int field2}) = Class1.named;
+
+  factory Class1.redirectNamedReorder({int field2, int field1}) = Class1.named;
+
+  factory Class1.redirectNamedFewer1({int field1}) = Class1.named;
+
+  factory Class1.redirectNamedFewer2({int field2}) = Class1.named;
+
+  factory Class1.redirectNamedFewer3() = Class1.named;
+}
+
+testDefaultValues() {
+  var f1a = Class1.redirectPositionalSame;
+  var c1a = f1a();
+  expect(1, c1a.field1);
+  expect(2, c1a.field2);
+  var c1b = f1a(42);
+  expect(42, c1b.field1);
+  expect(2, c1b.field2);
+  var c1c = f1a(42, 87);
+  expect(42, c1c.field1);
+  expect(87, c1c.field2);
+
+  var f1b = Class1.redirectPositionalFewer1;
+  var c1d = f1b();
+  expect(1, c1d.field1);
+  expect(2, c1d.field2);
+  var c1e = f1b(42);
+  expect(42, c1e.field1);
+  expect(2, c1e.field2);
+  () {
+    f1b(42, 87); // error
+  };
+
+  var f1c = Class1.redirectPositionalFewer2;
+  var c1f = f1c();
+  expect(1, c1f.field1);
+  expect(2, c1f.field2);
+  () {
+    f1c(42); // error
+    f1c(42, 87); // error
+  };
+
+  var f2a = Class1.redirectNamedSame;
+  var c2a = f2a();
+  expect(1, c2a.field1);
+  expect(2, c2a.field2);
+  var c2b = f2a(field1: 42);
+  expect(42, c2b.field1);
+  expect(2, c2b.field2);
+  var c2c = f2a(field1: 42, field2: 87);
+  expect(42, c2c.field1);
+  expect(87, c2c.field2);
+  var c2d = f2a(field2: 87);
+  expect(1, c2d.field1);
+  expect(87, c2d.field2);
+  var c2e = f2a(field2: 87, field1: 42);
+  expect(42, c2e.field1);
+  expect(87, c2e.field2);
+
+  var f2b = Class1.redirectNamedReorder;
+  var c3a = f2b();
+  expect(1, c3a.field1);
+  expect(2, c3a.field2);
+  var c3b = f2b(field1: 42);
+  expect(42, c3b.field1);
+  expect(2, c3b.field2);
+  var c3c = f2b(field1: 42, field2: 87);
+  expect(42, c3c.field1);
+  expect(87, c3c.field2);
+  var c3d = f2b(field2: 87);
+  expect(1, c3d.field1);
+  expect(87, c3d.field2);
+  var c3e = f2b(field2: 87, field1: 42);
+  expect(42, c3e.field1);
+  expect(87, c3e.field2);
+
+  var f2c = Class1.redirectNamedFewer1;
+  var c4a = f2c();
+  expect(1, c4a.field1);
+  expect(2, c4a.field2);
+  var c4b = f2c(field1: 42);
+  expect(42, c4b.field1);
+  expect(2, c4b.field2);
+  () {
+    f2c(field1: 42, field2: 87); // error
+  };
+
+  var f2d = Class1.redirectNamedFewer2;
+  var c5a = f2d();
+  expect(1, c5a.field1);
+  expect(2, c5a.field2);
+  var c5b = f2d(field2: 87);
+  expect(1, c5b.field1);
+  expect(87, c5b.field2);
+  () {
+    f2d(field1: 42, field2: 87); // error
+  };
+
+  var f2e = Class1.redirectNamedFewer3;
+  var c6a = f2e();
+  expect(1, c6a.field1);
+  expect(2, c6a.field2);
+  () {
+    f2e(field1: 42); // error
+    f2e(field2: 87); // error
+    f2e(field1: 42, field2: 87); // error
+  };
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.expect
new file mode 100644
index 0000000..6d9d205
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1b(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f1c(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1c(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+//     f2c(field1: 42, field2: 87); // error
+//                     ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+//     f2d(field1: 42, field2: 87); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+//     f2e(field1: 42); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+//     f2e(field2: 87); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+//     f2e(field1: 42, field2: 87); // error
+//         ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field1;
+  final field core::int field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::redirectPositionalSame, self::Class1::redirectPositionalFewer1, self::Class1::redirectPositionalFewer2, self::Class1::redirectNamedSame, self::Class1::redirectNamedReorder, self::Class1::redirectNamedFewer1, self::Class1::redirectNamedFewer2, self::Class1::redirectNamedFewer3]/*isLegacy*/;
+  constructor positional([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+    ;
+  constructor named({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+    ;
+  static method _#positional#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    return new self::Class1::positional(field1, field2);
+  static factory redirectPositionalSame([core::int field1 = #C3, core::int field2 = #C3]) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalSame#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    return new self::Class1::positional(field1, field2);
+  static factory redirectPositionalFewer1([core::int field1 = #C3]) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalFewer1#tearOff([core::int field1 = #C1]) → self::Class1
+    return new self::Class1::positional(field1);
+  static factory redirectPositionalFewer2() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalFewer2#tearOff() → self::Class1
+    return new self::Class1::positional();
+  static method _#named#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field1: field1, field2: field2);
+  static factory redirectNamedSame({core::int field1 = #C3, core::int field2 = #C3}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedSame#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field1: field1, field2: field2);
+  static factory redirectNamedReorder({core::int field2 = #C3, core::int field1 = #C3}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedReorder#tearOff({core::int field2 = #C2, core::int field1 = #C1}) → self::Class1
+    return new self::Class1::named(field2: field2, field1: field1);
+  static factory redirectNamedFewer1({core::int field1 = #C3}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer1#tearOff({core::int field1 = #C1}) → self::Class1
+    return new self::Class1::named(field1: field1);
+  static factory redirectNamedFewer2({core::int field2 = #C3}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer2#tearOff({core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field2: field2);
+  static factory redirectNamedFewer3() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer3#tearOff() → self::Class1
+    return new self::Class1::named();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → dynamic {
+  ([core::int, core::int]) → self::Class1 f1a = #C4;
+  self::Class1 c1a = f1a(){([core::int, core::int]) → self::Class1};
+  self::expect(1, c1a.{self::Class1::field1}{core::int});
+  self::expect(2, c1a.{self::Class1::field2}{core::int});
+  self::Class1 c1b = f1a(42){([core::int, core::int]) → self::Class1};
+  self::expect(42, c1b.{self::Class1::field1}{core::int});
+  self::expect(2, c1b.{self::Class1::field2}{core::int});
+  self::Class1 c1c = f1a(42, 87){([core::int, core::int]) → self::Class1};
+  self::expect(42, c1c.{self::Class1::field1}{core::int});
+  self::expect(87, c1c.{self::Class1::field2}{core::int});
+  ([core::int]) → self::Class1 f1b = #C5;
+  self::Class1 c1d = f1b(){([core::int]) → self::Class1};
+  self::expect(1, c1d.{self::Class1::field1}{core::int});
+  self::expect(2, c1d.{self::Class1::field2}{core::int});
+  self::Class1 c1e = f1b(42){([core::int]) → self::Class1};
+  self::expect(42, c1e.{self::Class1::field1}{core::int});
+  self::expect(2, c1e.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1b(42, 87); // error
+       ^" in f1b{<inapplicable>}.(42, 87);
+  };
+  () → self::Class1 f1c = #C6;
+  self::Class1 c1f = f1c(){() → self::Class1};
+  self::expect(1, c1f.{self::Class1::field1}{core::int});
+  self::expect(2, c1f.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f1c(42); // error
+       ^" in f1c{<inapplicable>}.(42);
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1c(42, 87); // error
+       ^" in f1c{<inapplicable>}.(42, 87);
+  };
+  ({field1: core::int, field2: core::int}) → self::Class1 f2a = #C7;
+  self::Class1 c2a = f2a(){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c2a.{self::Class1::field1}{core::int});
+  self::expect(2, c2a.{self::Class1::field2}{core::int});
+  self::Class1 c2b = f2a(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2b.{self::Class1::field1}{core::int});
+  self::expect(2, c2b.{self::Class1::field2}{core::int});
+  self::Class1 c2c = f2a(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2c.{self::Class1::field1}{core::int});
+  self::expect(87, c2c.{self::Class1::field2}{core::int});
+  self::Class1 c2d = f2a(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c2d.{self::Class1::field1}{core::int});
+  self::expect(87, c2d.{self::Class1::field2}{core::int});
+  self::Class1 c2e = f2a(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2e.{self::Class1::field1}{core::int});
+  self::expect(87, c2e.{self::Class1::field2}{core::int});
+  ({field1: core::int, field2: core::int}) → self::Class1 f2b = #C8;
+  self::Class1 c3a = f2b(){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c3a.{self::Class1::field1}{core::int});
+  self::expect(2, c3a.{self::Class1::field2}{core::int});
+  self::Class1 c3b = f2b(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3b.{self::Class1::field1}{core::int});
+  self::expect(2, c3b.{self::Class1::field2}{core::int});
+  self::Class1 c3c = f2b(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3c.{self::Class1::field1}{core::int});
+  self::expect(87, c3c.{self::Class1::field2}{core::int});
+  self::Class1 c3d = f2b(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c3d.{self::Class1::field1}{core::int});
+  self::expect(87, c3d.{self::Class1::field2}{core::int});
+  self::Class1 c3e = f2b(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3e.{self::Class1::field1}{core::int});
+  self::expect(87, c3e.{self::Class1::field2}{core::int});
+  ({field1: core::int}) → self::Class1 f2c = #C9;
+  self::Class1 c4a = f2c(){({field1: core::int}) → self::Class1};
+  self::expect(1, c4a.{self::Class1::field1}{core::int});
+  self::expect(2, c4a.{self::Class1::field2}{core::int});
+  self::Class1 c4b = f2c(field1: 42){({field1: core::int}) → self::Class1};
+  self::expect(42, c4b.{self::Class1::field1}{core::int});
+  self::expect(2, c4b.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+    f2c(field1: 42, field2: 87); // error
+                    ^^^^^^" in f2c{<inapplicable>}.(field1: 42, field2: 87);
+  };
+  ({field2: core::int}) → self::Class1 f2d = #C10;
+  self::Class1 c5a = f2d(){({field2: core::int}) → self::Class1};
+  self::expect(1, c5a.{self::Class1::field1}{core::int});
+  self::expect(2, c5a.{self::Class1::field2}{core::int});
+  self::Class1 c5b = f2d(field2: 87){({field2: core::int}) → self::Class1};
+  self::expect(1, c5b.{self::Class1::field1}{core::int});
+  self::expect(87, c5b.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+    f2d(field1: 42, field2: 87); // error
+        ^^^^^^" in f2d{<inapplicable>}.(field1: 42, field2: 87);
+  };
+  () → self::Class1 f2e = #C11;
+  self::Class1 c6a = f2e(){() → self::Class1};
+  self::expect(1, c6a.{self::Class1::field1}{core::int});
+  self::expect(2, c6a.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+    f2e(field1: 42); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field1: 42);
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+    f2e(field2: 87); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field2: 87);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+    f2e(field1: 42, field2: 87); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field1: 42, field2: 87);
+  };
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C12}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = null
+  #C4 = static-tearoff self::Class1::_#redirectPositionalSame#tearOff
+  #C5 = static-tearoff self::Class1::_#redirectPositionalFewer1#tearOff
+  #C6 = static-tearoff self::Class1::_#redirectPositionalFewer2#tearOff
+  #C7 = static-tearoff self::Class1::_#redirectNamedSame#tearOff
+  #C8 = static-tearoff self::Class1::_#redirectNamedReorder#tearOff
+  #C9 = static-tearoff self::Class1::_#redirectNamedFewer1#tearOff
+  #C10 = static-tearoff self::Class1::_#redirectNamedFewer2#tearOff
+  #C11 = static-tearoff self::Class1::_#redirectNamedFewer3#tearOff
+  #C12 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.transformed.expect
new file mode 100644
index 0000000..ae52285
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.transformed.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1b(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f1c(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1c(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+//     f2c(field1: 42, field2: 87); // error
+//                     ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+//     f2d(field1: 42, field2: 87); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+//     f2e(field1: 42); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+//     f2e(field2: 87); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+//     f2e(field1: 42, field2: 87); // error
+//         ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field1;
+  final field core::int field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::redirectPositionalSame, self::Class1::redirectPositionalFewer1, self::Class1::redirectPositionalFewer2, self::Class1::redirectNamedSame, self::Class1::redirectNamedReorder, self::Class1::redirectNamedFewer1, self::Class1::redirectNamedFewer2, self::Class1::redirectNamedFewer3]/*isLegacy*/;
+  constructor positional([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+    ;
+  constructor named({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+    ;
+  static method _#positional#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    return new self::Class1::positional(field1, field2);
+  static factory redirectPositionalSame([core::int field1 = #C3, core::int field2 = #C3]) → self::Class1
+    let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalSame#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    return new self::Class1::positional(field1, field2);
+  static factory redirectPositionalFewer1([core::int field1 = #C3]) → self::Class1
+    let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalFewer1#tearOff([core::int field1 = #C1]) → self::Class1
+    return new self::Class1::positional(field1);
+  static factory redirectPositionalFewer2() → self::Class1
+    let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalFewer2#tearOff() → self::Class1
+    return new self::Class1::positional();
+  static method _#named#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field1: field1, field2: field2);
+  static factory redirectNamedSame({core::int field1 = #C3, core::int field2 = #C3}) → self::Class1
+    let Never #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedSame#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field1: field1, field2: field2);
+  static factory redirectNamedReorder({core::int field2 = #C3, core::int field1 = #C3}) → self::Class1
+    let Never #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedReorder#tearOff({core::int field2 = #C2, core::int field1 = #C1}) → self::Class1
+    return new self::Class1::named(field2: field2, field1: field1);
+  static factory redirectNamedFewer1({core::int field1 = #C3}) → self::Class1
+    let Never #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer1#tearOff({core::int field1 = #C1}) → self::Class1
+    return new self::Class1::named(field1: field1);
+  static factory redirectNamedFewer2({core::int field2 = #C3}) → self::Class1
+    let Never #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer2#tearOff({core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field2: field2);
+  static factory redirectNamedFewer3() → self::Class1
+    let Never #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer3#tearOff() → self::Class1
+    return new self::Class1::named();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → dynamic {
+  ([core::int, core::int]) → self::Class1 f1a = #C4;
+  self::Class1 c1a = f1a(){([core::int, core::int]) → self::Class1};
+  self::expect(1, c1a.{self::Class1::field1}{core::int});
+  self::expect(2, c1a.{self::Class1::field2}{core::int});
+  self::Class1 c1b = f1a(42){([core::int, core::int]) → self::Class1};
+  self::expect(42, c1b.{self::Class1::field1}{core::int});
+  self::expect(2, c1b.{self::Class1::field2}{core::int});
+  self::Class1 c1c = f1a(42, 87){([core::int, core::int]) → self::Class1};
+  self::expect(42, c1c.{self::Class1::field1}{core::int});
+  self::expect(87, c1c.{self::Class1::field2}{core::int});
+  ([core::int]) → self::Class1 f1b = #C5;
+  self::Class1 c1d = f1b(){([core::int]) → self::Class1};
+  self::expect(1, c1d.{self::Class1::field1}{core::int});
+  self::expect(2, c1d.{self::Class1::field2}{core::int});
+  self::Class1 c1e = f1b(42){([core::int]) → self::Class1};
+  self::expect(42, c1e.{self::Class1::field1}{core::int});
+  self::expect(2, c1e.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1b(42, 87); // error
+       ^" in f1b{<inapplicable>}.(42, 87);
+  };
+  () → self::Class1 f1c = #C6;
+  self::Class1 c1f = f1c(){() → self::Class1};
+  self::expect(1, c1f.{self::Class1::field1}{core::int});
+  self::expect(2, c1f.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f1c(42); // error
+       ^" in f1c{<inapplicable>}.(42);
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1c(42, 87); // error
+       ^" in f1c{<inapplicable>}.(42, 87);
+  };
+  ({field1: core::int, field2: core::int}) → self::Class1 f2a = #C7;
+  self::Class1 c2a = f2a(){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c2a.{self::Class1::field1}{core::int});
+  self::expect(2, c2a.{self::Class1::field2}{core::int});
+  self::Class1 c2b = f2a(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2b.{self::Class1::field1}{core::int});
+  self::expect(2, c2b.{self::Class1::field2}{core::int});
+  self::Class1 c2c = f2a(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2c.{self::Class1::field1}{core::int});
+  self::expect(87, c2c.{self::Class1::field2}{core::int});
+  self::Class1 c2d = f2a(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c2d.{self::Class1::field1}{core::int});
+  self::expect(87, c2d.{self::Class1::field2}{core::int});
+  self::Class1 c2e = f2a(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2e.{self::Class1::field1}{core::int});
+  self::expect(87, c2e.{self::Class1::field2}{core::int});
+  ({field1: core::int, field2: core::int}) → self::Class1 f2b = #C8;
+  self::Class1 c3a = f2b(){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c3a.{self::Class1::field1}{core::int});
+  self::expect(2, c3a.{self::Class1::field2}{core::int});
+  self::Class1 c3b = f2b(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3b.{self::Class1::field1}{core::int});
+  self::expect(2, c3b.{self::Class1::field2}{core::int});
+  self::Class1 c3c = f2b(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3c.{self::Class1::field1}{core::int});
+  self::expect(87, c3c.{self::Class1::field2}{core::int});
+  self::Class1 c3d = f2b(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c3d.{self::Class1::field1}{core::int});
+  self::expect(87, c3d.{self::Class1::field2}{core::int});
+  self::Class1 c3e = f2b(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3e.{self::Class1::field1}{core::int});
+  self::expect(87, c3e.{self::Class1::field2}{core::int});
+  ({field1: core::int}) → self::Class1 f2c = #C9;
+  self::Class1 c4a = f2c(){({field1: core::int}) → self::Class1};
+  self::expect(1, c4a.{self::Class1::field1}{core::int});
+  self::expect(2, c4a.{self::Class1::field2}{core::int});
+  self::Class1 c4b = f2c(field1: 42){({field1: core::int}) → self::Class1};
+  self::expect(42, c4b.{self::Class1::field1}{core::int});
+  self::expect(2, c4b.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+    f2c(field1: 42, field2: 87); // error
+                    ^^^^^^" in f2c{<inapplicable>}.(field1: 42, field2: 87);
+  };
+  ({field2: core::int}) → self::Class1 f2d = #C10;
+  self::Class1 c5a = f2d(){({field2: core::int}) → self::Class1};
+  self::expect(1, c5a.{self::Class1::field1}{core::int});
+  self::expect(2, c5a.{self::Class1::field2}{core::int});
+  self::Class1 c5b = f2d(field2: 87){({field2: core::int}) → self::Class1};
+  self::expect(1, c5b.{self::Class1::field1}{core::int});
+  self::expect(87, c5b.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+    f2d(field1: 42, field2: 87); // error
+        ^^^^^^" in f2d{<inapplicable>}.(field1: 42, field2: 87);
+  };
+  () → self::Class1 f2e = #C11;
+  self::Class1 c6a = f2e(){() → self::Class1};
+  self::expect(1, c6a.{self::Class1::field1}{core::int});
+  self::expect(2, c6a.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+    f2e(field1: 42); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field1: 42);
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+    f2e(field2: 87); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field2: 87);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+    f2e(field1: 42, field2: 87); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field1: 42, field2: 87);
+  };
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C12}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = null
+  #C4 = static-tearoff self::Class1::_#redirectPositionalSame#tearOff
+  #C5 = static-tearoff self::Class1::_#redirectPositionalFewer1#tearOff
+  #C6 = static-tearoff self::Class1::_#redirectPositionalFewer2#tearOff
+  #C7 = static-tearoff self::Class1::_#redirectNamedSame#tearOff
+  #C8 = static-tearoff self::Class1::_#redirectNamedReorder#tearOff
+  #C9 = static-tearoff self::Class1::_#redirectNamedFewer1#tearOff
+  #C10 = static-tearoff self::Class1::_#redirectNamedFewer2#tearOff
+  #C11 = static-tearoff self::Class1::_#redirectNamedFewer3#tearOff
+  #C12 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline.expect
new file mode 100644
index 0000000..90fc9da
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+  final int field1;
+  final int field2;
+  Class1.positional([this.field1 = 1, this.field2 = 2]);
+  factory Class1.redirectPositionalSame([int field1, int field2]) =
+      Class1.positional;
+  factory Class1.redirectPositionalFewer1([int field1]) = Class1.positional;
+  factory Class1.redirectPositionalFewer2() = Class1.positional;
+  Class1.named({this.field1 = 1, this.field2 = 2});
+  factory Class1.redirectNamedSame({int field1, int field2}) = Class1.named;
+  factory Class1.redirectNamedReorder({int field2, int field1}) = Class1.named;
+  factory Class1.redirectNamedFewer1({int field1}) = Class1.named;
+  factory Class1.redirectNamedFewer2({int field2}) = Class1.named;
+  factory Class1.redirectNamedFewer3() = Class1.named;
+}
+
+testDefaultValues() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5735aef
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class Class1 {
+  Class1.named({this.field1 = 1, this.field2 = 2});
+  Class1.positional([this.field1 = 1, this.field2 = 2]);
+  factory Class1.redirectNamedFewer1({int field1}) = Class1.named;
+  factory Class1.redirectNamedFewer2({int field2}) = Class1.named;
+  factory Class1.redirectNamedFewer3() = Class1.named;
+  factory Class1.redirectNamedReorder({int field2, int field1}) = Class1.named;
+  factory Class1.redirectNamedSame({int field1, int field2}) = Class1.named;
+  factory Class1.redirectPositionalFewer1([int field1]) = Class1.positional;
+  factory Class1.redirectPositionalFewer2() = Class1.positional;
+  factory Class1.redirectPositionalSame([int field1, int field2]) =
+      Class1.positional;
+  final int field1;
+  final int field2;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testDefaultValues() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.expect
new file mode 100644
index 0000000..6d9d205
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1b(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f1c(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1c(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+//     f2c(field1: 42, field2: 87); // error
+//                     ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+//     f2d(field1: 42, field2: 87); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+//     f2e(field1: 42); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+//     f2e(field2: 87); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+//     f2e(field1: 42, field2: 87); // error
+//         ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field1;
+  final field core::int field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::redirectPositionalSame, self::Class1::redirectPositionalFewer1, self::Class1::redirectPositionalFewer2, self::Class1::redirectNamedSame, self::Class1::redirectNamedReorder, self::Class1::redirectNamedFewer1, self::Class1::redirectNamedFewer2, self::Class1::redirectNamedFewer3]/*isLegacy*/;
+  constructor positional([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+    ;
+  constructor named({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+    ;
+  static method _#positional#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    return new self::Class1::positional(field1, field2);
+  static factory redirectPositionalSame([core::int field1 = #C3, core::int field2 = #C3]) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalSame#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    return new self::Class1::positional(field1, field2);
+  static factory redirectPositionalFewer1([core::int field1 = #C3]) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalFewer1#tearOff([core::int field1 = #C1]) → self::Class1
+    return new self::Class1::positional(field1);
+  static factory redirectPositionalFewer2() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalFewer2#tearOff() → self::Class1
+    return new self::Class1::positional();
+  static method _#named#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field1: field1, field2: field2);
+  static factory redirectNamedSame({core::int field1 = #C3, core::int field2 = #C3}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedSame#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field1: field1, field2: field2);
+  static factory redirectNamedReorder({core::int field2 = #C3, core::int field1 = #C3}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedReorder#tearOff({core::int field2 = #C2, core::int field1 = #C1}) → self::Class1
+    return new self::Class1::named(field2: field2, field1: field1);
+  static factory redirectNamedFewer1({core::int field1 = #C3}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer1#tearOff({core::int field1 = #C1}) → self::Class1
+    return new self::Class1::named(field1: field1);
+  static factory redirectNamedFewer2({core::int field2 = #C3}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer2#tearOff({core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field2: field2);
+  static factory redirectNamedFewer3() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer3#tearOff() → self::Class1
+    return new self::Class1::named();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → dynamic {
+  ([core::int, core::int]) → self::Class1 f1a = #C4;
+  self::Class1 c1a = f1a(){([core::int, core::int]) → self::Class1};
+  self::expect(1, c1a.{self::Class1::field1}{core::int});
+  self::expect(2, c1a.{self::Class1::field2}{core::int});
+  self::Class1 c1b = f1a(42){([core::int, core::int]) → self::Class1};
+  self::expect(42, c1b.{self::Class1::field1}{core::int});
+  self::expect(2, c1b.{self::Class1::field2}{core::int});
+  self::Class1 c1c = f1a(42, 87){([core::int, core::int]) → self::Class1};
+  self::expect(42, c1c.{self::Class1::field1}{core::int});
+  self::expect(87, c1c.{self::Class1::field2}{core::int});
+  ([core::int]) → self::Class1 f1b = #C5;
+  self::Class1 c1d = f1b(){([core::int]) → self::Class1};
+  self::expect(1, c1d.{self::Class1::field1}{core::int});
+  self::expect(2, c1d.{self::Class1::field2}{core::int});
+  self::Class1 c1e = f1b(42){([core::int]) → self::Class1};
+  self::expect(42, c1e.{self::Class1::field1}{core::int});
+  self::expect(2, c1e.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1b(42, 87); // error
+       ^" in f1b{<inapplicable>}.(42, 87);
+  };
+  () → self::Class1 f1c = #C6;
+  self::Class1 c1f = f1c(){() → self::Class1};
+  self::expect(1, c1f.{self::Class1::field1}{core::int});
+  self::expect(2, c1f.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f1c(42); // error
+       ^" in f1c{<inapplicable>}.(42);
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1c(42, 87); // error
+       ^" in f1c{<inapplicable>}.(42, 87);
+  };
+  ({field1: core::int, field2: core::int}) → self::Class1 f2a = #C7;
+  self::Class1 c2a = f2a(){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c2a.{self::Class1::field1}{core::int});
+  self::expect(2, c2a.{self::Class1::field2}{core::int});
+  self::Class1 c2b = f2a(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2b.{self::Class1::field1}{core::int});
+  self::expect(2, c2b.{self::Class1::field2}{core::int});
+  self::Class1 c2c = f2a(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2c.{self::Class1::field1}{core::int});
+  self::expect(87, c2c.{self::Class1::field2}{core::int});
+  self::Class1 c2d = f2a(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c2d.{self::Class1::field1}{core::int});
+  self::expect(87, c2d.{self::Class1::field2}{core::int});
+  self::Class1 c2e = f2a(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2e.{self::Class1::field1}{core::int});
+  self::expect(87, c2e.{self::Class1::field2}{core::int});
+  ({field1: core::int, field2: core::int}) → self::Class1 f2b = #C8;
+  self::Class1 c3a = f2b(){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c3a.{self::Class1::field1}{core::int});
+  self::expect(2, c3a.{self::Class1::field2}{core::int});
+  self::Class1 c3b = f2b(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3b.{self::Class1::field1}{core::int});
+  self::expect(2, c3b.{self::Class1::field2}{core::int});
+  self::Class1 c3c = f2b(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3c.{self::Class1::field1}{core::int});
+  self::expect(87, c3c.{self::Class1::field2}{core::int});
+  self::Class1 c3d = f2b(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c3d.{self::Class1::field1}{core::int});
+  self::expect(87, c3d.{self::Class1::field2}{core::int});
+  self::Class1 c3e = f2b(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3e.{self::Class1::field1}{core::int});
+  self::expect(87, c3e.{self::Class1::field2}{core::int});
+  ({field1: core::int}) → self::Class1 f2c = #C9;
+  self::Class1 c4a = f2c(){({field1: core::int}) → self::Class1};
+  self::expect(1, c4a.{self::Class1::field1}{core::int});
+  self::expect(2, c4a.{self::Class1::field2}{core::int});
+  self::Class1 c4b = f2c(field1: 42){({field1: core::int}) → self::Class1};
+  self::expect(42, c4b.{self::Class1::field1}{core::int});
+  self::expect(2, c4b.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+    f2c(field1: 42, field2: 87); // error
+                    ^^^^^^" in f2c{<inapplicable>}.(field1: 42, field2: 87);
+  };
+  ({field2: core::int}) → self::Class1 f2d = #C10;
+  self::Class1 c5a = f2d(){({field2: core::int}) → self::Class1};
+  self::expect(1, c5a.{self::Class1::field1}{core::int});
+  self::expect(2, c5a.{self::Class1::field2}{core::int});
+  self::Class1 c5b = f2d(field2: 87){({field2: core::int}) → self::Class1};
+  self::expect(1, c5b.{self::Class1::field1}{core::int});
+  self::expect(87, c5b.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+    f2d(field1: 42, field2: 87); // error
+        ^^^^^^" in f2d{<inapplicable>}.(field1: 42, field2: 87);
+  };
+  () → self::Class1 f2e = #C11;
+  self::Class1 c6a = f2e(){() → self::Class1};
+  self::expect(1, c6a.{self::Class1::field1}{core::int});
+  self::expect(2, c6a.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+    f2e(field1: 42); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field1: 42);
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+    f2e(field2: 87); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field2: 87);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+    f2e(field1: 42, field2: 87); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field1: 42, field2: 87);
+  };
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C12}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = null
+  #C4 = static-tearoff self::Class1::_#redirectPositionalSame#tearOff
+  #C5 = static-tearoff self::Class1::_#redirectPositionalFewer1#tearOff
+  #C6 = static-tearoff self::Class1::_#redirectPositionalFewer2#tearOff
+  #C7 = static-tearoff self::Class1::_#redirectNamedSame#tearOff
+  #C8 = static-tearoff self::Class1::_#redirectNamedReorder#tearOff
+  #C9 = static-tearoff self::Class1::_#redirectNamedFewer1#tearOff
+  #C10 = static-tearoff self::Class1::_#redirectNamedFewer2#tearOff
+  #C11 = static-tearoff self::Class1::_#redirectNamedFewer3#tearOff
+  #C12 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.outline.expect
new file mode 100644
index 0000000..9ef35eb
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.outline.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field1;
+  final field core::int field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::redirectPositionalSame, self::Class1::redirectPositionalFewer1, self::Class1::redirectPositionalFewer2, self::Class1::redirectNamedSame, self::Class1::redirectNamedReorder, self::Class1::redirectNamedFewer1, self::Class1::redirectNamedFewer2, self::Class1::redirectNamedFewer3]/*isLegacy*/;
+  constructor positional([core::int field1, core::int field2]) → self::Class1
+    ;
+  constructor named({core::int field1, core::int field2}) → self::Class1
+    ;
+  static method _#positional#tearOff([core::int field1, core::int field2]) → self::Class1
+    return new self::Class1::positional(field1, field2);
+  static factory redirectPositionalSame([core::int field1, core::int field2]) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalSame#tearOff([core::int field1, core::int field2]) → self::Class1
+    return new self::Class1::positional(field1, field2);
+  static factory redirectPositionalFewer1([core::int field1]) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalFewer1#tearOff([core::int field1]) → self::Class1
+    return new self::Class1::positional(field1);
+  static factory redirectPositionalFewer2() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalFewer2#tearOff() → self::Class1
+    return new self::Class1::positional();
+  static method _#named#tearOff({core::int field1, core::int field2}) → self::Class1
+    return new self::Class1::named(field1: field1, field2: field2);
+  static factory redirectNamedSame({core::int field1, core::int field2}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedSame#tearOff({core::int field1, core::int field2}) → self::Class1
+    return new self::Class1::named(field1: field1, field2: field2);
+  static factory redirectNamedReorder({core::int field2, core::int field1}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedReorder#tearOff({core::int field2, core::int field1}) → self::Class1
+    return new self::Class1::named(field2: field2, field1: field1);
+  static factory redirectNamedFewer1({core::int field1}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer1#tearOff({core::int field1}) → self::Class1
+    return new self::Class1::named(field1: field1);
+  static factory redirectNamedFewer2({core::int field2}) → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer2#tearOff({core::int field2}) → self::Class1
+    return new self::Class1::named(field2: field2);
+  static factory redirectNamedFewer3() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer3#tearOff() → self::Class1
+    return new self::Class1::named();
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+  ;
+static method testDefaultValues() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.transformed.expect
new file mode 100644
index 0000000..ae52285
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.transformed.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1b(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f1c(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f1c(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+//     f2c(field1: 42, field2: 87); // error
+//                     ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+//     f2d(field1: 42, field2: 87); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+//     f2e(field1: 42); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+//     f2e(field2: 87); // error
+//         ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+//     f2e(field1: 42, field2: 87); // error
+//         ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  final field core::int field1;
+  final field core::int field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::redirectPositionalSame, self::Class1::redirectPositionalFewer1, self::Class1::redirectPositionalFewer2, self::Class1::redirectNamedSame, self::Class1::redirectNamedReorder, self::Class1::redirectNamedFewer1, self::Class1::redirectNamedFewer2, self::Class1::redirectNamedFewer3]/*isLegacy*/;
+  constructor positional([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+    ;
+  constructor named({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+    ;
+  static method _#positional#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    return new self::Class1::positional(field1, field2);
+  static factory redirectPositionalSame([core::int field1 = #C3, core::int field2 = #C3]) → self::Class1
+    let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalSame#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+    return new self::Class1::positional(field1, field2);
+  static factory redirectPositionalFewer1([core::int field1 = #C3]) → self::Class1
+    let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalFewer1#tearOff([core::int field1 = #C1]) → self::Class1
+    return new self::Class1::positional(field1);
+  static factory redirectPositionalFewer2() → self::Class1
+    let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+  static method _#redirectPositionalFewer2#tearOff() → self::Class1
+    return new self::Class1::positional();
+  static method _#named#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field1: field1, field2: field2);
+  static factory redirectNamedSame({core::int field1 = #C3, core::int field2 = #C3}) → self::Class1
+    let Never #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedSame#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field1: field1, field2: field2);
+  static factory redirectNamedReorder({core::int field2 = #C3, core::int field1 = #C3}) → self::Class1
+    let Never #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedReorder#tearOff({core::int field2 = #C2, core::int field1 = #C1}) → self::Class1
+    return new self::Class1::named(field2: field2, field1: field1);
+  static factory redirectNamedFewer1({core::int field1 = #C3}) → self::Class1
+    let Never #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer1#tearOff({core::int field1 = #C1}) → self::Class1
+    return new self::Class1::named(field1: field1);
+  static factory redirectNamedFewer2({core::int field2 = #C3}) → self::Class1
+    let Never #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer2#tearOff({core::int field2 = #C2}) → self::Class1
+    return new self::Class1::named(field2: field2);
+  static factory redirectNamedFewer3() → self::Class1
+    let Never #redirecting_factory = self::Class1::named in invalid-expression;
+  static method _#redirectNamedFewer3#tearOff() → self::Class1
+    return new self::Class1::named();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testDefaultValues();
+}
+static method testDefaultValues() → dynamic {
+  ([core::int, core::int]) → self::Class1 f1a = #C4;
+  self::Class1 c1a = f1a(){([core::int, core::int]) → self::Class1};
+  self::expect(1, c1a.{self::Class1::field1}{core::int});
+  self::expect(2, c1a.{self::Class1::field2}{core::int});
+  self::Class1 c1b = f1a(42){([core::int, core::int]) → self::Class1};
+  self::expect(42, c1b.{self::Class1::field1}{core::int});
+  self::expect(2, c1b.{self::Class1::field2}{core::int});
+  self::Class1 c1c = f1a(42, 87){([core::int, core::int]) → self::Class1};
+  self::expect(42, c1c.{self::Class1::field1}{core::int});
+  self::expect(87, c1c.{self::Class1::field2}{core::int});
+  ([core::int]) → self::Class1 f1b = #C5;
+  self::Class1 c1d = f1b(){([core::int]) → self::Class1};
+  self::expect(1, c1d.{self::Class1::field1}{core::int});
+  self::expect(2, c1d.{self::Class1::field2}{core::int});
+  self::Class1 c1e = f1b(42){([core::int]) → self::Class1};
+  self::expect(42, c1e.{self::Class1::field1}{core::int});
+  self::expect(2, c1e.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1b(42, 87); // error
+       ^" in f1b{<inapplicable>}.(42, 87);
+  };
+  () → self::Class1 f1c = #C6;
+  self::Class1 c1f = f1c(){() → self::Class1};
+  self::expect(1, c1f.{self::Class1::field1}{core::int});
+  self::expect(2, c1f.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f1c(42); // error
+       ^" in f1c{<inapplicable>}.(42);
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f1c(42, 87); // error
+       ^" in f1c{<inapplicable>}.(42, 87);
+  };
+  ({field1: core::int, field2: core::int}) → self::Class1 f2a = #C7;
+  self::Class1 c2a = f2a(){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c2a.{self::Class1::field1}{core::int});
+  self::expect(2, c2a.{self::Class1::field2}{core::int});
+  self::Class1 c2b = f2a(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2b.{self::Class1::field1}{core::int});
+  self::expect(2, c2b.{self::Class1::field2}{core::int});
+  self::Class1 c2c = f2a(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2c.{self::Class1::field1}{core::int});
+  self::expect(87, c2c.{self::Class1::field2}{core::int});
+  self::Class1 c2d = f2a(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c2d.{self::Class1::field1}{core::int});
+  self::expect(87, c2d.{self::Class1::field2}{core::int});
+  self::Class1 c2e = f2a(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c2e.{self::Class1::field1}{core::int});
+  self::expect(87, c2e.{self::Class1::field2}{core::int});
+  ({field1: core::int, field2: core::int}) → self::Class1 f2b = #C8;
+  self::Class1 c3a = f2b(){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c3a.{self::Class1::field1}{core::int});
+  self::expect(2, c3a.{self::Class1::field2}{core::int});
+  self::Class1 c3b = f2b(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3b.{self::Class1::field1}{core::int});
+  self::expect(2, c3b.{self::Class1::field2}{core::int});
+  self::Class1 c3c = f2b(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3c.{self::Class1::field1}{core::int});
+  self::expect(87, c3c.{self::Class1::field2}{core::int});
+  self::Class1 c3d = f2b(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(1, c3d.{self::Class1::field1}{core::int});
+  self::expect(87, c3d.{self::Class1::field2}{core::int});
+  self::Class1 c3e = f2b(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+  self::expect(42, c3e.{self::Class1::field1}{core::int});
+  self::expect(87, c3e.{self::Class1::field2}{core::int});
+  ({field1: core::int}) → self::Class1 f2c = #C9;
+  self::Class1 c4a = f2c(){({field1: core::int}) → self::Class1};
+  self::expect(1, c4a.{self::Class1::field1}{core::int});
+  self::expect(2, c4a.{self::Class1::field2}{core::int});
+  self::Class1 c4b = f2c(field1: 42){({field1: core::int}) → self::Class1};
+  self::expect(42, c4b.{self::Class1::field1}{core::int});
+  self::expect(2, c4b.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+    f2c(field1: 42, field2: 87); // error
+                    ^^^^^^" in f2c{<inapplicable>}.(field1: 42, field2: 87);
+  };
+  ({field2: core::int}) → self::Class1 f2d = #C10;
+  self::Class1 c5a = f2d(){({field2: core::int}) → self::Class1};
+  self::expect(1, c5a.{self::Class1::field1}{core::int});
+  self::expect(2, c5a.{self::Class1::field2}{core::int});
+  self::Class1 c5b = f2d(field2: 87){({field2: core::int}) → self::Class1};
+  self::expect(1, c5b.{self::Class1::field1}{core::int});
+  self::expect(87, c5b.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+    f2d(field1: 42, field2: 87); // error
+        ^^^^^^" in f2d{<inapplicable>}.(field1: 42, field2: 87);
+  };
+  () → self::Class1 f2e = #C11;
+  self::Class1 c6a = f2e(){() → self::Class1};
+  self::expect(1, c6a.{self::Class1::field1}{core::int});
+  self::expect(2, c6a.{self::Class1::field2}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+    f2e(field1: 42); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field1: 42);
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+    f2e(field2: 87); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field2: 87);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+    f2e(field1: 42, field2: 87); // error
+        ^^^^^^" in f2e{<inapplicable>}.(field1: 42, field2: 87);
+  };
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C12}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = null
+  #C4 = static-tearoff self::Class1::_#redirectPositionalSame#tearOff
+  #C5 = static-tearoff self::Class1::_#redirectPositionalFewer1#tearOff
+  #C6 = static-tearoff self::Class1::_#redirectPositionalFewer2#tearOff
+  #C7 = static-tearoff self::Class1::_#redirectNamedSame#tearOff
+  #C8 = static-tearoff self::Class1::_#redirectNamedReorder#tearOff
+  #C9 = static-tearoff self::Class1::_#redirectNamedFewer1#tearOff
+  #C10 = static-tearoff self::Class1::_#redirectNamedFewer2#tearOff
+  #C11 = static-tearoff self::Class1::_#redirectNamedFewer3#tearOff
+  #C12 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart
new file mode 100644
index 0000000..aa3ec2f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.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 'main_lib.dart';
+
+typedef H<X, Y> = A<Y>;
+
+// TODO(johnniwinther): Use 'var' here when dependency on inferred parameter
+// types is handled.
+dynamic H_new = H.new;
+dynamic H_named = H.named;
+dynamic H_fact = H.fact;
+dynamic H_redirect = H.redirect;
+
+dynamic F_new = F.new;
+dynamic F_named = F.named;
+dynamic F_fact = F.fact;
+dynamic F_redirect = F.redirect;
+
+main() {
+  expect(true, identical(F_new, F_new_lib));
+  expect(false, identical(F_new, F_named_lib));
+  expect(false, identical(F_new, F_fact_lib));
+  expect(false, identical(F_new, F_redirect_lib));
+  expect(false, identical(F_new, G_new_lib));
+  expect(false, identical(F_new, G_named_lib));
+  expect(false, identical(F_new, G_fact_lib));
+  expect(false, identical(F_new, G_redirect_lib));
+  expect(false, identical(F_new, H_new));
+  expect(false, identical(F_new, H_named));
+  expect(false, identical(F_new, H_fact));
+  expect(false, identical(F_new, H_redirect));
+
+  expect(false, identical(F_named, F_new_lib));
+  expect(true, identical(F_named, F_named_lib));
+  expect(false, identical(F_named, F_fact_lib));
+  expect(false, identical(F_named, F_redirect_lib));
+  expect(false, identical(F_named, G_new_lib));
+  expect(false, identical(F_named, G_named_lib));
+  expect(false, identical(F_named, G_fact_lib));
+  expect(false, identical(F_named, G_redirect_lib));
+  expect(false, identical(F_named, H_new));
+  expect(false, identical(F_named, H_named));
+  expect(false, identical(F_named, H_fact));
+  expect(false, identical(F_named, H_redirect));
+
+  expect(false, identical(F_fact, F_new_lib));
+  expect(false, identical(F_fact, F_named_lib));
+  expect(true, identical(F_fact, F_fact_lib));
+  expect(false, identical(F_fact, F_redirect_lib));
+  expect(false, identical(F_fact, G_new_lib));
+  expect(false, identical(F_fact, G_named_lib));
+  expect(false, identical(F_fact, G_fact_lib));
+  expect(false, identical(F_fact, G_redirect_lib));
+  expect(false, identical(F_fact, H_new));
+  expect(false, identical(F_fact, H_named));
+  expect(false, identical(F_fact, H_fact));
+  expect(false, identical(F_fact, H_redirect));
+
+  expect(false, identical(F_redirect, F_new_lib));
+  expect(false, identical(F_redirect, F_named_lib));
+  expect(false, identical(F_redirect, F_fact_lib));
+  expect(true, identical(F_redirect, F_redirect_lib));
+  expect(false, identical(F_redirect, G_new_lib));
+  expect(false, identical(F_redirect, G_named_lib));
+  expect(false, identical(F_redirect, G_fact_lib));
+  expect(false, identical(F_redirect, G_redirect_lib));
+  expect(false, identical(F_redirect, H_new));
+  expect(false, identical(F_redirect, H_named));
+  expect(false, identical(F_redirect, H_fact));
+  expect(false, identical(F_redirect, H_redirect));
+}
+
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.expect
new file mode 100644
index 0000000..2dc1f69
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+  self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_new, self::H_new));
+  self::expect(false, core::identical(self::F_new, self::H_named));
+  self::expect(false, core::identical(self::F_new, self::H_fact));
+  self::expect(false, core::identical(self::F_new, self::H_redirect));
+  self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+  self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_named, self::H_new));
+  self::expect(false, core::identical(self::F_named, self::H_named));
+  self::expect(false, core::identical(self::F_named, self::H_fact));
+  self::expect(false, core::identical(self::F_named, self::H_redirect));
+  self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+  self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, self::H_new));
+  self::expect(false, core::identical(self::F_fact, self::H_named));
+  self::expect(false, core::identical(self::F_fact, self::H_fact));
+  self::expect(false, core::identical(self::F_fact, self::H_redirect));
+  self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+  self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, self::H_new));
+  self::expect(false, core::identical(self::F_redirect, self::H_named));
+  self::expect(false, core::identical(self::F_redirect, self::H_fact));
+  self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+  return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+  return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+  return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+  constructor •() → mai::A<mai::A::T%>
+    : super core::Object::•()
+    ;
+  constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+    return new mai::A::•<mai::A::_#new#tearOff::T%>();
+  static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+    return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+  static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+    return new mai::A::•<mai::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+    return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+  static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+    let dynamic #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+    return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+  return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+  return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+  return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+  return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+  return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+  return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants  {
+  #C1 = static-tearoff self::_#H#new#tearOff
+  #C2 = static-tearoff self::_#H#named#tearOff
+  #C3 = static-tearoff self::_#H#fact#tearOff
+  #C4 = static-tearoff self::_#H#redirect#tearOff
+  #C5 = static-tearoff mai::_#F#new#tearOff
+  #C6 = static-tearoff mai::_#F#named#tearOff
+  #C7 = static-tearoff mai::_#F#fact#tearOff
+  #C8 = static-tearoff mai::_#F#redirect#tearOff
+  #C9 = null
+  #C10 = 42
+  #C11 = static-tearoff mai::_#G#new#tearOff
+  #C12 = static-tearoff mai::_#G#named#tearOff
+  #C13 = static-tearoff mai::_#G#fact#tearOff
+  #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..a5b6962
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+  self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_new, self::H_new));
+  self::expect(false, core::identical(self::F_new, self::H_named));
+  self::expect(false, core::identical(self::F_new, self::H_fact));
+  self::expect(false, core::identical(self::F_new, self::H_redirect));
+  self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+  self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_named, self::H_new));
+  self::expect(false, core::identical(self::F_named, self::H_named));
+  self::expect(false, core::identical(self::F_named, self::H_fact));
+  self::expect(false, core::identical(self::F_named, self::H_redirect));
+  self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+  self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, self::H_new));
+  self::expect(false, core::identical(self::F_fact, self::H_named));
+  self::expect(false, core::identical(self::F_fact, self::H_fact));
+  self::expect(false, core::identical(self::F_fact, self::H_redirect));
+  self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+  self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, self::H_new));
+  self::expect(false, core::identical(self::F_redirect, self::H_named));
+  self::expect(false, core::identical(self::F_redirect, self::H_fact));
+  self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+  return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+  return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+  return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+  constructor •() → mai::A<mai::A::T%>
+    : super core::Object::•()
+    ;
+  constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+    return new mai::A::•<mai::A::_#new#tearOff::T%>();
+  static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+    return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+  static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+    return new mai::A::•<mai::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+    return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+  static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+    let Never #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+    return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+  return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+  return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+  return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+  return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+  return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+  return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants  {
+  #C1 = static-tearoff self::_#H#new#tearOff
+  #C2 = static-tearoff self::_#H#named#tearOff
+  #C3 = static-tearoff self::_#H#fact#tearOff
+  #C4 = static-tearoff self::_#H#redirect#tearOff
+  #C5 = static-tearoff mai::_#F#new#tearOff
+  #C6 = static-tearoff mai::_#F#named#tearOff
+  #C7 = static-tearoff mai::_#F#fact#tearOff
+  #C8 = static-tearoff mai::_#F#redirect#tearOff
+  #C9 = null
+  #C10 = 42
+  #C11 = static-tearoff mai::_#G#new#tearOff
+  #C12 = static-tearoff mai::_#G#named#tearOff
+  #C13 = static-tearoff mai::_#G#fact#tearOff
+  #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.textual_outline.expect
new file mode 100644
index 0000000..4d2dfc1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+import 'main_lib.dart';
+typedef H<X, Y> = A<Y>;
+dynamic H_new = H.new;
+dynamic H_named = H.named;
+dynamic H_fact = H.fact;
+dynamic H_redirect = H.redirect;
+dynamic F_new = F.new;
+dynamic F_named = F.named;
+dynamic F_fact = F.fact;
+dynamic F_redirect = F.redirect;
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.expect
new file mode 100644
index 0000000..2dc1f69
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+  self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_new, self::H_new));
+  self::expect(false, core::identical(self::F_new, self::H_named));
+  self::expect(false, core::identical(self::F_new, self::H_fact));
+  self::expect(false, core::identical(self::F_new, self::H_redirect));
+  self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+  self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_named, self::H_new));
+  self::expect(false, core::identical(self::F_named, self::H_named));
+  self::expect(false, core::identical(self::F_named, self::H_fact));
+  self::expect(false, core::identical(self::F_named, self::H_redirect));
+  self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+  self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, self::H_new));
+  self::expect(false, core::identical(self::F_fact, self::H_named));
+  self::expect(false, core::identical(self::F_fact, self::H_fact));
+  self::expect(false, core::identical(self::F_fact, self::H_redirect));
+  self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+  self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, self::H_new));
+  self::expect(false, core::identical(self::F_redirect, self::H_named));
+  self::expect(false, core::identical(self::F_redirect, self::H_fact));
+  self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+  return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+  return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+  return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+  constructor •() → mai::A<mai::A::T%>
+    : super core::Object::•()
+    ;
+  constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+    return new mai::A::•<mai::A::_#new#tearOff::T%>();
+  static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+    return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+  static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+    return new mai::A::•<mai::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+    return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+  static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+    let dynamic #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+    return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+  return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+  return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+  return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+  return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+  return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+  return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants  {
+  #C1 = static-tearoff self::_#H#new#tearOff
+  #C2 = static-tearoff self::_#H#named#tearOff
+  #C3 = static-tearoff self::_#H#fact#tearOff
+  #C4 = static-tearoff self::_#H#redirect#tearOff
+  #C5 = static-tearoff mai::_#F#new#tearOff
+  #C6 = static-tearoff mai::_#F#named#tearOff
+  #C7 = static-tearoff mai::_#F#fact#tearOff
+  #C8 = static-tearoff mai::_#F#redirect#tearOff
+  #C9 = null
+  #C10 = 42
+  #C11 = static-tearoff mai::_#G#new#tearOff
+  #C12 = static-tearoff mai::_#G#named#tearOff
+  #C13 = static-tearoff mai::_#G#fact#tearOff
+  #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.outline.expect
new file mode 100644
index 0000000..f1af048
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.outline.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new;
+static field dynamic H_named;
+static field dynamic H_fact;
+static field dynamic H_redirect;
+static field dynamic F_new;
+static field dynamic F_named;
+static field dynamic F_fact;
+static field dynamic F_redirect;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b, core::int c}) → mai::A<self::_#H#fact#tearOff::Y%>
+  return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+  return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b]) → mai::A<self::_#H#named#tearOff::Y%>
+  return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+  constructor •() → mai::A<mai::A::T%>
+    ;
+  constructor named(mai::A::T% a, [core::int? b]) → mai::A<mai::A::T%>
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+    return new mai::A::•<mai::A::_#new#tearOff::T%>();
+  static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b]) → mai::A<mai::A::_#named#tearOff::T%>
+    return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+  static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b, core::int c}) → mai::A<mai::A::fact::T%>
+    ;
+  static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b, core::int c}) → mai::A<mai::A::_#fact#tearOff::T%>
+    return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+  static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+    let dynamic #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+    return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib;
+static field dynamic F_named_lib;
+static field dynamic F_fact_lib;
+static field dynamic F_redirect_lib;
+static field dynamic G_new_lib;
+static field dynamic G_named_lib;
+static field dynamic G_fact_lib;
+static field dynamic G_redirect_lib;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+  return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b]) → mai::A<mai::_#F#named#tearOff::Y%>
+  return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b, core::int c}) → mai::A<mai::_#F#fact#tearOff::Y%>
+  return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+  return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b]) → mai::A<mai::_#G#named#tearOff::Y%>
+  return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b, core::int c}) → mai::A<mai::_#G#fact#tearOff::Y%>
+  return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..a5b6962
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+  self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_new, self::H_new));
+  self::expect(false, core::identical(self::F_new, self::H_named));
+  self::expect(false, core::identical(self::F_new, self::H_fact));
+  self::expect(false, core::identical(self::F_new, self::H_redirect));
+  self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+  self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_named, self::H_new));
+  self::expect(false, core::identical(self::F_named, self::H_named));
+  self::expect(false, core::identical(self::F_named, self::H_fact));
+  self::expect(false, core::identical(self::F_named, self::H_redirect));
+  self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+  self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+  self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, self::H_new));
+  self::expect(false, core::identical(self::F_fact, self::H_named));
+  self::expect(false, core::identical(self::F_fact, self::H_fact));
+  self::expect(false, core::identical(self::F_fact, self::H_redirect));
+  self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+  self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+  self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, self::H_new));
+  self::expect(false, core::identical(self::F_redirect, self::H_named));
+  self::expect(false, core::identical(self::F_redirect, self::H_fact));
+  self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+  return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+  return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+  return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+  constructor •() → mai::A<mai::A::T%>
+    : super core::Object::•()
+    ;
+  constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+    return new mai::A::•<mai::A::_#new#tearOff::T%>();
+  static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+    return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+  static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+    return new mai::A::•<mai::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+    return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+  static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+    let Never #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+    return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+  return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+  return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+  return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+  return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+  return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+  return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+  return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants  {
+  #C1 = static-tearoff self::_#H#new#tearOff
+  #C2 = static-tearoff self::_#H#named#tearOff
+  #C3 = static-tearoff self::_#H#fact#tearOff
+  #C4 = static-tearoff self::_#H#redirect#tearOff
+  #C5 = static-tearoff mai::_#F#new#tearOff
+  #C6 = static-tearoff mai::_#F#named#tearOff
+  #C7 = static-tearoff mai::_#F#fact#tearOff
+  #C8 = static-tearoff mai::_#F#redirect#tearOff
+  #C9 = null
+  #C10 = 42
+  #C11 = static-tearoff mai::_#G#new#tearOff
+  #C12 = static-tearoff mai::_#G#named#tearOff
+  #C13 = static-tearoff mai::_#G#fact#tearOff
+  #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main_lib.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main_lib.dart
new file mode 100644
index 0000000..a57b86b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main_lib.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.
+
+class A<T> {
+  A();
+  A.named(T a, [int? b]);
+  factory A.fact(T a, {int? b, int c = 42}) => new A();
+  factory A.redirect() = A;
+}
+
+typedef F<X, Y> = A<Y>;
+typedef G<X, Y> = A<Y>;
+
+dynamic F_new_lib = F.new;
+dynamic F_named_lib = F.named;
+dynamic F_fact_lib = F.fact;
+dynamic F_redirect_lib = F.redirect;
+
+dynamic G_new_lib = G.new;
+dynamic G_named_lib = G.named;
+dynamic G_fact_lib = G.fact;
+dynamic G_redirect_lib = G.redirect;
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/test.options b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/test.options
new file mode 100644
index 0000000..bfe6dc8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/test.options
@@ -0,0 +1 @@
+main_lib.dart
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart
new file mode 100644
index 0000000..33453f6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart
@@ -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.
+
+import 'typedef_identical_lib.dart';
+
+typedef H<X, Y> = A<Y>;
+
+var H_new = H.new;
+var H_named = H.named;
+var H_fact = H.fact;
+var H_redirect = H.redirect;
+
+var F_new = F.new;
+var F_named = F.named;
+var F_fact = F.fact;
+var F_redirect = F.redirect;
+
+main() {
+  expect(true, identical(F_new, F_new_lib));
+  expect(false, identical(F_new, F_named_lib));
+  expect(false, identical(F_new, F_fact_lib));
+  expect(false, identical(F_new, F_redirect_lib));
+  expect(false, identical(F_new, G_new_lib));
+  expect(false, identical(F_new, G_named_lib));
+  expect(false, identical(F_new, G_fact_lib));
+  expect(false, identical(F_new, G_redirect_lib));
+  expect(false, identical(F_new, H_new));
+  expect(false, identical(F_new, H_named));
+  expect(false, identical(F_new, H_fact));
+  expect(false, identical(F_new, H_redirect));
+
+  expect(false, identical(F_named, F_new_lib));
+  expect(true, identical(F_named, F_named_lib));
+  expect(false, identical(F_named, F_fact_lib));
+  expect(false, identical(F_named, F_redirect_lib));
+  expect(false, identical(F_named, G_new_lib));
+  expect(false, identical(F_named, G_named_lib));
+  expect(false, identical(F_named, G_fact_lib));
+  expect(false, identical(F_named, G_redirect_lib));
+  expect(false, identical(F_named, H_new));
+  expect(false, identical(F_named, H_named));
+  expect(false, identical(F_named, H_fact));
+  expect(false, identical(F_named, H_redirect));
+
+  expect(false, identical(F_fact, F_new_lib));
+  expect(false, identical(F_fact, F_named_lib));
+  expect(true, identical(F_fact, F_fact_lib));
+  expect(false, identical(F_fact, F_redirect_lib));
+  expect(false, identical(F_fact, G_new_lib));
+  expect(false, identical(F_fact, G_named_lib));
+  expect(false, identical(F_fact, G_fact_lib));
+  expect(false, identical(F_fact, G_redirect_lib));
+  expect(false, identical(F_fact, H_new));
+  expect(false, identical(F_fact, H_named));
+  expect(false, identical(F_fact, H_fact));
+  expect(false, identical(F_fact, H_redirect));
+
+  expect(false, identical(F_redirect, F_new_lib));
+  expect(false, identical(F_redirect, F_named_lib));
+  expect(false, identical(F_redirect, F_fact_lib));
+  expect(true, identical(F_redirect, F_redirect_lib));
+  expect(false, identical(F_redirect, G_new_lib));
+  expect(false, identical(F_redirect, G_named_lib));
+  expect(false, identical(F_redirect, G_fact_lib));
+  expect(false, identical(F_redirect, G_redirect_lib));
+  expect(false, identical(F_redirect, H_new));
+  expect(false, identical(F_redirect, H_named));
+  expect(false, identical(F_redirect, H_fact));
+  expect(false, identical(F_redirect, H_redirect));
+}
+
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect
new file mode 100644
index 0000000..3e82a43
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
+static method main() → dynamic {
+  self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_new, self::H_new));
+  self::expect(false, core::identical(self::F_new, self::H_named));
+  self::expect(false, core::identical(self::F_new, self::H_fact));
+  self::expect(false, core::identical(self::F_new, self::H_redirect));
+  self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+  self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_named, self::H_new));
+  self::expect(false, core::identical(self::F_named, self::H_named));
+  self::expect(false, core::identical(self::F_named, self::H_fact));
+  self::expect(false, core::identical(self::F_named, self::H_redirect));
+  self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+  self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, self::H_new));
+  self::expect(false, core::identical(self::F_fact, self::H_named));
+  self::expect(false, core::identical(self::F_fact, self::H_fact));
+  self::expect(false, core::identical(self::F_fact, self::H_redirect));
+  self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+  self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, self::H_new));
+  self::expect(false, core::identical(self::F_redirect, self::H_named));
+  self::expect(false, core::identical(self::F_redirect, self::H_fact));
+  self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+  return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+  return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+  return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+  constructor •() → typ::A<typ::A::T%>
+    : super core::Object::•()
+    ;
+  constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+    return new typ::A::•<typ::A::_#new#tearOff::T%>();
+  static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+    return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+  static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+    return new typ::A::•<typ::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+    return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+  static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+    let dynamic #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+    return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+  return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+  return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+  return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+  return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+  return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+  return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants  {
+  #C1 = static-tearoff self::_#H#new#tearOff
+  #C2 = static-tearoff self::_#H#named#tearOff
+  #C3 = static-tearoff self::_#H#fact#tearOff
+  #C4 = static-tearoff self::_#H#redirect#tearOff
+  #C5 = static-tearoff typ::_#F#new#tearOff
+  #C6 = static-tearoff typ::_#F#named#tearOff
+  #C7 = static-tearoff typ::_#F#fact#tearOff
+  #C8 = static-tearoff typ::_#F#redirect#tearOff
+  #C9 = null
+  #C10 = 42
+  #C11 = static-tearoff typ::_#G#new#tearOff
+  #C12 = static-tearoff typ::_#G#named#tearOff
+  #C13 = static-tearoff typ::_#G#fact#tearOff
+  #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect
new file mode 100644
index 0000000..f7eae91
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
+static method main() → dynamic {
+  self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_new, self::H_new));
+  self::expect(false, core::identical(self::F_new, self::H_named));
+  self::expect(false, core::identical(self::F_new, self::H_fact));
+  self::expect(false, core::identical(self::F_new, self::H_redirect));
+  self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+  self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_named, self::H_new));
+  self::expect(false, core::identical(self::F_named, self::H_named));
+  self::expect(false, core::identical(self::F_named, self::H_fact));
+  self::expect(false, core::identical(self::F_named, self::H_redirect));
+  self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+  self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, self::H_new));
+  self::expect(false, core::identical(self::F_fact, self::H_named));
+  self::expect(false, core::identical(self::F_fact, self::H_fact));
+  self::expect(false, core::identical(self::F_fact, self::H_redirect));
+  self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+  self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, self::H_new));
+  self::expect(false, core::identical(self::F_redirect, self::H_named));
+  self::expect(false, core::identical(self::F_redirect, self::H_fact));
+  self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+  return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+  return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+  return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+  constructor •() → typ::A<typ::A::T%>
+    : super core::Object::•()
+    ;
+  constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+    return new typ::A::•<typ::A::_#new#tearOff::T%>();
+  static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+    return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+  static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+    return new typ::A::•<typ::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+    return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+  static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+    let Never #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+    return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+  return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+  return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+  return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+  return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+  return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+  return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants  {
+  #C1 = static-tearoff self::_#H#new#tearOff
+  #C2 = static-tearoff self::_#H#named#tearOff
+  #C3 = static-tearoff self::_#H#fact#tearOff
+  #C4 = static-tearoff self::_#H#redirect#tearOff
+  #C5 = static-tearoff typ::_#F#new#tearOff
+  #C6 = static-tearoff typ::_#F#named#tearOff
+  #C7 = static-tearoff typ::_#F#fact#tearOff
+  #C8 = static-tearoff typ::_#F#redirect#tearOff
+  #C9 = null
+  #C10 = 42
+  #C11 = static-tearoff typ::_#G#new#tearOff
+  #C12 = static-tearoff typ::_#G#named#tearOff
+  #C13 = static-tearoff typ::_#G#fact#tearOff
+  #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect
new file mode 100644
index 0000000..8ca6604
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+import 'typedef_identical_lib.dart';
+typedef H<X, Y> = A<Y>;
+var H_new = H.new;
+var H_named = H.named;
+var H_fact = H.fact;
+var H_redirect = H.redirect;
+var F_new = F.new;
+var F_named = F.named;
+var F_fact = F.fact;
+var F_redirect = F.redirect;
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect
new file mode 100644
index 0000000..3e82a43
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
+static method main() → dynamic {
+  self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_new, self::H_new));
+  self::expect(false, core::identical(self::F_new, self::H_named));
+  self::expect(false, core::identical(self::F_new, self::H_fact));
+  self::expect(false, core::identical(self::F_new, self::H_redirect));
+  self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+  self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_named, self::H_new));
+  self::expect(false, core::identical(self::F_named, self::H_named));
+  self::expect(false, core::identical(self::F_named, self::H_fact));
+  self::expect(false, core::identical(self::F_named, self::H_redirect));
+  self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+  self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, self::H_new));
+  self::expect(false, core::identical(self::F_fact, self::H_named));
+  self::expect(false, core::identical(self::F_fact, self::H_fact));
+  self::expect(false, core::identical(self::F_fact, self::H_redirect));
+  self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+  self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, self::H_new));
+  self::expect(false, core::identical(self::F_redirect, self::H_named));
+  self::expect(false, core::identical(self::F_redirect, self::H_fact));
+  self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+  return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+  return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+  return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+  constructor •() → typ::A<typ::A::T%>
+    : super core::Object::•()
+    ;
+  constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+    return new typ::A::•<typ::A::_#new#tearOff::T%>();
+  static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+    return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+  static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+    return new typ::A::•<typ::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+    return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+  static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+    let dynamic #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+    return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+  return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+  return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+  return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+  return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+  return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+  return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants  {
+  #C1 = static-tearoff self::_#H#new#tearOff
+  #C2 = static-tearoff self::_#H#named#tearOff
+  #C3 = static-tearoff self::_#H#fact#tearOff
+  #C4 = static-tearoff self::_#H#redirect#tearOff
+  #C5 = static-tearoff typ::_#F#new#tearOff
+  #C6 = static-tearoff typ::_#F#named#tearOff
+  #C7 = static-tearoff typ::_#F#fact#tearOff
+  #C8 = static-tearoff typ::_#F#redirect#tearOff
+  #C9 = null
+  #C10 = 42
+  #C11 = static-tearoff typ::_#G#new#tearOff
+  #C12 = static-tearoff typ::_#G#named#tearOff
+  #C13 = static-tearoff typ::_#G#fact#tearOff
+  #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect
new file mode 100644
index 0000000..feafdc3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+  return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b]) → typ::A<self::_#H#named#tearOff::Y%>
+  return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b, core::int c}) → typ::A<self::_#H#fact#tearOff::Y%>
+  return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+  constructor •() → typ::A<typ::A::T%>
+    ;
+  constructor named(typ::A::T% a, [core::int? b]) → typ::A<typ::A::T%>
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+    return new typ::A::•<typ::A::_#new#tearOff::T%>();
+  static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b]) → typ::A<typ::A::_#named#tearOff::T%>
+    return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+  static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b, core::int c}) → typ::A<typ::A::fact::T%>
+    ;
+  static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b, core::int c}) → typ::A<typ::A::_#fact#tearOff::T%>
+    return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+  static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+    let dynamic #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+    return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+  return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b]) → typ::A<typ::_#F#named#tearOff::Y%>
+  return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b, core::int c}) → typ::A<typ::_#F#fact#tearOff::Y%>
+  return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+  return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b]) → typ::A<typ::_#G#named#tearOff::Y%>
+  return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b, core::int c}) → typ::A<typ::_#G#fact#tearOff::Y%>
+  return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect
new file mode 100644
index 0000000..f7eae91
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
+static method main() → dynamic {
+  self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_new, self::H_new));
+  self::expect(false, core::identical(self::F_new, self::H_named));
+  self::expect(false, core::identical(self::F_new, self::H_fact));
+  self::expect(false, core::identical(self::F_new, self::H_redirect));
+  self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+  self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_named, self::H_new));
+  self::expect(false, core::identical(self::F_named, self::H_named));
+  self::expect(false, core::identical(self::F_named, self::H_fact));
+  self::expect(false, core::identical(self::F_named, self::H_redirect));
+  self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+  self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+  self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_fact, self::H_new));
+  self::expect(false, core::identical(self::F_fact, self::H_named));
+  self::expect(false, core::identical(self::F_fact, self::H_fact));
+  self::expect(false, core::identical(self::F_fact, self::H_redirect));
+  self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+  self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+  self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+  self::expect(false, core::identical(self::F_redirect, self::H_new));
+  self::expect(false, core::identical(self::F_redirect, self::H_named));
+  self::expect(false, core::identical(self::F_redirect, self::H_fact));
+  self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+  return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+  return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+  return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+  constructor •() → typ::A<typ::A::T%>
+    : super core::Object::•()
+    ;
+  constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+    return new typ::A::•<typ::A::_#new#tearOff::T%>();
+  static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+    return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+  static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+    return new typ::A::•<typ::A::fact::T%>();
+  static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+    return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+  static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+    let Never #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+  static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+    return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+  return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+  return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+  return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+  return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+  return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+  return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+  return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants  {
+  #C1 = static-tearoff self::_#H#new#tearOff
+  #C2 = static-tearoff self::_#H#named#tearOff
+  #C3 = static-tearoff self::_#H#fact#tearOff
+  #C4 = static-tearoff self::_#H#redirect#tearOff
+  #C5 = static-tearoff typ::_#F#new#tearOff
+  #C6 = static-tearoff typ::_#F#named#tearOff
+  #C7 = static-tearoff typ::_#F#fact#tearOff
+  #C8 = static-tearoff typ::_#F#redirect#tearOff
+  #C9 = null
+  #C10 = 42
+  #C11 = static-tearoff typ::_#G#new#tearOff
+  #C12 = static-tearoff typ::_#G#named#tearOff
+  #C13 = static-tearoff typ::_#G#fact#tearOff
+  #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart
new file mode 100644
index 0000000..e21df56
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.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.
+
+class A<T> {
+  A();
+  A.named(T a, [int? b]);
+  factory A.fact(T a, {int? b, int c = 42}) => new A();
+  factory A.redirect() = A;
+}
+
+typedef F<X, Y> = A<Y>;
+typedef G<X, Y> = A<Y>;
+
+var F_new_lib = F.new;
+var F_named_lib = F.named;
+var F_fact_lib = F.fact;
+var F_redirect_lib = F.redirect;
+
+var G_new_lib = G.new;
+var G_named_lib = G.named;
+var G_fact_lib = G.fact;
+var G_redirect_lib = G.redirect;
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart
new file mode 100644
index 0000000..0433631
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart
@@ -0,0 +1,186 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+class A {}
+
+class B<X> {
+  int field1;
+  String field2;
+
+  B._(this.field1, this.field2);
+  B() : this._(0, '');
+  B.foo(this.field1) : field2 = '';
+  factory B.bar(int i, String j) => new B<X>._(i, j);
+}
+
+typedef DA1 = A;
+
+typedef DA2<X extends num> = A;
+
+typedef DB1 = B<String>;
+
+typedef DB2<X extends num> = B<X>;
+
+typedef DB3<X extends num, Y extends String> = B<X>;
+
+main() {
+  var f1a = DA1.new;
+  var c1a = f1a();
+  expect(true, c1a is A);
+  () {
+    f1a(0); // error
+  };
+
+  dynamic f1b = DA1.new;
+  var c1b = f1b();
+  expect(true, c1b is A);
+  throws(() => f1b(0));
+
+  var f2a = DA2.new;
+  var c2a = f2a();
+  expect(true, c2a is A);
+  () {
+    f2a(0); // error
+    f2a<String>(); // error
+  };
+
+  dynamic f2b = DA2.new;
+  var c2b = f2b();
+  expect(true, c2b is A);
+  var c2c = f2b<int>();
+  expect(true, c2c is A);
+  throws(() => f2b(0));
+  throws(() => f2b<String>());
+
+  var f3a = DB1.new;
+  var c3a = f3a();
+  expect(true, c3a is B<String>);
+  expect(false, c3a is B<int>);
+  expect(0, c3a.field1);
+  expect('', c3a.field2);
+  () {
+    f3a(0); // error
+    f3a<String>(); // error
+  };
+
+  dynamic f3b = DB1.new;
+  var c3b = f3b();
+  expect(true, c3b is B<String>);
+  expect(false, c3b is B<int>);
+  expect(0, c3a.field1);
+  expect('', c3a.field2);
+  throws(() => f3b(0));
+  throws(() => f3b<String>());
+
+  var f3c = DB1.foo;
+  var c3c = f3c(42);
+  expect(true, c3c is B<String>);
+  expect(false, c3c is B<int>);
+  expect(42, c3c.field1);
+  expect('', c3c.field2);
+  () {
+    f3c(); // error
+    f3c(0, 0); // error
+    f3c<String>(0); // error
+  };
+
+  dynamic f3d = DB1.foo;
+  var c3d = f3d(42);
+  expect(true, c3d is B<String>);
+  expect(false, c3d is B<int>);
+  expect(42, c3d.field1);
+  expect('', c3d.field2);
+  throws(() => f3d());
+  throws(() => f3d(0, 0));
+  throws(() => f3d<String>(0));
+
+  var f3e = DB1.bar;
+  var c3e = f3e(42, 'foo');
+  expect(true, c3e is B<String>);
+  expect(false, c3e is B<int>);
+  expect(42, c3e.field1);
+  expect('foo', c3e.field2);
+  () {
+    f3e(); // error
+    f3e(0); // error
+    f3e<String>(0, ''); // error
+  };
+
+  dynamic f3f = DB1.bar;
+  var c3f = f3f(42, 'foo');
+  expect(true, c3f is B<String>);
+  expect(false, c3f is B<int>);
+  expect(42, c3f.field1);
+  expect('foo', c3f.field2);
+  throws(() => c3f());
+  throws(() => c3f(0));
+  throws(() => c3f<String>(0));
+
+  var f4a = DB2.new;
+  var c4a = f4a();
+  expect(true, c4a is B<num>);
+  expect(false, c4a is B<int>);
+  var c4b = f4a<int>();
+  expect(true, c4b is B<int>);
+  expect(false, c4b is B<double>);
+  () {
+    f4a(0); // error
+    f4a<String>(); // error
+  };
+
+  dynamic f4b = DB2.new;
+  var c4c = f4b();
+  expect(true, c4c is B<num>);
+  expect(false, c4c is B<int>);
+  var c4d = f4b<int>();
+  expect(true, c4d is B<int>);
+  expect(false, c4d is B<double>);
+  throws(() => f4b(0));
+  throws(() => f4b<String>());
+
+  var f5a = DB3.new;
+  var c5a = f5a();
+  expect(true, c5a is B<num>);
+  expect(false, c5a is B<int>);
+  var c5b = f5a<int, String>();
+  expect(true, c5b is B<int>);
+  expect(false, c5b is B<double>);
+  () {
+    f5a(0); // error
+    f5a<String>(); // error
+    f5a<String, String>(); // error
+    f5a<num, num>(); // error
+  };
+
+  dynamic f5b = DB3.new;
+  var c5c = f5b();
+  expect(true, c5c is B<num>);
+  expect(false, c5c is B<int>);
+  var c5d = f5b<int, String>();
+  expect(true, c5d is B<int>);
+  expect(false, c5d is B<double>);
+  throws(() => f5b(0));
+  throws(() => f5b<String>());
+  throws(() => f5b<String, String>());
+  throws(() => f5b<num, num>());
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.expect
new file mode 100644
index 0000000..848dbdd
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.expect
@@ -0,0 +1,330 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f1a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:47:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f3a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+//     f3a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3c(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3c(0, 0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+//     f3c<String>(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+//     f3e(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+//     f3e(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+//     f3e<String>(0, ''); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f4a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:131:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f4a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f5a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+//     f5a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:154:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<String, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:155:8: Error: Type argument 'num' doesn't conform to the bound 'String' of the type variable 'Y' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<num, num>(); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef DA1 = self::A;
+typedef DA2<unrelated X extends core::num> = self::A;
+typedef DB1 = self::B<core::String>;
+typedef DB2<X extends core::num> = self::B<X>;
+typedef DB3<X extends core::num, unrelated Y extends core::String> = self::B<X>;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::A
+    return new self::A::•();
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+  field core::int field1;
+  field core::String field2;
+  constructor _(core::int field1, core::String field2) → self::B<self::B::X%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor •() → self::B<self::B::X%>
+    : this self::B::_(0, "")
+    ;
+  constructor foo(core::int field1) → self::B<self::B::X%>
+    : self::B::field1 = field1, self::B::field2 = "", super core::Object::•()
+    ;
+  static method _#_#tearOff<X extends core::Object? = dynamic>(core::int field1, core::String field2) → self::B<self::B::_#_#tearOff::X%>
+    return new self::B::_<self::B::_#_#tearOff::X%>(field1, field2);
+  static method _#new#tearOff<X extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::X%>
+    return new self::B::•<self::B::_#new#tearOff::X%>();
+  static method _#foo#tearOff<X extends core::Object? = dynamic>(core::int field1) → self::B<self::B::_#foo#tearOff::X%>
+    return new self::B::foo<self::B::_#foo#tearOff::X%>(field1);
+  static factory bar<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::bar::X%>
+    return new self::B::_<self::B::bar::X%>(i, j);
+  static method _#bar#tearOff<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::_#bar#tearOff::X%>
+    return self::B::bar<self::B::_#bar#tearOff::X%>(i, j);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  () → self::A f1a = #C1;
+  self::A c1a = f1a(){() → self::A};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::A);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f1a(0); // error
+       ^" in f1a{<inapplicable>}.(0);
+  };
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::A);
+  self::throws(() → dynamic => f1b{dynamic}.call(0));
+  <unrelated X extends core::num>() → self::A f2a = #C2;
+  self::A c2a = f2a<core::num>(){() → self::A};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::A);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(0); // error
+       ^" in f2a{<inapplicable>}.<core::num>(0);
+    f2a<core::String>(){() → self::A};
+  };
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::A);
+  dynamic c2c = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::A);
+  self::throws(() → dynamic => f2b{dynamic}.call(0));
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  () → self::B<core::String> f3a = #C4;
+  self::B<core::String> c3a = f3a(){() → self::B<core::String>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(0, c3a.{self::B::field1}{core::int});
+  self::expect("", c3a.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f3a(0); // error
+       ^" in f3a{<inapplicable>}.(0);
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+    f3a<String>(); // error
+       ^" in f3a{<inapplicable>}.<core::String>();
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call();
+  self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(0, c3a.{self::B::field1}{core::int});
+  self::expect("", c3a.{self::B::field2}{core::String});
+  self::throws(() → dynamic => f3b{dynamic}.call(0));
+  self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
+  (core::int) → self::B<core::String> f3c = #C6;
+  self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
+  self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3c.{self::B::field1}{core::int});
+  self::expect("", c3c.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3c(); // error
+       ^" in f3c{<inapplicable>}.();
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3c(0, 0); // error
+       ^" in f3c{<inapplicable>}.(0, 0);
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+    f3c<String>(0); // error
+       ^" in f3c{<inapplicable>}.<core::String>(0);
+  };
+  dynamic f3d = #C6;
+  dynamic c3d = f3d{dynamic}.call(42);
+  self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3d{dynamic}.field1);
+  self::expect("", c3d{dynamic}.field2);
+  self::throws(() → dynamic => f3d{dynamic}.call());
+  self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
+  self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
+  (core::int, core::String) → self::B<core::String> f3e = #C8;
+  self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
+  self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3e.{self::B::field1}{core::int});
+  self::expect("foo", c3e.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+    f3e(); // error
+       ^" in f3e{<inapplicable>}.();
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+    f3e(0); // error
+       ^" in f3e{<inapplicable>}.(0);
+    let final Never #t10 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+    f3e<String>(0, ''); // error
+       ^" in f3e{<inapplicable>}.<core::String>(0, "");
+  };
+  dynamic f3f = #C8;
+  dynamic c3f = f3f{dynamic}.call(42, "foo");
+  self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3f{dynamic}.field1);
+  self::expect("foo", c3f{dynamic}.field2);
+  self::throws(() → dynamic => c3f{dynamic}.call());
+  self::throws(() → dynamic => c3f{dynamic}.call(0));
+  self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
+  <X extends core::num>() → self::B<X> f4a = #C9;
+  self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
+  self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
+  self::B<core::int> c4b = f4a<core::int>(){() → self::B<core::int>};
+  self::expect(true, c4b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c4b is{ForNonNullableByDefault} self::B<core::double>);
+  () → Null {
+    let final Never #t11 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f4a(0); // error
+       ^" in f4a{<inapplicable>}.<core::num>(0);
+    f4a<core::String>(){() → self::B<core::String>};
+  };
+  dynamic f4b = #C9;
+  dynamic c4c = f4b{dynamic}.call();
+  self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
+  dynamic c4d = f4b{dynamic}.call<core::int>();
+  self::expect(true, c4d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
+  self::throws(() → dynamic => f4b{dynamic}.call(0));
+  self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
+  <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
+  self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
+  self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
+  self::B<core::int> c5b = f5a<core::int, core::String>(){() → self::B<core::int>};
+  self::expect(true, c5b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c5b is{ForNonNullableByDefault} self::B<core::double>);
+  () → Null {
+    let final Never #t12 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f5a(0); // error
+       ^" in f5a{<inapplicable>}.<core::num, core::String>(0);
+    let final Never #t13 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+    f5a<String>(); // error
+       ^" in f5a{<inapplicable>}.<core::String>();
+    f5a<core::String, core::String>(){() → self::B<core::String>};
+    f5a<core::num, core::num>(){() → self::B<core::num>};
+  };
+  dynamic f5b = #C10;
+  dynamic c5c = f5b{dynamic}.call();
+  self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
+  dynamic c5d = f5b{dynamic}.call<core::int, core::String>();
+  self::expect(true, c5d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c5d is{ForNonNullableByDefault} self::B<core::double>);
+  self::throws(() → dynamic => f5b{dynamic}.call(0));
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String, core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::num, core::num>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+  return new self::A::•();
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+  return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+  return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+  return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+  return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+  return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+  return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+  return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+  return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::_#DA2#new#tearOff
+  #C3 = static-tearoff self::B::_#new#tearOff
+  #C4 = instantiation self::B::_#new#tearOff <core::String>
+  #C5 = static-tearoff self::B::_#foo#tearOff
+  #C6 = instantiation self::B::_#foo#tearOff <core::String>
+  #C7 = static-tearoff self::B::_#bar#tearOff
+  #C8 = instantiation self::B::_#bar#tearOff <core::String>
+  #C9 = static-tearoff self::_#DB2#new#tearOff
+  #C10 = static-tearoff self::_#DB3#new#tearOff
+  #C11 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..7c8571b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,330 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f1a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:47:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f3a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+//     f3a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3c(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3c(0, 0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+//     f3c<String>(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+//     f3e(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+//     f3e(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+//     f3e<String>(0, ''); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f4a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:131:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f4a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f5a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+//     f5a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:154:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<String, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:155:8: Error: Type argument 'num' doesn't conform to the bound 'String' of the type variable 'Y' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<num, num>(); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef DA1 = self::A;
+typedef DA2<unrelated X extends core::num> = self::A;
+typedef DB1 = self::B<core::String>;
+typedef DB2<X extends core::num> = self::B<X>;
+typedef DB3<X extends core::num, unrelated Y extends core::String> = self::B<X>;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::A
+    return new self::A::•();
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+  field core::int field1;
+  field core::String field2;
+  constructor _(core::int field1, core::String field2) → self::B<self::B::X%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor •() → self::B<self::B::X%>
+    : this self::B::_(0, "")
+    ;
+  constructor foo(core::int field1) → self::B<self::B::X%>
+    : self::B::field1 = field1, self::B::field2 = "", super core::Object::•()
+    ;
+  static method _#_#tearOff<X extends core::Object? = dynamic>(core::int field1, core::String field2) → self::B<self::B::_#_#tearOff::X%>
+    return new self::B::_<self::B::_#_#tearOff::X%>(field1, field2);
+  static method _#new#tearOff<X extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::X%>
+    return new self::B::•<self::B::_#new#tearOff::X%>();
+  static method _#foo#tearOff<X extends core::Object? = dynamic>(core::int field1) → self::B<self::B::_#foo#tearOff::X%>
+    return new self::B::foo<self::B::_#foo#tearOff::X%>(field1);
+  static factory bar<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::bar::X%>
+    return new self::B::_<self::B::bar::X%>(i, j);
+  static method _#bar#tearOff<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::_#bar#tearOff::X%>
+    return self::B::bar<self::B::_#bar#tearOff::X%>(i, j);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  () → self::A f1a = #C1;
+  self::A c1a = f1a(){() → self::A};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::A);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f1a(0); // error
+       ^" in f1a{<inapplicable>}.(0);
+  };
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::A);
+  self::throws(() → dynamic => f1b{dynamic}.call(0));
+  <unrelated X extends core::num>() → self::A f2a = #C2;
+  self::A c2a = f2a<core::num>(){() → self::A};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::A);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(0); // error
+       ^" in f2a{<inapplicable>}.<core::num>(0);
+    f2a<core::String>(){() → self::A};
+  };
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::A);
+  dynamic c2c = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::A);
+  self::throws(() → dynamic => f2b{dynamic}.call(0));
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  () → self::B<core::String> f3a = #C4;
+  self::B<core::String> c3a = f3a(){() → self::B<core::String>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(0, c3a.{self::B::field1}{core::int});
+  self::expect("", c3a.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f3a(0); // error
+       ^" in f3a{<inapplicable>}.(0);
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+    f3a<String>(); // error
+       ^" in f3a{<inapplicable>}.<core::String>();
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call();
+  self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(0, c3a.{self::B::field1}{core::int});
+  self::expect("", c3a.{self::B::field2}{core::String});
+  self::throws(() → dynamic => f3b{dynamic}.call(0));
+  self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
+  (core::int) → self::B<core::String> f3c = #C6;
+  self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
+  self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3c.{self::B::field1}{core::int});
+  self::expect("", c3c.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3c(); // error
+       ^" in f3c{<inapplicable>}.();
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3c(0, 0); // error
+       ^" in f3c{<inapplicable>}.(0, 0);
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+    f3c<String>(0); // error
+       ^" in f3c{<inapplicable>}.<core::String>(0);
+  };
+  dynamic f3d = #C6;
+  dynamic c3d = f3d{dynamic}.call(42);
+  self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3d{dynamic}.field1);
+  self::expect("", c3d{dynamic}.field2);
+  self::throws(() → dynamic => f3d{dynamic}.call());
+  self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
+  self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
+  (core::int, core::String) → self::B<core::String> f3e = #C8;
+  self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
+  self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3e.{self::B::field1}{core::int});
+  self::expect("foo", c3e.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+    f3e(); // error
+       ^" in f3e{<inapplicable>}.();
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+    f3e(0); // error
+       ^" in f3e{<inapplicable>}.(0);
+    let final Never #t10 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+    f3e<String>(0, ''); // error
+       ^" in f3e{<inapplicable>}.<core::String>(0, "");
+  };
+  dynamic f3f = #C8;
+  dynamic c3f = f3f{dynamic}.call(42, "foo");
+  self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3f{dynamic}.field1);
+  self::expect("foo", c3f{dynamic}.field2);
+  self::throws(() → dynamic => c3f{dynamic}.call());
+  self::throws(() → dynamic => c3f{dynamic}.call(0));
+  self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
+  <X extends core::num>() → self::B<X> f4a = #C9;
+  self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
+  self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
+  self::B<core::int> c4b = f4a<core::int>(){() → self::B<core::int>};
+  self::expect(true, c4b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c4b is{ForNonNullableByDefault} self::B<core::double>);
+  () → Null {
+    let final Never #t11 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f4a(0); // error
+       ^" in f4a{<inapplicable>}.<core::num>(0);
+    f4a<core::String>(){() → self::B<core::String>};
+  };
+  dynamic f4b = #C9;
+  dynamic c4c = f4b{dynamic}.call();
+  self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
+  dynamic c4d = f4b{dynamic}.call<core::int>();
+  self::expect(true, c4d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
+  self::throws(() → dynamic => f4b{dynamic}.call(0));
+  self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
+  <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
+  self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
+  self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
+  self::B<core::int> c5b = f5a<core::int, core::String>(){() → self::B<core::int>};
+  self::expect(true, c5b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c5b is{ForNonNullableByDefault} self::B<core::double>);
+  () → Null {
+    let final Never #t12 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f5a(0); // error
+       ^" in f5a{<inapplicable>}.<core::num, core::String>(0);
+    let final Never #t13 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+    f5a<String>(); // error
+       ^" in f5a{<inapplicable>}.<core::String>();
+    f5a<core::String, core::String>(){() → self::B<core::String>};
+    f5a<core::num, core::num>(){() → self::B<core::num>};
+  };
+  dynamic f5b = #C10;
+  dynamic c5c = f5b{dynamic}.call();
+  self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
+  dynamic c5d = f5b{dynamic}.call<core::int, core::String>();
+  self::expect(true, c5d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c5d is{ForNonNullableByDefault} self::B<core::double>);
+  self::throws(() → dynamic => f5b{dynamic}.call(0));
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String, core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::num, core::num>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+  return new self::A::•();
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+  return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+  return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+  return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+  return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+  return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+  return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+  return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+  return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::_#DA2#new#tearOff
+  #C3 = static-tearoff self::B::_#new#tearOff
+  #C4 = instantiation self::B::_#new#tearOff <core::String>
+  #C5 = static-tearoff self::B::_#foo#tearOff
+  #C6 = instantiation self::B::_#foo#tearOff <core::String>
+  #C7 = static-tearoff self::B::_#bar#tearOff
+  #C8 = instantiation self::B::_#bar#tearOff <core::String>
+  #C9 = static-tearoff self::_#DB2#new#tearOff
+  #C10 = static-tearoff self::_#DB3#new#tearOff
+  #C11 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..fa1b6a2
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline.expect
@@ -0,0 +1,21 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+
+class A {}
+
+class B<X> {
+  int field1;
+  String field2;
+  B._(this.field1, this.field2);
+  B() : this._(0, '');
+  B.foo(this.field1) : field2 = '';
+  factory B.bar(int i, String j) => new B<X>._(i, j);
+}
+
+typedef DA1 = A;
+typedef DA2<X extends num> = A;
+typedef DB1 = B<String>;
+typedef DB2<X extends num> = B<X>;
+typedef DB3<X extends num, Y extends String> = B<X>;
+main() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f65e858
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,20 @@
+class A {}
+
+class B<X> {
+  B() : this._(0, '');
+  B._(this.field1, this.field2);
+  B.foo(this.field1) : field2 = '';
+  String field2;
+  factory B.bar(int i, String j) => new B<X>._(i, j);
+  int field1;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
+typedef DA1 = A;
+typedef DA2<X extends num> = A;
+typedef DB1 = B<String>;
+typedef DB2<X extends num> = B<X>;
+typedef DB3<X extends num, Y extends String> = B<X>;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.expect
new file mode 100644
index 0000000..f4e5e89
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.expect
@@ -0,0 +1,330 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f1a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:47:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f3a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+//     f3a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3c(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3c(0, 0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+//     f3c<String>(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+//     f3e(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+//     f3e(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+//     f3e<String>(0, ''); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f4a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:131:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f4a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f5a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+//     f5a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:154:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<String, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:155:8: Error: Type argument 'num' doesn't conform to the bound 'String' of the type variable 'Y' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<num, num>(); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef DA1 = self::A;
+typedef DA2<unrelated X extends core::num> = self::A;
+typedef DB1 = self::B<core::String>;
+typedef DB2<X extends core::num> = self::B<X>;
+typedef DB3<X extends core::num, unrelated Y extends core::String> = self::B<X>;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::A
+    return new self::A::•();
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+  field core::int field1;
+  field core::String field2;
+  constructor _(core::int field1, core::String field2) → self::B<self::B::X%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor •() → self::B<self::B::X%>
+    : this self::B::_(0, "")
+    ;
+  constructor foo(core::int field1) → self::B<self::B::X%>
+    : self::B::field1 = field1, self::B::field2 = "", super core::Object::•()
+    ;
+  static method _#_#tearOff<X extends core::Object? = dynamic>(core::int field1, core::String field2) → self::B<self::B::_#_#tearOff::X%>
+    return new self::B::_<self::B::_#_#tearOff::X%>(field1, field2);
+  static method _#new#tearOff<X extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::X%>
+    return new self::B::•<self::B::_#new#tearOff::X%>();
+  static method _#foo#tearOff<X extends core::Object? = dynamic>(core::int field1) → self::B<self::B::_#foo#tearOff::X%>
+    return new self::B::foo<self::B::_#foo#tearOff::X%>(field1);
+  static factory bar<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::bar::X%>
+    return new self::B::_<self::B::bar::X%>(i, j);
+  static method _#bar#tearOff<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::_#bar#tearOff::X%>
+    return self::B::bar<self::B::_#bar#tearOff::X%>(i, j);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  () → self::A f1a = #C1;
+  self::A c1a = f1a(){() → self::A};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::A);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f1a(0); // error
+       ^" in f1a{<inapplicable>}.(0);
+  };
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::A);
+  self::throws(() → dynamic => f1b{dynamic}.call(0));
+  <unrelated X extends core::num>() → self::A f2a = #C2;
+  self::A c2a = f2a<core::num>(){() → self::A};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::A);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(0); // error
+       ^" in f2a{<inapplicable>}.<core::num>(0);
+    f2a<core::String>(){() → self::A};
+  };
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::A);
+  dynamic c2c = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::A);
+  self::throws(() → dynamic => f2b{dynamic}.call(0));
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  () → self::B<core::String> f3a = #C4;
+  self::B<core::String> c3a = f3a(){() → self::B<core::String>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(0, c3a.{self::B::field1}{core::int});
+  self::expect("", c3a.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f3a(0); // error
+       ^" in f3a{<inapplicable>}.(0);
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+    f3a<String>(); // error
+       ^" in f3a{<inapplicable>}.<core::String>();
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call();
+  self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(0, c3a.{self::B::field1}{core::int});
+  self::expect("", c3a.{self::B::field2}{core::String});
+  self::throws(() → dynamic => f3b{dynamic}.call(0));
+  self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
+  (core::int) → self::B<core::String> f3c = #C6;
+  self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
+  self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3c.{self::B::field1}{core::int});
+  self::expect("", c3c.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3c(); // error
+       ^" in f3c{<inapplicable>}.();
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3c(0, 0); // error
+       ^" in f3c{<inapplicable>}.(0, 0);
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+    f3c<String>(0); // error
+       ^" in f3c{<inapplicable>}.<core::String>(0);
+  };
+  dynamic f3d = #C6;
+  dynamic c3d = f3d{dynamic}.call(42);
+  self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3d{dynamic}.field1);
+  self::expect("", c3d{dynamic}.field2);
+  self::throws(() → dynamic => f3d{dynamic}.call());
+  self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
+  self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
+  (core::int, core::String) → self::B<core::String> f3e = #C8;
+  self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
+  self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3e.{self::B::field1}{core::int});
+  self::expect("foo", c3e.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+    f3e(); // error
+       ^" in f3e{<inapplicable>}.();
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+    f3e(0); // error
+       ^" in f3e{<inapplicable>}.(0);
+    let final Never #t10 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+    f3e<String>(0, ''); // error
+       ^" in f3e{<inapplicable>}.<core::String>(0, "");
+  };
+  dynamic f3f = #C8;
+  dynamic c3f = f3f{dynamic}.call(42, "foo");
+  self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3f{dynamic}.field1);
+  self::expect("foo", c3f{dynamic}.field2);
+  self::throws(() → dynamic => c3f{dynamic}.call());
+  self::throws(() → dynamic => c3f{dynamic}.call(0));
+  self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
+  <X extends core::num>() → self::B<X> f4a = #C9;
+  self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
+  self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
+  self::B<core::int> c4b = f4a<core::int>(){() → self::B<core::int>};
+  self::expect(true, c4b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c4b is{ForNonNullableByDefault} self::B<core::double>);
+  () → Null {
+    let final Never #t11 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f4a(0); // error
+       ^" in f4a{<inapplicable>}.<core::num>(0);
+    f4a<core::String>(){() → self::B<core::String>};
+  };
+  dynamic f4b = #C9;
+  dynamic c4c = f4b{dynamic}.call();
+  self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
+  dynamic c4d = f4b{dynamic}.call<core::int>();
+  self::expect(true, c4d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
+  self::throws(() → dynamic => f4b{dynamic}.call(0));
+  self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
+  <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
+  self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
+  self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
+  self::B<core::int> c5b = f5a<core::int, core::String>(){() → self::B<core::int>};
+  self::expect(true, c5b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c5b is{ForNonNullableByDefault} self::B<core::double>);
+  () → Null {
+    let final Never #t12 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f5a(0); // error
+       ^" in f5a{<inapplicable>}.<core::num, core::String>(0);
+    let final Never #t13 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+    f5a<String>(); // error
+       ^" in f5a{<inapplicable>}.<core::String>();
+    f5a<core::String, core::String>(){() → self::B<core::String>};
+    f5a<core::num, core::num>(){() → self::B<core::num>};
+  };
+  dynamic f5b = #C10;
+  dynamic c5c = f5b{dynamic}.call();
+  self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
+  dynamic c5d = f5b{dynamic}.call<core::int, core::String>();
+  self::expect(true, c5d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c5d is{ForNonNullableByDefault} self::B<core::double>);
+  self::throws(() → dynamic => f5b{dynamic}.call(0));
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String, core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::num, core::num>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+  return new self::A::•();
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+  return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+  return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+  return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+  return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+  return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+  return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+  return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+  return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::_#DA2#new#tearOff
+  #C3 = static-tearoff self::B::_#new#tearOff
+  #C4 = instantiation self::B::_#new#tearOff <core::String*>
+  #C5 = static-tearoff self::B::_#foo#tearOff
+  #C6 = instantiation self::B::_#foo#tearOff <core::String*>
+  #C7 = static-tearoff self::B::_#bar#tearOff
+  #C8 = instantiation self::B::_#bar#tearOff <core::String*>
+  #C9 = static-tearoff self::_#DB2#new#tearOff
+  #C10 = static-tearoff self::_#DB3#new#tearOff
+  #C11 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..10537bf
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.outline.expect
@@ -0,0 +1,60 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef DA1 = self::A;
+typedef DA2<unrelated X extends core::num> = self::A;
+typedef DB1 = self::B<core::String>;
+typedef DB2<X extends core::num> = self::B<X>;
+typedef DB3<X extends core::num, unrelated Y extends core::String> = self::B<X>;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  static method _#new#tearOff() → self::A
+    return new self::A::•();
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+  field core::int field1;
+  field core::String field2;
+  constructor _(core::int field1, core::String field2) → self::B<self::B::X%>
+    ;
+  constructor •() → self::B<self::B::X%>
+    ;
+  constructor foo(core::int field1) → self::B<self::B::X%>
+    ;
+  static method _#_#tearOff<X extends core::Object? = dynamic>(core::int field1, core::String field2) → self::B<self::B::_#_#tearOff::X%>
+    return new self::B::_<self::B::_#_#tearOff::X%>(field1, field2);
+  static method _#new#tearOff<X extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::X%>
+    return new self::B::•<self::B::_#new#tearOff::X%>();
+  static method _#foo#tearOff<X extends core::Object? = dynamic>(core::int field1) → self::B<self::B::_#foo#tearOff::X%>
+    return new self::B::foo<self::B::_#foo#tearOff::X%>(field1);
+  static factory bar<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::bar::X%>
+    ;
+  static method _#bar#tearOff<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::_#bar#tearOff::X%>
+    return self::B::bar<self::B::_#bar#tearOff::X%>(i, j);
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+  return new self::A::•();
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+  return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+  return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+  return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+  return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+  return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+  return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+  return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+  return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..12bd083
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,330 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f1a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f2a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:47:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f2a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f3a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+//     f3a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3c(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3c(0, 0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+//     f3c<String>(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+//     f3e(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+//     f3e(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+//     f3e<String>(0, ''); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f4a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:131:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f4a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//     f5a(0); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+//     f5a<String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:154:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<String, String>(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:155:8: Error: Type argument 'num' doesn't conform to the bound 'String' of the type variable 'Y' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+//     f5a<num, num>(); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef DA1 = self::A;
+typedef DA2<unrelated X extends core::num> = self::A;
+typedef DB1 = self::B<core::String>;
+typedef DB2<X extends core::num> = self::B<X>;
+typedef DB3<X extends core::num, unrelated Y extends core::String> = self::B<X>;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::A
+    return new self::A::•();
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+  field core::int field1;
+  field core::String field2;
+  constructor _(core::int field1, core::String field2) → self::B<self::B::X%>
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+    ;
+  constructor •() → self::B<self::B::X%>
+    : this self::B::_(0, "")
+    ;
+  constructor foo(core::int field1) → self::B<self::B::X%>
+    : self::B::field1 = field1, self::B::field2 = "", super core::Object::•()
+    ;
+  static method _#_#tearOff<X extends core::Object? = dynamic>(core::int field1, core::String field2) → self::B<self::B::_#_#tearOff::X%>
+    return new self::B::_<self::B::_#_#tearOff::X%>(field1, field2);
+  static method _#new#tearOff<X extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::X%>
+    return new self::B::•<self::B::_#new#tearOff::X%>();
+  static method _#foo#tearOff<X extends core::Object? = dynamic>(core::int field1) → self::B<self::B::_#foo#tearOff::X%>
+    return new self::B::foo<self::B::_#foo#tearOff::X%>(field1);
+  static factory bar<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::bar::X%>
+    return new self::B::_<self::B::bar::X%>(i, j);
+  static method _#bar#tearOff<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::_#bar#tearOff::X%>
+    return self::B::bar<self::B::_#bar#tearOff::X%>(i, j);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  () → self::A f1a = #C1;
+  self::A c1a = f1a(){() → self::A};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::A);
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f1a(0); // error
+       ^" in f1a{<inapplicable>}.(0);
+  };
+  dynamic f1b = #C1;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::A);
+  self::throws(() → dynamic => f1b{dynamic}.call(0));
+  <unrelated X extends core::num>() → self::A f2a = #C2;
+  self::A c2a = f2a<core::num>(){() → self::A};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::A);
+  () → Null {
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f2a(0); // error
+       ^" in f2a{<inapplicable>}.<core::num>(0);
+    f2a<core::String>(){() → self::A};
+  };
+  dynamic f2b = #C2;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::A);
+  dynamic c2c = f2b{dynamic}.call<core::int>();
+  self::expect(true, c2c is{ForNonNullableByDefault} self::A);
+  self::throws(() → dynamic => f2b{dynamic}.call(0));
+  self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+  () → self::B<core::String> f3a = #C4;
+  self::B<core::String> c3a = f3a(){() → self::B<core::String>};
+  self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(0, c3a.{self::B::field1}{core::int});
+  self::expect("", c3a.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f3a(0); // error
+       ^" in f3a{<inapplicable>}.(0);
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+    f3a<String>(); // error
+       ^" in f3a{<inapplicable>}.<core::String>();
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call();
+  self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(0, c3a.{self::B::field1}{core::int});
+  self::expect("", c3a.{self::B::field2}{core::String});
+  self::throws(() → dynamic => f3b{dynamic}.call(0));
+  self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
+  (core::int) → self::B<core::String> f3c = #C6;
+  self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
+  self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3c.{self::B::field1}{core::int});
+  self::expect("", c3c.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3c(); // error
+       ^" in f3c{<inapplicable>}.();
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3c(0, 0); // error
+       ^" in f3c{<inapplicable>}.(0, 0);
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+    f3c<String>(0); // error
+       ^" in f3c{<inapplicable>}.<core::String>(0);
+  };
+  dynamic f3d = #C6;
+  dynamic c3d = f3d{dynamic}.call(42);
+  self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3d{dynamic}.field1);
+  self::expect("", c3d{dynamic}.field2);
+  self::throws(() → dynamic => f3d{dynamic}.call());
+  self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
+  self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
+  (core::int, core::String) → self::B<core::String> f3e = #C8;
+  self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
+  self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3e.{self::B::field1}{core::int});
+  self::expect("foo", c3e.{self::B::field2}{core::String});
+  () → Null {
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+    f3e(); // error
+       ^" in f3e{<inapplicable>}.();
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+    f3e(0); // error
+       ^" in f3e{<inapplicable>}.(0);
+    let final Never #t10 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+    f3e<String>(0, ''); // error
+       ^" in f3e{<inapplicable>}.<core::String>(0, "");
+  };
+  dynamic f3f = #C8;
+  dynamic c3f = f3f{dynamic}.call(42, "foo");
+  self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
+  self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(42, c3f{dynamic}.field1);
+  self::expect("foo", c3f{dynamic}.field2);
+  self::throws(() → dynamic => c3f{dynamic}.call());
+  self::throws(() → dynamic => c3f{dynamic}.call(0));
+  self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
+  <X extends core::num>() → self::B<X> f4a = #C9;
+  self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
+  self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
+  self::B<core::int> c4b = f4a<core::int>(){() → self::B<core::int>};
+  self::expect(true, c4b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c4b is{ForNonNullableByDefault} self::B<core::double>);
+  () → Null {
+    let final Never #t11 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f4a(0); // error
+       ^" in f4a{<inapplicable>}.<core::num>(0);
+    f4a<core::String>(){() → self::B<core::String>};
+  };
+  dynamic f4b = #C9;
+  dynamic c4c = f4b{dynamic}.call();
+  self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
+  dynamic c4d = f4b{dynamic}.call<core::int>();
+  self::expect(true, c4d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
+  self::throws(() → dynamic => f4b{dynamic}.call(0));
+  self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
+  <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
+  self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
+  self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
+  self::B<core::int> c5b = f5a<core::int, core::String>(){() → self::B<core::int>};
+  self::expect(true, c5b is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c5b is{ForNonNullableByDefault} self::B<core::double>);
+  () → Null {
+    let final Never #t12 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    f5a(0); // error
+       ^" in f5a{<inapplicable>}.<core::num, core::String>(0);
+    let final Never #t13 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+    f5a<String>(); // error
+       ^" in f5a{<inapplicable>}.<core::String>();
+    f5a<core::String, core::String>(){() → self::B<core::String>};
+    f5a<core::num, core::num>(){() → self::B<core::num>};
+  };
+  dynamic f5b = #C10;
+  dynamic c5c = f5b{dynamic}.call();
+  self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
+  self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
+  dynamic c5d = f5b{dynamic}.call<core::int, core::String>();
+  self::expect(true, c5d is{ForNonNullableByDefault} self::B<core::int>);
+  self::expect(false, c5d is{ForNonNullableByDefault} self::B<core::double>);
+  self::throws(() → dynamic => f5b{dynamic}.call(0));
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::String, core::String>());
+  self::throws(() → dynamic => f5b{dynamic}.call<core::num, core::num>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+  return new self::A::•();
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+  return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+  return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+  return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+  return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+  return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+  return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+  return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+  return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
+
+constants  {
+  #C1 = static-tearoff self::A::_#new#tearOff
+  #C2 = static-tearoff self::_#DA2#new#tearOff
+  #C3 = static-tearoff self::B::_#new#tearOff
+  #C4 = instantiation self::B::_#new#tearOff <core::String*>
+  #C5 = static-tearoff self::B::_#foo#tearOff
+  #C6 = instantiation self::B::_#foo#tearOff <core::String*>
+  #C7 = static-tearoff self::B::_#bar#tearOff
+  #C8 = instantiation self::B::_#bar#tearOff <core::String*>
+  #C9 = static-tearoff self::_#DB2#new#tearOff
+  #C10 = static-tearoff self::_#DB3#new#tearOff
+  #C11 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.expect
index f6026a2..7292491 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.expect
@@ -31,24 +31,31 @@
     return new self::A::•();
 }
 static method test1() → () → self::A
-  return self::A::foo1;
+  return #C1;
 static method test2() → () → self::A
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:13:25: Error: A value of type 'A Function(int)' can't be returned from a function with return type 'A Function()'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function() test2() => A.foo2; // Error.
-                        ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} () → self::A;
+                        ^" in (#C2) as{TypeError,ForNonNullableByDefault} () → self::A;
 static method test3() → () → self::A
-  return self::A::•;
+  return #C3;
 static method test4() → (core::int) → self::A
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:15:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function(int) test4() => A.new; // Error.
-                           ^" in self::A::• as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+                           ^" in (#C3) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
 static method test5() → () → self::A
-  return self::A::bar1;
+  return #C4;
 static method test6() → (core::int) → self::A
   return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:17:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function(int) test6() => A.bar1; // Error.
-                           ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+                           ^" in (#C4) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo1
+  #C2 = constructor-tearoff self::A::foo2
+  #C3 = constructor-tearoff self::A::•
+  #C4 = static-tearoff self::A::bar1
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.transformed.expect
index f6026a2..7292491 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.transformed.expect
@@ -31,24 +31,31 @@
     return new self::A::•();
 }
 static method test1() → () → self::A
-  return self::A::foo1;
+  return #C1;
 static method test2() → () → self::A
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:13:25: Error: A value of type 'A Function(int)' can't be returned from a function with return type 'A Function()'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function() test2() => A.foo2; // Error.
-                        ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} () → self::A;
+                        ^" in (#C2) as{TypeError,ForNonNullableByDefault} () → self::A;
 static method test3() → () → self::A
-  return self::A::•;
+  return #C3;
 static method test4() → (core::int) → self::A
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:15:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function(int) test4() => A.new; // Error.
-                           ^" in self::A::• as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+                           ^" in (#C3) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
 static method test5() → () → self::A
-  return self::A::bar1;
+  return #C4;
 static method test6() → (core::int) → self::A
   return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:17:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function(int) test6() => A.bar1; // Error.
-                           ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+                           ^" in (#C4) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo1
+  #C2 = constructor-tearoff self::A::foo2
+  #C3 = constructor-tearoff self::A::•
+  #C4 = static-tearoff self::A::bar1
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.expect
index f6026a2..7292491 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.expect
@@ -31,24 +31,31 @@
     return new self::A::•();
 }
 static method test1() → () → self::A
-  return self::A::foo1;
+  return #C1;
 static method test2() → () → self::A
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:13:25: Error: A value of type 'A Function(int)' can't be returned from a function with return type 'A Function()'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function() test2() => A.foo2; // Error.
-                        ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} () → self::A;
+                        ^" in (#C2) as{TypeError,ForNonNullableByDefault} () → self::A;
 static method test3() → () → self::A
-  return self::A::•;
+  return #C3;
 static method test4() → (core::int) → self::A
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:15:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function(int) test4() => A.new; // Error.
-                           ^" in self::A::• as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+                           ^" in (#C3) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
 static method test5() → () → self::A
-  return self::A::bar1;
+  return #C4;
 static method test6() → (core::int) → self::A
   return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:17:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function(int) test6() => A.bar1; // Error.
-                           ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+                           ^" in (#C4) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo1
+  #C2 = constructor-tearoff self::A::foo2
+  #C3 = constructor-tearoff self::A::•
+  #C4 = static-tearoff self::A::bar1
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.transformed.expect
index f6026a2..7292491 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.transformed.expect
@@ -31,24 +31,31 @@
     return new self::A::•();
 }
 static method test1() → () → self::A
-  return self::A::foo1;
+  return #C1;
 static method test2() → () → self::A
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:13:25: Error: A value of type 'A Function(int)' can't be returned from a function with return type 'A Function()'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function() test2() => A.foo2; // Error.
-                        ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} () → self::A;
+                        ^" in (#C2) as{TypeError,ForNonNullableByDefault} () → self::A;
 static method test3() → () → self::A
-  return self::A::•;
+  return #C3;
 static method test4() → (core::int) → self::A
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:15:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function(int) test4() => A.new; // Error.
-                           ^" in self::A::• as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+                           ^" in (#C3) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
 static method test5() → () → self::A
-  return self::A::bar1;
+  return #C4;
 static method test6() → (core::int) → self::A
   return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:17:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
 A Function(int) test6() => A.bar1; // Error.
-                           ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+                           ^" in (#C4) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo1
+  #C2 = constructor-tearoff self::A::foo2
+  #C3 = constructor-tearoff self::A::•
+  #C4 = static-tearoff self::A::bar1
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.expect
index f6db3b2..5d000f0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.expect
@@ -32,11 +32,11 @@
     return new self::A::•();
 }
 static method testFoo() → dynamic
-  return self::A::foo;
+  return #C1;
 static method testNew() → dynamic
-  return self::A::•;
+  return #C2;
 static method testBar() → dynamic
-  return self::A::bar;
+  return #C3;
 static method testFooExtraArgs() → dynamic
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart:15:23: Error: The static type of the explicit instantiation operand must be a generic function type but is 'A Function()'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart'.
@@ -56,3 +56,9 @@
 testBarExtraArgs() => A<int>.bar; // Error.
                       ^";
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = constructor-tearoff self::A::•
+  #C3 = static-tearoff self::A::bar
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.transformed.expect
index f6db3b2..5d000f0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.transformed.expect
@@ -32,11 +32,11 @@
     return new self::A::•();
 }
 static method testFoo() → dynamic
-  return self::A::foo;
+  return #C1;
 static method testNew() → dynamic
-  return self::A::•;
+  return #C2;
 static method testBar() → dynamic
-  return self::A::bar;
+  return #C3;
 static method testFooExtraArgs() → dynamic
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart:15:23: Error: The static type of the explicit instantiation operand must be a generic function type but is 'A Function()'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart'.
@@ -56,3 +56,9 @@
 testBarExtraArgs() => A<int>.bar; // Error.
                       ^";
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = constructor-tearoff self::A::•
+  #C3 = static-tearoff self::A::bar
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.expect
index f6db3b2..5d000f0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.expect
@@ -32,11 +32,11 @@
     return new self::A::•();
 }
 static method testFoo() → dynamic
-  return self::A::foo;
+  return #C1;
 static method testNew() → dynamic
-  return self::A::•;
+  return #C2;
 static method testBar() → dynamic
-  return self::A::bar;
+  return #C3;
 static method testFooExtraArgs() → dynamic
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart:15:23: Error: The static type of the explicit instantiation operand must be a generic function type but is 'A Function()'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart'.
@@ -56,3 +56,9 @@
 testBarExtraArgs() => A<int>.bar; // Error.
                       ^";
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = constructor-tearoff self::A::•
+  #C3 = static-tearoff self::A::bar
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.transformed.expect
index f6db3b2..5d000f0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.transformed.expect
@@ -32,11 +32,11 @@
     return new self::A::•();
 }
 static method testFoo() → dynamic
-  return self::A::foo;
+  return #C1;
 static method testNew() → dynamic
-  return self::A::•;
+  return #C2;
 static method testBar() → dynamic
-  return self::A::bar;
+  return #C3;
 static method testFooExtraArgs() → dynamic
   return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart:15:23: Error: The static type of the explicit instantiation operand must be a generic function type but is 'A Function()'.
  - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart'.
@@ -56,3 +56,9 @@
 testBarExtraArgs() => A<int>.bar; // Error.
                       ^";
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::foo
+  #C2 = constructor-tearoff self::A::•
+  #C3 = static-tearoff self::A::bar
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
index 145140e..b589af6 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
@@ -2,55 +2,20 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.new();
-//     ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactory() = A.new;
-//                                      ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactoryChild() = B.new;
-//                                           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-//   factory A.redirectingFactory() = A.new;
-//                                    ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-//   A Function() f1 = A.redirectingFactory;
-//                       ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-//   A Function() f2 = A.redirectingFactoryChild;
-//                       ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-//   A Function() f3 = A.redirectingTwice;
-//                       ^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
 //   A x3 f3();
 //     ^^
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild, self::A::redirectingTwice]/*isLegacy*/;
-  constructor new() → self::A
+  constructor •() → self::A
     : super core::Object::•()
     ;
   static factory redirectingFactory() → self::A
-    let dynamic #redirecting_factory = "A.new" in invalid-expression;
+    let dynamic #redirecting_factory = self::A::• in invalid-expression;
   static factory redirectingFactoryChild() → self::A
     let dynamic #redirecting_factory = self::B::• in invalid-expression;
   static factory redirectingTwice() → self::A
@@ -58,19 +23,13 @@
 }
 class B extends self::A {
   synthetic constructor •() → self::B
-    : invalid-initializer
+    : super self::A::•()
     ;
 }
 static method test() → dynamic {
-  () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-  A Function() f1 = A.redirectingFactory;
-                      ^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
-  () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-  A Function() f2 = A.redirectingFactoryChild;
-                      ^^^^^^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
-  () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-  A Function() f3 = A.redirectingTwice;
-                      ^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
+  () → self::A f1 = #C1;
+  () → self::A f2 = #C2;
+  () → self::A f3 = #C3;
   self::A x1 = f1(){() → self::A};
   self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
   self::A x3;
@@ -78,3 +37,9 @@
 }
 static method main() → dynamic
   return self::test();
+
+constants  {
+  #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+  #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+  #C3 = redirecting-factory-tearoff self::A::redirectingTwice
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
index 943d69c..a3c5d1d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
@@ -2,55 +2,20 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.new();
-//     ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactory() = A.new;
-//                                      ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactoryChild() = B.new;
-//                                           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-//   factory A.redirectingFactory() = A.new;
-//                                    ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-//   A Function() f1 = A.redirectingFactory;
-//                       ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-//   A Function() f2 = A.redirectingFactoryChild;
-//                       ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-//   A Function() f3 = A.redirectingTwice;
-//                       ^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
 //   A x3 f3();
 //     ^^
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild, self::A::redirectingTwice]/*isLegacy*/;
-  constructor new() → self::A
+  constructor •() → self::A
     : super core::Object::•()
     ;
   static factory redirectingFactory() → self::A
-    let core::String* #redirecting_factory = "A.new" in invalid-expression;
+    let Never #redirecting_factory = self::A::• in invalid-expression;
   static factory redirectingFactoryChild() → self::A
     let Never #redirecting_factory = self::B::• in invalid-expression;
   static factory redirectingTwice() → self::A
@@ -58,19 +23,13 @@
 }
 class B extends self::A {
   synthetic constructor •() → self::B
-    : invalid-initializer
+    : super self::A::•()
     ;
 }
 static method test() → dynamic {
-  () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-  A Function() f1 = A.redirectingFactory;
-                      ^^^^^^^^^^^^^^^^^^";
-  () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-  A Function() f2 = A.redirectingFactoryChild;
-                      ^^^^^^^^^^^^^^^^^^^^^^^";
-  () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-  A Function() f3 = A.redirectingTwice;
-                      ^^^^^^^^^^^^^^^^";
+  () → self::A f1 = #C1;
+  () → self::A f2 = #C2;
+  () → self::A f3 = #C3;
   self::A x1 = f1(){() → self::A};
   self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
   self::A x3;
@@ -78,3 +37,9 @@
 }
 static method main() → dynamic
   return self::test();
+
+constants  {
+  #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+  #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+  #C3 = redirecting-factory-tearoff self::A::redirectingTwice
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
index 145140e..b589af6 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
@@ -2,55 +2,20 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.new();
-//     ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactory() = A.new;
-//                                      ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactoryChild() = B.new;
-//                                           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-//   factory A.redirectingFactory() = A.new;
-//                                    ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-//   A Function() f1 = A.redirectingFactory;
-//                       ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-//   A Function() f2 = A.redirectingFactoryChild;
-//                       ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-//   A Function() f3 = A.redirectingTwice;
-//                       ^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
 //   A x3 f3();
 //     ^^
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild, self::A::redirectingTwice]/*isLegacy*/;
-  constructor new() → self::A
+  constructor •() → self::A
     : super core::Object::•()
     ;
   static factory redirectingFactory() → self::A
-    let dynamic #redirecting_factory = "A.new" in invalid-expression;
+    let dynamic #redirecting_factory = self::A::• in invalid-expression;
   static factory redirectingFactoryChild() → self::A
     let dynamic #redirecting_factory = self::B::• in invalid-expression;
   static factory redirectingTwice() → self::A
@@ -58,19 +23,13 @@
 }
 class B extends self::A {
   synthetic constructor •() → self::B
-    : invalid-initializer
+    : super self::A::•()
     ;
 }
 static method test() → dynamic {
-  () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-  A Function() f1 = A.redirectingFactory;
-                      ^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
-  () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-  A Function() f2 = A.redirectingFactoryChild;
-                      ^^^^^^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
-  () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-  A Function() f3 = A.redirectingTwice;
-                      ^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
+  () → self::A f1 = #C1;
+  () → self::A f2 = #C2;
+  () → self::A f3 = #C3;
   self::A x1 = f1(){() → self::A};
   self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
   self::A x3;
@@ -78,3 +37,9 @@
 }
 static method main() → dynamic
   return self::test();
+
+constants  {
+  #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+  #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+  #C3 = redirecting-factory-tearoff self::A::redirectingTwice
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.outline.expect
index b9415d3..e80d672 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.outline.expect
@@ -1,35 +1,13 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.new();
-//     ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactory() = A.new;
-//                                      ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactoryChild() = B.new;
-//                                           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-//   factory A.redirectingFactory() = A.new;
-//                                    ^
-//
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild, self::A::redirectingTwice]/*isLegacy*/;
-  constructor new() → self::A
+  constructor •() → self::A
     ;
   static factory redirectingFactory() → self::A
-    let dynamic #redirecting_factory = "A.new" in invalid-expression;
+    let dynamic #redirecting_factory = self::A::• in invalid-expression;
   static factory redirectingFactoryChild() → self::A
     let dynamic #redirecting_factory = self::B::• in invalid-expression;
   static factory redirectingTwice() → self::A
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
index 943d69c..a3c5d1d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
@@ -2,55 +2,20 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.new();
-//     ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactory() = A.new;
-//                                      ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactoryChild() = B.new;
-//                                           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-//   factory A.redirectingFactory() = A.new;
-//                                    ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-//   A Function() f1 = A.redirectingFactory;
-//                       ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-//   A Function() f2 = A.redirectingFactoryChild;
-//                       ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-//   A Function() f3 = A.redirectingTwice;
-//                       ^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
 //   A x3 f3();
 //     ^^
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild, self::A::redirectingTwice]/*isLegacy*/;
-  constructor new() → self::A
+  constructor •() → self::A
     : super core::Object::•()
     ;
   static factory redirectingFactory() → self::A
-    let core::String* #redirecting_factory = "A.new" in invalid-expression;
+    let Never #redirecting_factory = self::A::• in invalid-expression;
   static factory redirectingFactoryChild() → self::A
     let Never #redirecting_factory = self::B::• in invalid-expression;
   static factory redirectingTwice() → self::A
@@ -58,19 +23,13 @@
 }
 class B extends self::A {
   synthetic constructor •() → self::B
-    : invalid-initializer
+    : super self::A::•()
     ;
 }
 static method test() → dynamic {
-  () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-  A Function() f1 = A.redirectingFactory;
-                      ^^^^^^^^^^^^^^^^^^";
-  () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-  A Function() f2 = A.redirectingFactoryChild;
-                      ^^^^^^^^^^^^^^^^^^^^^^^";
-  () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-  A Function() f3 = A.redirectingTwice;
-                      ^^^^^^^^^^^^^^^^";
+  () → self::A f1 = #C1;
+  () → self::A f2 = #C2;
+  () → self::A f3 = #C3;
   self::A x1 = f1(){() → self::A};
   self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
   self::A x3;
@@ -78,3 +37,9 @@
 }
 static method main() → dynamic
   return self::test();
+
+constants  {
+  #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+  #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+  #C3 = redirecting-factory-tearoff self::A::redirectingTwice
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart
new file mode 100644
index 0000000..4ac8aea
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart
@@ -0,0 +1,194 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+  print('inSoundMode: $inSoundMode');
+  testNoArgs();
+  testArgs();
+}
+
+class Class1 {
+  Class1._();
+  factory Class1() = Class1._;
+}
+
+class Class2 {
+  Class2.__();
+  factory Class2._() => Class2.__();
+  factory Class2.named() = Class2._;
+}
+
+testNoArgs() {
+  var f1a = Class1.new;
+  var c1a = f1a();
+  expect(true, c1a is Class1);
+
+  dynamic f1b = Class1.new;
+  var c1b = f1b();
+  expect(true, c1b is Class1);
+
+  expect(true, identical(f1a, f1b));
+
+  var f2a = Class2.named;
+  var c2a = f2a();
+  expect(true, c2a is Class2);
+
+  dynamic f2b = Class2.named;
+  var c2b = f2b();
+  expect(true, c2b is Class2);
+
+  expect(true, identical(f2a, f2b));
+}
+
+class Class3 {
+  final int field;
+
+  Class3._(this.field);
+  factory Class3(int field) = Class3._;
+}
+
+class Class4 {
+  final int? field;
+
+  Class4._([this.field]);
+  factory Class4([int? field]) = Class4._;
+}
+
+class Class5 {
+  final int field1;
+  final int? field2;
+
+  Class5._(this.field1, [this.field2]);
+  factory Class5(int field1, [int? field2]) = Class5._;
+}
+
+class Class6 {
+  final int field1;
+  final int? field2;
+  final int field3;
+
+  Class6._(this.field1, {this.field2, required this.field3});
+  factory Class6(int field1, {int? field2, required int field3}) =
+      Class6._;
+}
+
+class Class7a implements Class7b {
+  Class7a();
+}
+
+class Class7b {
+  factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+  Class8a();
+}
+
+class Class8b<T> {
+  factory Class8b() = Class8a<T>;
+}
+
+testArgs() {
+  var f3a = Class3.new;
+  var c3a = f3a(42);
+  expect(42, c3a.field);
+  () {
+    f3a(); // error
+    f3a(42, 87); // error
+  };
+
+  dynamic f3b = Class3.new;
+  var c3b = f3b(87);
+  expect(87, c3b.field);
+  throws(() => f3b());
+  throws(() => f3b(42, 87));
+
+  var f4a = Class4.new;
+  var c4a = f4a();
+  expect(null, c4a.field);
+  var c4b = f4a(42);
+  expect(42, c4b.field);
+  () {
+    f4a(42, 87); // error
+  };
+  dynamic f4b = Class4.new;
+  throws(() => f4b(42, 87));
+
+
+  var f5a = Class5.new;
+  var c5a = f5a(42);
+  expect(42, c5a.field1);
+  expect(null, c5a.field2);
+  var c5b = f5a(87, 42);
+  expect(87, c5b.field1);
+  expect(42, c5b.field2);
+  () {
+    f5a(); // error
+    f5a(42, 87, 123); // error
+  };
+  dynamic f5b = Class5.new;
+  throws(() => f5b());
+  throws(() => f5b(42, 87, 123));
+
+  var f6a = Class6.new;
+  var c6a = f6a(42, field3: 87);
+  expect(42, c6a.field1);
+  expect(null, c6a.field2);
+  expect(87, c6a.field3);
+  () {
+    f6a(); // error
+    f6a(42); // error
+    f6a(42, 87); // error
+    f6a(field1: 87, field2: 87); // error
+  };
+
+  var c6b = f6a(42, field2: 123, field3: 87);
+  expect(42, c6b.field1);
+  expect(123, c6b.field2);
+  expect(87, c6b.field3);
+
+  var c6c = f6a(87, field3: 42, field2: 123);
+  expect(87, c6c.field1);
+  expect(123, c6c.field2);
+  expect(42, c6c.field3);
+
+  dynamic f6b = Class6.new;
+  throws(() => f6b());
+  throws(() => f6b(42), inSoundModeOnly: true);
+  throws(() => f6b(42, 87), inSoundModeOnly: true);
+  throws(() => f6b(field1: 87, field2: 87));
+
+  var f7a = Class7b.new;
+  var c7a = f7a();
+  expect(true, c7a is Class7a);
+  expect(true, c7a is Class7b);
+
+  var f8a = Class8b.new;
+  var c8a = f8a();
+  expect(true, c8a is Class8a);
+  expect(true, c8a is Class8b);
+  var c8b = f8a<int>();
+  expect(true, c8b is Class8a<int>);
+  expect(true, c8b is Class8b<int>);
+  expect(false, c8b is Class8b<String>);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+  try {
+    f();
+  } catch (e) {
+    print('Thrown: $e');
+    return;
+  }
+  if (!inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..ce07a22
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.expect
@@ -0,0 +1,272 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static factory •() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+  constructor __() → self::Class2
+    : super core::Object::•()
+    ;
+  static factory _() → self::Class2
+    return new self::Class2::__();
+  static factory named() → self::Class2
+    let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static factory •(core::int field) → self::Class3
+    let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static factory •([core::int? field = #C1]) → self::Class4
+    let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+class Class7a extends core::Object implements self::Class7b {
+  constructor •() → self::Class7a
+    : super core::Object::•()
+    ;
+}
+class Class7b extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+  static factory •() → self::Class7b
+    let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+  constructor •() → self::Class8a<self::Class8a::T%>
+    : super core::Object::•()
+    ;
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+  static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+    let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+  () → self::Class7b f7a = #C8;
+  self::Class7b c7a = f7a(){() → self::Class7b};
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+  <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+  self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+  self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+  self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = redirecting-factory-tearoff self::Class1::•
+  #C3 = redirecting-factory-tearoff self::Class2::named
+  #C4 = redirecting-factory-tearoff self::Class3::•
+  #C5 = redirecting-factory-tearoff self::Class4::•
+  #C6 = redirecting-factory-tearoff self::Class5::•
+  #C7 = redirecting-factory-tearoff self::Class6::•
+  #C8 = redirecting-factory-tearoff self::Class7b::•
+  #C9 = redirecting-factory-tearoff self::Class8b::•
+  #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..872ae36
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,272 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static factory •() → self::Class1
+    let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+  constructor __() → self::Class2
+    : super core::Object::•()
+    ;
+  static factory _() → self::Class2
+    return new self::Class2::__();
+  static factory named() → self::Class2
+    let () → self::Class2 #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static factory •(core::int field) → self::Class3
+    let Never #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static factory •([core::int? field = #C1]) → self::Class4
+    let Never #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    let Never #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    let Never #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+class Class7a extends core::Object implements self::Class7b {
+  constructor •() → self::Class7a
+    : super core::Object::•()
+    ;
+}
+class Class7b extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+  static factory •() → self::Class7b
+    let Never #redirecting_factory = self::Class7a::• in invalid-expression;
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+  constructor •() → self::Class8a<self::Class8a::T%>
+    : super core::Object::•()
+    ;
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+  static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+    let Never #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+  () → self::Class7b f7a = #C8;
+  self::Class7b c7a = f7a(){() → self::Class7b};
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+  <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+  self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+  self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+  self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = redirecting-factory-tearoff self::Class1::•
+  #C3 = redirecting-factory-tearoff self::Class2::named
+  #C4 = redirecting-factory-tearoff self::Class3::•
+  #C5 = redirecting-factory-tearoff self::Class4::•
+  #C6 = redirecting-factory-tearoff self::Class5::•
+  #C7 = redirecting-factory-tearoff self::Class6::•
+  #C8 = redirecting-factory-tearoff self::Class7b::•
+  #C9 = redirecting-factory-tearoff self::Class8b::•
+  #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..2fa25d6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,62 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+  Class1._();
+  factory Class1() = Class1._;
+}
+
+class Class2 {
+  Class2.__();
+  factory Class2._() => Class2.__();
+  factory Class2.named() = Class2._;
+}
+
+testNoArgs() {}
+
+class Class3 {
+  final int field;
+  Class3._(this.field);
+  factory Class3(int field) = Class3._;
+}
+
+class Class4 {
+  final int? field;
+  Class4._([this.field]);
+  factory Class4([int? field]) = Class4._;
+}
+
+class Class5 {
+  final int field1;
+  final int? field2;
+  Class5._(this.field1, [this.field2]);
+  factory Class5(int field1, [int? field2]) = Class5._;
+}
+
+class Class6 {
+  final int field1;
+  final int? field2;
+  final int field3;
+  Class6._(this.field1, {this.field2, required this.field3});
+  factory Class6(int field1, {int? field2, required int field3}) = Class6._;
+}
+
+class Class7a implements Class7b {
+  Class7a();
+}
+
+class Class7b {
+  factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+  Class8a();
+}
+
+class Class8b<T> {
+  factory Class8b() = Class8a<T>;
+}
+
+testArgs() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0500e74
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,60 @@
+class Class1 {
+  Class1._();
+  factory Class1() = Class1._;
+}
+
+class Class2 {
+  Class2.__();
+  factory Class2._() => Class2.__();
+  factory Class2.named() = Class2._;
+}
+
+class Class3 {
+  Class3._(this.field);
+  factory Class3(int field) = Class3._;
+  final int field;
+}
+
+class Class4 {
+  Class4._([this.field]);
+  factory Class4([int? field]) = Class4._;
+  final int? field;
+}
+
+class Class5 {
+  Class5._(this.field1, [this.field2]);
+  factory Class5(int field1, [int? field2]) = Class5._;
+  final int? field2;
+  final int field1;
+}
+
+class Class6 {
+  Class6._(this.field1, {this.field2, required this.field3});
+  factory Class6(int field1, {int? field2, required int field3}) = Class6._;
+  final int? field2;
+  final int field1;
+  final int field3;
+}
+
+class Class7a implements Class7b {
+  Class7a();
+}
+
+class Class7b {
+  factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+  Class8a();
+}
+
+class Class8b<T> {
+  factory Class8b() = Class8a<T>;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testArgs() {}
+testNoArgs() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..ce07a22
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.expect
@@ -0,0 +1,272 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static factory •() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+  constructor __() → self::Class2
+    : super core::Object::•()
+    ;
+  static factory _() → self::Class2
+    return new self::Class2::__();
+  static factory named() → self::Class2
+    let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static factory •(core::int field) → self::Class3
+    let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static factory •([core::int? field = #C1]) → self::Class4
+    let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+class Class7a extends core::Object implements self::Class7b {
+  constructor •() → self::Class7a
+    : super core::Object::•()
+    ;
+}
+class Class7b extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+  static factory •() → self::Class7b
+    let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+  constructor •() → self::Class8a<self::Class8a::T%>
+    : super core::Object::•()
+    ;
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+  static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+    let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+  () → self::Class7b f7a = #C8;
+  self::Class7b c7a = f7a(){() → self::Class7b};
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+  <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+  self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+  self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+  self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = redirecting-factory-tearoff self::Class1::•
+  #C3 = redirecting-factory-tearoff self::Class2::named
+  #C4 = redirecting-factory-tearoff self::Class3::•
+  #C5 = redirecting-factory-tearoff self::Class4::•
+  #C6 = redirecting-factory-tearoff self::Class5::•
+  #C7 = redirecting-factory-tearoff self::Class6::•
+  #C8 = redirecting-factory-tearoff self::Class7b::•
+  #C9 = redirecting-factory-tearoff self::Class8b::•
+  #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..d972b38
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,84 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    ;
+  static factory •() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+  constructor __() → self::Class2
+    ;
+  static factory _() → self::Class2
+    ;
+  static factory named() → self::Class2
+    let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _(core::int field) → self::Class3
+    ;
+  static factory •(core::int field) → self::Class3
+    let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _([core::int? field]) → self::Class4
+    ;
+  static factory •([core::int? field]) → self::Class4
+    let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+  constructor _(core::int field1, [core::int? field2]) → self::Class5
+    ;
+  static factory •(core::int field1, [core::int? field2]) → self::Class5
+    let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+  constructor _(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+    ;
+  static factory •(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+    let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+class Class7a extends core::Object implements self::Class7b {
+  constructor •() → self::Class7a
+    ;
+}
+class Class7b extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+  static factory •() → self::Class7b
+    let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+  constructor •() → self::Class8a<self::Class8a::T%>
+    ;
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+  static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+    let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+  ;
+static method testNoArgs() → dynamic
+  ;
+static method testArgs() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..872ae36
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,272 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f3a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f3a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f4a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f5a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+//     f5a(42, 87, 123); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+//     f6a(42); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     f6a(42, 87); // error
+//        ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+//     f6a(field1: 87, field2: 87); // error
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static factory •() → self::Class1
+    let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+  constructor __() → self::Class2
+    : super core::Object::•()
+    ;
+  static factory _() → self::Class2
+    return new self::Class2::__();
+  static factory named() → self::Class2
+    let () → self::Class2 #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+  constructor _(core::int field) → self::Class3
+    : self::Class3::field = field, super core::Object::•()
+    ;
+  static factory •(core::int field) → self::Class3
+    let Never #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+  final field core::int? field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+  constructor _([core::int? field = #C1]) → self::Class4
+    : self::Class4::field = field, super core::Object::•()
+    ;
+  static factory •([core::int? field = #C1]) → self::Class4
+    let Never #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+  constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+    ;
+  static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+    let Never #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+  final field core::int field1;
+  final field core::int? field2;
+  final field core::int field3;
+  static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+  constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+    ;
+  static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+    let Never #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+class Class7a extends core::Object implements self::Class7b {
+  constructor •() → self::Class7a
+    : super core::Object::•()
+    ;
+}
+class Class7b extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+  static factory •() → self::Class7b
+    let Never #redirecting_factory = self::Class7a::• in invalid-expression;
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+  constructor •() → self::Class8a<self::Class8a::T%>
+    : super core::Object::•()
+    ;
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+  static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+    let Never #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+  core::print("inSoundMode: ${self::inSoundMode}");
+  self::testNoArgs();
+  self::testArgs();
+}
+static method testNoArgs() → dynamic {
+  () → self::Class1 f1a = #C2;
+  self::Class1 c1a = f1a(){() → self::Class1};
+  self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+  dynamic f1b = #C2;
+  dynamic c1b = f1b{dynamic}.call();
+  self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+  self::expect(true, core::identical(f1a, f1b));
+  () → self::Class2 f2a = #C3;
+  self::Class2 c2a = f2a(){() → self::Class2};
+  self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+  dynamic f2b = #C3;
+  dynamic c2b = f2b{dynamic}.call();
+  self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+  self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+  (core::int) → self::Class3 f3a = #C4;
+  self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+  self::expect(42, c3a.{self::Class3::field}{core::int});
+  () → Null {
+    let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+    f3a(); // error
+       ^" in f3a{<inapplicable>}.();
+    let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f3a(42, 87); // error
+       ^" in f3a{<inapplicable>}.(42, 87);
+  };
+  dynamic f3b = #C4;
+  dynamic c3b = f3b{dynamic}.call(87);
+  self::expect(87, c3b{dynamic}.field);
+  self::throws(() → dynamic => f3b{dynamic}.call());
+  self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+  ([core::int?]) → self::Class4 f4a = #C5;
+  self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+  self::expect(null, c4a.{self::Class4::field}{core::int?});
+  self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+  self::expect(42, c4b.{self::Class4::field}{core::int?});
+  () → Null {
+    let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f4a(42, 87); // error
+       ^" in f4a{<inapplicable>}.(42, 87);
+  };
+  dynamic f4b = #C5;
+  self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+  (core::int, [core::int?]) → self::Class5 f5a = #C6;
+  self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+  self::expect(42, c5a.{self::Class5::field1}{core::int});
+  self::expect(null, c5a.{self::Class5::field2}{core::int?});
+  self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+  self::expect(87, c5b.{self::Class5::field1}{core::int});
+  self::expect(42, c5b.{self::Class5::field2}{core::int?});
+  () → Null {
+    let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+    f5a(); // error
+       ^" in f5a{<inapplicable>}.();
+    let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+    f5a(42, 87, 123); // error
+       ^" in f5a{<inapplicable>}.(42, 87, 123);
+  };
+  dynamic f5b = #C6;
+  self::throws(() → dynamic => f5b{dynamic}.call());
+  self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+  (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+  self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6a.{self::Class6::field1}{core::int});
+  self::expect(null, c6a.{self::Class6::field2}{core::int?});
+  self::expect(87, c6a.{self::Class6::field3}{core::int});
+  () → Null {
+    let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(); // error
+       ^" in f6a{<inapplicable>}.();
+    let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+    f6a(42); // error
+       ^" in f6a{<inapplicable>}.(42);
+    let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    f6a(42, 87); // error
+       ^" in f6a{<inapplicable>}.(42, 87);
+    let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+    f6a(field1: 87, field2: 87); // error
+       ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+  };
+  self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(42, c6b.{self::Class6::field1}{core::int});
+  self::expect(123, c6b.{self::Class6::field2}{core::int?});
+  self::expect(87, c6b.{self::Class6::field3}{core::int});
+  self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+  self::expect(87, c6c.{self::Class6::field1}{core::int});
+  self::expect(123, c6c.{self::Class6::field2}{core::int?});
+  self::expect(42, c6c.{self::Class6::field3}{core::int});
+  dynamic f6b = #C7;
+  self::throws(() → dynamic => f6b{dynamic}.call());
+  self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+  self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+  () → self::Class7b f7a = #C8;
+  self::Class7b c7a = f7a(){() → self::Class7b};
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+  self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+  <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+  self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+  self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+  self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+  self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+  self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+  try {
+    f(){() → dynamic};
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Thrown: ${e}");
+    return;
+  }
+  if(!self::inSoundMode && inSoundModeOnly) {
+    return;
+  }
+  throw "Expected exception";
+}
+
+constants  {
+  #C1 = null
+  #C2 = redirecting-factory-tearoff self::Class1::•
+  #C3 = redirecting-factory-tearoff self::Class2::named
+  #C4 = redirecting-factory-tearoff self::Class3::•
+  #C5 = redirecting-factory-tearoff self::Class4::•
+  #C6 = redirecting-factory-tearoff self::Class5::•
+  #C7 = redirecting-factory-tearoff self::Class6::•
+  #C8 = redirecting-factory-tearoff self::Class7b::•
+  #C9 = redirecting-factory-tearoff self::Class8b::•
+  #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart
new file mode 100644
index 0000000..969cca4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart
@@ -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.
+
+class A1<T> {}
+
+typedef B1<T> = A1<T>;
+
+class A2<T extends num> {}
+
+typedef B2<T extends num> = A2<T>;
+
+class A3<T extends List<dynamic>, S extends Never?> {}
+
+typedef B3<T extends List<Object?>, S extends Null> = A3<T, S>;
+
+class A4<T extends num> {}
+
+typedef B4<T extends int> = A4<T>;
+
+class A5<T extends List<dynamic>, S extends Never?> {}
+
+typedef B5<T extends List<Object?>, S extends Null> = A5;
+
+class StaticIdentityTest {
+  const StaticIdentityTest(a, b) : assert(identical(a, b));
+}
+
+test1() => const StaticIdentityTest(A1.new, B1.new); // Ok.
+test2() => const StaticIdentityTest(A2.new, B2.new); // Ok.
+test3() => const StaticIdentityTest(A3.new, B3.new); // Ok.
+test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.expect
new file mode 100644
index 0000000..2949323
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B1<T extends core::Object? = dynamic> = self::A1<T%>;
+typedef B2<T extends core::num> = self::A2<T>;
+typedef B3<T extends core::List<core::Object?>, S extends Null> = self::A3<T, S%>;
+typedef B4<T extends core::int> = self::A4<T>;
+typedef B5<unrelated T extends core::List<core::Object?>, unrelated S extends Null> = self::A5<core::List<dynamic>, Never?>;
+class A1<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A1<self::A1::T%>
+    : super core::Object::•()
+    ;
+}
+class A2<T extends core::num> extends core::Object {
+  synthetic constructor •() → self::A2<self::A2::T>
+    : super core::Object::•()
+    ;
+}
+class A3<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+  synthetic constructor •() → self::A3<self::A3::T, self::A3::S%>
+    : super core::Object::•()
+    ;
+}
+class A4<T extends core::num> extends core::Object {
+  synthetic constructor •() → self::A4<self::A4::T>
+    : super core::Object::•()
+    ;
+}
+class A5<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+  synthetic constructor •() → self::A5<self::A5::T, self::A5::S%>
+    : super core::Object::•()
+    ;
+}
+class StaticIdentityTest extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic a, dynamic b) → self::StaticIdentityTest
+    : assert(core::identical(a, b)), super core::Object::•()
+    ;
+}
+static method test1() → dynamic
+  return #C1;
+static method test2() → dynamic
+  return #C1;
+static method test3() → dynamic
+  return #C1;
+static method test4() → dynamic
+  return invalid-expression "This assertion failed.";
+static method test5() → dynamic
+  return invalid-expression "This assertion failed.";
+static method main() → dynamic {}
+
+constants  {
+  #C1 = self::StaticIdentityTest {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_proper_rename_identity.dart:
+- StaticIdentityTest. (from org-dartlang-testcase:///simple_proper_rename_identity.dart:26:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.transformed.expect
new file mode 100644
index 0000000..2949323
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.transformed.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B1<T extends core::Object? = dynamic> = self::A1<T%>;
+typedef B2<T extends core::num> = self::A2<T>;
+typedef B3<T extends core::List<core::Object?>, S extends Null> = self::A3<T, S%>;
+typedef B4<T extends core::int> = self::A4<T>;
+typedef B5<unrelated T extends core::List<core::Object?>, unrelated S extends Null> = self::A5<core::List<dynamic>, Never?>;
+class A1<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A1<self::A1::T%>
+    : super core::Object::•()
+    ;
+}
+class A2<T extends core::num> extends core::Object {
+  synthetic constructor •() → self::A2<self::A2::T>
+    : super core::Object::•()
+    ;
+}
+class A3<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+  synthetic constructor •() → self::A3<self::A3::T, self::A3::S%>
+    : super core::Object::•()
+    ;
+}
+class A4<T extends core::num> extends core::Object {
+  synthetic constructor •() → self::A4<self::A4::T>
+    : super core::Object::•()
+    ;
+}
+class A5<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+  synthetic constructor •() → self::A5<self::A5::T, self::A5::S%>
+    : super core::Object::•()
+    ;
+}
+class StaticIdentityTest extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic a, dynamic b) → self::StaticIdentityTest
+    : assert(core::identical(a, b)), super core::Object::•()
+    ;
+}
+static method test1() → dynamic
+  return #C1;
+static method test2() → dynamic
+  return #C1;
+static method test3() → dynamic
+  return #C1;
+static method test4() → dynamic
+  return invalid-expression "This assertion failed.";
+static method test5() → dynamic
+  return invalid-expression "This assertion failed.";
+static method main() → dynamic {}
+
+constants  {
+  #C1 = self::StaticIdentityTest {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_proper_rename_identity.dart:
+- StaticIdentityTest. (from org-dartlang-testcase:///simple_proper_rename_identity.dart:26:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.textual_outline.expect
new file mode 100644
index 0000000..77787a1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class A1<T> {}
+typedef B1<T> = A1<T>;
+class A2<T extends num> {}
+typedef B2<T extends num> = A2<T>;
+class A3<T extends List<dynamic>, S extends Never?> {}
+typedef B3<T extends List<Object?>, S extends Null> = A3<T, S>;
+class A4<T extends num> {}
+typedef B4<T extends int> = A4<T>;
+class A5<T extends List<dynamic>, S extends Never?> {}
+typedef B5<T extends List<Object?>, S extends Null> = A5;
+class StaticIdentityTest {
+  const StaticIdentityTest(a, b) : assert(identical(a, b));
+}
+test1() => const StaticIdentityTest(A1.new, B1.new);
+test2() => const StaticIdentityTest(A2.new, B2.new);
+test3() => const StaticIdentityTest(A3.new, B3.new);
+test4() => const StaticIdentityTest(A4.new, B4.new);
+test5() => const StaticIdentityTest(A5.new, B5.new);
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.expect
new file mode 100644
index 0000000..2949323
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B1<T extends core::Object? = dynamic> = self::A1<T%>;
+typedef B2<T extends core::num> = self::A2<T>;
+typedef B3<T extends core::List<core::Object?>, S extends Null> = self::A3<T, S%>;
+typedef B4<T extends core::int> = self::A4<T>;
+typedef B5<unrelated T extends core::List<core::Object?>, unrelated S extends Null> = self::A5<core::List<dynamic>, Never?>;
+class A1<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A1<self::A1::T%>
+    : super core::Object::•()
+    ;
+}
+class A2<T extends core::num> extends core::Object {
+  synthetic constructor •() → self::A2<self::A2::T>
+    : super core::Object::•()
+    ;
+}
+class A3<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+  synthetic constructor •() → self::A3<self::A3::T, self::A3::S%>
+    : super core::Object::•()
+    ;
+}
+class A4<T extends core::num> extends core::Object {
+  synthetic constructor •() → self::A4<self::A4::T>
+    : super core::Object::•()
+    ;
+}
+class A5<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+  synthetic constructor •() → self::A5<self::A5::T, self::A5::S%>
+    : super core::Object::•()
+    ;
+}
+class StaticIdentityTest extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic a, dynamic b) → self::StaticIdentityTest
+    : assert(core::identical(a, b)), super core::Object::•()
+    ;
+}
+static method test1() → dynamic
+  return #C1;
+static method test2() → dynamic
+  return #C1;
+static method test3() → dynamic
+  return #C1;
+static method test4() → dynamic
+  return invalid-expression "This assertion failed.";
+static method test5() → dynamic
+  return invalid-expression "This assertion failed.";
+static method main() → dynamic {}
+
+constants  {
+  #C1 = self::StaticIdentityTest {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_proper_rename_identity.dart:
+- StaticIdentityTest. (from org-dartlang-testcase:///simple_proper_rename_identity.dart:26:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.outline.expect
new file mode 100644
index 0000000..fd75da2
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.outline.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B1<T extends core::Object? = dynamic> = self::A1<T%>;
+typedef B2<T extends core::num> = self::A2<T>;
+typedef B3<T extends core::List<core::Object?>, S extends Null> = self::A3<T, S%>;
+typedef B4<T extends core::int> = self::A4<T>;
+typedef B5<unrelated T extends core::List<core::Object?>, unrelated S extends Null> = self::A5<core::List<dynamic>, Never?>;
+class A1<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A1<self::A1::T%>
+    ;
+}
+class A2<T extends core::num> extends core::Object {
+  synthetic constructor •() → self::A2<self::A2::T>
+    ;
+}
+class A3<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+  synthetic constructor •() → self::A3<self::A3::T, self::A3::S%>
+    ;
+}
+class A4<T extends core::num> extends core::Object {
+  synthetic constructor •() → self::A4<self::A4::T>
+    ;
+}
+class A5<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+  synthetic constructor •() → self::A5<self::A5::T, self::A5::S%>
+    ;
+}
+class StaticIdentityTest extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic a, dynamic b) → self::StaticIdentityTest
+    : assert(core::identical(a, b)), super core::Object::•()
+    ;
+}
+static method test1() → dynamic
+  ;
+static method test2() → dynamic
+  ;
+static method test3() → dynamic
+  ;
+static method test4() → dynamic
+  ;
+static method test5() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.transformed.expect
new file mode 100644
index 0000000..2949323
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.transformed.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B1<T extends core::Object? = dynamic> = self::A1<T%>;
+typedef B2<T extends core::num> = self::A2<T>;
+typedef B3<T extends core::List<core::Object?>, S extends Null> = self::A3<T, S%>;
+typedef B4<T extends core::int> = self::A4<T>;
+typedef B5<unrelated T extends core::List<core::Object?>, unrelated S extends Null> = self::A5<core::List<dynamic>, Never?>;
+class A1<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A1<self::A1::T%>
+    : super core::Object::•()
+    ;
+}
+class A2<T extends core::num> extends core::Object {
+  synthetic constructor •() → self::A2<self::A2::T>
+    : super core::Object::•()
+    ;
+}
+class A3<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+  synthetic constructor •() → self::A3<self::A3::T, self::A3::S%>
+    : super core::Object::•()
+    ;
+}
+class A4<T extends core::num> extends core::Object {
+  synthetic constructor •() → self::A4<self::A4::T>
+    : super core::Object::•()
+    ;
+}
+class A5<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+  synthetic constructor •() → self::A5<self::A5::T, self::A5::S%>
+    : super core::Object::•()
+    ;
+}
+class StaticIdentityTest extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic a, dynamic b) → self::StaticIdentityTest
+    : assert(core::identical(a, b)), super core::Object::•()
+    ;
+}
+static method test1() → dynamic
+  return #C1;
+static method test2() → dynamic
+  return #C1;
+static method test3() → dynamic
+  return #C1;
+static method test4() → dynamic
+  return invalid-expression "This assertion failed.";
+static method test5() → dynamic
+  return invalid-expression "This assertion failed.";
+static method main() → dynamic {}
+
+constants  {
+  #C1 = self::StaticIdentityTest {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_proper_rename_identity.dart:
+- StaticIdentityTest. (from org-dartlang-testcase:///simple_proper_rename_identity.dart:26:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart
index 0abf8e6..1ee6b80 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart
@@ -45,7 +45,9 @@
 B<num> Function() test19() => DB3<num, String>.foo; // Ok.
 B<num> Function() test20() => DB3<num, String>.bar; // Ok.
 B<num> Function() test21() => DB3.new; // Ok.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+B<Y> Function<Y extends num, Z extends String>() test22() => DB3.new; // Ok.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+
+B<String> Function() test24() => DB2.new; // Ok.
 
 main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect
index 0a4373e..b69871d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect
@@ -15,24 +15,24 @@
 // B<num> Function() test9() => DB1.new; // Error.
 //                              ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-//                                            ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 // B<Y> Function<Y>() test17() => DB2.new; // Error.
 //                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-//                                                              ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+//                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+//                                   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
 //                                   ^
 //
 import self as self;
@@ -59,64 +59,83 @@
     return new self::B::•<self::B::bar::X%>();
 }
 static method test1() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test2() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test3() → () → self::A
-  return self::A::•;
+  return #C2;
 static method test4() → () → self::A
-  return self::A::•;
+  return #C2;
 static method test5() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test6() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test7() → () → self::B<core::String>
-  return self::B::•<core::String>;
+  return #C4;
 static method test8() → () → self::B<core::String>
-  return self::B::•<core::String>;
+  return #C4;
 static method test9() → () → self::B<core::num>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<num> Function() test9() => DB1.new; // Error.
-                             ^" in (self::B::•<core::String>) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+                             ^" in (#C4) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
 static method test10() → () → self::B<core::String>
-  return self::B::foo<core::String>;
+  return #C6;
 static method test11() → () → self::B<core::String>
-  return self::B::bar<core::String>;
+  return #C8;
 static method test12() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test13() → () → self::B<core::num>
-  return self::B::foo<core::num>;
+  return #C10;
 static method test14() → () → self::B<core::num>
-  return self::B::bar<core::num>;
+  return #C11;
 static method test15() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-                                           ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+  return #C12;
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" in (let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y>() test17() => DB2.new; // Error.
+                               ^" in (#C12) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
 static method test18() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test19() → () → self::B<core::num>
-  return self::B::foo<core::num>;
+  return #C10;
 static method test20() → () → self::B<core::num>
-  return self::B::bar<core::num>;
+  return #C11;
 static method test21() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-                                                             ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+  return #C13;
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
-                                  ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" in (let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+static method test24() → () → self::B<core::String>
+  return #C14;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <>
+  #C3 = constructor-tearoff self::B::•
+  #C4 = instantiation self::B::• <core::String>
+  #C5 = constructor-tearoff self::B::foo
+  #C6 = instantiation self::B::foo <core::String>
+  #C7 = static-tearoff self::B::bar
+  #C8 = instantiation self::B::bar <core::String>
+  #C9 = instantiation self::B::• <core::num>
+  #C10 = instantiation self::B::foo <core::num>
+  #C11 = instantiation self::B::bar <core::num>
+  #C12 = typedef-tearoff <X extends core::num>.(#C3<X>)
+  #C13 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C3<X>)
+  #C14 = instantiation self::B::• <Never>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect
index 0a4373e..382b745 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect
@@ -15,24 +15,24 @@
 // B<num> Function() test9() => DB1.new; // Error.
 //                              ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-//                                            ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 // B<Y> Function<Y>() test17() => DB2.new; // Error.
 //                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-//                                                              ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+//                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+//                                   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
 //                                   ^
 //
 import self as self;
@@ -59,64 +59,83 @@
     return new self::B::•<self::B::bar::X%>();
 }
 static method test1() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test2() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test3() → () → self::A
-  return self::A::•;
+  return #C2;
 static method test4() → () → self::A
-  return self::A::•;
+  return #C2;
 static method test5() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test6() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test7() → () → self::B<core::String>
-  return self::B::•<core::String>;
+  return #C4;
 static method test8() → () → self::B<core::String>
-  return self::B::•<core::String>;
+  return #C4;
 static method test9() → () → self::B<core::num>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<num> Function() test9() => DB1.new; // Error.
-                             ^" in (self::B::•<core::String>) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+                             ^" in (#C4) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
 static method test10() → () → self::B<core::String>
-  return self::B::foo<core::String>;
+  return #C6;
 static method test11() → () → self::B<core::String>
-  return self::B::bar<core::String>;
+  return #C8;
 static method test12() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test13() → () → self::B<core::num>
-  return self::B::foo<core::num>;
+  return #C10;
 static method test14() → () → self::B<core::num>
-  return self::B::bar<core::num>;
+  return #C11;
 static method test15() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-                                           ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+  return #C12;
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" in let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y>() test17() => DB2.new; // Error.
+                               ^" in (#C12) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
 static method test18() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test19() → () → self::B<core::num>
-  return self::B::foo<core::num>;
+  return #C10;
 static method test20() → () → self::B<core::num>
-  return self::B::bar<core::num>;
+  return #C11;
 static method test21() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-                                                             ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+  return #C13;
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
-                                  ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" in let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+static method test24() → () → self::B<core::String>
+  return #C14;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <>
+  #C3 = constructor-tearoff self::B::•
+  #C4 = instantiation self::B::• <core::String>
+  #C5 = constructor-tearoff self::B::foo
+  #C6 = instantiation self::B::foo <core::String>
+  #C7 = static-tearoff self::B::bar
+  #C8 = instantiation self::B::bar <core::String>
+  #C9 = instantiation self::B::• <core::num>
+  #C10 = instantiation self::B::foo <core::num>
+  #C11 = instantiation self::B::bar <core::num>
+  #C12 = typedef-tearoff <X extends core::num>.(#C3<X>)
+  #C13 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C3<X>)
+  #C14 = instantiation self::B::• <Never>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect
index fe0d7be..c3a7ab9 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect
@@ -30,6 +30,7 @@
 B<num> Function() test19() => DB3<num, String>.foo;
 B<num> Function() test20() => DB3<num, String>.bar;
 B<num> Function() test21() => DB3.new;
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new;
-B<Y> Function<Y, Z>() test23() => DB2.new;
+B<Y> Function<Y extends num, Z extends String>() test22() => DB3.new;
+B<Y> Function<Y, Z>() test23() => DB3.new;
+B<String> Function() test24() => DB2.new;
 main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect
index 0a4373e..10912e2 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect
@@ -15,24 +15,24 @@
 // B<num> Function() test9() => DB1.new; // Error.
 //                              ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-//                                            ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 // B<Y> Function<Y>() test17() => DB2.new; // Error.
 //                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-//                                                              ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+//                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+//                                   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
 //                                   ^
 //
 import self as self;
@@ -59,64 +59,83 @@
     return new self::B::•<self::B::bar::X%>();
 }
 static method test1() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test2() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test3() → () → self::A
-  return self::A::•;
+  return #C2;
 static method test4() → () → self::A
-  return self::A::•;
+  return #C2;
 static method test5() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test6() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test7() → () → self::B<core::String>
-  return self::B::•<core::String>;
+  return #C4;
 static method test8() → () → self::B<core::String>
-  return self::B::•<core::String>;
+  return #C4;
 static method test9() → () → self::B<core::num>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<num> Function() test9() => DB1.new; // Error.
-                             ^" in (self::B::•<core::String>) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+                             ^" in (#C4) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
 static method test10() → () → self::B<core::String>
-  return self::B::foo<core::String>;
+  return #C6;
 static method test11() → () → self::B<core::String>
-  return self::B::bar<core::String>;
+  return #C8;
 static method test12() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test13() → () → self::B<core::num>
-  return self::B::foo<core::num>;
+  return #C10;
 static method test14() → () → self::B<core::num>
-  return self::B::bar<core::num>;
+  return #C11;
 static method test15() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-                                           ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+  return #C12;
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" in (let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y>() test17() => DB2.new; // Error.
+                               ^" in (#C12) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
 static method test18() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test19() → () → self::B<core::num>
-  return self::B::foo<core::num>;
+  return #C10;
 static method test20() → () → self::B<core::num>
-  return self::B::bar<core::num>;
+  return #C11;
 static method test21() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-                                                             ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+  return #C13;
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
-                                  ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" in (let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+static method test24() → () → self::B<core::String>
+  return #C14;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <>
+  #C3 = constructor-tearoff self::B::•
+  #C4 = instantiation self::B::• <core::String*>
+  #C5 = constructor-tearoff self::B::foo
+  #C6 = instantiation self::B::foo <core::String*>
+  #C7 = static-tearoff self::B::bar
+  #C8 = instantiation self::B::bar <core::String*>
+  #C9 = instantiation self::B::• <core::num*>
+  #C10 = instantiation self::B::foo <core::num*>
+  #C11 = instantiation self::B::bar <core::num*>
+  #C12 = typedef-tearoff <X extends core::num>.(#C3<X>)
+  #C13 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C3<X>)
+  #C14 = instantiation self::B::• <Never*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect
index 7110e07..fda6d4f 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect
@@ -65,5 +65,7 @@
   ;
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
   ;
+static method test24() → () → self::B<core::String>
+  ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect
index 0a4373e..86a1666 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect
@@ -15,24 +15,24 @@
 // B<num> Function() test9() => DB1.new; // Error.
 //                              ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-//                                            ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 // B<Y> Function<Y>() test17() => DB2.new; // Error.
 //                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-//                                                              ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+//                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
 //  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+//                                   ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
 //                                   ^
 //
 import self as self;
@@ -59,64 +59,83 @@
     return new self::B::•<self::B::bar::X%>();
 }
 static method test1() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test2() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test3() → () → self::A
-  return self::A::•;
+  return #C2;
 static method test4() → () → self::A
-  return self::A::•;
+  return #C2;
 static method test5() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test6() → () → self::A
-  return self::A::•;
+  return #C1;
 static method test7() → () → self::B<core::String>
-  return self::B::•<core::String>;
+  return #C4;
 static method test8() → () → self::B<core::String>
-  return self::B::•<core::String>;
+  return #C4;
 static method test9() → () → self::B<core::num>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<num> Function() test9() => DB1.new; // Error.
-                             ^" in (self::B::•<core::String>) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+                             ^" in (#C4) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
 static method test10() → () → self::B<core::String>
-  return self::B::foo<core::String>;
+  return #C6;
 static method test11() → () → self::B<core::String>
-  return self::B::bar<core::String>;
+  return #C8;
 static method test12() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test13() → () → self::B<core::num>
-  return self::B::foo<core::num>;
+  return #C10;
 static method test14() → () → self::B<core::num>
-  return self::B::bar<core::num>;
+  return #C11;
 static method test15() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-                                           ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+  return #C12;
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" in let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y>() test17() => DB2.new; // Error.
+                               ^" in (#C12) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
 static method test18() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test19() → () → self::B<core::num>
-  return self::B::foo<core::num>;
+  return #C10;
 static method test20() → () → self::B<core::num>
-  return self::B::bar<core::num>;
+  return #C11;
 static method test21() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return #C9;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-                                                             ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+  return #C13;
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
-                                  ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" in let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+static method test24() → () → self::B<core::String>
+  return #C14;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <>
+  #C3 = constructor-tearoff self::B::•
+  #C4 = instantiation self::B::• <core::String*>
+  #C5 = constructor-tearoff self::B::foo
+  #C6 = instantiation self::B::foo <core::String*>
+  #C7 = static-tearoff self::B::bar
+  #C8 = instantiation self::B::bar <core::String*>
+  #C9 = instantiation self::B::• <core::num*>
+  #C10 = instantiation self::B::foo <core::num*>
+  #C11 = instantiation self::B::bar <core::num*>
+  #C12 = typedef-tearoff <X extends core::num>.(#C3<X>)
+  #C13 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C3<X>)
+  #C14 = instantiation self::B::• <Never*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart
index c8527be..5784e0a 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart
@@ -16,7 +16,7 @@
   const C.new(this.x);
 }
 
-class D extend C {
+class D extends C {
   D(int x) : super.new(x * 2);
 }
 
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.expect
index 74eb491..50ef75f8 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.expect
@@ -1,142 +1,70 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.new();
-//     ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactory() = A.new;
-//                                      ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactoryChild() = B.new;
-//                                           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:9:26: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.redirecting() : this.new();
-//                          ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:16:11: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   const C.new(this.x);
-//           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:19:9: Error: Expected 'extends' instead of this.
-// class D extend C {
-//         ^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:20: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   D(int x) : super.new(x * 2);
-//                    ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-//   factory A.redirectingFactory() = A.new;
-//                                    ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-//   D(int x) : super.new(x * 2);
-//              ^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-//   const C.new(1);
-//           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-//   new C.new(1);
-//         ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-//   var f1 = A.new;
-//              ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-//   var f3 = C.new;
-//              ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-//   A Function() g1 = A.new;
-//                       ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-//   C Function(int x) g3 = C.new;
-//                            ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild]/*isLegacy*/;
-  constructor new() → self::A
+  constructor •() → self::A
     : super core::Object::•()
     ;
   constructor redirecting() → self::A
-    : this self::A::new()
+    : this self::A::•()
     ;
   static factory redirectingFactory() → self::A
-    let dynamic #redirecting_factory = "A.new" in invalid-expression;
+    let dynamic #redirecting_factory = self::A::• in invalid-expression;
   static factory redirectingFactoryChild() → self::A
     let dynamic #redirecting_factory = self::B::• in invalid-expression;
 }
 class B extends self::A {
   synthetic constructor •() → self::B
-    : invalid-initializer
+    : super self::A::•()
     ;
 }
 class C extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
-  const constructor new(core::int x) → self::C
+  const constructor •(core::int x) → self::C
     : self::C::x = x, super core::Object::•()
     ;
 }
-class D extends core::Object {
+class D extends self::C {
   constructor •(core::int x) → self::D
-    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-  D(int x) : super.new(x * 2);
-             ^^^^^"
+    : super self::C::•(x.{core::num::*}(2){(core::num) → core::int})
     ;
 }
 static method test() → dynamic {
   new self::D::•(1);
-  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-  const C.new(1);
-          ^^^";
-  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-  new C.new(1);
-        ^^^";
-  dynamic f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-  var f1 = A.new;
-             ^^^";
-  () → self::B f2 = self::B::•;
-  dynamic f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-  var f3 = C.new;
-             ^^^";
-  (core::int) → self::D f4 = self::D::•;
-  f1{dynamic}.call();
+  #C2;
+  new self::C::•(1);
+  () → self::A f1 = #C3;
+  () → self::B f2 = #C4;
+  (core::int) → self::C f3 = #C5;
+  (core::int) → self::D f4 = #C6;
+  f1(){() → self::A};
   f2(){() → self::B};
-  f3{dynamic}.call(1);
+  f3(1){(core::int) → self::C};
   f4(1){(core::int) → self::D};
-  () → self::A g1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-  A Function() g1 = A.new;
-                      ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
-  () → self::B g2 = self::B::•;
-  (core::int) → self::C g3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-  C Function(int x) g3 = C.new;
-                           ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} (core::int) → self::C;
-  (core::int) → self::D g4 = self::D::•;
+  () → self::A g1 = #C3;
+  () → self::B g2 = #C4;
+  (core::int) → self::C g3 = #C5;
+  (core::int) → self::D g4 = #C6;
   g1(){() → self::A};
   g2(){() → self::B};
   g3(1){(core::int) → self::C};
   g4(1){(core::int) → self::D};
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = self::C {x:#C1}
+  #C3 = constructor-tearoff self::A::•
+  #C4 = constructor-tearoff self::B::•
+  #C5 = constructor-tearoff self::C::•
+  #C6 = constructor-tearoff self::D::•
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///unnamed_constructor.dart:
+- C. (from org-dartlang-testcase:///unnamed_constructor.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.transformed.expect
index 5779400..44b6f22 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.transformed.expect
@@ -1,142 +1,70 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.new();
-//     ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactory() = A.new;
-//                                      ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactoryChild() = B.new;
-//                                           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:9:26: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.redirecting() : this.new();
-//                          ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:16:11: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   const C.new(this.x);
-//           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:19:9: Error: Expected 'extends' instead of this.
-// class D extend C {
-//         ^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:20: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   D(int x) : super.new(x * 2);
-//                    ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-//   factory A.redirectingFactory() = A.new;
-//                                    ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-//   D(int x) : super.new(x * 2);
-//              ^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-//   const C.new(1);
-//           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-//   new C.new(1);
-//         ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-//   var f1 = A.new;
-//              ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-//   var f3 = C.new;
-//              ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-//   A Function() g1 = A.new;
-//                       ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-//   C Function(int x) g3 = C.new;
-//                            ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild]/*isLegacy*/;
-  constructor new() → self::A
+  constructor •() → self::A
     : super core::Object::•()
     ;
   constructor redirecting() → self::A
-    : this self::A::new()
+    : this self::A::•()
     ;
   static factory redirectingFactory() → self::A
-    let core::String* #redirecting_factory = "A.new" in invalid-expression;
+    let Never #redirecting_factory = self::A::• in invalid-expression;
   static factory redirectingFactoryChild() → self::A
     let Never #redirecting_factory = self::B::• in invalid-expression;
 }
 class B extends self::A {
   synthetic constructor •() → self::B
-    : invalid-initializer
+    : super self::A::•()
     ;
 }
 class C extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
-  const constructor new(core::int x) → self::C
+  const constructor •(core::int x) → self::C
     : self::C::x = x, super core::Object::•()
     ;
 }
-class D extends core::Object {
+class D extends self::C {
   constructor •(core::int x) → self::D
-    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-  D(int x) : super.new(x * 2);
-             ^^^^^"
+    : super self::C::•(x.{core::num::*}(2){(core::num) → core::int})
     ;
 }
 static method test() → dynamic {
   new self::D::•(1);
-  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-  const C.new(1);
-          ^^^";
-  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-  new C.new(1);
-        ^^^";
-  dynamic f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-  var f1 = A.new;
-             ^^^";
-  () → self::B f2 = self::B::•;
-  dynamic f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-  var f3 = C.new;
-             ^^^";
-  (core::int) → self::D f4 = self::D::•;
-  f1{dynamic}.call();
+  #C2;
+  new self::C::•(1);
+  () → self::A f1 = #C3;
+  () → self::B f2 = #C4;
+  (core::int) → self::C f3 = #C5;
+  (core::int) → self::D f4 = #C6;
+  f1(){() → self::A};
   f2(){() → self::B};
-  f3{dynamic}.call(1);
+  f3(1){(core::int) → self::C};
   f4(1){(core::int) → self::D};
-  () → self::A g1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-  A Function() g1 = A.new;
-                      ^^^";
-  () → self::B g2 = self::B::•;
-  (core::int) → self::C g3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-  C Function(int x) g3 = C.new;
-                           ^^^";
-  (core::int) → self::D g4 = self::D::•;
+  () → self::A g1 = #C3;
+  () → self::B g2 = #C4;
+  (core::int) → self::C g3 = #C5;
+  (core::int) → self::D g4 = #C6;
   g1(){() → self::A};
   g2(){() → self::B};
   g3(1){(core::int) → self::C};
   g4(1){(core::int) → self::D};
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = self::C {x:#C1}
+  #C3 = constructor-tearoff self::A::•
+  #C4 = constructor-tearoff self::B::•
+  #C5 = constructor-tearoff self::C::•
+  #C6 = constructor-tearoff self::D::•
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///unnamed_constructor.dart:
+- C. (from org-dartlang-testcase:///unnamed_constructor.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.textual_outline.expect
index d70331c..3e34a96 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.textual_outline.expect
@@ -9,7 +9,7 @@
   final int x;
   const C.new(this.x);
 }
-class D extend C {
+class D extends C {
   D(int x) : super.new(x * 2);
 }
 test() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.expect
index 74eb491..50ef75f8 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.expect
@@ -1,142 +1,70 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.new();
-//     ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactory() = A.new;
-//                                      ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactoryChild() = B.new;
-//                                           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:9:26: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.redirecting() : this.new();
-//                          ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:16:11: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   const C.new(this.x);
-//           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:19:9: Error: Expected 'extends' instead of this.
-// class D extend C {
-//         ^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:20: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   D(int x) : super.new(x * 2);
-//                    ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-//   factory A.redirectingFactory() = A.new;
-//                                    ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-//   D(int x) : super.new(x * 2);
-//              ^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-//   const C.new(1);
-//           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-//   new C.new(1);
-//         ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-//   var f1 = A.new;
-//              ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-//   var f3 = C.new;
-//              ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-//   A Function() g1 = A.new;
-//                       ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-//   C Function(int x) g3 = C.new;
-//                            ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild]/*isLegacy*/;
-  constructor new() → self::A
+  constructor •() → self::A
     : super core::Object::•()
     ;
   constructor redirecting() → self::A
-    : this self::A::new()
+    : this self::A::•()
     ;
   static factory redirectingFactory() → self::A
-    let dynamic #redirecting_factory = "A.new" in invalid-expression;
+    let dynamic #redirecting_factory = self::A::• in invalid-expression;
   static factory redirectingFactoryChild() → self::A
     let dynamic #redirecting_factory = self::B::• in invalid-expression;
 }
 class B extends self::A {
   synthetic constructor •() → self::B
-    : invalid-initializer
+    : super self::A::•()
     ;
 }
 class C extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
-  const constructor new(core::int x) → self::C
+  const constructor •(core::int x) → self::C
     : self::C::x = x, super core::Object::•()
     ;
 }
-class D extends core::Object {
+class D extends self::C {
   constructor •(core::int x) → self::D
-    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-  D(int x) : super.new(x * 2);
-             ^^^^^"
+    : super self::C::•(x.{core::num::*}(2){(core::num) → core::int})
     ;
 }
 static method test() → dynamic {
   new self::D::•(1);
-  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-  const C.new(1);
-          ^^^";
-  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-  new C.new(1);
-        ^^^";
-  dynamic f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-  var f1 = A.new;
-             ^^^";
-  () → self::B f2 = self::B::•;
-  dynamic f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-  var f3 = C.new;
-             ^^^";
-  (core::int) → self::D f4 = self::D::•;
-  f1{dynamic}.call();
+  #C2;
+  new self::C::•(1);
+  () → self::A f1 = #C3;
+  () → self::B f2 = #C4;
+  (core::int) → self::C f3 = #C5;
+  (core::int) → self::D f4 = #C6;
+  f1(){() → self::A};
   f2(){() → self::B};
-  f3{dynamic}.call(1);
+  f3(1){(core::int) → self::C};
   f4(1){(core::int) → self::D};
-  () → self::A g1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-  A Function() g1 = A.new;
-                      ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
-  () → self::B g2 = self::B::•;
-  (core::int) → self::C g3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-  C Function(int x) g3 = C.new;
-                           ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} (core::int) → self::C;
-  (core::int) → self::D g4 = self::D::•;
+  () → self::A g1 = #C3;
+  () → self::B g2 = #C4;
+  (core::int) → self::C g3 = #C5;
+  (core::int) → self::D g4 = #C6;
   g1(){() → self::A};
   g2(){() → self::B};
   g3(1){(core::int) → self::C};
   g4(1){(core::int) → self::D};
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = self::C {x:#C1}
+  #C3 = constructor-tearoff self::A::•
+  #C4 = constructor-tearoff self::B::•
+  #C5 = constructor-tearoff self::C::•
+  #C6 = constructor-tearoff self::D::•
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///unnamed_constructor.dart:
+- C. (from org-dartlang-testcase:///unnamed_constructor.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.outline.expect
index aa40cc6..b0b2882 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.outline.expect
@@ -1,56 +1,15 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.new();
-//     ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactory() = A.new;
-//                                      ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactoryChild() = B.new;
-//                                           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:9:26: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.redirecting() : this.new();
-//                          ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:16:11: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   const C.new(this.x);
-//           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:19:9: Error: Expected 'extends' instead of this.
-// class D extend C {
-//         ^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:20: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   D(int x) : super.new(x * 2);
-//                    ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-//   factory A.redirectingFactory() = A.new;
-//                                    ^
-//
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild]/*isLegacy*/;
-  constructor new() → self::A
+  constructor •() → self::A
     ;
   constructor redirecting() → self::A
     ;
   static factory redirectingFactory() → self::A
-    let dynamic #redirecting_factory = "A.new" in invalid-expression;
+    let dynamic #redirecting_factory = self::A::• in invalid-expression;
   static factory redirectingFactoryChild() → self::A
     let dynamic #redirecting_factory = self::B::• in invalid-expression;
 }
@@ -60,11 +19,11 @@
 }
 class C extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
-  const constructor new(core::int x) → self::C
+  const constructor •(core::int x) → self::C
     : self::C::x = x, super core::Object::•()
     ;
 }
-class D extends core::Object {
+class D extends self::C {
   constructor •(core::int x) → self::D
     ;
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.transformed.expect
index 5779400..44b6f22 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.transformed.expect
@@ -1,142 +1,70 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.new();
-//     ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactory() = A.new;
-//                                      ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   factory A.redirectingFactoryChild() = B.new;
-//                                           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:9:26: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   A.redirecting() : this.new();
-//                          ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:16:11: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   const C.new(this.x);
-//           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:19:9: Error: Expected 'extends' instead of this.
-// class D extend C {
-//         ^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:20: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-//   D(int x) : super.new(x * 2);
-//                    ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-//   factory A.redirectingFactory() = A.new;
-//                                    ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-//   D(int x) : super.new(x * 2);
-//              ^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-//   const C.new(1);
-//           ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-//   new C.new(1);
-//         ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-//   var f1 = A.new;
-//              ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-//   var f3 = C.new;
-//              ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-//   A Function() g1 = A.new;
-//                       ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-//   C Function(int x) g3 = C.new;
-//                            ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild]/*isLegacy*/;
-  constructor new() → self::A
+  constructor •() → self::A
     : super core::Object::•()
     ;
   constructor redirecting() → self::A
-    : this self::A::new()
+    : this self::A::•()
     ;
   static factory redirectingFactory() → self::A
-    let core::String* #redirecting_factory = "A.new" in invalid-expression;
+    let Never #redirecting_factory = self::A::• in invalid-expression;
   static factory redirectingFactoryChild() → self::A
     let Never #redirecting_factory = self::B::• in invalid-expression;
 }
 class B extends self::A {
   synthetic constructor •() → self::B
-    : invalid-initializer
+    : super self::A::•()
     ;
 }
 class C extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
-  const constructor new(core::int x) → self::C
+  const constructor •(core::int x) → self::C
     : self::C::x = x, super core::Object::•()
     ;
 }
-class D extends core::Object {
+class D extends self::C {
   constructor •(core::int x) → self::D
-    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-  D(int x) : super.new(x * 2);
-             ^^^^^"
+    : super self::C::•(x.{core::num::*}(2){(core::num) → core::int})
     ;
 }
 static method test() → dynamic {
   new self::D::•(1);
-  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-  const C.new(1);
-          ^^^";
-  invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-  new C.new(1);
-        ^^^";
-  dynamic f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-  var f1 = A.new;
-             ^^^";
-  () → self::B f2 = self::B::•;
-  dynamic f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-  var f3 = C.new;
-             ^^^";
-  (core::int) → self::D f4 = self::D::•;
-  f1{dynamic}.call();
+  #C2;
+  new self::C::•(1);
+  () → self::A f1 = #C3;
+  () → self::B f2 = #C4;
+  (core::int) → self::C f3 = #C5;
+  (core::int) → self::D f4 = #C6;
+  f1(){() → self::A};
   f2(){() → self::B};
-  f3{dynamic}.call(1);
+  f3(1){(core::int) → self::C};
   f4(1){(core::int) → self::D};
-  () → self::A g1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-  A Function() g1 = A.new;
-                      ^^^";
-  () → self::B g2 = self::B::•;
-  (core::int) → self::C g3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-  C Function(int x) g3 = C.new;
-                           ^^^";
-  (core::int) → self::D g4 = self::D::•;
+  () → self::A g1 = #C3;
+  () → self::B g2 = #C4;
+  (core::int) → self::C g3 = #C5;
+  (core::int) → self::D g4 = #C6;
   g1(){() → self::A};
   g2(){() → self::B};
   g3(1){(core::int) → self::C};
   g4(1){(core::int) → self::D};
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = self::C {x:#C1}
+  #C3 = constructor-tearoff self::A::•
+  #C4 = constructor-tearoff self::B::•
+  #C5 = constructor-tearoff self::C::•
+  #C6 = constructor-tearoff self::D::•
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///unnamed_constructor.dart:
+- C. (from org-dartlang-testcase:///unnamed_constructor.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.expect b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.expect
index e29a84e..d463dc9 100644
--- a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.expect
@@ -21,5 +21,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
+  #C1 = static-tearoff self::id
 }
diff --git a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.transformed.expect
index 6a431a4..977003e 100644
--- a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
+  #C1 = static-tearoff self::id
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.expect b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.expect
index e29a84e..d463dc9 100644
--- a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.expect
+++ b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.expect
@@ -21,5 +21,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
+  #C1 = static-tearoff self::id
 }
diff --git a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.transformed.expect
index 6a431a4..977003e 100644
--- a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.transformed.expect
@@ -21,7 +21,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
+  #C1 = static-tearoff self::id
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/libraries.json b/pkg/front_end/testcases/dartdevc/factory_patch/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/libraries.json
@@ -0,0 +1,12 @@
+{
+  "none": {
+    "libraries": {
+      "test": {
+        "patches": [
+          "patch_lib.dart"
+        ],
+        "uri": "origin_lib.dart"
+      }
+    }
+  }
+}
diff --git a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart
similarity index 70%
copy from tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
copy to pkg/front_end/testcases/dartdevc/factory_patch/main.dart
index e6185da..8e6257c 100644
--- a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.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 'extends_test_util.dart';
+import 'dart:test';
 
-void main() {
-  setUpWithES6Syntax();
-  testSubtyping();
+main() {
+  new Class.fact();
+  //const Class.redirect();
 }
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+}
+
+constants  {
+  #C1 = _js::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+}
+
+constants  {
+  #C1 = _js::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+}
+
+constants  {
+  #C1 = _js::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect
new file mode 100644
index 0000000..fe1495b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@_js::patch
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = false}) → self2::Class
+    : self2::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @_js::patch
+  external static factory fact({core::bool defaultValue}) → self2::Class;
+  @_js::patch
+  external static factory constFact({core::bool defaultValue = true}) → self2::Class;
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:6:50 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:8:28 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 4, effectively constant: 3
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+}
+
+constants  {
+  #C1 = _js::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/origin_lib.dart b/pkg/front_end/testcases/dartdevc/factory_patch/origin_lib.dart
new file mode 100644
index 0000000..e7895f2
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/origin_lib.dart
@@ -0,0 +1,9 @@
+// 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.
+
+class Class {
+  external factory Class.fact({bool defaultValue: true});
+  external const factory Class.constFact({bool defaultValue: true});
+  //external const factory Class.redirect({bool defaultValue: true});
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/patch_lib.dart b/pkg/front_end/testcases/dartdevc/factory_patch/patch_lib.dart
new file mode 100644
index 0000000..394388b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/patch_lib.dart
@@ -0,0 +1,24 @@
+// 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.
+
+// ignore: import_internal_library
+import 'dart:_js_helper';
+
+@patch
+class Class {
+  final bool defaultValue;
+
+  const Class._internal({this.defaultValue: false});
+
+  @patch
+  factory Class.fact({bool defaultValue: true}) =>
+      new Class._internal(defaultValue: defaultValue);
+
+  @patch
+  factory Class.constFact({bool defaultValue: true}) => throw 'unsupported';
+
+  /*@patch
+  const factory Class.redirect({bool defaultValue: true}) =
+      this._internal(defaultValue: defaultValue);*/
+}
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect
index e29a84e..d463dc9 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect
@@ -21,5 +21,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
+  #C1 = static-tearoff self::id
 }
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect
index 6a431a4..977003e 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
+  #C1 = static-tearoff self::id
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect
index e29a84e..d463dc9 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect
@@ -21,5 +21,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
+  #C1 = static-tearoff self::id
 }
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect
index 6a431a4..977003e 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect
@@ -21,7 +21,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
+  #C1 = static-tearoff self::id
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart b/pkg/front_end/testcases/dartdevc/symbol.dart
new file mode 100644
index 0000000..e899102
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.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.
+
+main() => const Symbol('a');
\ No newline at end of file
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.strong.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.strong.expect
new file mode 100644
index 0000000..d827f5b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.strong.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:_internal" as _in;
+
+static method main() → dynamic
+  return #C1;
+
+constants  {
+  #C1 = #a
+}
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.strong.transformed.expect
new file mode 100644
index 0000000..d827f5b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.strong.transformed.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:_internal" as _in;
+
+static method main() → dynamic
+  return #C1;
+
+constants  {
+  #C1 = #a
+}
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline.expect
new file mode 100644
index 0000000..3aa6646
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline.expect
@@ -0,0 +1 @@
+main() => const Symbol('a');
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3aa6646
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline_modelled.expect
@@ -0,0 +1 @@
+main() => const Symbol('a');
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.weak.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.expect
new file mode 100644
index 0000000..d827f5b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:_internal" as _in;
+
+static method main() → dynamic
+  return #C1;
+
+constants  {
+  #C1 = #a
+}
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.outline.expect
new file mode 100644
index 0000000..e2cba6b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.outline.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.transformed.expect
new file mode 100644
index 0000000..d827f5b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.transformed.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:_internal" as _in;
+
+static method main() → dynamic
+  return #C1;
+
+constants  {
+  #C1 = #a
+}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide.dart b/pkg/front_end/testcases/extension_types/simple_show_hide.dart
new file mode 100644
index 0000000..e64df54
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide.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.
+
+extension E1 on int show num {}
+
+test1(E1 e1) {
+  e1.ceil(); // Ok.
+  e2.floor(); // Ok.
+  e1.isEven; // Error.
+}
+
+extension E2 on int show num hide ceil {}
+
+test2(E2 e2) {
+  e2.ceil(); // Error.
+  e2.floor(); // Ok.
+  e2.isEven; // Error.
+}
+
+extension E3 on int hide isEven {}
+
+test3(E3 e3) {
+  e3.isOdd; // Ok.
+  e3.isEven; // Error.
+}
+
+extension type MyInt on int show num, isEven hide floor {
+  int get twice => 2 * this;
+}
+
+test() {
+  MyInt m = 42;
+  m.twice; // OK, in the extension type.
+  m.isEven; // OK, a shown instance member.
+  m.ceil(); // OK, a shown instance member.
+  m.toString(); // OK, an `Object` member.
+  m.floor(); // Error, hidden.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide.dart.strong.expect b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.strong.expect
new file mode 100644
index 0000000..d246aca
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.strong.expect
@@ -0,0 +1,256 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {}
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {}
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {}
+//                          ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {}
+//                                   ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {}
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {}
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:25: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension type MyInt on int show num, isEven hide floor {
+//                         ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: Expected ';' after this.
+// extension type MyInt on int show num, isEven hide floor {
+//                                       ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:34: Error: 'num' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+//                                  ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Context: Previous declaration of 'num'.
+// extension E2 on int show num hide ceil {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: 'isEven' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+//                                       ^^^^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Context: Previous declaration of 'isEven'.
+// extension E3 on int hide isEven {}
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:51: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension type MyInt on int show num, isEven hide floor {
+//                                                   ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {}
+//                              ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:29: Error: Type 'show' not found.
+// extension type MyInt on int show num, isEven hide floor {
+//                             ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:46: Error: Type 'hide' not found.
+// extension type MyInt on int show num, isEven hide floor {
+//                                              ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:9:3: Error: Getter not found: 'e2'.
+//   e2.floor(); // Ok.
+//   ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:8:6: Error: The method 'ceil' isn't defined for the extension 'E1'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+//   e1.ceil(); // Ok.
+//      ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:10:6: Error: The getter 'isEven' isn't defined for the extension 'E1'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+//   e1.isEven; // Error.
+//      ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:16:6: Error: The method 'ceil' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+//   e2.ceil(); // Error.
+//      ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:17:6: Error: The method 'floor' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+//   e2.floor(); // Ok.
+//      ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:18:6: Error: The getter 'isEven' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+//   e2.isEven; // Error.
+//      ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:24:6: Error: The getter 'isOdd' isn't defined for the extension 'E3'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isOdd'.
+//   e3.isOdd; // Ok.
+//      ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:25:6: Error: The getter 'isEven' isn't defined for the extension 'E3'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+//   e3.isEven; // Error.
+//      ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:29: Error: 'show' isn't a type.
+// extension type MyInt on int show num, isEven hide floor {
+//                             ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:7: Error: Expected ';' after this.
+//   int get twice => 2 * this;
+//       ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:17: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+//   int get twice => 2 * this;
+//                 ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:24: Error: Expected identifier, but got 'this'.
+//   int get twice => 2 * this;
+//                        ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:34:5: Error: The getter 'twice' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'twice'.
+//   m.twice; // OK, in the extension type.
+//     ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:35:5: Error: The getter 'isEven' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+//   m.isEven; // OK, a shown instance member.
+//     ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:36:5: Error: The method 'ceil' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+//   m.ceil(); // OK, a shown instance member.
+//     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:38:5: Error: The method 'floor' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+//   m.floor(); // Error, hidden.
+//     ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+extension type MyInt on core::int {
+}
+static method num() → invalid-type {}
+static method test1(self::E1 e1) → dynamic {
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:8:6: Error: The method 'ceil' isn't defined for the extension 'E1'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+  e1.ceil(); // Ok.
+     ^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:9:3: Error: Getter not found: 'e2'.
+  e2.floor(); // Ok.
+  ^^"{dynamic}.floor();
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:10:6: Error: The getter 'isEven' isn't defined for the extension 'E1'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+  e1.isEven; // Error.
+     ^^^^^^";
+}
+static method ceil() → invalid-type {}
+static method test2(self::E2 e2) → dynamic {
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:16:6: Error: The method 'ceil' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+  e2.ceil(); // Error.
+     ^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:17:6: Error: The method 'floor' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+  e2.floor(); // Ok.
+     ^^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:18:6: Error: The getter 'isEven' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+  e2.isEven; // Error.
+     ^^^^^^";
+}
+static method isEven() → invalid-type {}
+static method test3(self::E3 e3) → dynamic {
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:24:6: Error: The getter 'isOdd' isn't defined for the extension 'E3'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isOdd'.
+  e3.isOdd; // Ok.
+     ^^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:25:6: Error: The getter 'isEven' isn't defined for the extension 'E3'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+  e3.isEven; // Error.
+     ^^^^^^";
+}
+static method floor() → invalid-type {
+  core::int get;
+  function twice() → core::num
+    return 2.{core::num::*}(invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:24: Error: Expected identifier, but got 'this'.
+  int get twice => 2 * this;
+                       ^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num};
+}
+static method test() → dynamic {
+  self::MyInt m = 42;
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:34:5: Error: The getter 'twice' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'twice'.
+  m.twice; // OK, in the extension type.
+    ^^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:35:5: Error: The getter 'isEven' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+  m.isEven; // OK, a shown instance member.
+    ^^^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:36:5: Error: The method 'ceil' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+  m.ceil(); // OK, a shown instance member.
+    ^^^^";
+  m.{core::Object::toString}(){() → core::String};
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:38:5: Error: The method 'floor' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+  m.floor(); // Error, hidden.
+    ^^^^^";
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.textual_outline.expect
new file mode 100644
index 0000000..6296476
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.textual_outline.expect
@@ -0,0 +1,15 @@
+extension E1 on int {}
+show num (){}
+test1(E1 e1) {}
+extension E2 on int {}
+show num ;
+hide ceil (){}
+test2(E2 e2) {}
+extension E3 on int {}
+hide isEven (){}
+test3(E3 e3) {}
+extension type MyInt on int {}
+show num, isEven ;
+hide floor (){}
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.expect b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.expect
new file mode 100644
index 0000000..d246aca
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.expect
@@ -0,0 +1,256 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {}
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {}
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {}
+//                          ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {}
+//                                   ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {}
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {}
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:25: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension type MyInt on int show num, isEven hide floor {
+//                         ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: Expected ';' after this.
+// extension type MyInt on int show num, isEven hide floor {
+//                                       ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:34: Error: 'num' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+//                                  ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Context: Previous declaration of 'num'.
+// extension E2 on int show num hide ceil {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: 'isEven' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+//                                       ^^^^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Context: Previous declaration of 'isEven'.
+// extension E3 on int hide isEven {}
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:51: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension type MyInt on int show num, isEven hide floor {
+//                                                   ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {}
+//                              ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:29: Error: Type 'show' not found.
+// extension type MyInt on int show num, isEven hide floor {
+//                             ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:46: Error: Type 'hide' not found.
+// extension type MyInt on int show num, isEven hide floor {
+//                                              ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:9:3: Error: Getter not found: 'e2'.
+//   e2.floor(); // Ok.
+//   ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:8:6: Error: The method 'ceil' isn't defined for the extension 'E1'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+//   e1.ceil(); // Ok.
+//      ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:10:6: Error: The getter 'isEven' isn't defined for the extension 'E1'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+//   e1.isEven; // Error.
+//      ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:16:6: Error: The method 'ceil' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+//   e2.ceil(); // Error.
+//      ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:17:6: Error: The method 'floor' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+//   e2.floor(); // Ok.
+//      ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:18:6: Error: The getter 'isEven' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+//   e2.isEven; // Error.
+//      ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:24:6: Error: The getter 'isOdd' isn't defined for the extension 'E3'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isOdd'.
+//   e3.isOdd; // Ok.
+//      ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:25:6: Error: The getter 'isEven' isn't defined for the extension 'E3'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+//   e3.isEven; // Error.
+//      ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:29: Error: 'show' isn't a type.
+// extension type MyInt on int show num, isEven hide floor {
+//                             ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:7: Error: Expected ';' after this.
+//   int get twice => 2 * this;
+//       ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:17: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+//   int get twice => 2 * this;
+//                 ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:24: Error: Expected identifier, but got 'this'.
+//   int get twice => 2 * this;
+//                        ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:34:5: Error: The getter 'twice' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'twice'.
+//   m.twice; // OK, in the extension type.
+//     ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:35:5: Error: The getter 'isEven' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+//   m.isEven; // OK, a shown instance member.
+//     ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:36:5: Error: The method 'ceil' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+//   m.ceil(); // OK, a shown instance member.
+//     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:38:5: Error: The method 'floor' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+//   m.floor(); // Error, hidden.
+//     ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+extension type MyInt on core::int {
+}
+static method num() → invalid-type {}
+static method test1(self::E1 e1) → dynamic {
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:8:6: Error: The method 'ceil' isn't defined for the extension 'E1'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+  e1.ceil(); // Ok.
+     ^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:9:3: Error: Getter not found: 'e2'.
+  e2.floor(); // Ok.
+  ^^"{dynamic}.floor();
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:10:6: Error: The getter 'isEven' isn't defined for the extension 'E1'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+  e1.isEven; // Error.
+     ^^^^^^";
+}
+static method ceil() → invalid-type {}
+static method test2(self::E2 e2) → dynamic {
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:16:6: Error: The method 'ceil' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+  e2.ceil(); // Error.
+     ^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:17:6: Error: The method 'floor' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+  e2.floor(); // Ok.
+     ^^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:18:6: Error: The getter 'isEven' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+  e2.isEven; // Error.
+     ^^^^^^";
+}
+static method isEven() → invalid-type {}
+static method test3(self::E3 e3) → dynamic {
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:24:6: Error: The getter 'isOdd' isn't defined for the extension 'E3'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isOdd'.
+  e3.isOdd; // Ok.
+     ^^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:25:6: Error: The getter 'isEven' isn't defined for the extension 'E3'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+  e3.isEven; // Error.
+     ^^^^^^";
+}
+static method floor() → invalid-type {
+  core::int get;
+  function twice() → core::num
+    return 2.{core::num::*}(invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:24: Error: Expected identifier, but got 'this'.
+  int get twice => 2 * this;
+                       ^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num};
+}
+static method test() → dynamic {
+  self::MyInt m = 42;
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:34:5: Error: The getter 'twice' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'twice'.
+  m.twice; // OK, in the extension type.
+    ^^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:35:5: Error: The getter 'isEven' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+  m.isEven; // OK, a shown instance member.
+    ^^^^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:36:5: Error: The method 'ceil' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+  m.ceil(); // OK, a shown instance member.
+    ^^^^";
+  m.{core::Object::toString}(){() → core::String};
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:38:5: Error: The method 'floor' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+  m.floor(); // Error, hidden.
+    ^^^^^";
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.outline.expect
new file mode 100644
index 0000000..7a2b050
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.outline.expect
@@ -0,0 +1,126 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {}
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {}
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {}
+//                          ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {}
+//                                   ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {}
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {}
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:25: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension type MyInt on int show num, isEven hide floor {
+//                         ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: Expected ';' after this.
+// extension type MyInt on int show num, isEven hide floor {
+//                                       ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:34: Error: 'num' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+//                                  ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Context: Previous declaration of 'num'.
+// extension E2 on int show num hide ceil {}
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: 'isEven' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+//                                       ^^^^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Context: Previous declaration of 'isEven'.
+// extension E3 on int hide isEven {}
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:51: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension type MyInt on int show num, isEven hide floor {
+//                                                   ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {}
+//                              ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {}
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:29: Error: Type 'show' not found.
+// extension type MyInt on int show num, isEven hide floor {
+//                             ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:46: Error: Type 'hide' not found.
+// extension type MyInt on int show num, isEven hide floor {
+//                                              ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+extension type MyInt on core::int {
+}
+static method num() → invalid-type
+  ;
+static method test1(self::E1 e1) → dynamic
+  ;
+static method ceil() → invalid-type
+  ;
+static method test2(self::E2 e2) → dynamic
+  ;
+static method isEven() → invalid-type
+  ;
+static method test3(self::E3 e3) → dynamic
+  ;
+static method floor() → invalid-type
+  ;
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart
new file mode 100644
index 0000000..7f5ac0d
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart
@@ -0,0 +1,20 @@
+// 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.
+
+extension E1 on int show num {
+  int ceil() {} // Error.
+}
+
+extension E2 on int show num hide ceil {
+  int ceil() {} // Ok.
+  int floor() {} // Error.
+}
+
+extension E3 on int hide isEven {
+  // `on int hide isEven` means `on int show int hide isEven`.
+  bool get isOdd => throw 42; // Error.
+  bool get isEven => throw 42; // Ok.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.expect
new file mode 100644
index 0000000..6d68160
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {
+//                          ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {
+//                                   ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {
+//                              ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int ceil() {} // Error.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int ceil() {} // Ok.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int floor() {} // Error.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Error: Expected ';' after this.
+//   bool get isOdd => throw 42; // Error.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:18: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+//   bool get isOdd => throw 42; // Error.
+//                  ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+//   bool get isEven => throw 42; // Ok.
+//        ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Context: Previous declaration of 'get'.
+//   bool get isOdd => throw 42; // Error.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: Expected ';' after this.
+//   bool get isEven => throw 42; // Ok.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:19: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+//   bool get isEven => throw 42; // Ok.
+//                   ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+static method num() → invalid-type {
+  function ceil() → core::int {
+    return let final Never #t1 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int ceil() {} // Error.
+  ^" in null;
+  }
+}
+static method ceil() → invalid-type {
+  function ceil() → core::int {
+    return let final Never #t2 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int ceil() {} // Ok.
+  ^" in null;
+  }
+  function floor() → core::int {
+    return let final Never #t3 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int floor() {} // Error.
+  ^" in null;
+  }
+}
+static method isEven() → invalid-type {
+  core::bool get;
+  function isOdd() → Never
+    return throw 42;
+  core::bool get = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+  bool get isEven => throw 42; // Ok.
+       ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
+  function isEven() → Never
+    return throw 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.transformed.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.transformed.expect
new file mode 100644
index 0000000..9fe722e
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.transformed.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {
+//                          ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {
+//                                   ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {
+//                              ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int ceil() {} // Error.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int ceil() {} // Ok.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int floor() {} // Error.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Error: Expected ';' after this.
+//   bool get isOdd => throw 42; // Error.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:18: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+//   bool get isOdd => throw 42; // Error.
+//                  ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+//   bool get isEven => throw 42; // Ok.
+//        ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Context: Previous declaration of 'get'.
+//   bool get isOdd => throw 42; // Error.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: Expected ';' after this.
+//   bool get isEven => throw 42; // Ok.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:19: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+//   bool get isEven => throw 42; // Ok.
+//                   ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+static method num() → invalid-type {
+  function ceil() → core::int {
+    return let final Never #t1 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int ceil() {} // Error.
+  ^" in null;
+  }
+}
+static method ceil() → invalid-type {
+  function ceil() → core::int {
+    return let final Never #t2 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int ceil() {} // Ok.
+  ^" in null;
+  }
+  function floor() → core::int {
+    return let final Never #t3 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int floor() {} // Error.
+  ^" in null;
+  }
+}
+static method isEven() → invalid-type {
+  core::bool get;
+  function isOdd() → Never
+    return throw 42;
+  core::bool get = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+  bool get isEven => throw 42; // Ok.
+       ^^^";
+  function isEven() → Never
+    return throw 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline.expect
new file mode 100644
index 0000000..b92215c
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline.expect
@@ -0,0 +1,13 @@
+extension E1 on int {}
+
+show num() {}
+
+extension E2 on int {}
+
+show num;
+hide ceil() {}
+
+extension E3 on int {}
+
+hide isEven() {}
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4d9e489
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+extension E1 on int {}
+
+extension E2 on int {}
+
+extension E3 on int {}
+
+hide ceil() {}
+hide isEven() {}
+main() {}
+show num() {}
+show num;
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.expect
new file mode 100644
index 0000000..6d68160
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {
+//                          ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {
+//                                   ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {
+//                              ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int ceil() {} // Error.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int ceil() {} // Ok.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int floor() {} // Error.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Error: Expected ';' after this.
+//   bool get isOdd => throw 42; // Error.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:18: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+//   bool get isOdd => throw 42; // Error.
+//                  ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+//   bool get isEven => throw 42; // Ok.
+//        ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Context: Previous declaration of 'get'.
+//   bool get isOdd => throw 42; // Error.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: Expected ';' after this.
+//   bool get isEven => throw 42; // Ok.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:19: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+//   bool get isEven => throw 42; // Ok.
+//                   ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+static method num() → invalid-type {
+  function ceil() → core::int {
+    return let final Never #t1 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int ceil() {} // Error.
+  ^" in null;
+  }
+}
+static method ceil() → invalid-type {
+  function ceil() → core::int {
+    return let final Never #t2 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int ceil() {} // Ok.
+  ^" in null;
+  }
+  function floor() → core::int {
+    return let final Never #t3 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int floor() {} // Error.
+  ^" in null;
+  }
+}
+static method isEven() → invalid-type {
+  core::bool get;
+  function isOdd() → Never
+    return throw 42;
+  core::bool get = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+  bool get isEven => throw 42; // Ok.
+       ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
+  function isEven() → Never
+    return throw 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.outline.expect
new file mode 100644
index 0000000..5c68071
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.outline.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {
+//                          ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {
+//                                   ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {
+//                              ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {
+//                     ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+static method num() → invalid-type
+  ;
+static method ceil() → invalid-type
+  ;
+static method isEven() → invalid-type
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.transformed.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.transformed.expect
new file mode 100644
index 0000000..9fe722e
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.transformed.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {
+//                          ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {
+//                          ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {
+//                                   ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {
+//                 ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {
+//                          ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {
+//                              ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int ceil() {} // Error.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {
+//                     ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int ceil() {} // Ok.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+//   int floor() {} // Error.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Error: Expected ';' after this.
+//   bool get isOdd => throw 42; // Error.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:18: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+//   bool get isOdd => throw 42; // Error.
+//                  ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+//   bool get isEven => throw 42; // Ok.
+//        ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Context: Previous declaration of 'get'.
+//   bool get isOdd => throw 42; // Error.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: Expected ';' after this.
+//   bool get isEven => throw 42; // Ok.
+//        ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:19: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+//   bool get isEven => throw 42; // Ok.
+//                   ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+static method num() → invalid-type {
+  function ceil() → core::int {
+    return let final Never #t1 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int ceil() {} // Error.
+  ^" in null;
+  }
+}
+static method ceil() → invalid-type {
+  function ceil() → core::int {
+    return let final Never #t2 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int ceil() {} // Ok.
+  ^" in null;
+  }
+  function floor() → core::int {
+    return let final Never #t3 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+  int floor() {} // Error.
+  ^" in null;
+  }
+}
+static method isEven() → invalid-type {
+  core::bool get;
+  function isOdd() → Never
+    return throw 42;
+  core::bool get = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+  bool get isEven => throw 42; // Ok.
+       ^^^";
+  function isEven() → Never
+    return throw 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/default_values.dart.weak.expect b/pkg/front_end/testcases/extensions/default_values.dart.weak.expect
index f4256f5..99dd7ec 100644
--- a/pkg/front_end/testcases/extensions/default_values.dart.weak.expect
+++ b/pkg/front_end/testcases/extensions/default_values.dart.weak.expect
@@ -71,5 +71,5 @@
   #C1 = null
   #C2 = 42
   #C3 = 87
-  #C4 = tearoff self::Extension|staticMethod
+  #C4 = static-tearoff self::Extension|staticMethod
 }
diff --git a/pkg/front_end/testcases/extensions/default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/default_values.dart.weak.transformed.expect
index f4256f5..99dd7ec 100644
--- a/pkg/front_end/testcases/extensions/default_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/default_values.dart.weak.transformed.expect
@@ -71,5 +71,5 @@
   #C1 = null
   #C2 = 42
   #C3 = 87
-  #C4 = tearoff self::Extension|staticMethod
+  #C4 = static-tearoff self::Extension|staticMethod
 }
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.expect
index bef26cf..942973c 100644
--- a/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.expect
+++ b/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.expect
@@ -232,11 +232,11 @@
 
 constants  {
   #C1 = null
-  #C2 = tearoff self::Extension|readGetter
-  #C3 = tearoff self::Extension|writeSetterRequired
-  #C4 = tearoff self::Extension|writeSetterOptional
-  #C5 = tearoff self::Extension|writeSetterNamed
-  #C6 = tearoff self::Extension|genericWriteSetterRequired
-  #C7 = tearoff self::Extension|genericWriteSetterOptional
-  #C8 = tearoff self::Extension|genericWriteSetterNamed
+  #C2 = static-tearoff self::Extension|readGetter
+  #C3 = static-tearoff self::Extension|writeSetterRequired
+  #C4 = static-tearoff self::Extension|writeSetterOptional
+  #C5 = static-tearoff self::Extension|writeSetterNamed
+  #C6 = static-tearoff self::Extension|genericWriteSetterRequired
+  #C7 = static-tearoff self::Extension|genericWriteSetterOptional
+  #C8 = static-tearoff self::Extension|genericWriteSetterNamed
 }
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.transformed.expect
index bef26cf..942973c 100644
--- a/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.transformed.expect
@@ -232,11 +232,11 @@
 
 constants  {
   #C1 = null
-  #C2 = tearoff self::Extension|readGetter
-  #C3 = tearoff self::Extension|writeSetterRequired
-  #C4 = tearoff self::Extension|writeSetterOptional
-  #C5 = tearoff self::Extension|writeSetterNamed
-  #C6 = tearoff self::Extension|genericWriteSetterRequired
-  #C7 = tearoff self::Extension|genericWriteSetterOptional
-  #C8 = tearoff self::Extension|genericWriteSetterNamed
+  #C2 = static-tearoff self::Extension|readGetter
+  #C3 = static-tearoff self::Extension|writeSetterRequired
+  #C4 = static-tearoff self::Extension|writeSetterOptional
+  #C5 = static-tearoff self::Extension|writeSetterNamed
+  #C6 = static-tearoff self::Extension|genericWriteSetterRequired
+  #C7 = static-tearoff self::Extension|genericWriteSetterOptional
+  #C8 = static-tearoff self::Extension|genericWriteSetterNamed
 }
diff --git a/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.expect b/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.expect
index d7c5320..214f428 100644
--- a/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.expect
+++ b/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.expect
@@ -56,5 +56,5 @@
 
 constants  {
   #C1 = 42
-  #C2 = tearoff mai::Extension|staticMethod
+  #C2 = static-tearoff mai::Extension|staticMethod
 }
diff --git a/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.transformed.expect
index d7c5320..214f428 100644
--- a/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.transformed.expect
@@ -56,5 +56,5 @@
 
 constants  {
   #C1 = 42
-  #C2 = tearoff mai::Extension|staticMethod
+  #C2 = static-tearoff mai::Extension|staticMethod
 }
diff --git a/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.expect b/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.expect
index dda54b1..4dc6953 100644
--- a/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.expect
+++ b/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.expect
@@ -48,5 +48,5 @@
 
 constants  {
   #C1 = 42
-  #C2 = tearoff mai::Extension|staticMethod
+  #C2 = static-tearoff mai::Extension|staticMethod
 }
diff --git a/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.transformed.expect
index dda54b1..4dc6953 100644
--- a/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.transformed.expect
@@ -48,5 +48,5 @@
 
 constants  {
   #C1 = 42
-  #C2 = tearoff mai::Extension|staticMethod
+  #C2 = static-tearoff mai::Extension|staticMethod
 }
diff --git a/pkg/front_end/testcases/extensions/static_access.dart.weak.expect b/pkg/front_end/testcases/extensions/static_access.dart.weak.expect
index 5cc472a..973805f 100644
--- a/pkg/front_end/testcases/extensions/static_access.dart.weak.expect
+++ b/pkg/front_end/testcases/extensions/static_access.dart.weak.expect
@@ -53,6 +53,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::Extension|method
-  #C2 = tearoff self::Extension|genericMethod
+  #C1 = static-tearoff self::Extension|method
+  #C2 = static-tearoff self::Extension|genericMethod
 }
diff --git a/pkg/front_end/testcases/extensions/static_access.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/static_access.dart.weak.transformed.expect
index 5cc472a..973805f 100644
--- a/pkg/front_end/testcases/extensions/static_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/static_access.dart.weak.transformed.expect
@@ -53,6 +53,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::Extension|method
-  #C2 = tearoff self::Extension|genericMethod
+  #C1 = static-tearoff self::Extension|method
+  #C2 = static-tearoff self::Extension|genericMethod
 }
diff --git a/pkg/front_end/testcases/general/argument.dart.weak.expect b/pkg/front_end/testcases/general/argument.dart.weak.expect
index 90b185e..e667193 100644
--- a/pkg/front_end/testcases/general/argument.dart.weak.expect
+++ b/pkg/front_end/testcases/general/argument.dart.weak.expect
@@ -47,6 +47,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::foo_escaped
-  #C2 = tearoff self::bar_escaped
+  #C1 = static-tearoff self::foo_escaped
+  #C2 = static-tearoff self::bar_escaped
 }
diff --git a/pkg/front_end/testcases/general/argument.dart.weak.transformed.expect b/pkg/front_end/testcases/general/argument.dart.weak.transformed.expect
index 90b185e..e667193 100644
--- a/pkg/front_end/testcases/general/argument.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/argument.dart.weak.transformed.expect
@@ -47,6 +47,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::foo_escaped
-  #C2 = tearoff self::bar_escaped
+  #C1 = static-tearoff self::foo_escaped
+  #C2 = static-tearoff self::bar_escaped
 }
diff --git a/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
index 45a2ff8..758329d 100644
--- a/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
@@ -36,9 +36,9 @@
   core::int* :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
-  dynamic :async_temporary_0;
-  dynamic :async_temporary_1;
-  dynamic :async_temporary_2;
+  self::Node* :async_temporary_0;
+  self::Node* :async_temporary_1;
+  self::Node* :async_temporary_2;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
diff --git a/pkg/front_end/testcases/general/await_complex.dart.weak.expect b/pkg/front_end/testcases/general/await_complex.dart.weak.expect
index df8fc27..20324c7 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.weak.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.weak.expect
@@ -254,7 +254,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = tearoff self::future
+  #C1 = static-tearoff self::id
+  #C2 = static-tearoff self::future
   #C3 = 2
 }
diff --git a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
index cb5a62a..087766ec 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
@@ -65,12 +65,12 @@
   core::int* :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
-  dynamic :async_temporary_0;
-  dynamic :async_temporary_1;
-  dynamic :async_temporary_2;
-  dynamic :async_temporary_3;
-  dynamic :async_temporary_4;
-  dynamic :async_temporary_5;
+  core::int* :async_temporary_0;
+  core::int* :async_temporary_1;
+  core::int* :async_temporary_2;
+  core::int* :async_temporary_3;
+  core::int* :async_temporary_4;
+  core::int* :async_temporary_5;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
@@ -121,11 +121,11 @@
   core::int* :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
-  dynamic :async_temporary_0;
-  dynamic :async_temporary_1;
-  dynamic :async_temporary_2;
-  dynamic :async_temporary_3;
-  dynamic :async_temporary_4;
+  core::int* :async_temporary_0;
+  core::int* :async_temporary_1;
+  core::int* :async_temporary_2;
+  core::int* :async_temporary_3;
+  core::int* :async_temporary_4;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L2:
@@ -172,11 +172,11 @@
   core::int* :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
-  dynamic :async_temporary_0;
-  dynamic :async_temporary_1;
-  dynamic :async_temporary_2;
-  dynamic :async_temporary_3;
-  dynamic :async_temporary_4;
+  core::int* :async_temporary_0;
+  core::int* :async_temporary_1;
+  core::int* :async_temporary_2;
+  core::int* :async_temporary_3;
+  core::int* :async_temporary_4;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L3:
@@ -225,10 +225,10 @@
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
   dynamic :async_temporary_0;
-  dynamic :async_temporary_1;
-  dynamic :async_temporary_2;
-  dynamic :async_temporary_3;
-  dynamic :async_temporary_4;
+  core::int* :async_temporary_1;
+  core::int* :async_temporary_2;
+  core::List<core::int*>* :async_temporary_3;
+  core::int* :async_temporary_4;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L4:
@@ -288,13 +288,13 @@
         core::bool* a = false;
         core::bool* b = true;
         :async_temporary_0 = (a || b) =={core::Object::==}{(core::Object) → core::bool} true;
-        if(:async_temporary_0)
+        if(_in::unsafeCast<core::bool*>(:async_temporary_0))
           ;
         else {
           [yield] let dynamic #t22 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
           :async_temporary_0 = :result as{TypeError,ForDynamic} core::bool* =={core::Object::==}{(core::Object) → core::bool} true;
         }
-        core::bool* c = :async_temporary_0;
+        core::bool* c = _in::unsafeCast<core::bool*>(:async_temporary_0);
         self::expect(true, c);
         if(a || b) {
           :async_temporary_1 = a;
@@ -426,8 +426,8 @@
   dynamic :saved_try_context_var3;
   dynamic :exception0;
   dynamic :stack_trace0;
-  dynamic :async_temporary_0;
-  dynamic :async_temporary_1;
+  core::List<dynamic>* :async_temporary_0;
+  core::List<dynamic>* :async_temporary_1;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L7:
@@ -811,7 +811,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = tearoff self::future
+  #C1 = static-tearoff self::id
+  #C2 = static-tearoff self::future
   #C3 = 2
 }
diff --git a/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect b/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
index 7178e45..85541c5 100644
--- a/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
@@ -105,7 +105,7 @@
   core::int* :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
-  dynamic :async_temporary_0;
+  self::Y* :async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L3:
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart
new file mode 100644
index 0000000..0210c32
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart
@@ -0,0 +1,15 @@
+// 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 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+  external const factory ParallaxOptions();
+}
+
+test() => const ParallaxOptions();
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline.expect
new file mode 100644
index 0000000..8b3f432
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+  external const factory ParallaxOptions();
+}
+
+test() => const ParallaxOptions();
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..bef2d3d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+  external const factory ParallaxOptions();
+}
+
+main() {}
+test() => const ParallaxOptions();
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.expect
new file mode 100644
index 0000000..c1c307d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart:13:17: Error: Constant evaluation error:
+// test() => const ParallaxOptions();
+//                 ^
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart:13:17: Context: External factory constructors can't be evaluated in constant expressions.
+// test() => const ParallaxOptions();
+//                 ^
+//
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@#C2
+@#C3
+class ParallaxOptions extends core::Object {
+  external static factory •() → self::ParallaxOptions;
+}
+static method test() → dynamic
+  return invalid-expression "External factory constructors can't be evaluated in constant expressions.";
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+  #C2 = js::JS {name:#C1}
+  #C3 = js::_Anonymous {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46123.dart:
+- JS. (from org-dartlang-testcase-sdk:///pkg/js/lib/js.dart:21:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.outline.expect
new file mode 100644
index 0000000..d5602f8
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.outline.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@js::JS::•()
+@js::anonymous
+class ParallaxOptions extends core::Object {
+  external static factory •() → self::ParallaxOptions;
+}
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue46123.dart:7:2 -> InstanceConstant(const JS{JS.name: null})
+Evaluated: StaticGet @ org-dartlang-testcase:///issue46123.dart:8:2 -> InstanceConstant(const _Anonymous{})
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.transformed.expect
new file mode 100644
index 0000000..c1c307d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.transformed.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart:13:17: Error: Constant evaluation error:
+// test() => const ParallaxOptions();
+//                 ^
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart:13:17: Context: External factory constructors can't be evaluated in constant expressions.
+// test() => const ParallaxOptions();
+//                 ^
+//
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@#C2
+@#C3
+class ParallaxOptions extends core::Object {
+  external static factory •() → self::ParallaxOptions;
+}
+static method test() → dynamic
+  return invalid-expression "External factory constructors can't be evaluated in constant expressions.";
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+  #C2 = js::JS {name:#C1}
+  #C3 = js::_Anonymous {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46123.dart:
+- JS. (from org-dartlang-testcase-sdk:///pkg/js/lib/js.dart:21:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart
new file mode 100644
index 0000000..ecc1c05
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart
@@ -0,0 +1,15 @@
+// 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 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+  external const ParallaxOptions();
+}
+
+test() => const ParallaxOptions();
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline.expect
new file mode 100644
index 0000000..2d26ea3
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+  external const ParallaxOptions();
+}
+
+test() => const ParallaxOptions();
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0c3a93a
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+  external const ParallaxOptions();
+}
+
+main() {}
+test() => const ParallaxOptions();
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.expect
new file mode 100644
index 0000000..29f09a1
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.expect
@@ -0,0 +1,39 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart:13:17: Error: Constant evaluation error:
+// test() => const ParallaxOptions();
+//                 ^
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart:13:17: Context: External constructors can't be evaluated in constant expressions.
+// test() => const ParallaxOptions();
+//                 ^
+//
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@#C2
+@#C3
+class ParallaxOptions extends core::Object /*hasConstConstructor*/  {
+  external const constructor •() → self::ParallaxOptions
+    : super core::Object::•()
+    ;
+}
+static method test() → dynamic
+  return invalid-expression "External constructors can't be evaluated in constant expressions.";
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+  #C2 = js::JS {name:#C1}
+  #C3 = js::_Anonymous {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46123b.dart:
+- JS. (from org-dartlang-testcase-sdk:///pkg/js/lib/js.dart:21:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.outline.expect
new file mode 100644
index 0000000..78273bc
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.outline.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@js::JS::•()
+@js::anonymous
+class ParallaxOptions extends core::Object /*hasConstConstructor*/  {
+  external const constructor •() → self::ParallaxOptions
+    : super core::Object::•()
+    ;
+}
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue46123b.dart:7:2 -> InstanceConstant(const JS{JS.name: null})
+Evaluated: StaticGet @ org-dartlang-testcase:///issue46123b.dart:8:2 -> InstanceConstant(const _Anonymous{})
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.transformed.expect
new file mode 100644
index 0000000..29f09a1
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.transformed.expect
@@ -0,0 +1,39 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart:13:17: Error: Constant evaluation error:
+// test() => const ParallaxOptions();
+//                 ^
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart:13:17: Context: External constructors can't be evaluated in constant expressions.
+// test() => const ParallaxOptions();
+//                 ^
+//
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@#C2
+@#C3
+class ParallaxOptions extends core::Object /*hasConstConstructor*/  {
+  external const constructor •() → self::ParallaxOptions
+    : super core::Object::•()
+    ;
+}
+static method test() → dynamic
+  return invalid-expression "External constructors can't be evaluated in constant expressions.";
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+  #C2 = js::JS {name:#C1}
+  #C3 = js::_Anonymous {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46123b.dart:
+- JS. (from org-dartlang-testcase-sdk:///pkg/js/lib/js.dart:21:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constants/various.dart.weak.expect b/pkg/front_end/testcases/general/constants/various.dart.weak.expect
index 8c8d29f..1cde25c 100644
--- a/pkg/front_end/testcases/general/constants/various.dart.weak.expect
+++ b/pkg/front_end/testcases/general/constants/various.dart.weak.expect
@@ -621,8 +621,8 @@
   #C18 = #I.Have.Dots
   #C19 = self::ClassWithTypeArguments<core::int*, core::int*, core::int*> {}
   #C20 = self::ClassWithTypeArguments<dynamic, dynamic, dynamic> {}
-  #C21 = tearoff self::id1
-  #C22 = partial-instantiation self::id1 <core::int*>
+  #C21 = static-tearoff self::id1
+  #C22 = instantiation self::id1 <core::int*>
 }
 
 
diff --git a/pkg/front_end/testcases/general/constants/various.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/various.dart.weak.transformed.expect
index 6998464..f39f9ab 100644
--- a/pkg/front_end/testcases/general/constants/various.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/various.dart.weak.transformed.expect
@@ -621,8 +621,8 @@
   #C18 = #I.Have.Dots
   #C19 = self::ClassWithTypeArguments<core::int*, core::int*, core::int*> {}
   #C20 = self::ClassWithTypeArguments<dynamic, dynamic, dynamic> {}
-  #C21 = tearoff self::id1
-  #C22 = partial-instantiation self::id1 <core::int*>
+  #C21 = static-tearoff self::id1
+  #C22 = instantiation self::id1 <core::int*>
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.expect
index 9b677e7..ce2a935 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.expect
@@ -232,7 +232,7 @@
   #C38 = eval const core::bool::fromEnvironment(#C33) ?{self::Subclass<self::A>?} #C9 : self::Subclass<self::A*>{(self::A{}) as{ForNonNullableByDefault} self::A*}
   #C39 = eval const core::bool::fromEnvironment(#C33) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B*>{(self::B{}) as{ForNonNullableByDefault} self::B*}
   #C40 = TypeLiteralConstant((core::int*, {named: core::int*}) →* core::int*)
-  #C41 = tearoff self::procedure
+  #C41 = static-tearoff self::procedure
   #C42 = self::ConstClassWithF {foo:#C41}
   #C43 = eval const core::bool::fromEnvironment(#C1)
   #C44 = eval !const core::bool::fromEnvironment(#C1)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.transformed.expect
index b2b5426..fef7a55 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.transformed.expect
@@ -232,7 +232,7 @@
   #C38 = eval const core::bool::fromEnvironment(#C33) ?{self::Subclass<self::A>?} #C9 : self::Subclass<self::A*>{(self::A{}) as{ForNonNullableByDefault} self::A*}
   #C39 = eval const core::bool::fromEnvironment(#C33) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B*>{(self::B{}) as{ForNonNullableByDefault} self::B*}
   #C40 = TypeLiteralConstant((core::int*, {named: core::int*}) →* core::int*)
-  #C41 = tearoff self::procedure
+  #C41 = static-tearoff self::procedure
   #C42 = self::ConstClassWithF {foo:#C41}
   #C43 = eval const core::bool::fromEnvironment(#C1)
   #C44 = eval !const core::bool::fromEnvironment(#C1)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect
index 65655e9..942009a 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect
@@ -103,8 +103,8 @@
 
 constants  {
   #C1 = TypeLiteralConstant(core::Object*)
-  #C2 = tearoff var::id1
-  #C3 = partial-instantiation var::id1 <core::int*>
+  #C2 = static-tearoff var::id1
+  #C3 = instantiation var::id1 <core::int*>
   #C4 = 0
   #C5 = var::Class<core::int*> {field:#C4}
   #C6 = 42
@@ -121,10 +121,10 @@
   #C17 = null
   #C18 = <dynamic, dynamic>{#C7:#C15, #C17:#C7)
   #C19 = true
-  #C20 = tearoff var::id2
+  #C20 = static-tearoff var::id2
   #C21 = eval const core::identical(#C3, const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>)
   #C22 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
-  #C23 = tearoff core::identical
+  #C23 = static-tearoff core::identical
 }
 
 
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect
index 8f668a2..6a48cb7 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect
@@ -103,8 +103,8 @@
 
 constants  {
   #C1 = TypeLiteralConstant(core::Object*)
-  #C2 = tearoff var::id1
-  #C3 = partial-instantiation var::id1 <core::int*>
+  #C2 = static-tearoff var::id1
+  #C3 = instantiation var::id1 <core::int*>
   #C4 = 0
   #C5 = var::Class<core::int*> {field:#C4}
   #C6 = 42
@@ -121,11 +121,11 @@
   #C17 = null
   #C18 = <dynamic, dynamic>{#C7:#C15, #C17:#C7)
   #C19 = true
-  #C20 = tearoff var::id2
+  #C20 = static-tearoff var::id2
   #C21 = eval const core::identical(#C3, const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>)
   #C22 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
   #C23 = eval const core::identical(#C3, const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>)
-  #C24 = tearoff core::identical
+  #C24 = static-tearoff core::identical
   #C25 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
 }
 
diff --git a/pkg/front_end/testcases/general/constructor_patch/libraries.json b/pkg/front_end/testcases/general/constructor_patch/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/libraries.json
@@ -0,0 +1,12 @@
+{
+  "none": {
+    "libraries": {
+      "test": {
+        "patches": [
+          "patch_lib.dart"
+        ],
+        "uri": "origin_lib.dart"
+      }
+    }
+  }
+}
diff --git a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart b/pkg/front_end/testcases/general/constructor_patch/main.dart
similarity index 70%
copy from tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
copy to pkg/front_end/testcases/general/constructor_patch/main.dart
index e6185da..dd2a110 100644
--- a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
+++ b/pkg/front_end/testcases/general/constructor_patch/main.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 'extends_test_util.dart';
+import 'dart:test';
 
-void main() {
-  setUpWithES6Syntax();
-  testSubtyping();
+main() {
+  new Class.generative();
+  const Class.constGenerative();
 }
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.expect
new file mode 100644
index 0000000..40f37f3
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  new test::Class::generative();
+  #C2;
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C3
+class Class extends core::Object /*hasConstConstructor*/  {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  @#C3
+  constructor generative({core::bool defaultValue = #C1}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C3
+  const constructor constGenerative({core::bool defaultValue = #C1}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = true
+  #C2 = test::Class {defaultValue:#C1}
+  #C3 = _in::_Patch {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- Class.constGenerative (from org-dartlang-testcase:///patch_lib.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.outline.expect
new file mode 100644
index 0000000..d5e5658
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:test";
+
+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 /*hasConstConstructor*/  {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  @_in::patch
+  external constructor generative({core::bool defaultValue}) → self2::Class
+    ;
+  @_in::patch
+  const constructor constGenerative({core::bool defaultValue = true}) → self2::Class
+    : self2::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:6:49 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:7:44 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:16:9 -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 4, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..40f37f3
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.transformed.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  new test::Class::generative();
+  #C2;
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C3
+class Class extends core::Object /*hasConstConstructor*/  {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  @#C3
+  constructor generative({core::bool defaultValue = #C1}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C3
+  const constructor constGenerative({core::bool defaultValue = #C1}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = true
+  #C2 = test::Class {defaultValue:#C1}
+  #C3 = _in::_Patch {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- Class.constGenerative (from org-dartlang-testcase:///patch_lib.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/tests/lib/js/extends_test/extends_subtyping_test.dart b/pkg/front_end/testcases/general/constructor_patch/origin_lib.dart
similarity index 60%
copy from tests/lib/js/extends_test/extends_subtyping_test.dart
copy to pkg/front_end/testcases/general/constructor_patch/origin_lib.dart
index 76dc51e..2906fbf 100644
--- a/tests/lib/js/extends_test/extends_subtyping_test.dart
+++ b/pkg/front_end/testcases/general/constructor_patch/origin_lib.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'extends_test_util.dart';
-
-void main() {
-  setUpWithoutES6Syntax();
-  testSubtyping();
+class Class {
+  external Class.generative({bool defaultValue: true});
+  external const Class.constGenerative({bool defaultValue: true});
 }
diff --git a/pkg/front_end/testcases/general/constructor_patch/patch_lib.dart b/pkg/front_end/testcases/general/constructor_patch/patch_lib.dart
new file mode 100644
index 0000000..0c4899c
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/patch_lib.dart
@@ -0,0 +1,17 @@
+// 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.
+
+// ignore: import_internal_library
+import 'dart:_internal';
+
+@patch
+class Class {
+  final bool defaultValue;
+
+  @patch
+  Class.generative({this.defaultValue: true});
+
+  @patch
+  const Class.constGenerative({this.defaultValue: true});
+}
diff --git a/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.expect b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.expect
new file mode 100644
index 0000000..9b02f5d
--- /dev/null
+++ b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:19: Error: Type 'C' not found.
+// mixin A<T extends C> on D {}
+//                   ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:25: Error: Type 'D' not found.
+// mixin A<T extends C> on D {}
+//                         ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:3:17: Error: Type 'D' not found.
+// class B extends D with A {}
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends invalid-type> extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class _B&D&A = core::Object with self::A<invalid-type> /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_B&D&A
+    : super core::Object::•()
+    ;
+}
+class B extends self::_B&D&A {
+  synthetic constructor •() → self::B
+    : super self::_B&D&A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.outline.expect
new file mode 100644
index 0000000..e9d2a26
--- /dev/null
+++ b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.outline.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:19: Error: Type 'C' not found.
+// mixin A<T extends C> on D {}
+//                   ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:25: Error: Type 'D' not found.
+// mixin A<T extends C> on D {}
+//                         ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:3:17: Error: Type 'D' not found.
+// class B extends D with A {}
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends invalid-type> extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class _B&D&A = core::Object with self::A<invalid-type> /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_B&D&A
+    ;
+}
+class B extends self::_B&D&A {
+  synthetic constructor •() → self::B
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..8b03fd8a
--- /dev/null
+++ b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.transformed.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:19: Error: Type 'C' not found.
+// mixin A<T extends C> on D {}
+//                   ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:25: Error: Type 'D' not found.
+// mixin A<T extends C> on D {}
+//                         ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:3:17: Error: Type 'D' not found.
+// class B extends D with A {}
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends invalid-type> extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class _B&D&A extends core::Object implements self::A<invalid-type> /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_B&D&A
+    : super core::Object::•()
+    ;
+}
+class B extends self::_B&D&A {
+  synthetic constructor •() → self::B
+    : super self::_B&D&A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/external.dart.weak.expect b/pkg/front_end/testcases/general/external.dart.weak.expect
index ab78ddb..5e9b241 100644
--- a/pkg/front_end/testcases/general/external.dart.weak.expect
+++ b/pkg/front_end/testcases/general/external.dart.weak.expect
@@ -19,5 +19,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::onData
+  #C1 = static-tearoff self::onData
 }
diff --git a/pkg/front_end/testcases/general/external.dart.weak.transformed.expect b/pkg/front_end/testcases/general/external.dart.weak.transformed.expect
index ab78ddb..5e9b241 100644
--- a/pkg/front_end/testcases/general/external.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/external.dart.weak.transformed.expect
@@ -19,5 +19,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::onData
+  #C1 = static-tearoff self::onData
 }
diff --git a/pkg/front_end/testcases/general/factory_patch/libraries.json b/pkg/front_end/testcases/general/factory_patch/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/libraries.json
@@ -0,0 +1,12 @@
+{
+  "none": {
+    "libraries": {
+      "test": {
+        "patches": [
+          "patch_lib.dart"
+        ],
+        "uri": "origin_lib.dart"
+      }
+    }
+  }
+}
diff --git a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart b/pkg/front_end/testcases/general/factory_patch/main.dart
similarity index 70%
copy from tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
copy to pkg/front_end/testcases/general/factory_patch/main.dart
index e6185da..8e6257c 100644
--- a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
+++ b/pkg/front_end/testcases/general/factory_patch/main.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 'extends_test_util.dart';
+import 'dart:test';
 
-void main() {
-  setUpWithES6Syntax();
-  testSubtyping();
+main() {
+  new Class.fact();
+  //const Class.redirect();
 }
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.weak.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.expect
new file mode 100644
index 0000000..3cddf53
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/factory_patch/patch_lib.dart:22:52: Error: Can't have a default value here because any default values of 'Class._internal' would be used instead.
+// Try removing the default value.
+//   const factory Class.redirect({bool defaultValue: true}) = Class._internal;
+//                                                    ^
+//
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  static final field dynamic _redirecting# = <dynamic>[test::Class::redirect]/*isLegacy*/;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ redirect({core::bool defaultValue = #C3}) → test::Class
+    let dynamic #redirecting_factory = test::Class::_internal in invalid-expression;
+}
+
+constants  {
+  #C1 = _in::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.outline.expect
new file mode 100644
index 0000000..62a00f1
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.outline.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:test";
+
+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 {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  static final field dynamic _redirecting# = <dynamic>[self2::Class::redirect]/*isLegacy*/;
+  const constructor _internal({core::bool defaultValue = false}) → self2::Class
+    : self2::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @_in::patch
+  external static factory fact({core::bool defaultValue}) → self2::Class;
+  @_in::patch
+  external static factory constFact({core::bool defaultValue = true}) → self2::Class;
+  @_in::patch
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ redirect({core::bool defaultValue = true}) → self2::Class
+    let dynamic #redirecting_factory = self2::Class::_internal in invalid-expression;
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:6:49 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:8:27 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:22:17 -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 9, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..3cddf53
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.transformed.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/factory_patch/patch_lib.dart:22:52: Error: Can't have a default value here because any default values of 'Class._internal' would be used instead.
+// Try removing the default value.
+//   const factory Class.redirect({bool defaultValue: true}) = Class._internal;
+//                                                    ^
+//
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  static final field dynamic _redirecting# = <dynamic>[test::Class::redirect]/*isLegacy*/;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ redirect({core::bool defaultValue = #C3}) → test::Class
+    let dynamic #redirecting_factory = test::Class::_internal in invalid-expression;
+}
+
+constants  {
+  #C1 = _in::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/origin_lib.dart b/pkg/front_end/testcases/general/factory_patch/origin_lib.dart
new file mode 100644
index 0000000..300b31e
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/origin_lib.dart
@@ -0,0 +1,9 @@
+// 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.
+
+class Class {
+  external factory Class.fact({bool defaultValue: true});
+  external const factory Class.constFact({bool defaultValue: true});
+  external const factory Class.redirect({bool defaultValue: true});
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/patch_lib.dart b/pkg/front_end/testcases/general/factory_patch/patch_lib.dart
new file mode 100644
index 0000000..e1fe3fd
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/patch_lib.dart
@@ -0,0 +1,23 @@
+// 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.
+
+// ignore: import_internal_library
+import 'dart:_internal';
+
+@patch
+class Class {
+  final bool defaultValue;
+
+  const Class._internal({this.defaultValue: false});
+
+  @patch
+  factory Class.fact({bool defaultValue: true}) =>
+      new Class._internal(defaultValue: defaultValue);
+
+  @patch
+  factory Class.constFact({bool defaultValue: true}) => throw 'unsupported';
+
+  @patch
+  const factory Class.redirect({bool defaultValue: true}) = Class._internal;
+}
diff --git a/pkg/front_end/testcases/general/function_type_assignments.dart.weak.expect b/pkg/front_end/testcases/general/function_type_assignments.dart.weak.expect
index 0d92c04..cc24e09 100644
--- a/pkg/front_end/testcases/general/function_type_assignments.dart.weak.expect
+++ b/pkg/front_end/testcases/general/function_type_assignments.dart.weak.expect
@@ -39,7 +39,7 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::identity
-  #C2 = tearoff self::identityObject
-  #C3 = tearoff self::identityList
+  #C1 = static-tearoff self::identity
+  #C2 = static-tearoff self::identityObject
+  #C3 = static-tearoff self::identityList
 }
diff --git a/pkg/front_end/testcases/general/function_type_assignments.dart.weak.transformed.expect b/pkg/front_end/testcases/general/function_type_assignments.dart.weak.transformed.expect
index 0d92c04..cc24e09 100644
--- a/pkg/front_end/testcases/general/function_type_assignments.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/function_type_assignments.dart.weak.transformed.expect
@@ -39,7 +39,7 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::identity
-  #C2 = tearoff self::identityObject
-  #C3 = tearoff self::identityList
+  #C1 = static-tearoff self::identity
+  #C2 = static-tearoff self::identityObject
+  #C3 = static-tearoff self::identityList
 }
diff --git a/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.expect b/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.expect
index 61a26ba..c406e1e 100644
--- a/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.expect
+++ b/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.expect
@@ -22,5 +22,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::add
+  #C1 = static-tearoff self::add
 }
diff --git a/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.transformed.expect b/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.transformed.expect
index 61a26ba..c406e1e 100644
--- a/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.transformed.expect
@@ -22,5 +22,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::add
+  #C1 = static-tearoff self::add
 }
diff --git a/pkg/front_end/testcases/general/getter_call.dart.weak.expect b/pkg/front_end/testcases/general/getter_call.dart.weak.expect
index 9430786..bcf489c 100644
--- a/pkg/front_end/testcases/general/getter_call.dart.weak.expect
+++ b/pkg/front_end/testcases/general/getter_call.dart.weak.expect
@@ -176,12 +176,12 @@
 }
 
 constants  {
-  #C1 = tearoff self::method1
-  #C2 = tearoff self::method2
-  #C3 = tearoff self::method3
-  #C4 = tearoff self::method4
-  #C5 = tearoff self::method5
-  #C6 = tearoff self::method6
-  #C7 = tearoff self::method7
+  #C1 = static-tearoff self::method1
+  #C2 = static-tearoff self::method2
+  #C3 = static-tearoff self::method3
+  #C4 = static-tearoff self::method4
+  #C5 = static-tearoff self::method5
+  #C6 = static-tearoff self::method6
+  #C7 = static-tearoff self::method7
   #C8 = 0
 }
diff --git a/pkg/front_end/testcases/general/getter_call.dart.weak.transformed.expect b/pkg/front_end/testcases/general/getter_call.dart.weak.transformed.expect
index c9ab79c..1ff1cbc 100644
--- a/pkg/front_end/testcases/general/getter_call.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/getter_call.dart.weak.transformed.expect
@@ -176,13 +176,13 @@
 }
 
 constants  {
-  #C1 = tearoff self::method1
-  #C2 = tearoff self::method2
-  #C3 = tearoff self::method3
-  #C4 = tearoff self::method4
-  #C5 = tearoff self::method5
-  #C6 = tearoff self::method6
-  #C7 = tearoff self::method7
+  #C1 = static-tearoff self::method1
+  #C2 = static-tearoff self::method2
+  #C3 = static-tearoff self::method3
+  #C4 = static-tearoff self::method4
+  #C5 = static-tearoff self::method5
+  #C6 = static-tearoff self::method6
+  #C7 = static-tearoff self::method7
   #C8 = 0
 }
 
diff --git a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect
index daf6f36..db34700 100644
--- a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect
+++ b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect
@@ -22,6 +22,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = partial-instantiation self::id <core::int*>
+  #C1 = static-tearoff self::id
+  #C2 = instantiation self::id <core::int*>
 }
diff --git a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
index e0f574c..acbe826 100644
--- a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
@@ -22,8 +22,8 @@
 }
 
 constants  {
-  #C1 = tearoff self::id
-  #C2 = partial-instantiation self::id <core::int*>
+  #C1 = static-tearoff self::id
+  #C2 = instantiation self::id <core::int*>
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/general/invalid_cast.dart.weak.expect b/pkg/front_end/testcases/general/invalid_cast.dart.weak.expect
index 95af468..e123159 100644
--- a/pkg/front_end/testcases/general/invalid_cast.dart.weak.expect
+++ b/pkg/front_end/testcases/general/invalid_cast.dart.weak.expect
@@ -169,6 +169,6 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::C::staticFunction
-  #C2 = tearoff self::topLevelFunction
+  #C1 = static-tearoff self::C::staticFunction
+  #C2 = static-tearoff self::topLevelFunction
 }
diff --git a/pkg/front_end/testcases/general/invalid_cast.dart.weak.transformed.expect b/pkg/front_end/testcases/general/invalid_cast.dart.weak.transformed.expect
index 7cd74f4..c4466eb 100644
--- a/pkg/front_end/testcases/general/invalid_cast.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/invalid_cast.dart.weak.transformed.expect
@@ -169,6 +169,6 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::C::staticFunction
-  #C2 = tearoff self::topLevelFunction
+  #C1 = static-tearoff self::C::staticFunction
+  #C2 = static-tearoff self::topLevelFunction
 }
diff --git a/pkg/front_end/testcases/general/invalid_super_initializer.dart b/pkg/front_end/testcases/general/invalid_super_initializer.dart
new file mode 100644
index 0000000..1e3f1aa
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_super_initializer.dart
@@ -0,0 +1,15 @@
+// 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 A {}
+
+class B extends A {
+  B(): super()?.foo() {}
+}
+
+bad() {
+  new B();
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/invalid_super_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/general/invalid_super_initializer.dart.textual_outline.expect
new file mode 100644
index 0000000..946f9ea
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_super_initializer.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+abstract class A {}
+class B extends A {
+  B(): super()?.foo() {}
+}
+bad() {}
+main() {}
diff --git a/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.expect b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.expect
new file mode 100644
index 0000000..d8ef127
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Can't use 'super' as an expression.
+// To delegate a constructor to a super constructor, put the super call as an initializer.
+//   B(): super()?.foo() {}
+//        ^
+//
+// pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Expected an initializer.
+//   B(): super()?.foo() {}
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends self::A {
+  constructor •() → self::B
+    : final dynamic #t1 = let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Can't use 'super' as an expression.
+To delegate a constructor to a super constructor, put the super call as an initializer.
+  B(): super()?.foo() {}
+       ^" in #t2 == null ?{dynamic} null : #t2{dynamic}.foo() {}
+}
+static method bad() → dynamic {
+  new self::B::•();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.outline.expect
new file mode 100644
index 0000000..13e0b1e
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.outline.expect
@@ -0,0 +1,16 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+}
+class B extends self::A {
+  constructor •() → self::B
+    ;
+}
+static method bad() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.transformed.expect
new file mode 100644
index 0000000..d8ef127
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.transformed.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Can't use 'super' as an expression.
+// To delegate a constructor to a super constructor, put the super call as an initializer.
+//   B(): super()?.foo() {}
+//        ^
+//
+// pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Expected an initializer.
+//   B(): super()?.foo() {}
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends self::A {
+  constructor •() → self::B
+    : final dynamic #t1 = let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Can't use 'super' as an expression.
+To delegate a constructor to a super constructor, put the super call as an initializer.
+  B(): super()?.foo() {}
+       ^" in #t2 == null ?{dynamic} null : #t2{dynamic}.foo() {}
+}
+static method bad() → dynamic {
+  new self::B::•();
+}
+static method main() → dynamic {}
diff --git a/pkg/kernel/test/regression_37753_test.dart b/pkg/front_end/testcases/general/issue37753.dart
similarity index 100%
rename from pkg/kernel/test/regression_37753_test.dart
rename to pkg/front_end/testcases/general/issue37753.dart
diff --git a/pkg/front_end/testcases/general/issue37753.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue37753.dart.textual_outline.expect
new file mode 100644
index 0000000..771fd22
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue37753.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+// @dart = 2.9
+Iterable<int> getElements() sync* {}
+main() => print(getElements());
diff --git a/pkg/front_end/testcases/general/issue37753.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue37753.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..771fd22
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue37753.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+// @dart = 2.9
+Iterable<int> getElements() sync* {}
+main() => print(getElements());
diff --git a/pkg/front_end/testcases/general/issue37753.dart.weak.expect b/pkg/front_end/testcases/general/issue37753.dart.weak.expect
new file mode 100644
index 0000000..8ce1e9b
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue37753.dart.weak.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method getElements() → core::Iterable<core::int*>* sync* {
+  core::Iterable<core::int*>* elements;
+  elements = (() → core::Iterable<core::int*>* sync* {
+    yield 7;
+  })(){() →* core::Iterable<core::int*>*};
+  yield* elements;
+}
+static method main() → dynamic
+  return core::print(self::getElements());
diff --git a/pkg/front_end/testcases/general/issue37753.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue37753.dart.weak.outline.expect
new file mode 100644
index 0000000..2032eab
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue37753.dart.weak.outline.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method getElements() → core::Iterable<core::int*>* sync* 
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue37753.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue37753.dart.weak.transformed.expect
new file mode 100644
index 0000000..7321092
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue37753.dart.weak.transformed.expect
@@ -0,0 +1,41 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method getElements() → core::Iterable<core::int*>* /* originally sync* */ {
+  function :sync_op_gen() → (core::_SyncIterator<dynamic>*, dynamic, dynamic) →* core::bool* {
+    core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    function :sync_op(core::_SyncIterator<dynamic>* :iterator, dynamic :exception, dynamic :stack_trace) → core::bool* yielding {
+      {
+        core::Iterable<core::int*>* elements;
+        elements = (() → core::Iterable<core::int*>* /* originally sync* */ {
+          function :sync_op_gen() → (core::_SyncIterator<dynamic>*, dynamic, dynamic) →* core::bool* {
+            core::int* :await_jump_var = 0;
+            dynamic :await_ctx_var;
+            function :sync_op(core::_SyncIterator<dynamic>* :iterator, dynamic :exception, dynamic :stack_trace) → core::bool* yielding {
+              {
+                {
+                  :iterator.{core::_SyncIterator::_current} = 7;
+                  [yield] true;
+                }
+              }
+              return false;
+            }
+            return :sync_op;
+          }
+          return new core::_SyncIterable::•<core::int*>(:sync_op_gen);
+        })(){() →* core::Iterable<core::int*>*};
+        {
+          :iterator.{core::_SyncIterator::_yieldEachIterable} = elements;
+          [yield] true;
+        }
+      }
+      return false;
+    }
+    return :sync_op;
+  }
+  return new core::_SyncIterable::•<core::int*>(:sync_op_gen);
+}
+static method main() → dynamic
+  return core::print(self::getElements());
diff --git a/pkg/front_end/testcases/general/issue40662.dart b/pkg/front_end/testcases/general/issue40662.dart
index 611fc81..fba166b 100644
--- a/pkg/front_end/testcases/general/issue40662.dart
+++ b/pkg/front_end/testcases/general/issue40662.dart
@@ -3,7 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 //
 // Regression test for https://github.com/dart-lang/sdk/issues/40662.
+
 // @dart=2.9
+
 bar(int a, List<int> b) {
   expect(-1, a);
   expect(-1, (b[0] - 2));
diff --git a/pkg/front_end/testcases/general/issue40662.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue40662.dart.weak.transformed.expect
index b5dfa01..90be483 100644
--- a/pkg/front_end/testcases/general/issue40662.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue40662.dart.weak.transformed.expect
@@ -17,10 +17,10 @@
   core::int* :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
-  dynamic :async_temporary_0;
-  dynamic :async_temporary_1;
+  core::int* :async_temporary_0;
+  core::int* :async_temporary_1;
   core::List<core::int*>* :async_temporary_2;
-  dynamic :async_temporary_3;
+  core::int* :async_temporary_3;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
@@ -35,7 +35,7 @@
         else {
           :async_temporary_2 = null;
         }
-        :return_value = self::bar(_in::unsafeCast<core::int*>(:async_temporary_3), :async_temporary_2);
+        :return_value = self::bar(_in::unsafeCast<core::int*>(:async_temporary_3), _in::unsafeCast<core::List<core::int*>*>(:async_temporary_2));
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -86,6 +86,6 @@
 
 
 Extra constant evaluation status:
-Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue40662.dart:8:10 -> IntConstant(-1)
-Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue40662.dart:9:10 -> IntConstant(-1)
-Extra constant evaluation: evaluated: 93, effectively constant: 2
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue40662.dart:10:10 -> IntConstant(-1)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue40662.dart:11:10 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 94, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/issue44007.dart b/pkg/front_end/testcases/general/issue44007.dart
new file mode 100644
index 0000000..9e5ebd9
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart
@@ -0,0 +1,19 @@
+// 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.
+
+void test() {
+  var list = [
+    DateTime.now().add(Duration(days: 3)),
+    DateTime.now().add(Duration(days: 2)),
+    DateTime.now(),
+    DateTime.now().subtract(Duration(days: 1))
+  ];
+
+  list.sort((a, b) => a.compareTo(b));
+  print(list);
+
+  print(DateTime.parse(2019-01-17 00:00:00.000));
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/issue44007.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue44007.dart.textual_outline.expect
new file mode 100644
index 0000000..31c91a2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+void test() {}
+main() {}
diff --git a/pkg/front_end/testcases/general/issue44007.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue44007.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4742c78
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+main() {}
+void test() {}
diff --git a/pkg/front_end/testcases/general/issue44007.dart.weak.expect b/pkg/front_end/testcases/general/issue44007.dart.weak.expect
new file mode 100644
index 0000000..efd3a92
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart.weak.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:35: Error: Expected ',' before this.
+//   print(DateTime.parse(2019-01-17 00:00:00.000));
+//                                   ^^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:35: Error: Expected an identifier, but got '00'.
+// Try inserting an identifier before '00'.
+//   print(DateTime.parse(2019-01-17 00:00:00.000));
+//                                   ^^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:40: Error: Expected ')' before this.
+//   print(DateTime.parse(2019-01-17 00:00:00.000));
+//                                        ^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:18: Error: Expected an identifier, but got 'parse'.
+// Try inserting an identifier before 'parse'.
+//   print(DateTime.parse(2019-01-17 00:00:00.000));
+//                  ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test() → void {
+  core::List<core::DateTime> list = <core::DateTime>[new core::DateTime::now().{core::DateTime::add}(new core::Duration::•(days: 3)){(core::Duration) → core::DateTime}, new core::DateTime::now().{core::DateTime::add}(new core::Duration::•(days: 2)){(core::Duration) → core::DateTime}, new core::DateTime::now(), new core::DateTime::now().{core::DateTime::subtract}(new core::Duration::•(days: 1)){(core::Duration) → core::DateTime}];
+  list.{core::List::sort}((core::DateTime a, core::DateTime b) → core::int => a.{core::DateTime::compareTo}(b){(core::DateTime) → core::int}){([(core::DateTime, core::DateTime) →? core::int]) → void};
+  core::print(list);
+  core::print(invalid-expression "pkg/front_end/testcases/general/issue44007.dart:16:18: Error: Expected an identifier, but got 'parse'.
+Try inserting an identifier before 'parse'.
+  print(DateTime.parse(2019-01-17 00:00:00.000));
+                 ^^^^^");
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44007.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue44007.dart.weak.outline.expect
new file mode 100644
index 0000000..d7d3d2f
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart.weak.outline.expect
@@ -0,0 +1,7 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue44007.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue44007.dart.weak.transformed.expect
new file mode 100644
index 0000000..244d264
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart.weak.transformed.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:35: Error: Expected ',' before this.
+//   print(DateTime.parse(2019-01-17 00:00:00.000));
+//                                   ^^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:35: Error: Expected an identifier, but got '00'.
+// Try inserting an identifier before '00'.
+//   print(DateTime.parse(2019-01-17 00:00:00.000));
+//                                   ^^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:40: Error: Expected ')' before this.
+//   print(DateTime.parse(2019-01-17 00:00:00.000));
+//                                        ^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:18: Error: Expected an identifier, but got 'parse'.
+// Try inserting an identifier before 'parse'.
+//   print(DateTime.parse(2019-01-17 00:00:00.000));
+//                  ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test() → void {
+  core::List<core::DateTime> list = core::_GrowableList::_literal4<core::DateTime>(new core::DateTime::now().{core::DateTime::add}(new core::Duration::•(days: 3)){(core::Duration) → core::DateTime}, new core::DateTime::now().{core::DateTime::add}(new core::Duration::•(days: 2)){(core::Duration) → core::DateTime}, new core::DateTime::now(), new core::DateTime::now().{core::DateTime::subtract}(new core::Duration::•(days: 1)){(core::Duration) → core::DateTime});
+  list.{core::List::sort}((core::DateTime a, core::DateTime b) → core::int => a.{core::DateTime::compareTo}(b){(core::DateTime) → core::int}){([(core::DateTime, core::DateTime) →? core::int]) → void};
+  core::print(list);
+  core::print(invalid-expression "pkg/front_end/testcases/general/issue44007.dart:16:18: Error: Expected an identifier, but got 'parse'.
+Try inserting an identifier before 'parse'.
+  print(DateTime.parse(2019-01-17 00:00:00.000));
+                 ^^^^^");
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44347.dart b/pkg/front_end/testcases/general/issue44347.dart
index 2d9a01e..074b4e5 100644
--- a/pkg/front_end/testcases/general/issue44347.dart
+++ b/pkg/front_end/testcases/general/issue44347.dart
@@ -1,7 +1,9 @@
 // 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.
+
 // @dart=2.9
+
 test() {
   Set<int>.();
 }
diff --git a/pkg/front_end/testcases/general/issue44347.dart.weak.expect b/pkg/front_end/testcases/general/issue44347.dart.weak.expect
index 23f91b5..fc179e1 100644
--- a/pkg/front_end/testcases/general/issue44347.dart.weak.expect
+++ b/pkg/front_end/testcases/general/issue44347.dart.weak.expect
@@ -2,17 +2,17 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/issue44347.dart:6:6: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
+// pkg/front_end/testcases/general/issue44347.dart:8:6: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
 // Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
 //   Set<int>.();
 //      ^
 //
-// pkg/front_end/testcases/general/issue44347.dart:6:13: Error: Expected an identifier, but got ')'.
+// pkg/front_end/testcases/general/issue44347.dart:8:13: Error: Expected an identifier, but got ')'.
 // Try inserting an identifier before ')'.
 //   Set<int>.();
 //             ^
 //
-// pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
+// pkg/front_end/testcases/general/issue44347.dart:8:12: Error: Expected an identifier, but got '('.
 // Try inserting an identifier before '('.
 //   Set<int>.();
 //            ^
@@ -20,7 +20,7 @@
 import self as self;
 
 static method test() → dynamic {
-  invalid-expression "pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
+  invalid-expression "pkg/front_end/testcases/general/issue44347.dart:8:12: Error: Expected an identifier, but got '('.
 Try inserting an identifier before '('.
   Set<int>.();
            ^";
diff --git a/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect
index 23f91b5..fc179e1 100644
--- a/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect
@@ -2,17 +2,17 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/issue44347.dart:6:6: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
+// pkg/front_end/testcases/general/issue44347.dart:8:6: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
 // Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
 //   Set<int>.();
 //      ^
 //
-// pkg/front_end/testcases/general/issue44347.dart:6:13: Error: Expected an identifier, but got ')'.
+// pkg/front_end/testcases/general/issue44347.dart:8:13: Error: Expected an identifier, but got ')'.
 // Try inserting an identifier before ')'.
 //   Set<int>.();
 //             ^
 //
-// pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
+// pkg/front_end/testcases/general/issue44347.dart:8:12: Error: Expected an identifier, but got '('.
 // Try inserting an identifier before '('.
 //   Set<int>.();
 //            ^
@@ -20,7 +20,7 @@
 import self as self;
 
 static method test() → dynamic {
-  invalid-expression "pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
+  invalid-expression "pkg/front_end/testcases/general/issue44347.dart:8:12: Error: Expected an identifier, but got '('.
 Try inserting an identifier before '('.
   Set<int>.();
            ^";
diff --git a/pkg/front_end/testcases/general/issue44733.dart b/pkg/front_end/testcases/general/issue44733.dart
new file mode 100644
index 0000000..92227d1
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44733.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.
+
+abstract class B extends A with C {}
+
+mixin C on D {}
+
+B get x => super.x;
+void f() {
+  switch (x.y.z) {
+  }
+}
+
+abstract class E {}
+
+abstract class D {
+  E get y {}
+}
+
+abstract class A {
+  F get y => super.y as F;
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/issue44733.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue44733.dart.textual_outline.expect
new file mode 100644
index 0000000..7fafd11
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44733.dart.textual_outline.expect
@@ -0,0 +1,17 @@
+abstract class B extends A with C {}
+
+mixin C on D {}
+B get x => super.x;
+void f() {}
+
+abstract class E {}
+
+abstract class D {
+  E get y {}
+}
+
+abstract class A {
+  F get y => super.y as F;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue44733.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue44733.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ba7e44d
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44733.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+B get x => super.x;
+
+abstract class A {
+  F get y => super.y as F;
+}
+
+abstract class B extends A with C {}
+
+abstract class D {
+  E get y {}
+}
+
+abstract class E {}
+
+main() {}
+mixin C on D {}
+void f() {}
diff --git a/pkg/front_end/testcases/general/issue44733.dart.weak.expect b/pkg/front_end/testcases/general/issue44733.dart.weak.expect
new file mode 100644
index 0000000..186db3f
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44733.dart.weak.expect
@@ -0,0 +1,79 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44733.dart:22:3: Error: Type 'F' not found.
+//   F get y => super.y as F;
+//   ^
+//
+// pkg/front_end/testcases/general/issue44733.dart:5:16: Error: 'A' doesn't implement 'D' so it can't be used with 'C'.
+//  - 'A' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+//  - 'D' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+// abstract class B extends A with C {}
+//                ^
+//
+// pkg/front_end/testcases/general/issue44733.dart:9:12: Error: Expected identifier, but got 'super'.
+// B get x => super.x;
+//            ^^^^^
+//
+// pkg/front_end/testcases/general/issue44733.dart:18:9: Error: A non-null value must be returned since the return type 'E' doesn't allow null.
+//  - 'E' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+//   E get y {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44733.dart:22:25: Error: 'F' isn't a type.
+//   F get y => super.y as F;
+//                         ^
+//
+// pkg/front_end/testcases/general/issue44733.dart:22:20: Error: Superclass has no getter named 'y'.
+//   F get y => super.y as F;
+//                    ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class _B&A&C = self::A with self::C /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_B&A&C
+    : super self::A::•()
+    ;
+}
+abstract class B extends self::_B&A&C {
+  synthetic constructor •() → self::B
+    : super self::_B&A&C::•()
+    ;
+}
+abstract class C extends self::D /*isMixinDeclaration*/  {
+}
+abstract class E extends core::Object {
+  synthetic constructor •() → self::E
+    : super core::Object::•()
+    ;
+}
+abstract class D extends core::Object {
+  synthetic constructor •() → self::D
+    : super core::Object::•()
+    ;
+  get y() → self::E {
+    return let final Never #t1 = invalid-expression "pkg/front_end/testcases/general/issue44733.dart:18:9: Error: A non-null value must be returned since the return type 'E' doesn't allow null.
+ - 'E' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+  E get y {}
+        ^" in null;
+  }
+}
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  get y() → invalid-type
+    return super.y as{ForNonNullableByDefault} invalid-type;
+}
+static get x() → self::B
+  return invalid-expression "pkg/front_end/testcases/general/issue44733.dart:9:12: Error: Expected identifier, but got 'super'.
+B get x => super.x;
+           ^^^^^"{dynamic}.x as{TypeError,ForDynamic,ForNonNullableByDefault} self::B;
+static method f() → void {
+  switch(self::x.{self::A::y}{invalid-type}{<invalid>}.z) {
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44733.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue44733.dart.weak.outline.expect
new file mode 100644
index 0000000..b1f8519
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44733.dart.weak.outline.expect
@@ -0,0 +1,51 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44733.dart:22:3: Error: Type 'F' not found.
+//   F get y => super.y as F;
+//   ^
+//
+// pkg/front_end/testcases/general/issue44733.dart:5:16: Error: 'A' doesn't implement 'D' so it can't be used with 'C'.
+//  - 'A' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+//  - 'D' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+// abstract class B extends A with C {}
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class _B&A&C = self::A with self::C /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_B&A&C
+    : super self::A::•()
+    ;
+}
+abstract class B extends self::_B&A&C {
+  synthetic constructor •() → self::B
+    ;
+}
+abstract class C extends self::D /*isMixinDeclaration*/  {
+}
+abstract class E extends core::Object {
+  synthetic constructor •() → self::E
+    ;
+}
+abstract class D extends core::Object {
+  synthetic constructor •() → self::D
+    ;
+  get y() → self::E
+    ;
+}
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  get y() → invalid-type
+    ;
+}
+static get x() → self::B
+  ;
+static method f() → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect
index c56c375..68f366e 100644
--- a/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect
@@ -34,7 +34,7 @@
 class Array<T extends core::Object* = dynamic> extends core::Object {
   static final field dynamic _redirecting# = <dynamic>[self2::Array::•];
   @_in::patch
-  external static factory •<T extends core::Object* = dynamic>(core::int* foo) → self2::Array<self2::Array::•::T*>*
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ •<T extends core::Object* = dynamic>(core::int* foo) → self2::Array<self2::Array::•::T*>*
     let dynamic #redirecting_factory = self2::_ArraySize::• in let self2::Array::•::T* #typeArg0 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
@@ -52,5 +52,5 @@
 Extra constant evaluation status:
 Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:10:1 -> InstanceConstant(const _Patch{})
 Evaluated: ConstructorInvocation @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const pragma{pragma.name: "vm:entry-point", pragma.options: null})
-Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:14:17 -> InstanceConstant(const _Patch{})
 Extra constant evaluation: evaluated: 9, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/issue46745.dart b/pkg/front_end/testcases/general/issue46745.dart
new file mode 100644
index 0000000..8eb5b1b
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.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.
+
+class A {
+  A._();
+  factory A.foo() => A._();
+  A.foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue46745.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue46745.dart.textual_outline.expect
new file mode 100644
index 0000000..59dd347
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart.textual_outline.expect
@@ -0,0 +1,7 @@
+class A {
+  A._();
+  factory A.foo() => A._();
+  A.foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue46745.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue46745.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..77788ac
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+class A {
+  A._();
+  A.foo();
+  factory A.foo() => A._();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue46745.dart.weak.expect b/pkg/front_end/testcases/general/issue46745.dart.weak.expect
new file mode 100644
index 0000000..a375575
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart.weak.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue46745.dart:8:3: Error: 'A.foo' is already declared in this scope.
+//   A.foo();
+//   ^^^^^
+// pkg/front_end/testcases/general/issue46745.dart:7:11: Context: Previous declaration of 'A.foo'.
+//   factory A.foo() => A._();
+//           ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor _() → self::A
+    : super core::Object::•()
+    ;
+  static factory foo() → self::A
+    return new self::A::_();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue46745.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue46745.dart.weak.outline.expect
new file mode 100644
index 0000000..eb5a0eb
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart.weak.outline.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue46745.dart:8:3: Error: 'A.foo' is already declared in this scope.
+//   A.foo();
+//   ^^^^^
+// pkg/front_end/testcases/general/issue46745.dart:7:11: Context: Previous declaration of 'A.foo'.
+//   factory A.foo() => A._();
+//           ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor _() → self::A
+    ;
+  static factory foo() → self::A
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue46745.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue46745.dart.weak.transformed.expect
new file mode 100644
index 0000000..a375575
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart.weak.transformed.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue46745.dart:8:3: Error: 'A.foo' is already declared in this scope.
+//   A.foo();
+//   ^^^^^
+// pkg/front_end/testcases/general/issue46745.dart:7:11: Context: Previous declaration of 'A.foo'.
+//   factory A.foo() => A._();
+//           ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  constructor _() → self::A
+    : super core::Object::•()
+    ;
+  static factory foo() → self::A
+    return new self::A::_();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart
new file mode 100644
index 0000000..9a68b87
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.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 A {
+  final int field;
+
+  A([this.field = 42]);
+
+  factory A.redirect([int field = 87]) = A;
+}
+
+main() {
+  expect(42, new A().field);
+  expect(123, new A(123).field);
+  expect(42, new A.redirect().field);
+  expect(123, new A.redirect(123).field);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline.expect b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline.expect
new file mode 100644
index 0000000..6351dd7
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+class A {
+  final int field;
+  A([this.field = 42]);
+  factory A.redirect([int field = 87]) = A;
+}
+
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..23adf6f
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+class A {
+  A([this.field = 42]);
+  factory A.redirect([int field = 87]) = A;
+  final int field;
+}
+
+expect(expected, actual) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.expect b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.expect
new file mode 100644
index 0000000..1e7a7cc4
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/redirecting_factory_default_value.dart:10:35: Error: Can't have a default value here because any default values of 'A' would be used instead.
+// Try removing the default value.
+//   factory A.redirect([int field = 87]) = A;
+//                                   ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •([core::int field = #C1]) → self::A
+    : self::A::field = field, super core::Object::•()
+    ;
+  static factory redirect([core::int field]) → self::A
+    let dynamic #redirecting_factory = self::A::• in invalid-expression;
+}
+static method main() → dynamic {
+  self::expect(42, new self::A::•().{self::A::field}{core::int});
+  self::expect(123, new self::A::•(123).{self::A::field}{core::int});
+  self::expect(42, new self::A::•().{self::A::field}{core::int});
+  self::expect(123, new self::A::•(123).{self::A::field}{core::int});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.outline.expect
new file mode 100644
index 0000000..352e5d1
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.outline.expect
@@ -0,0 +1,16 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •([core::int field]) → self::A
+    ;
+  static factory redirect([core::int field]) → self::A
+    let dynamic #redirecting_factory = self::A::• in invalid-expression;
+}
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.transformed.expect
new file mode 100644
index 0000000..6b1dd68
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.transformed.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/redirecting_factory_default_value.dart:10:35: Error: Can't have a default value here because any default values of 'A' would be used instead.
+// Try removing the default value.
+//   factory A.redirect([int field = 87]) = A;
+//                                   ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  final field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •([core::int field = #C1]) → self::A
+    : self::A::field = field, super core::Object::•()
+    ;
+  static factory redirect([core::int field]) → self::A
+    let Never #redirecting_factory = self::A::• in invalid-expression;
+}
+static method main() → dynamic {
+  self::expect(42, new self::A::•().{self::A::field}{core::int});
+  self::expect(123, new self::A::•(123).{self::A::field}{core::int});
+  self::expect(42, new self::A::•().{self::A::field}{core::int});
+  self::expect(123, new self::A::•(123).{self::A::field}{core::int});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart
new file mode 100644
index 0000000..d12b28b
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart
@@ -0,0 +1,63 @@
+// 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.md file.
+
+class Class1 {
+  int field = 0;
+
+  factory Class1() = Class1._;
+
+  Class1._();
+
+  int get getter => 0;
+}
+
+class Class2 extends Class1 {
+  final Class2 _c2;
+
+  Class2(this._c2) : super._() {
+    // Invocation inside an invalid unary expression.
+    -new Class1();
+    // Invocation inside an invalid binary expression.
+    ('' + '') - new Class1();
+    // Invocation inside an invalid index set.
+    (0 + 1)[0] = new Class1();
+    _c2[0] = new Class1();
+    // Invocation inside an invalid index get.
+    (0 + 1)[new Class1()];
+    // Invocation inside an invalid property get.
+    new Class1().foo;
+    // Invocation inside an invalid property set.
+    (0 + 1).foo = new Class1();
+    // Invocation inside an invalid invocation.
+    new Class1().foo();
+    // Invocation inside an invalid implicit call invocation.
+    new Class1()();
+    // Invocation inside an invalid implicit field invocation.
+    new Class1().field();
+    // Invocation inside an invalid implicit getter invocation.
+    new Class1().getter();
+    // Invocation inside an invalid implicit call-getter invocation.
+    _c2(new Class1());
+    // Duplicate named arguments
+    method(a: 0, a: new Class1());
+    // Triple named arguments
+    method(a: 0, a: 1, a: new Class1());
+    // Invocation inside an invalid super index get.
+    super[new Class1()];
+    // Invocation inside an invalid super index set.
+    super[0] = new Class1();
+    // Invocation inside an invalid super set.
+    super.foo = new Class1();
+    // Invocation inside an invalid super invocation.
+    super.foo(new Class1());
+    // Invocation inside an invalid super binary.
+    super + new Class1();
+  }
+
+  method({a}) {}
+
+  int get call => 0;
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline.expect b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline.expect
new file mode 100644
index 0000000..607b231
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline.expect
@@ -0,0 +1,15 @@
+class Class1 {
+  int field = 0;
+  factory Class1() = Class1._;
+  Class1._();
+  int get getter => 0;
+}
+
+class Class2 extends Class1 {
+  final Class2 _c2;
+  Class2(this._c2) : super._() {}
+  method({a}) {}
+  int get call => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ca3ab16
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class Class1 {
+  Class1._();
+  factory Class1() = Class1._;
+  int field = 0;
+  int get getter => 0;
+}
+
+class Class2 extends Class1 {
+  Class2(this._c2) : super._() {}
+  final Class2 _c2;
+  int get call => 0;
+  method({a}) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.expect b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.expect
new file mode 100644
index 0000000..232d5ac
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.expect
@@ -0,0 +1,187 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:47:10: Error: Superclass has no method named '[]'.
+//     super[new Class1()];
+//          ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:49:10: Error: Superclass has no method named '[]='.
+//     super[0] = new Class1();
+//          ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:51:11: Error: Superclass has no setter named 'foo'.
+//     super.foo = new Class1();
+//           ^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:53:11: Error: Superclass has no method named 'foo'.
+//     super.foo(new Class1());
+//           ^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:55:11: Error: Superclass has no method named '+'.
+//     super + new Class1();
+//           ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:20:5: Error: The operator 'unary-' isn't defined for the class 'Class1'.
+//  - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+// Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+//     -new Class1();
+//     ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:22:15: Error: The operator '-' isn't defined for the class 'String'.
+// Try correcting the operator to an existing operator, or defining a '-' operator.
+//     ('' + '') - new Class1();
+//               ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:24:12: Error: The operator '[]=' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '[]=' operator.
+//     (0 + 1)[0] = new Class1();
+//            ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:25:8: Error: The operator '[]=' isn't defined for the class 'Class2'.
+//  - 'Class2' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+// Try correcting the operator to an existing operator, or defining a '[]=' operator.
+//     _c2[0] = new Class1();
+//        ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:27:12: Error: The operator '[]' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '[]' operator.
+//     (0 + 1)[new Class1()];
+//            ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:29:18: Error: The getter 'foo' isn't defined for the class 'Class1'.
+//  - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+//     new Class1().foo;
+//                  ^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:31:13: Error: The setter 'foo' isn't defined for the class 'int'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
+//     (0 + 1).foo = new Class1();
+//             ^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:33:18: Error: The method 'foo' isn't defined for the class 'Class1'.
+//  - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'foo'.
+//     new Class1().foo();
+//                  ^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:35:17: Error: The method 'call' isn't defined for the class 'Class1'.
+//  - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'call'.
+//     new Class1()();
+//                 ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:37:23: Error: 'field' isn't a function or method and can't be invoked.
+//     new Class1().field();
+//                       ^^^^...
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:39:24: Error: 'getter' isn't a function or method and can't be invoked.
+//     new Class1().getter();
+//                        ^^^^...
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:41:8: Error: 'call' isn't a function or method and can't be invoked.
+//     _c2(new Class1());
+//        ^^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:43:18: Error: Duplicated named argument 'a'.
+//     method(a: 0, a: new Class1());
+//                  ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:45:18: Error: Duplicated named argument 'a'.
+//     method(a: 0, a: 1, a: new Class1());
+//                  ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:45:24: Error: Duplicated named argument 'a'.
+//     method(a: 0, a: 1, a: new Class1());
+//                        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int field = 0;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    : super core::Object::•()
+    ;
+  static factory •() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+  get getter() → core::int
+    return 0;
+}
+class Class2 extends self::Class1 {
+  final field self::Class2 _c2;
+  constructor •(self::Class2 _c2) → self::Class2
+    : self::Class2::_c2 = _c2, super self::Class1::_() {
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:20:5: Error: The operator 'unary-' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+    -new Class1();
+    ^";
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:22:15: Error: The operator '-' isn't defined for the class 'String'.
+Try correcting the operator to an existing operator, or defining a '-' operator.
+    ('' + '') - new Class1();
+              ^";
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:24:12: Error: The operator '[]=' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '[]=' operator.
+    (0 + 1)[0] = new Class1();
+           ^";
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:25:8: Error: The operator '[]=' isn't defined for the class 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+Try correcting the operator to an existing operator, or defining a '[]=' operator.
+    _c2[0] = new Class1();
+       ^";
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:27:12: Error: The operator '[]' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '[]' operator.
+    (0 + 1)[new Class1()];
+           ^";
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:29:18: Error: The getter 'foo' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+    new Class1().foo;
+                 ^^^";
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:31:13: Error: The setter 'foo' isn't defined for the class 'int'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
+    (0 + 1).foo = new Class1();
+            ^^^";
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:33:18: Error: The method 'foo' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'foo'.
+    new Class1().foo();
+                 ^^^";
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:35:17: Error: The method 'call' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+    new Class1()();
+                ^";
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:37:23: Error: 'field' isn't a function or method and can't be invoked.
+    new Class1().field();
+                      ^^^^...";
+    invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:39:24: Error: 'getter' isn't a function or method and can't be invoked.
+    new Class1().getter();
+                       ^^^^...";
+    let final self::Class2 #t1 = this.{self::Class2::_c2}{self::Class2} in let final self::Class1 #t2 = new self::Class1::_() in invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:41:8: Error: 'call' isn't a function or method and can't be invoked.
+    _c2(new Class1());
+       ^^^^";
+    this.{self::Class2::method}(a: invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:43:18: Error: Duplicated named argument 'a'.
+    method(a: 0, a: new Class1());
+                 ^"){({a: dynamic}) → dynamic};
+    this.{self::Class2::method}(a: invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:45:24: Error: Duplicated named argument 'a'.
+    method(a: 0, a: 1, a: new Class1());
+                       ^"){({a: dynamic}) → dynamic};
+    super.[](new self::Class1::_());
+    super.[]=(0, new self::Class1::_());
+    super.foo = new self::Class1::_();
+    super.foo(new self::Class1::_());
+    super.+(new self::Class1::_());
+  }
+  method method({dynamic a = #C1}) → dynamic {}
+  get call() → core::int
+    return 0;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.outline.expect
new file mode 100644
index 0000000..83aea2e
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.outline.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int field;
+  static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+  constructor _() → self::Class1
+    ;
+  static factory •() → self::Class1
+    let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+  get getter() → core::int
+    ;
+}
+class Class2 extends self::Class1 {
+  final field self::Class2 _c2;
+  constructor •(self::Class2 _c2) → self::Class2
+    ;
+  method method({dynamic a}) → dynamic
+    ;
+  get call() → core::int
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart
index da569e7..d25c571 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart
+++ b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart
@@ -1,7 +1,9 @@
 // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 // @dart=2.9
+
 // This test checks that annotations on redirecting factories and their formals
 // aren't skipped by the compiler and are observable in its output.
 
diff --git a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.weak.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.weak.outline.expect
index 31008cf..a83d25d 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.weak.outline.expect
@@ -28,5 +28,5 @@
 
 
 Extra constant evaluation status:
-Evaluated: StaticGet @ org-dartlang-testcase:///redirecting_factory_metadata.dart:13:4 -> IntConstant(2)
+Evaluated: StaticGet @ org-dartlang-testcase:///redirecting_factory_metadata.dart:15:4 -> IntConstant(2)
 Extra constant evaluation: evaluated: 5, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart
index 7b4cd53..7d7ffec 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart
@@ -1,7 +1,9 @@
 // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE.md file.
+
 // @dart=2.9
+
 // The test checks that type arguments of the target of redirection factory
 // constructors are preserved throughout the chain of redirections.
 
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
index 23aa402..3d879b8 100644
--- a/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
@@ -91,7 +91,7 @@
   core::int* :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
-  dynamic :async_temporary_0;
+  self::B* :async_temporary_0;
   dynamic :async_temporary_1;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
diff --git a/pkg/front_end/testcases/general/type_of_null.dart.weak.expect b/pkg/front_end/testcases/general/type_of_null.dart.weak.expect
index 5387e91..4f0b860 100644
--- a/pkg/front_end/testcases/general/type_of_null.dart.weak.expect
+++ b/pkg/front_end/testcases/general/type_of_null.dart.weak.expect
@@ -23,5 +23,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/general/type_of_null.dart.weak.transformed.expect b/pkg/front_end/testcases/general/type_of_null.dart.weak.transformed.expect
index 5387e91..4f0b860 100644
--- a/pkg/front_end/testcases/general/type_of_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/type_of_null.dart.weak.transformed.expect
@@ -23,5 +23,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/general/typedef.dart.weak.expect b/pkg/front_end/testcases/general/typedef.dart.weak.expect
index 979f6c8..77eee56 100644
--- a/pkg/front_end/testcases/general/typedef.dart.weak.expect
+++ b/pkg/front_end/testcases/general/typedef.dart.weak.expect
@@ -12,5 +12,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::main
+  #C1 = static-tearoff self::main
 }
diff --git a/pkg/front_end/testcases/general/typedef.dart.weak.transformed.expect b/pkg/front_end/testcases/general/typedef.dart.weak.transformed.expect
index c1747f2..2bbbce2 100644
--- a/pkg/front_end/testcases/general/typedef.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/typedef.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::main
+  #C1 = static-tearoff self::main
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect
index 1b6e2a9..86bb196 100644
--- a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect
@@ -21,5 +21,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
index 56b3959..4a42619 100644
--- a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
@@ -21,5 +21,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect
index 1b6e2a9..86bb196 100644
--- a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect
@@ -21,5 +21,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
index 56b3959..4a42619 100644
--- a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
@@ -21,5 +21,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.expect b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.expect
index b258f3f..90a2cad 100644
--- a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.expect
+++ b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.expect
@@ -176,12 +176,12 @@
 }
 
 constants  {
-  #C1 = tearoff self::method1
-  #C2 = tearoff self::method2
-  #C3 = tearoff self::method3
-  #C4 = tearoff self::method4
-  #C5 = tearoff self::method5
-  #C6 = tearoff self::method6
-  #C7 = tearoff self::method7
+  #C1 = static-tearoff self::method1
+  #C2 = static-tearoff self::method2
+  #C3 = static-tearoff self::method3
+  #C4 = static-tearoff self::method4
+  #C5 = static-tearoff self::method5
+  #C6 = static-tearoff self::method6
+  #C7 = static-tearoff self::method7
   #C8 = 0
 }
diff --git a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.transformed.expect b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.transformed.expect
index 384940b..19a91a7 100644
--- a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.transformed.expect
@@ -176,13 +176,13 @@
 }
 
 constants  {
-  #C1 = tearoff self::method1
-  #C2 = tearoff self::method2
-  #C3 = tearoff self::method3
-  #C4 = tearoff self::method4
-  #C5 = tearoff self::method5
-  #C6 = tearoff self::method6
-  #C7 = tearoff self::method7
+  #C1 = static-tearoff self::method1
+  #C2 = static-tearoff self::method2
+  #C3 = static-tearoff self::method3
+  #C4 = static-tearoff self::method4
+  #C5 = static-tearoff self::method5
+  #C6 = static-tearoff self::method6
+  #C7 = static-tearoff self::method7
   #C8 = 0
 }
 
diff --git a/pkg/front_end/testcases/incremental.status b/pkg/front_end/testcases/incremental.status
index 7edb02b..afed71c 100644
--- a/pkg/front_end/testcases/incremental.status
+++ b/pkg/front_end/testcases/incremental.status
@@ -6,5 +6,3 @@
 
 # http://dartbug.com/41812#issuecomment-684825703
 strongmode_mixins_2: Crash
-
-crash_07: Crash
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental/issue_46666.yaml b/pkg/front_end/testcases/incremental/issue_46666.yaml
new file mode 100644
index 0000000..0ac3970
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/issue_46666.yaml
@@ -0,0 +1,54 @@
+# 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.md file.
+
+# Reproduces https://dartbug.com/46666.
+
+type: newworld
+worlds:
+  - entry: b.dart
+    experiments: non-nullable
+    sources:
+      a.dart: |
+        import 'dart:ffi';
+
+        class StructA extends Struct {
+          external Pointer<Void> a1;
+          external Pointer<Void> a2;
+          external Pointer<Void> a3;
+          external NestedStruct blah;
+        }
+
+        class NestedStruct extends Struct {
+          external Pointer<Void> n1;
+          external Pointer<Void> n2;
+          external Pointer<Void> n3;
+        }
+      b.dart: |
+        import 'dart:ffi';
+        import 'dart:isolate';
+        import 'dart:async';
+
+        import 'a.dart';
+
+        class StructB extends Struct {
+          external StructA b1;
+        }
+
+        void periodic() {
+          print(sizeOf<StructB>());
+        }
+
+        void main() {
+          Timer.periodic(const Duration(seconds: 1), (_) => periodic());
+        }
+    expectedLibraryCount: 2
+
+  - entry: b.dart
+    experiments: non-nullable
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - b.dart
+    expectedLibraryCount: 2
+    expectsRebuildBodiesOnly: false
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
new file mode 100644
index 0000000..516a77e
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/issue_46666.yaml.world.1.expect
@@ -0,0 +1,126 @@
+main = b::main;
+library from "org-dartlang-test:///a.dart" as a {
+
+  import "dart:ffi";
+
+  @#C7
+  class StructA extends dart.ffi::Struct {
+    synthetic constructor •() → a::StructA
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → a::StructA
+      : 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*}));
+    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});
+    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*}));
+    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});
+    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*}));
+    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});
+    get blah() → a::NestedStruct
+      return new a::NestedStruct::#fromTypedDataBase( block {
+        dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object};
+        dart.core::int #offset = (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+      } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<a::NestedStruct>(#typedDataBase.{dart.ffi::Pointer::address}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}{dart.typed_data::ByteBuffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}){([dart.core::int, dart.core::int?]) → dart.typed_data::Uint8List});
+    set blah(a::NestedStruct #externalFieldValue) → void
+      return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*});
+    @#C19
+    static get #sizeOf() → dart.core::int*
+      return (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+  }
+  @#C24
+  class NestedStruct extends dart.ffi::Struct {
+    synthetic constructor •() → a::NestedStruct
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → a::NestedStruct
+      : 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*}));
+    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});
+    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*}));
+    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});
+    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*}));
+    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});
+    @#C19
+    static get #sizeOf() → dart.core::int*
+      return (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+  }
+}
+library from "org-dartlang-test:///b.dart" as b {
+
+  import "dart:ffi";
+  import "dart:isolate";
+  import "dart:async";
+  import "org-dartlang-test:///a.dart";
+
+  @#C28
+  class StructB extends dart.ffi::Struct {
+    synthetic constructor •() → b::StructB
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → b::StructB
+      : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+      ;
+    get b1() → a::StructA
+      return new a::StructA::#fromTypedDataBase( block {
+        dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object};
+        dart.core::int #offset = (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+      } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<a::StructA>(#typedDataBase.{dart.ffi::Pointer::address}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}{dart.typed_data::ByteBuffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}, (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}){([dart.core::int, dart.core::int?]) → dart.typed_data::Uint8List});
+    set b1(a::StructA #externalFieldValue) → void
+      return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8, (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*});
+    @#C19
+    static get #sizeOf() → dart.core::int*
+      return (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+  }
+  static method periodic() → void {
+    dart.core::print(b::StructB::#sizeOf);
+  }
+  static method main() → void {
+    dart.async::Timer::periodic(#C30, (dart.async::Timer _) → void => b::periodic());
+  }
+}
+constants  {
+  #C1 = "vm:ffi:struct-fields"
+  #C2 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
+  #C3 = TypeLiteralConstant(a::NestedStruct)
+  #C4 = <dart.core::Type>[#C2, #C2, #C2, #C3]
+  #C5 = null
+  #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]
+  #C10 = 8
+  #C11 = 4
+  #C12 = <dart.core::int*>[#C10, #C11, #C11]
+  #C13 = 16
+  #C14 = <dart.core::int*>[#C13, #C10, #C10]
+  #C15 = 24
+  #C16 = 12
+  #C17 = <dart.core::int*>[#C15, #C16, #C16]
+  #C18 = "vm:prefer-inline"
+  #C19 = dart.core::pragma {name:#C18, options:#C5}
+  #C20 = 48
+  #C21 = <dart.core::int*>[#C20, #C15, #C15]
+  #C22 = <dart.core::Type>[#C2, #C2, #C2]
+  #C23 = dart.ffi::_FfiStructLayout {fieldTypes:#C22, packing:#C5}
+  #C24 = dart.core::pragma {name:#C1, options:#C23}
+  #C25 = TypeLiteralConstant(a::StructA)
+  #C26 = <dart.core::Type>[#C25]
+  #C27 = dart.ffi::_FfiStructLayout {fieldTypes:#C26, packing:#C5}
+  #C28 = dart.core::pragma {name:#C1, options:#C27}
+  #C29 = 1000000
+  #C30 = dart.core::Duration {_duration:#C29}
+}
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
new file mode 100644
index 0000000..516a77e
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/issue_46666.yaml.world.2.expect
@@ -0,0 +1,126 @@
+main = b::main;
+library from "org-dartlang-test:///a.dart" as a {
+
+  import "dart:ffi";
+
+  @#C7
+  class StructA extends dart.ffi::Struct {
+    synthetic constructor •() → a::StructA
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → a::StructA
+      : 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*}));
+    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});
+    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*}));
+    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});
+    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*}));
+    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});
+    get blah() → a::NestedStruct
+      return new a::NestedStruct::#fromTypedDataBase( block {
+        dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object};
+        dart.core::int #offset = (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+      } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<a::NestedStruct>(#typedDataBase.{dart.ffi::Pointer::address}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}{dart.typed_data::ByteBuffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}){([dart.core::int, dart.core::int?]) → dart.typed_data::Uint8List});
+    set blah(a::NestedStruct #externalFieldValue) → void
+      return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*});
+    @#C19
+    static get #sizeOf() → dart.core::int*
+      return (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+  }
+  @#C24
+  class NestedStruct extends dart.ffi::Struct {
+    synthetic constructor •() → a::NestedStruct
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → a::NestedStruct
+      : 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*}));
+    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});
+    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*}));
+    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});
+    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*}));
+    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});
+    @#C19
+    static get #sizeOf() → dart.core::int*
+      return (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+  }
+}
+library from "org-dartlang-test:///b.dart" as b {
+
+  import "dart:ffi";
+  import "dart:isolate";
+  import "dart:async";
+  import "org-dartlang-test:///a.dart";
+
+  @#C28
+  class StructB extends dart.ffi::Struct {
+    synthetic constructor •() → b::StructB
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → b::StructB
+      : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+      ;
+    get b1() → a::StructA
+      return new a::StructA::#fromTypedDataBase( block {
+        dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object};
+        dart.core::int #offset = (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+      } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<a::StructA>(#typedDataBase.{dart.ffi::Pointer::address}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}{dart.typed_data::ByteBuffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}, (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}){([dart.core::int, dart.core::int?]) → dart.typed_data::Uint8List});
+    set b1(a::StructA #externalFieldValue) → void
+      return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8, (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*});
+    @#C19
+    static get #sizeOf() → dart.core::int*
+      return (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+  }
+  static method periodic() → void {
+    dart.core::print(b::StructB::#sizeOf);
+  }
+  static method main() → void {
+    dart.async::Timer::periodic(#C30, (dart.async::Timer _) → void => b::periodic());
+  }
+}
+constants  {
+  #C1 = "vm:ffi:struct-fields"
+  #C2 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
+  #C3 = TypeLiteralConstant(a::NestedStruct)
+  #C4 = <dart.core::Type>[#C2, #C2, #C2, #C3]
+  #C5 = null
+  #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]
+  #C10 = 8
+  #C11 = 4
+  #C12 = <dart.core::int*>[#C10, #C11, #C11]
+  #C13 = 16
+  #C14 = <dart.core::int*>[#C13, #C10, #C10]
+  #C15 = 24
+  #C16 = 12
+  #C17 = <dart.core::int*>[#C15, #C16, #C16]
+  #C18 = "vm:prefer-inline"
+  #C19 = dart.core::pragma {name:#C18, options:#C5}
+  #C20 = 48
+  #C21 = <dart.core::int*>[#C20, #C15, #C15]
+  #C22 = <dart.core::Type>[#C2, #C2, #C2]
+  #C23 = dart.ffi::_FfiStructLayout {fieldTypes:#C22, packing:#C5}
+  #C24 = dart.core::pragma {name:#C1, options:#C23}
+  #C25 = TypeLiteralConstant(a::StructA)
+  #C26 = <dart.core::Type>[#C25]
+  #C27 = dart.ffi::_FfiStructLayout {fieldTypes:#C26, packing:#C5}
+  #C28 = dart.core::pragma {name:#C1, options:#C27}
+  #C29 = 1000000
+  #C30 = dart.core::Duration {_duration:#C29}
+}
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.1.expect
index 88cc8e1..1c3c19c 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.1.expect
@@ -17,5 +17,5 @@
     return LoadLibrary(foo);
 }
 constants  {
-  #C1 = tearoff main::_#loadLibrary_foo
+  #C1 = static-tearoff main::_#loadLibrary_foo
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.2.expect
index 8edd69c..e3b1ce9 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.2.expect
@@ -18,5 +18,5 @@
     return LoadLibrary(foo);
 }
 constants  {
-  #C1 = tearoff main::_#loadLibrary_foo
+  #C1 = static-tearoff main::_#loadLibrary_foo
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect
index 22e37ea..d6a452a 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect
@@ -543,6 +543,6 @@
   #C3 = dart.core::pragma {name:#C1, options:#C2}
   #C4 = ""
   #C5 = true
-  #C6 = tearoff dart.collection::ListMixin::_compareAny
+  #C6 = static-tearoff dart.collection::ListMixin::_compareAny
   #C7 = 0
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect
index 22e37ea..d6a452a 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect
@@ -543,6 +543,6 @@
   #C3 = dart.core::pragma {name:#C1, options:#C2}
   #C4 = ""
   #C5 = true
-  #C6 = tearoff dart.collection::ListMixin::_compareAny
+  #C6 = static-tearoff dart.collection::ListMixin::_compareAny
   #C7 = 0
 }
diff --git a/pkg/front_end/testcases/incremental/type_change_on_recompile.yaml.world.1.expect b/pkg/front_end/testcases/incremental/type_change_on_recompile.yaml.world.1.expect
index 5938335..38493c4 100644
--- a/pkg/front_end/testcases/incremental/type_change_on_recompile.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/type_change_on_recompile.yaml.world.1.expect
@@ -43,7 +43,7 @@
       ;
   }
   abstract class _A&B&C&D extends main::_A&B&C implements main::D /*isAnonymousMixin,isEliminatedMixin*/  {
-    synthetic constructor named(dynamic _field) → main::_A&B&C&D*
+    synthetic constructor named(lib::E* _field) → main::_A&B&C&D*
       : super main::_A&B&C::named(_field)
       ;
   }
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.expect
index a91da56..f1a6a23 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.expect
@@ -10,5 +10,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.transformed.expect
index a91da56..f1a6a23 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.transformed.expect
@@ -10,5 +10,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/bug30624.dart.weak.expect b/pkg/front_end/testcases/inference/bug30624.dart.weak.expect
index 679fdf5..d66aab0b 100644
--- a/pkg/front_end/testcases/inference/bug30624.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/bug30624.dart.weak.expect
@@ -44,5 +44,5 @@
 
 constants  {
   #C1 = null
-  #C2 = tearoff self::C::_default
+  #C2 = static-tearoff self::C::_default
 }
diff --git a/pkg/front_end/testcases/inference/bug30624.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/bug30624.dart.weak.transformed.expect
index 9449aa55..02a85fc 100644
--- a/pkg/front_end/testcases/inference/bug30624.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/bug30624.dart.weak.transformed.expect
@@ -44,7 +44,7 @@
 
 constants  {
   #C1 = null
-  #C2 = tearoff self::C::_default
+  #C2 = static-tearoff self::C::_default
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.weak.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.weak.expect
index 706d512..3ed0854 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.weak.expect
@@ -78,5 +78,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::myF
+  #C1 = static-tearoff self::myF
 }
diff --git a/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.expect b/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.expect
index 656a85c..36d60ee 100644
--- a/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.expect
@@ -15,6 +15,6 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::add
-  #C2 = tearoff self::add2
+  #C1 = static-tearoff self::add
+  #C2 = static-tearoff self::add2
 }
diff --git a/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.transformed.expect
index 656a85c..36d60ee 100644
--- a/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.transformed.expect
@@ -15,6 +15,6 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::add
-  #C2 = tearoff self::add2
+  #C1 = static-tearoff self::add
+  #C2 = static-tearoff self::add2
 }
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
index 6efd0ab..2c0fd45 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
             [yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
             :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
           }
-          :return_value = :async_temporary_0;
+          :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
index 29a38cc..ada0903 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
             [yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
             :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
           }
-          :return_value = :async_temporary_0;
+          :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
index 9ac9e7e..057adde 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
             [yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
             :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
           }
-          :return_value = :async_temporary_0;
+          :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
index 768aaeb..fd4b819 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
             [yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
             :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
           }
-          :return_value = :async_temporary_0;
+          :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
index 6fc6957..6e05707 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
             [yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
             :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
           }
-          :return_value = :async_temporary_0;
+          :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
index 4bf5a96..1968cbf 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
             [yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
             :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
           }
-          :return_value = :async_temporary_0;
+          :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
index d6e68fc..077bfa1 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
@@ -57,7 +57,7 @@
           else {
             :async_temporary_0 = #t1;
           }
-          :return_value = :async_temporary_0;
+          :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.expect b/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.expect
index 19380c0..94fc7a3 100644
--- a/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.expect
@@ -10,5 +10,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.transformed.expect
index 19380c0..94fc7a3 100644
--- a/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.transformed.expect
@@ -10,5 +10,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect
index 2c7b116..e8a716a 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect
@@ -176,6 +176,6 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff math::max
-  #C2 = tearoff math::min
+  #C1 = static-tearoff math::max
+  #C2 = static-tearoff math::min
 }
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect
index 9dc6b9b..1ee8bea 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect
@@ -176,8 +176,8 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff math::max
-  #C2 = tearoff math::min
+  #C1 = static-tearoff math::max
+  #C2 = static-tearoff math::min
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.expect b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.expect
index 860faf4..fe91228 100644
--- a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.expect
@@ -34,5 +34,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::make
+  #C1 = static-tearoff self::make
 }
diff --git a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.transformed.expect
index 99dc822..393b79d 100644
--- a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.transformed.expect
@@ -34,5 +34,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::make
+  #C1 = static-tearoff self::make
 }
diff --git a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.expect b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.expect
index 34108a8..3d04d1f 100644
--- a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.expect
@@ -44,5 +44,5 @@
 }
 
 constants  {
-  #C1 = tearoff math::max
+  #C1 = static-tearoff math::max
 }
diff --git a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.transformed.expect
index 8af73b0..b46e8a6 100644
--- a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.transformed.expect
@@ -44,7 +44,7 @@
 }
 
 constants  {
-  #C1 = tearoff math::max
+  #C1 = static-tearoff math::max
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.expect b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.expect
index 5f6e2e6..d6bd505 100644
--- a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.expect
@@ -30,5 +30,5 @@
 
 constants  {
   #C1 = null
-  #C2 = tearoff self::C::_compareAny
+  #C2 = static-tearoff self::C::_compareAny
 }
diff --git a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.transformed.expect
index 5f6e2e6..d6bd505 100644
--- a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.transformed.expect
@@ -30,5 +30,5 @@
 
 constants  {
   #C1 = null
-  #C2 = tearoff self::C::_compareAny
+  #C2 = static-tearoff self::C::_compareAny
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.expect
index b95e93b..6eef7cc 100644
--- a/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.expect
@@ -8,5 +8,5 @@
 }
 
 constants  {
-  #C1 = tearoff core::print
+  #C1 = static-tearoff core::print
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.transformed.expect
index b95e93b..6eef7cc 100644
--- a/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.transformed.expect
@@ -8,5 +8,5 @@
 }
 
 constants  {
-  #C1 = tearoff core::print
+  #C1 = static-tearoff core::print
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.expect
index 5fbc81e..21d3b06 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.expect
@@ -12,6 +12,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::g
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.transformed.expect
index 468a854..2e71da8 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.transformed.expect
@@ -12,6 +12,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::g
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.expect
index 5db9025..9be942f 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.expect
@@ -12,6 +12,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::g
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.transformed.expect
index 302d4f1..126d190 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.transformed.expect
@@ -12,6 +12,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::g
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.expect
index 7d05c01..0b7d047 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.expect
@@ -12,7 +12,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::g
   #C3 = null
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.transformed.expect
index d3dbe88..ee21ab4 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::g
   #C3 = null
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.expect
index 2eb4e4d..704ff597 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.expect
@@ -12,7 +12,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::g
   #C3 = null
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.transformed.expect
index d9781ac..2e47f05 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::g
   #C3 = null
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.expect
index 5a739ef..b495253 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.expect
@@ -12,6 +12,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::g
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.transformed.expect
index a8897a0..805ab2c 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.transformed.expect
@@ -12,6 +12,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::g
 }
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.expect b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.expect
index 41e2e41..5d83e0a 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.expect
@@ -44,6 +44,6 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::C::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::C::g
 }
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.transformed.expect
index 4c5080b..87decf1 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.transformed.expect
@@ -44,8 +44,8 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::f
-  #C2 = tearoff self::C::g
+  #C1 = static-tearoff self::f
+  #C2 = static-tearoff self::C::g
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.expect b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.expect
index af395c5..d6fb1da 100644
--- a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.expect
@@ -34,6 +34,6 @@
 constants  {
   #C1 = 0
   #C2 = <core::int*>[#C1]
-  #C3 = tearoff self::optional_toplevel
-  #C4 = tearoff self::named_toplevel
+  #C3 = static-tearoff self::optional_toplevel
+  #C4 = static-tearoff self::named_toplevel
 }
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.transformed.expect
index af395c5..d6fb1da 100644
--- a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.transformed.expect
@@ -34,6 +34,6 @@
 constants  {
   #C1 = 0
   #C2 = <core::int*>[#C1]
-  #C3 = tearoff self::optional_toplevel
-  #C4 = tearoff self::named_toplevel
+  #C3 = static-tearoff self::optional_toplevel
+  #C4 = static-tearoff self::named_toplevel
 }
diff --git a/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.expect b/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.expect
index 3a80563..b89fa7d 100644
--- a/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.expect
@@ -25,5 +25,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::C::f
+  #C1 = static-tearoff self::C::f
 }
diff --git a/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.transformed.expect
index 3a80563..b89fa7d 100644
--- a/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.transformed.expect
@@ -25,5 +25,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::C::f
+  #C1 = static-tearoff self::C::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.expect
index c90ed22..1307281 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.expect
@@ -18,5 +18,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.transformed.expect
index 2c7a1d7..56348a9 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.transformed.expect
@@ -18,5 +18,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
index ca3de8b..a621378 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
@@ -12,5 +12,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
index 1124860..1da0ab0 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
@@ -12,5 +12,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.expect
index d25a131..f64ec974 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.expect
@@ -18,5 +18,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.transformed.expect
index 6d9032c..a98e49b 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.transformed.expect
@@ -18,5 +18,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
index 169486b..ccba70a 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
@@ -12,5 +12,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
index 633c890..e9a5c4e 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
@@ -12,5 +12,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.expect
index bce5804..fc22443 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.expect
@@ -11,5 +11,5 @@
   return <self::f::T*>[g(){() →* self::f::T*}];
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.transformed.expect
index cb153d8..e7778dd 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.transformed.expect
@@ -11,5 +11,5 @@
   return core::_GrowableList::_literal1<self::f::T*>(g(){() →* self::f::T*});
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.expect
index 742f60c..432c8a0a 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.expect
@@ -11,5 +11,5 @@
   return 1.0;
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.transformed.expect
index 742f60c..432c8a0a 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.transformed.expect
@@ -11,5 +11,5 @@
   return 1.0;
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.expect b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.expect
index f86a055..751e547 100644
--- a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.expect
@@ -25,5 +25,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::printRunning
+  #C1 = static-tearoff self::printRunning
 }
diff --git a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
index f86a055..751e547 100644
--- a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
@@ -25,5 +25,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::printRunning
+  #C1 = static-tearoff self::printRunning
 }
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
index 169486b..ccba70a 100644
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
+++ b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
@@ -12,5 +12,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
index 633c890..e9a5c4e 100644
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
@@ -12,5 +12,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
index 169486b..ccba70a 100644
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
+++ b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
@@ -12,5 +12,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
index 633c890..e9a5c4e 100644
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
@@ -12,5 +12,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.expect b/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.expect
index 7e0013f..96e59b9 100644
--- a/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.expect
+++ b/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.expect
@@ -15,5 +15,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::printRunning
+  #C1 = static-tearoff self::printRunning
 }
diff --git a/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
index 7e0013f..96e59b9 100644
--- a/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
@@ -15,5 +15,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::printRunning
+  #C1 = static-tearoff self::printRunning
 }
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 d5af00b..d80fa11 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
@@ -160,5 +160,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::fisk
+  #C1 = static-tearoff self::fisk
 }
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 95d50a9..d009196 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
@@ -265,7 +265,7 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::fisk
+  #C1 = static-tearoff self::fisk
 }
 
 Extra constant evaluation status:
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 00a9a68..0026c6b 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
@@ -204,5 +204,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::fisk
+  #C1 = static-tearoff self::fisk
 }
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 7c57520..a808b23 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
@@ -309,5 +309,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::fisk
+  #C1 = static-tearoff self::fisk
 }
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect b/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect
index ee9ce9b..1cece20 100644
--- a/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect
@@ -96,11 +96,11 @@
   #C2 = false
   #C3 = null
   #C4 = 1
-  #C5 = tearoff self::f
-  #C6 = tearoff self::g
-  #C7 = tearoff self::f1
-  #C8 = tearoff self::f2
-  #C9 = tearoff self::f3
-  #C10 = tearoff self::f4
-  #C11 = tearoff self::f5
+  #C5 = static-tearoff self::f
+  #C6 = static-tearoff self::g
+  #C7 = static-tearoff self::f1
+  #C8 = static-tearoff self::f2
+  #C9 = static-tearoff self::f3
+  #C10 = static-tearoff self::f4
+  #C11 = static-tearoff self::f5
 }
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect
index 2eda141..55a7036 100644
--- a/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect
@@ -96,13 +96,13 @@
   #C2 = false
   #C3 = null
   #C4 = 1
-  #C5 = tearoff self::f
-  #C6 = tearoff self::g
-  #C7 = tearoff self::f1
-  #C8 = tearoff self::f2
-  #C9 = tearoff self::f3
-  #C10 = tearoff self::f4
-  #C11 = tearoff self::f5
+  #C5 = static-tearoff self::f
+  #C6 = static-tearoff self::g
+  #C7 = static-tearoff self::f1
+  #C8 = static-tearoff self::f2
+  #C9 = static-tearoff self::f3
+  #C10 = static-tearoff self::f4
+  #C11 = static-tearoff self::f5
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect b/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect
index 7da3b8f..dcba0f8 100644
--- a/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect
@@ -96,11 +96,11 @@
   #C2 = false
   #C3 = null
   #C4 = 1
-  #C5 = tearoff self::f
-  #C6 = tearoff self::g
-  #C7 = tearoff self::f1
-  #C8 = tearoff self::f2
-  #C9 = tearoff self::f3
-  #C10 = tearoff self::f4
-  #C11 = tearoff self::f5
+  #C5 = static-tearoff self::f
+  #C6 = static-tearoff self::g
+  #C7 = static-tearoff self::f1
+  #C8 = static-tearoff self::f2
+  #C9 = static-tearoff self::f3
+  #C10 = static-tearoff self::f4
+  #C11 = static-tearoff self::f5
 }
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect
index 67362a6..eda5d9f 100644
--- a/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect
@@ -96,13 +96,13 @@
   #C2 = false
   #C3 = null
   #C4 = 1
-  #C5 = tearoff self::f
-  #C6 = tearoff self::g
-  #C7 = tearoff self::f1
-  #C8 = tearoff self::f2
-  #C9 = tearoff self::f3
-  #C10 = tearoff self::f4
-  #C11 = tearoff self::f5
+  #C5 = static-tearoff self::f
+  #C6 = static-tearoff self::g
+  #C7 = static-tearoff self::f1
+  #C8 = static-tearoff self::f2
+  #C9 = static-tearoff self::f3
+  #C10 = static-tearoff self::f4
+  #C11 = static-tearoff self::f5
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.strong.expect b/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
index d1fd5fe..70ed240 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
@@ -89,8 +89,8 @@
 
 constants  {
   #C1 = TypeLiteralConstant(core::Object)
-  #C2 = tearoff con::id
-  #C3 = partial-instantiation con::id <core::int>
+  #C2 = static-tearoff con::id
+  #C3 = instantiation con::id <core::int>
   #C4 = 0
   #C5 = con::Class<core::int> {field:#C4}
   #C6 = TypeLiteralConstant((dynamic) → dynamic)
@@ -104,7 +104,7 @@
   #C14 = <dynamic>[#C4, #C13]
   #C15 = core::_ImmutableMap<core::int, core::String> {_kvPairs:#C14}
   #C16 = true
-  #C17 = tearoff core::identical
+  #C17 = static-tearoff core::identical
 }
 
 
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
index d1fd5fe..70ed240 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
@@ -89,8 +89,8 @@
 
 constants  {
   #C1 = TypeLiteralConstant(core::Object)
-  #C2 = tearoff con::id
-  #C3 = partial-instantiation con::id <core::int>
+  #C2 = static-tearoff con::id
+  #C3 = instantiation con::id <core::int>
   #C4 = 0
   #C5 = con::Class<core::int> {field:#C4}
   #C6 = TypeLiteralConstant((dynamic) → dynamic)
@@ -104,7 +104,7 @@
   #C14 = <dynamic>[#C4, #C13]
   #C15 = core::_ImmutableMap<core::int, core::String> {_kvPairs:#C14}
   #C16 = true
-  #C17 = tearoff core::identical
+  #C17 = static-tearoff core::identical
 }
 
 
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.weak.expect b/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
index 3adb498..b26ca6d 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
@@ -89,8 +89,8 @@
 
 constants  {
   #C1 = TypeLiteralConstant(core::Object*)
-  #C2 = tearoff con::id
-  #C3 = partial-instantiation con::id <core::int*>
+  #C2 = static-tearoff con::id
+  #C3 = instantiation con::id <core::int*>
   #C4 = 0
   #C5 = con::Class<core::int*> {field:#C4}
   #C6 = TypeLiteralConstant((dynamic) →* dynamic)
@@ -104,7 +104,7 @@
   #C14 = <dynamic>[#C4, #C13]
   #C15 = core::_ImmutableMap<core::int*, core::String*> {_kvPairs:#C14}
   #C16 = true
-  #C17 = tearoff core::identical
+  #C17 = static-tearoff core::identical
 }
 
 
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
index 3adb498..b26ca6d 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
@@ -89,8 +89,8 @@
 
 constants  {
   #C1 = TypeLiteralConstant(core::Object*)
-  #C2 = tearoff con::id
-  #C3 = partial-instantiation con::id <core::int*>
+  #C2 = static-tearoff con::id
+  #C3 = instantiation con::id <core::int*>
   #C4 = 0
   #C5 = con::Class<core::int*> {field:#C4}
   #C6 = TypeLiteralConstant((dynamic) →* dynamic)
@@ -104,7 +104,7 @@
   #C14 = <dynamic>[#C4, #C13]
   #C15 = core::_ImmutableMap<core::int*, core::String*> {_kvPairs:#C14}
   #C16 = true
-  #C17 = tearoff core::identical
+  #C17 = static-tearoff core::identical
 }
 
 
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
index 26e67a7..57a3b98 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
@@ -36,5 +36,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
index 26e67a7..57a3b98 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
@@ -36,5 +36,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect
index 26e67a7..57a3b98 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect
@@ -36,5 +36,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect
index 26e67a7..57a3b98 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect
@@ -36,5 +36,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42433.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42433.dart.strong.expect
index 2d7f2f7..81da4f2 100644
--- a/pkg/front_end/testcases/nnbd/issue42433.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42433.dart.strong.expect
@@ -14,5 +14,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::checkme
+  #C1 = static-tearoff self::checkme
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect
index 62a035b..d4ca87d 100644
--- a/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::checkme
+  #C1 = static-tearoff self::checkme
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd/issue42433.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42433.dart.weak.expect
index 2d7f2f7..81da4f2 100644
--- a/pkg/front_end/testcases/nnbd/issue42433.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42433.dart.weak.expect
@@ -14,5 +14,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::checkme
+  #C1 = static-tearoff self::checkme
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect
index 0fd30a8..005edee 100644
--- a/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect
@@ -14,7 +14,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::checkme
+  #C1 = static-tearoff self::checkme
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect
index 0bba0ad..5f9dc45 100644
--- a/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect
@@ -28,5 +28,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect
index 0bba0ad..5f9dc45 100644
--- a/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect
@@ -28,5 +28,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect
index 0bba0ad..5f9dc45 100644
--- a/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect
@@ -28,5 +28,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect
index 0bba0ad..5f9dc45 100644
--- a/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect
@@ -28,5 +28,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::f
+  #C1 = static-tearoff self::f
 }
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
index 076e56c..d9880ad 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
@@ -134,5 +134,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::fisk
+  #C1 = static-tearoff self::fisk
 }
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
index 90b2c25..2885cb8 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -246,5 +246,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::fisk
+  #C1 = static-tearoff self::fisk
 }
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
index 076e56c..d9880ad 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
@@ -134,5 +134,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::fisk
+  #C1 = static-tearoff self::fisk
 }
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
index 90b2c25..2885cb8 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -246,5 +246,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::fisk
+  #C1 = static-tearoff self::fisk
 }
diff --git a/pkg/front_end/testcases/nnbd/load_library.dart.strong.expect b/pkg/front_end/testcases/nnbd/load_library.dart.strong.expect
index 9513601..885e631 100644
--- a/pkg/front_end/testcases/nnbd/load_library.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/load_library.dart.strong.expect
@@ -15,5 +15,5 @@
   return LoadLibrary(math);
 
 constants  {
-  #C1 = tearoff self::_#loadLibrary_math
+  #C1 = static-tearoff self::_#loadLibrary_math
 }
diff --git a/pkg/front_end/testcases/nnbd/load_library.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/load_library.dart.strong.transformed.expect
index 9513601..885e631 100644
--- a/pkg/front_end/testcases/nnbd/load_library.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/load_library.dart.strong.transformed.expect
@@ -15,5 +15,5 @@
   return LoadLibrary(math);
 
 constants  {
-  #C1 = tearoff self::_#loadLibrary_math
+  #C1 = static-tearoff self::_#loadLibrary_math
 }
diff --git a/pkg/front_end/testcases/nnbd/load_library.dart.weak.expect b/pkg/front_end/testcases/nnbd/load_library.dart.weak.expect
index 9513601..885e631 100644
--- a/pkg/front_end/testcases/nnbd/load_library.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/load_library.dart.weak.expect
@@ -15,5 +15,5 @@
   return LoadLibrary(math);
 
 constants  {
-  #C1 = tearoff self::_#loadLibrary_math
+  #C1 = static-tearoff self::_#loadLibrary_math
 }
diff --git a/pkg/front_end/testcases/nnbd/load_library.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/load_library.dart.weak.transformed.expect
index 9513601..885e631 100644
--- a/pkg/front_end/testcases/nnbd/load_library.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/load_library.dart.weak.transformed.expect
@@ -15,5 +15,5 @@
   return LoadLibrary(math);
 
 constants  {
-  #C1 = tearoff self::_#loadLibrary_math
+  #C1 = static-tearoff self::_#loadLibrary_math
 }
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect
index 5612a60..e4d23f5 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect
@@ -225,8 +225,8 @@
 
 constants  {
   #C1 = 3
-  #C2 = tearoff self::idFunction
-  #C3 = partial-instantiation self::idFunction <core::int>
+  #C2 = static-tearoff self::idFunction
+  #C3 = instantiation self::idFunction <core::int>
   #C4 = 0
   #C5 = self::Class<dynamic> {field:#C4}
   #C6 = self::Class<core::num> {field:#C4}
@@ -244,13 +244,13 @@
   #C18 = self::ClassWithList<core::int> {field:#C16}
   #C19 = <core::String>[#C8]
   #C20 = self::ClassWithList<core::String> {field:#C19}
-  #C21 = tearoff self::dynamicFunction
+  #C21 = static-tearoff self::dynamicFunction
   #C22 = self::ClassWithFunction<dynamic> {field:#C21}
   #C23 = self::ClassWithFunction<core::Object?> {field:#C21}
-  #C24 = tearoff self::objectFunction
+  #C24 = static-tearoff self::objectFunction
   #C25 = self::ClassWithFunction<dynamic> {field:#C24}
   #C26 = self::ClassWithFunction<void> {field:#C24}
-  #C27 = tearoff self::intFunction
+  #C27 = static-tearoff self::intFunction
   #C28 = self::ClassWithFunction<core::int> {field:#C27}
   #C29 = self::ClassWithFunction<core::int> {field:#C3}
 }
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect
index 5612a60..e4d23f5 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect
@@ -225,8 +225,8 @@
 
 constants  {
   #C1 = 3
-  #C2 = tearoff self::idFunction
-  #C3 = partial-instantiation self::idFunction <core::int>
+  #C2 = static-tearoff self::idFunction
+  #C3 = instantiation self::idFunction <core::int>
   #C4 = 0
   #C5 = self::Class<dynamic> {field:#C4}
   #C6 = self::Class<core::num> {field:#C4}
@@ -244,13 +244,13 @@
   #C18 = self::ClassWithList<core::int> {field:#C16}
   #C19 = <core::String>[#C8]
   #C20 = self::ClassWithList<core::String> {field:#C19}
-  #C21 = tearoff self::dynamicFunction
+  #C21 = static-tearoff self::dynamicFunction
   #C22 = self::ClassWithFunction<dynamic> {field:#C21}
   #C23 = self::ClassWithFunction<core::Object?> {field:#C21}
-  #C24 = tearoff self::objectFunction
+  #C24 = static-tearoff self::objectFunction
   #C25 = self::ClassWithFunction<dynamic> {field:#C24}
   #C26 = self::ClassWithFunction<void> {field:#C24}
-  #C27 = tearoff self::intFunction
+  #C27 = static-tearoff self::intFunction
   #C28 = self::ClassWithFunction<core::int> {field:#C27}
   #C29 = self::ClassWithFunction<core::int> {field:#C3}
 }
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect
index ff4ef6e..8c2aa2a 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect
@@ -216,8 +216,8 @@
 
 constants  {
   #C1 = 3
-  #C2 = tearoff self::idFunction
-  #C3 = partial-instantiation self::idFunction <core::int*>
+  #C2 = static-tearoff self::idFunction
+  #C3 = instantiation self::idFunction <core::int*>
   #C4 = 0
   #C5 = self::Class<dynamic> {field:#C4}
   #C6 = self::Class<core::num*> {field:#C4}
@@ -235,13 +235,13 @@
   #C18 = self::ClassWithList<core::int*> {field:#C16}
   #C19 = <core::String*>[#C8]
   #C20 = self::ClassWithList<core::String*> {field:#C19}
-  #C21 = tearoff self::dynamicFunction
+  #C21 = static-tearoff self::dynamicFunction
   #C22 = self::ClassWithFunction<dynamic> {field:#C21}
   #C23 = self::ClassWithFunction<core::Object?> {field:#C21}
-  #C24 = tearoff self::objectFunction
+  #C24 = static-tearoff self::objectFunction
   #C25 = self::ClassWithFunction<dynamic> {field:#C24}
   #C26 = self::ClassWithFunction<void> {field:#C24}
-  #C27 = tearoff self::intFunction
+  #C27 = static-tearoff self::intFunction
   #C28 = self::ClassWithFunction<core::int*> {field:#C27}
   #C29 = self::ClassWithFunction<core::int*> {field:#C3}
   #C30 = self::ClassWithFunction<core::Object*> {field:#C24}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect
index ff4ef6e..8c2aa2a 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect
@@ -216,8 +216,8 @@
 
 constants  {
   #C1 = 3
-  #C2 = tearoff self::idFunction
-  #C3 = partial-instantiation self::idFunction <core::int*>
+  #C2 = static-tearoff self::idFunction
+  #C3 = instantiation self::idFunction <core::int*>
   #C4 = 0
   #C5 = self::Class<dynamic> {field:#C4}
   #C6 = self::Class<core::num*> {field:#C4}
@@ -235,13 +235,13 @@
   #C18 = self::ClassWithList<core::int*> {field:#C16}
   #C19 = <core::String*>[#C8]
   #C20 = self::ClassWithList<core::String*> {field:#C19}
-  #C21 = tearoff self::dynamicFunction
+  #C21 = static-tearoff self::dynamicFunction
   #C22 = self::ClassWithFunction<dynamic> {field:#C21}
   #C23 = self::ClassWithFunction<core::Object?> {field:#C21}
-  #C24 = tearoff self::objectFunction
+  #C24 = static-tearoff self::objectFunction
   #C25 = self::ClassWithFunction<dynamic> {field:#C24}
   #C26 = self::ClassWithFunction<void> {field:#C24}
-  #C27 = tearoff self::intFunction
+  #C27 = static-tearoff self::intFunction
   #C28 = self::ClassWithFunction<core::int*> {field:#C27}
   #C29 = self::ClassWithFunction<core::int*> {field:#C3}
   #C30 = self::ClassWithFunction<core::Object*> {field:#C24}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect
index c131260..f4b8262 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect
@@ -80,8 +80,8 @@
 
 constants  {
   #C1 = 3
-  #C2 = tearoff self::idFunction
-  #C3 = partial-instantiation self::idFunction <core::int>
+  #C2 = static-tearoff self::idFunction
+  #C3 = instantiation self::idFunction <core::int>
   #C4 = true
   #C5 = self::Class<dynamic> {field:#C4}
   #C6 = self::Class<core::num> {field:#C4}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect
index c131260..f4b8262 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect
@@ -80,8 +80,8 @@
 
 constants  {
   #C1 = 3
-  #C2 = tearoff self::idFunction
-  #C3 = partial-instantiation self::idFunction <core::int>
+  #C2 = static-tearoff self::idFunction
+  #C3 = instantiation self::idFunction <core::int>
   #C4 = true
   #C5 = self::Class<dynamic> {field:#C4}
   #C6 = self::Class<core::num> {field:#C4}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect
index d959fa2..3391fa7 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect
@@ -80,8 +80,8 @@
 
 constants  {
   #C1 = 3
-  #C2 = tearoff self::idFunction
-  #C3 = partial-instantiation self::idFunction <core::int*>
+  #C2 = static-tearoff self::idFunction
+  #C3 = instantiation self::idFunction <core::int*>
   #C4 = true
   #C5 = self::Class<dynamic> {field:#C4}
   #C6 = self::Class<core::num*> {field:#C4}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect
index d959fa2..3391fa7 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect
@@ -80,8 +80,8 @@
 
 constants  {
   #C1 = 3
-  #C2 = tearoff self::idFunction
-  #C3 = partial-instantiation self::idFunction <core::int*>
+  #C2 = static-tearoff self::idFunction
+  #C3 = instantiation self::idFunction <core::int*>
   #C4 = true
   #C5 = self::Class<dynamic> {field:#C4}
   #C6 = self::Class<core::num*> {field:#C4}
diff --git a/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.expect
index 496eb80..524b85c 100644
--- a/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.expect
@@ -43,9 +43,9 @@
 static method applyTakesNonNullableNamed({required (core::int) → void f = #C5}) → dynamic {}
 
 constants  {
-  #C1 = tearoff cal::takesNever
-  #C2 = tearoff cal::takesNull
-  #C3 = tearoff cal::takesNonNullable
-  #C4 = tearoff cal::takesNullable
+  #C1 = static-tearoff cal::takesNever
+  #C2 = static-tearoff cal::takesNull
+  #C3 = static-tearoff cal::takesNonNullable
+  #C4 = static-tearoff cal::takesNullable
   #C5 = null
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.transformed.expect
index 496eb80..524b85c 100644
--- a/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.transformed.expect
@@ -43,9 +43,9 @@
 static method applyTakesNonNullableNamed({required (core::int) → void f = #C5}) → dynamic {}
 
 constants  {
-  #C1 = tearoff cal::takesNever
-  #C2 = tearoff cal::takesNull
-  #C3 = tearoff cal::takesNonNullable
-  #C4 = tearoff cal::takesNullable
+  #C1 = static-tearoff cal::takesNever
+  #C2 = static-tearoff cal::takesNull
+  #C3 = static-tearoff cal::takesNonNullable
+  #C4 = static-tearoff cal::takesNullable
   #C5 = null
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect
index ce1ca58..b684e03a 100644
--- a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect
@@ -27,7 +27,7 @@
   return null;
 
 constants  {
-  #C1 = tearoff self2::fnWithNonNullObjectBound
+  #C1 = static-tearoff self2::fnWithNonNullObjectBound
   #C2 = true
-  #C3 = tearoff self2::fnWithNullBound
+  #C3 = static-tearoff self2::fnWithNullBound
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect
index 806f867..37ae0a7 100644
--- a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect
@@ -27,9 +27,9 @@
   return null;
 
 constants  {
-  #C1 = tearoff self2::fnWithNonNullObjectBound
+  #C1 = static-tearoff self2::fnWithNonNullObjectBound
   #C2 = true
-  #C3 = tearoff self2::fnWithNullBound
+  #C3 = static-tearoff self2::fnWithNullBound
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.expect
index 22db152..fc18272 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.expect
@@ -81,8 +81,8 @@
   return t;
 
 constants  {
-  #C1 = tearoff con::id
-  #C2 = partial-instantiation con::id <core::int*>
+  #C1 = static-tearoff con::id
+  #C2 = instantiation con::id <core::int*>
   #C3 = 0
   #C4 = con::Class<core::int*> {field:#C3}
   #C5 = <core::int*>[#C3]
@@ -94,7 +94,7 @@
   #C11 = <dynamic>[#C3, #C10]
   #C12 = core::_ImmutableMap<core::int*, core::String*> {_kvPairs:#C11}
   #C13 = true
-  #C14 = tearoff core::identical
+  #C14 = static-tearoff core::identical
 }
 
 
diff --git a/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.transformed.expect
index 22db152..fc18272 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.transformed.expect
@@ -81,8 +81,8 @@
   return t;
 
 constants  {
-  #C1 = tearoff con::id
-  #C2 = partial-instantiation con::id <core::int*>
+  #C1 = static-tearoff con::id
+  #C2 = instantiation con::id <core::int*>
   #C3 = 0
   #C4 = con::Class<core::int*> {field:#C3}
   #C5 = <core::int*>[#C3]
@@ -94,7 +94,7 @@
   #C11 = <dynamic>[#C3, #C10]
   #C12 = core::_ImmutableMap<core::int*, core::String*> {_kvPairs:#C11}
   #C13 = true
-  #C14 = tearoff core::identical
+  #C14 = static-tearoff core::identical
 }
 
 
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect
index bcfdbf4..5d1e11f 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect
@@ -24,5 +24,5 @@
 static method takesTakesNull((Null) → void f) → void {}
 
 constants  {
-  #C1 = tearoff iss::takesNever
+  #C1 = static-tearoff iss::takesNever
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect
index bcfdbf4..5d1e11f 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect
@@ -24,5 +24,5 @@
 static method takesTakesNull((Null) → void f) → void {}
 
 constants  {
-  #C1 = tearoff iss::takesNever
+  #C1 = static-tearoff iss::takesNever
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.expect
index 8d0b35b..9f64aae 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.expect
@@ -28,5 +28,5 @@
 typedef F = (core::int*) →* core::int*;
 
 constants  {
-  #C1 = tearoff self::f1
+  #C1 = static-tearoff self::f1
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.transformed.expect
index c100d45..c2af5e9 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.transformed.expect
@@ -28,5 +28,5 @@
 typedef F = (core::int*) →* core::int*;
 
 constants  {
-  #C1 = tearoff self::f1
+  #C1 = static-tearoff self::f1
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.expect
index 10c6848..3376fa8 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.expect
@@ -61,5 +61,5 @@
   return 4;
 
 constants  {
-  #C1 = tearoff iss::f
+  #C1 = static-tearoff iss::f
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.transformed.expect
index 10c6848..3376fa8 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.transformed.expect
@@ -61,5 +61,5 @@
   return 4;
 
 constants  {
-  #C1 = tearoff iss::f
+  #C1 = static-tearoff iss::f
 }
diff --git a/pkg/front_end/testcases/none/property_get.dart.strong.expect b/pkg/front_end/testcases/none/property_get.dart.strong.expect
index 4163115..e7de58d 100644
--- a/pkg/front_end/testcases/none/property_get.dart.strong.expect
+++ b/pkg/front_end/testcases/none/property_get.dart.strong.expect
@@ -144,6 +144,6 @@
 constants  {
   #C1 = "foo"
   #C2 = 3
-  #C3 = tearoff self::Class1::staticMethod
-  #C4 = tearoff self::topLevelMethod
+  #C3 = static-tearoff self::Class1::staticMethod
+  #C4 = static-tearoff self::topLevelMethod
 }
diff --git a/pkg/front_end/testcases/none/property_get.dart.weak.expect b/pkg/front_end/testcases/none/property_get.dart.weak.expect
index fcb468d..83e1366 100644
--- a/pkg/front_end/testcases/none/property_get.dart.weak.expect
+++ b/pkg/front_end/testcases/none/property_get.dart.weak.expect
@@ -145,6 +145,6 @@
 constants  {
   #C1 = "foo"
   #C2 = 3
-  #C3 = tearoff self::Class1::staticMethod
-  #C4 = tearoff self::topLevelMethod
+  #C3 = static-tearoff self::Class1::staticMethod
+  #C4 = static-tearoff self::topLevelMethod
 }
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index b866349..a59e9fd 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -9,11 +9,11 @@
 extension_types/simple_method_resolution: ExpectationFileMismatchSerialized
 extension_types/simple_operator_resolution: ExpectationFileMismatchSerialized
 extension_types/simple_setter_resolution: ExpectationFileMismatchSerialized
+extension_types/simple_show_hide: ExpectationFileMismatchSerialized # Expected.
 general/abstract_members: TypeCheckError
 general/bug30695: TypeCheckError
 general/covariant_field: TypeCheckError
 general/crashes/crash_02/main: Crash
-general/crashes/crash_04/main: Crash
 general/crashes/crash_06/main: Crash
 general/getter_vs_setter_type: TypeCheckError
 general/infer_field_from_multiple: TypeCheckError
diff --git a/pkg/front_end/testcases/rasta/deferred_load.dart.weak.expect b/pkg/front_end/testcases/rasta/deferred_load.dart.weak.expect
index 0c092f0..d01ac3d 100644
--- a/pkg/front_end/testcases/rasta/deferred_load.dart.weak.expect
+++ b/pkg/front_end/testcases/rasta/deferred_load.dart.weak.expect
@@ -18,5 +18,5 @@
   return null;
 
 constants  {
-  #C1 = tearoff self::_#loadLibrary_lib
+  #C1 = static-tearoff self::_#loadLibrary_lib
 }
diff --git a/pkg/front_end/testcases/rasta/deferred_load.dart.weak.transformed.expect b/pkg/front_end/testcases/rasta/deferred_load.dart.weak.transformed.expect
index 0c092f0..d01ac3d 100644
--- a/pkg/front_end/testcases/rasta/deferred_load.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/rasta/deferred_load.dart.weak.transformed.expect
@@ -18,5 +18,5 @@
   return null;
 
 constants  {
-  #C1 = tearoff self::_#loadLibrary_lib
+  #C1 = static-tearoff self::_#loadLibrary_lib
 }
diff --git a/pkg/front_end/testcases/rasta/static.dart.weak.expect b/pkg/front_end/testcases/rasta/static.dart.weak.expect
index 79e268c..e32deba4 100644
--- a/pkg/front_end/testcases/rasta/static.dart.weak.expect
+++ b/pkg/front_end/testcases/rasta/static.dart.weak.expect
@@ -335,5 +335,5 @@
 
 constants  {
   #C1 = 42
-  #C2 = tearoff self::Foo::staticFunction
+  #C2 = static-tearoff self::Foo::staticFunction
 }
diff --git a/pkg/front_end/testcases/rasta/static.dart.weak.transformed.expect b/pkg/front_end/testcases/rasta/static.dart.weak.transformed.expect
index f510042..6e667ff 100644
--- a/pkg/front_end/testcases/rasta/static.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/rasta/static.dart.weak.transformed.expect
@@ -335,7 +335,7 @@
 
 constants  {
   #C1 = 42
-  #C2 = tearoff self::Foo::staticFunction
+  #C2 = static-tearoff self::Foo::staticFunction
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.weak.expect b/pkg/front_end/testcases/regress/issue_30838.dart.weak.expect
index a71fae5..f1431a1 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.weak.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.weak.expect
@@ -32,5 +32,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_30838.dart.weak.transformed.expect
index acb1618..d1bd2c9 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.weak.transformed.expect
@@ -32,7 +32,7 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::foo
+  #C1 = static-tearoff self::foo
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.weak.expect b/pkg/front_end/testcases/regress/issue_31846.dart.weak.expect
index 0966591..450ca19 100644
--- a/pkg/front_end/testcases/regress/issue_31846.dart.weak.expect
+++ b/pkg/front_end/testcases/regress/issue_31846.dart.weak.expect
@@ -13,5 +13,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::main
+  #C1 = static-tearoff self::main
 }
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_31846.dart.weak.transformed.expect
index 1a1cf76..34ce0c6 100644
--- a/pkg/front_end/testcases/regress/issue_31846.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31846.dart.weak.transformed.expect
@@ -13,7 +13,7 @@
 }
 
 constants  {
-  #C1 = tearoff self::main
+  #C1 = static-tearoff self::main
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/regress/issue_39682.dart.weak.expect b/pkg/front_end/testcases/regress/issue_39682.dart.weak.expect
index 9ab919a..9866587 100644
--- a/pkg/front_end/testcases/regress/issue_39682.dart.weak.expect
+++ b/pkg/front_end/testcases/regress/issue_39682.dart.weak.expect
@@ -25,5 +25,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::_#loadLibrary_foo
+  #C1 = static-tearoff self::_#loadLibrary_foo
 }
diff --git a/pkg/front_end/testcases/regress/issue_39682.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_39682.dart.weak.transformed.expect
index 9ab919a..9866587 100644
--- a/pkg/front_end/testcases/regress/issue_39682.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_39682.dart.weak.transformed.expect
@@ -25,5 +25,5 @@
 }
 
 constants  {
-  #C1 = tearoff self::_#loadLibrary_foo
+  #C1 = static-tearoff self::_#loadLibrary_foo
 }
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.expect
index 28fb659..3f796f1 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.expect
@@ -34,5 +34,5 @@
 static method main() → void {}
 
 constants  {
-  #C1 = tearoff self::h
+  #C1 = static-tearoff self::h
 }
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.transformed.expect
index 28fb659..3f796f1 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.transformed.expect
@@ -34,5 +34,5 @@
 static method main() → void {}
 
 constants  {
-  #C1 = tearoff self::h
+  #C1 = static-tearoff self::h
 }
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.expect
index 14294a1..204effc 100644
--- a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.expect
+++ b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.expect
@@ -28,5 +28,5 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::h
+  #C1 = static-tearoff self::h
 }
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.transformed.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.transformed.expect
index bde2247..14d1ec2 100644
--- a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.transformed.expect
@@ -28,7 +28,7 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = tearoff self::h
+  #C1 = static-tearoff self::h
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.expect
index 889de80..378a300 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.expect
@@ -94,6 +94,6 @@
 }
 
 constants  {
-  #C1 = tearoff self::numToInt
-  #C2 = tearoff self::numToNum
+  #C1 = static-tearoff self::numToInt
+  #C2 = static-tearoff self::numToNum
 }
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.transformed.expect
index 4fec92e..92acd28 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.transformed.expect
@@ -94,8 +94,8 @@
 }
 
 constants  {
-  #C1 = tearoff self::numToInt
-  #C2 = tearoff self::numToNum
+  #C1 = static-tearoff self::numToInt
+  #C2 = static-tearoff self::numToNum
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 6b4d01c..2518fb5 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -8,8 +8,10 @@
 
 dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
 
-constructor_tearoffs/instantiation: TypeCheckError
+constructor_tearoffs/call_instantiation: TypeCheckError
+constructor_tearoffs/const_tear_off: RuntimeError
 constructor_tearoffs/redirecting_constructors: RuntimeError
+constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
 extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
 extension_types/simple: ExpectationFileMismatchSerialized # Expected.
@@ -17,6 +19,7 @@
 extension_types/simple_method_resolution: ExpectationFileMismatchSerialized # Expected.
 extension_types/simple_operator_resolution: ExpectationFileMismatchSerialized # Expected.
 extension_types/simple_setter_resolution: ExpectationFileMismatchSerialized # Expected.
+extension_types/simple_show_hide: ExpectationFileMismatchSerialized # Expected.
 late_lowering/covariant_late_field: TypeCheckError
 nnbd/covariant_late_field: TypeCheckError
 nnbd/getter_vs_setter_type: TypeCheckError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index b1e611f..7ea4ce0 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -6,15 +6,10 @@
 # the round trip for Kernel textual serialization where the initial binary
 # Kernel files are produced by compiling Dart code via Fasta.
 
-constructor_tearoffs/abstract_class_constructor_tear_off: TextSerializationFailure
-constructor_tearoffs/generic_tearoff_with_context: TextSerializationFailure
-constructor_tearoffs/generic_tearoff_without_context: TextSerializationFailure
-constructor_tearoffs/instantiation: TypeCheckError
-constructor_tearoffs/nongeneric_tearoff_with_context: TextSerializationFailure
-constructor_tearoffs/nongeneric_tearoff_without_context: TextSerializationFailure
+constructor_tearoffs/call_instantiation: TypeCheckError
+constructor_tearoffs/const_tear_off: RuntimeError
 constructor_tearoffs/redirecting_constructors: RuntimeError
-constructor_tearoffs/typedef_tearoffs: TextSerializationFailure
-constructor_tearoffs/unnamed_constructor: TextSerializationFailure
+constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
 extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
 extension_types/simple: ExpectationFileMismatchSerialized # Expected.
@@ -22,6 +17,7 @@
 extension_types/simple_method_resolution: ExpectationFileMismatchSerialized # Expected.
 extension_types/simple_operator_resolution: ExpectationFileMismatchSerialized # Expected.
 extension_types/simple_setter_resolution: ExpectationFileMismatchSerialized # Expected.
+extension_types/simple_show_hide: ExpectationFileMismatchSerialized # Expected.
 extensions/extension_setter_error: TypeCheckError
 extensions/instance_access_of_static: RuntimeError
 extensions/invalid_explicit_access: RuntimeError
@@ -40,7 +36,6 @@
 general/covariant_field: TypeCheckError
 general/covariant_generic: RuntimeError
 general/crashes/crash_02/main: Crash
-general/crashes/crash_04/main: Crash
 general/crashes/crash_06/main: Crash
 general/duplicated_declarations: TypeCheckError
 general/duplicated_field_initializer: RuntimeError
@@ -91,6 +86,7 @@
 general/issue41210a: TypeCheckError
 general/issue41210b/issue41210.no_link: TypeCheckError
 general/issue41210b/issue41210: TypeCheckError
+general/issue44733: TypeCheckError
 general/issue45204: TypeCheckError
 general/micro: RuntimeError
 general/mixin_application_override: TypeCheckError
@@ -105,6 +101,7 @@
 general/override_check_basic: TypeCheckError # Issue #31620
 general/override_check_with_covariant_modifier: TypeCheckError # Issue #31620
 general/override_setter_with_field: TypeCheckError
+general/redirecting_factory_invocation_in_invalid: TypeCheckError
 general/spread_collection: RuntimeError # Should be fixed as part of implementing spread collection support
 general/type_parameter_type_named_int: RuntimeError
 general/type_variable_as_super: RuntimeError
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index a8a4fb3..ed0e7e4 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -23,15 +23,27 @@
 const_functions/const_functions_const_ctor: FormatterCrash
 const_functions/const_functions_const_ctor_error: FormatterCrash
 const_functions/const_functions_const_factory: FormatterCrash
+constructor_tearoffs/call_instantiation: FormatterCrash
+constructor_tearoffs/const_tear_off: FormatterCrash
+constructor_tearoffs/dynamic_explicit_instantiation: FormatterCrash
 constructor_tearoffs/explicit_instantiation_errors: FormatterCrash
+constructor_tearoffs/explicit_new_as_unnamed: FormatterCrash
 constructor_tearoffs/generic_tearoff_with_context: FormatterCrash
 constructor_tearoffs/generic_tearoff_without_context: FormatterCrash
 constructor_tearoffs/identical_instantiated_function_tearoffs: FormatterCrash
+constructor_tearoffs/inferred_constructor_tear_off: FormatterCrash
+constructor_tearoffs/inferred_non_proper_rename: FormatterCrash
 constructor_tearoffs/instantiation: FormatterCrash
+constructor_tearoffs/lowering/inferred_constructor_tear_off: FormatterCrash
+constructor_tearoffs/lowering/inferred_non_proper_rename: FormatterCrash
+constructor_tearoffs/lowering/inferred_tear_off: FormatterCrash
+constructor_tearoffs/lowering/typedef_from_dill/main: FormatterCrash
+constructor_tearoffs/lowering/typedef_identical: FormatterCrash
 constructor_tearoffs/nongeneric_tearoff_with_context: FormatterCrash
 constructor_tearoffs/nongeneric_tearoff_without_context: FormatterCrash
 constructor_tearoffs/redirecting_constructors: FormatterCrash
 constructor_tearoffs/simple_instantiated_type_literals: FormatterCrash
+constructor_tearoffs/simple_proper_rename_identity: FormatterCrash
 constructor_tearoffs/typedef_tearoffs: FormatterCrash
 constructor_tearoffs/unnamed_constructor: FormatterCrash
 dart2js/late_fields: FormatterCrash
@@ -40,6 +52,7 @@
 extension_types/simple_method_resolution: FormatterCrash
 extension_types/simple_operator_resolution: FormatterCrash
 extension_types/simple_setter_resolution: FormatterCrash
+extension_types/simple_show_hide: FormatterCrash
 extensions/extension_constructor: FormatterCrash
 extensions/extension_field_with_type_parameter_usage: FormatterCrash
 extensions/issue38600: FormatterCrash
@@ -78,6 +91,7 @@
 general/incomplete_field_formal_parameter: FormatterCrash
 general/invalid_operator2: FormatterCrash
 general/invalid_operator: FormatterCrash
+general/invalid_super_initializer: FormatterCrash
 general/issue42997: FormatterCrash
 general/issue43363: FormatterCrash
 general/issue45490: FormatterCrash
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index d2ea6a0..8256003 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -11,8 +11,10 @@
 regress/utf_16_le_content.crash: SemiFuzzCrash
 dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
 
-constructor_tearoffs/instantiation: TypeCheckError
+constructor_tearoffs/call_instantiation: TypeCheckError
+constructor_tearoffs/const_tear_off: RuntimeError
 constructor_tearoffs/redirecting_constructors: RuntimeError
+constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
 extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
 extension_types/simple: ExpectationFileMismatchSerialized # Expected.
@@ -20,6 +22,7 @@
 extension_types/simple_method_resolution: ExpectationFileMismatchSerialized # Expected.
 extension_types/simple_operator_resolution: ExpectationFileMismatchSerialized # Expected.
 extension_types/simple_setter_resolution: ExpectationFileMismatchSerialized # Expected.
+extension_types/simple_show_hide: ExpectationFileMismatchSerialized # Expected.
 extensions/extension_setter_error: TypeCheckError
 extensions/instance_access_of_static: RuntimeError
 extensions/invalid_explicit_access: RuntimeError
@@ -38,7 +41,6 @@
 general/covariant_field: TypeCheckError
 general/covariant_generic: RuntimeError
 general/crashes/crash_02/main: Crash
-general/crashes/crash_04/main: Crash
 general/crashes/crash_06/main: Crash
 general/duplicated_declarations: TypeCheckError
 general/duplicated_field_initializer: RuntimeError
@@ -89,6 +91,7 @@
 general/issue41210a: TypeCheckError
 general/issue41210b/issue41210.no_link: TypeCheckError
 general/issue41210b/issue41210: TypeCheckError
+general/issue44733: TypeCheckError
 general/issue45204: TypeCheckError
 general/micro: RuntimeError
 general/mixin_application_override: ExpectationFileMismatch # Too many errors.
@@ -104,6 +107,7 @@
 general/override_check_basic: TypeCheckError # Issue #31620
 general/override_check_with_covariant_modifier: TypeCheckError # Issue #31620
 general/override_setter_with_field: TypeCheckError
+general/redirecting_factory_invocation_in_invalid: TypeCheckError
 general/spread_collection: RuntimeError
 general/type_parameter_type_named_int: RuntimeError # Expected
 general/type_variable_as_super: RuntimeError
diff --git a/pkg/front_end/tool/_fasta/abcompile.dart b/pkg/front_end/tool/_fasta/abcompile.dart
index 26f815a..a9e3125 100644
--- a/pkg/front_end/tool/_fasta/abcompile.dart
+++ b/pkg/front_end/tool/_fasta/abcompile.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:math';
@@ -11,7 +9,7 @@
 
 import 'standard_deviation.dart';
 
-const String bRootPath =
+const String? bRootPath =
     bool.hasEnvironment("bRoot") ? String.fromEnvironment("bRoot") : null;
 const int abIterations = int.fromEnvironment("abIterations", defaultValue: 15);
 const int iterations = int.fromEnvironment("iterations", defaultValue: 15);
@@ -31,7 +29,7 @@
   Uri aRoot = Platform.script.resolve('../../../..');
 
   // The root of the other Dart SDK repo "B"
-  Uri bRoot = new Uri.directory(bRootPath);
+  Uri bRoot = new Uri.directory(bRootPath!);
 
   // Sanity check
   String relPath = 'pkg/front_end/tool/_fasta/compile.dart';
@@ -183,15 +181,15 @@
       workingDirectory: workingDirPath);
   // ignore: unawaited_futures
   stderr.addStream(process.stderr);
-  StreamSubscription<String> stdOutSubscription;
+  StreamSubscription<String>? stdOutSubscription;
   stdOutSubscription = process.stdout
       .transform(utf8.decoder)
       .transform(new LineSplitter())
       .listen(processLine, onDone: () {
-    stdOutSubscription.cancel();
+    stdOutSubscription!.cancel();
   }, onError: (e) {
     print('Error: $e');
-    stdOutSubscription.cancel();
+    stdOutSubscription!.cancel();
   });
   int code = await process.exitCode;
   if (code != 0) {
diff --git a/pkg/front_end/tool/_fasta/bench_maker.dart b/pkg/front_end/tool/_fasta/bench_maker.dart
index 22732a7..4e95837 100644
--- a/pkg/front_end/tool/_fasta/bench_maker.dart
+++ b/pkg/front_end/tool/_fasta/bench_maker.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
-
 library fasta.tool.entry_points;
 
 import "dart:convert" show JsonEncoder;
@@ -49,8 +47,10 @@
   final List<TypeParameter> usedTypeParameters = <TypeParameter>[];
 
   String serializeTypeChecks(List<Object> typeChecks) {
-    for (List<Object> list in typeChecks) {
-      writeTypeCheck(list[0], list[1], list[2]);
+    for (Object list in typeChecks) {
+      List<Object> typeCheck = list as List<Object>;
+      writeTypeCheck(typeCheck[0] as DartType, typeCheck[1] as DartType,
+          typeCheck[2] as bool);
     }
     writeClasses();
     return jsonEncode(this);
@@ -133,11 +133,11 @@
     }
   }
 
-  void writeClass(Class cls, Set<Class> writtenClasses) {
+  void writeClass(Class? cls, Set<Class> writtenClasses) {
     if (cls == null || !writtenClasses.add(cls)) return;
-    Supertype supertype = cls.supertype;
+    Supertype? supertype = cls.supertype;
     writeClass(supertype?.classNode, writtenClasses);
-    Supertype mixedInType = cls.mixedInType;
+    Supertype? mixedInType = cls.mixedInType;
     writeClass(mixedInType?.classNode, writtenClasses);
     for (Supertype implementedType in cls.implementedTypes) {
       writeClass(implementedType.classNode, writtenClasses);
@@ -164,7 +164,7 @@
       implementedType.asInterfaceType.accept1(this, sb);
       first = false;
     }
-    Procedure callOperator;
+    Procedure? callOperator;
     for (Procedure procedure in cls.procedures) {
       if (procedure.name.text == "call") {
         callOperator = procedure;
@@ -183,11 +183,11 @@
   }
 
   String computeName(TreeNode node) {
-    String name = nodeNames[node];
+    String? name = nodeNames[node];
     if (name != null) return name;
     if (node is Class) {
       Library library = node.enclosingLibrary;
-      String uriString = "${library?.importUri}";
+      String uriString = "${library.importUri}";
       if (uriString == "dart:core" || uriString == "dart:async") {
         if (!usedNames.add(node.name)) {
           throw "Class name conflict for $node";
@@ -336,7 +336,7 @@
     sb.write(name);
     if (node.promotedBound != null) {
       sb.write(" & ");
-      node.promotedBound.accept1(this, sb);
+      node.promotedBound!.accept1(this, sb);
     }
   }
 
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index d4b5b05..6ab0e47 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.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
-
 library fasta.tool.command_line;
 
 import 'dart:io' show exit;
@@ -110,7 +108,7 @@
   /// All other options require an option value, either on the form `--option
   /// value` or `--option=value`.
   static ParsedArguments parse(
-      List<String> arguments, Map<String, ValueSpecification> specification) {
+      List<String> arguments, Map<String, ValueSpecification>? specification) {
     specification ??= const <String, ValueSpecification>{};
     ParsedArguments result = new ParsedArguments();
     int index = arguments.indexOf("--");
@@ -123,7 +121,7 @@
     while (iterator.moveNext()) {
       String argument = iterator.current;
       if (argument.startsWith("-") || argument == "/?" || argument == "/h") {
-        String value;
+        String? value;
         if (argument.startsWith("-D")) {
           value = argument.substring("-D".length);
           argument = "-D";
@@ -134,14 +132,14 @@
             argument = argument.substring(0, index);
           }
         }
-        ValueSpecification valueSpecification = specification[argument];
+        ValueSpecification? valueSpecification = specification[argument];
         if (valueSpecification == null) {
           throw new CommandLineProblem.deprecated(
               "Unknown option '$argument'.");
         }
         String canonicalArgument = argument;
         if (valueSpecification.alias != null) {
-          canonicalArgument = valueSpecification.alias;
+          canonicalArgument = valueSpecification.alias as String;
           valueSpecification = specification[valueSpecification.alias];
         }
         if (valueSpecification == null) {
@@ -268,7 +266,7 @@
       enableNullSafety: isExperimentEnabled(ExperimentalFlag.nonNullable,
           explicitExperimentalFlags: explicitExperimentalFlags));
 
-  final Target target = getTarget(targetName, flags);
+  final Target? target = getTarget(targetName, flags);
   if (target == null) {
     return throw new CommandLineProblem.deprecated(
         "Target '${targetName}' not recognized. "
@@ -302,7 +300,7 @@
 
   final bool compileSdk = options.containsKey(Flags.compileSdk);
 
-  final String singleRootScheme = options[Flags.singleRootScheme];
+  final String? singleRootScheme = options[Flags.singleRootScheme];
   final Uri singleRootBase = options[Flags.singleRootBase];
 
   final bool nnbdStrongMode = options[Flags.nnbdStrongMode];
@@ -418,7 +416,7 @@
             throwCommandLineProblem(
                 "Target '${target.name}' requires an explicit "
                 "'${Flags.platform}' option.");
-          })));
+          })!));
   compilerOptions
     ..sdkRoot = sdk
     ..sdkSummary = platform
@@ -439,9 +437,9 @@
     List<String> arguments,
     bool areRestArgumentsInputs,
     Future<T> f(CompilerContext context, List<String> restArguments)) {
-  ParsedArguments parsedArguments;
+  ParsedArguments? parsedArguments;
   ProcessedOptions options;
-  CommandLineProblem problem;
+  CommandLineProblem? problem;
   try {
     parsedArguments = ParsedArguments.parse(arguments, optionSpecification);
     options = analyzeCommandLine(
@@ -466,13 +464,13 @@
       exit(1);
     }
 
-    return f(c, parsedArguments.arguments);
+    return f(c, parsedArguments!.arguments);
   }, errorOnMissingInput: problem == null);
 }
 
 Message computeUsage(String programName, bool verbose) {
   String basicUsage = "Usage: $programName [options] dartfile\n";
-  String summary;
+  String? summary;
   String options =
       (verbose ? messageFastaUsageLong.message : messageFastaUsageShort.message)
           .trim();
@@ -508,7 +506,7 @@
 }
 
 Future<T> runProtectedFromAbort<T>(Future<T> Function() action,
-    [T failingValue]) async {
+    [T? failingValue]) async {
   if (CompilerContext.isActive) {
     throw "runProtectedFromAbort should be called from 'main',"
         " that is, outside a compiler context.";
@@ -527,14 +525,14 @@
 abstract class ValueSpecification {
   const ValueSpecification();
 
-  String get alias => null;
+  String? get alias => null;
 
   dynamic get defaultValue => null;
 
   bool get requiresValue => true;
 
   void processValue(ParsedArguments result, String canonicalArgument,
-      String argument, String value);
+      String argument, String? value);
 }
 
 class AliasValue extends ValueSpecification {
@@ -546,7 +544,7 @@
       throw new UnsupportedError("AliasValue.requiresValue");
 
   void processValue(ParsedArguments result, String canonicalArgument,
-      String argument, String value) {
+      String argument, String? value) {
     throw new UnsupportedError("AliasValue.processValue");
   }
 }
@@ -555,7 +553,7 @@
   const UriValue();
 
   void processValue(ParsedArguments result, String canonicalArgument,
-      String argument, String value) {
+      String argument, String? value) {
     if (result.options.containsKey(canonicalArgument)) {
       throw new CommandLineProblem.deprecated(
           "Multiple values for '$argument': "
@@ -563,7 +561,7 @@
     }
     // TODO(ahe): resolve Uris lazily, so that schemes provided by
     // other flags can be used for parsed command-line arguments too.
-    result.options[canonicalArgument] = resolveInputUri(value);
+    result.options[canonicalArgument] = resolveInputUri(value!);
   }
 }
 
@@ -571,13 +569,13 @@
   const StringValue();
 
   void processValue(ParsedArguments result, String canonicalArgument,
-      String argument, String value) {
+      String argument, String? value) {
     if (result.options.containsKey(canonicalArgument)) {
       throw new CommandLineProblem.deprecated(
           "Multiple values for '$argument': "
           "'${result.options[canonicalArgument]}' and '$value'.");
     }
-    result.options[canonicalArgument] = value;
+    result.options[canonicalArgument] = value!;
   }
 }
 
@@ -589,7 +587,7 @@
   bool get requiresValue => false;
 
   void processValue(ParsedArguments result, String canonicalArgument,
-      String argument, String value) {
+      String argument, String? value) {
     if (result.options.containsKey(canonicalArgument)) {
       throw new CommandLineProblem.deprecated(
           "Multiple values for '$argument': "
@@ -613,13 +611,13 @@
   const IntValue();
 
   void processValue(ParsedArguments result, String canonicalArgument,
-      String argument, String value) {
+      String argument, String? value) {
     if (result.options.containsKey(canonicalArgument)) {
       throw new CommandLineProblem.deprecated(
           "Multiple values for '$argument': "
           "'${result.options[canonicalArgument]}' and '$value'.");
     }
-    int parsedValue = int.tryParse(value);
+    int? parsedValue = int.tryParse(value!);
     if (parsedValue == null) {
       throw new CommandLineProblem.deprecated(
           "Value for '$argument', '$value', isn't an int.");
@@ -632,8 +630,8 @@
   const DefineValue();
 
   void processValue(ParsedArguments result, String canonicalArgument,
-      String argument, String value) {
-    int index = value.indexOf('=');
+      String argument, String? value) {
+    int index = value!.indexOf('=');
     String name;
     String expression;
     if (index != -1) {
@@ -651,10 +649,10 @@
   const StringListValue();
 
   void processValue(ParsedArguments result, String canonicalArgument,
-      String argument, String value) {
+      String argument, String? value) {
     result.options
         .putIfAbsent(canonicalArgument, () => <String>[])
-        .addAll(value.split(","));
+        .addAll(value!.split(","));
   }
 }
 
@@ -662,9 +660,9 @@
   const UriListValue();
 
   void processValue(ParsedArguments result, String canonicalArgument,
-      String argument, String value) {
+      String argument, String? value) {
     result.options
         .putIfAbsent(canonicalArgument, () => <Uri>[])
-        .addAll(value.split(",").map(resolveInputUri));
+        .addAll(value!.split(",").map(resolveInputUri));
   }
 }
diff --git a/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart b/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart
index 1f624d3..985026c 100644
--- a/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform_legacy_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.md file.
 
-// @dart=2.9
-
 library fasta.test.compile_platform_test;
 
 import 'dart:io';
diff --git a/pkg/front_end/tool/_fasta/compile_platform_test.dart b/pkg/front_end/tool/_fasta/compile_platform_test.dart
index 1f624d3..985026c 100644
--- a/pkg/front_end/tool/_fasta/compile_platform_test.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform_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.md file.
 
-// @dart=2.9
-
 library fasta.test.compile_platform_test;
 
 import 'dart:io';
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
index f52aee6..a452b9f 100644
--- a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags.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:io' show File;
 
 import 'package:_fe_analyzer_shared/src/scanner/characters.dart'
@@ -50,7 +48,7 @@
   int currentVersionMajor;
   int currentVersionMinor;
   {
-    String currentVersion = getAsVersionNumberString(yaml['current-version']);
+    String currentVersion = getAsVersionNumberString(yaml['current-version'])!;
     List<String> split = currentVersion.split(".");
     currentVersionMajor = int.parse(split[0]);
     currentVersionMinor = int.parse(split[1]);
@@ -84,7 +82,7 @@
   int currentVersionMajor;
   int currentVersionMinor;
   {
-    String currentVersion = getAsVersionNumberString(yaml['current-version']);
+    String currentVersion = getAsVersionNumberString(yaml['current-version'])!;
     List<String> split = currentVersion.split(".");
     currentVersionMajor = int.parse(split[0]);
     currentVersionMinor = int.parse(split[1]);
@@ -135,7 +133,7 @@
   for (String key in keys) {
     int major;
     int minor;
-    String enabledIn =
+    String? enabledIn =
         getAsVersionNumberString((features[key] as YamlMap)['enabledIn']);
     if (enabledIn == null) {
       major = currentVersionMajor;
@@ -192,7 +190,7 @@
   for (String key in keys) {
     int major;
     int minor;
-    String enabledIn =
+    String? enabledIn =
         getAsVersionNumberString((features[key] as YamlMap)['enabledIn']);
     if (enabledIn != null) {
       List<String> split = enabledIn.split(".");
@@ -213,9 +211,9 @@
   for (String key in keys) {
     int major;
     int minor;
-    String enabledIn =
+    String? enabledIn =
         getAsVersionNumberString((features[key] as YamlMap)['enabledIn']);
-    String experimentalReleaseVersion = getAsVersionNumberString(
+    String? experimentalReleaseVersion = getAsVersionNumberString(
         (features[key] as YamlMap)['experimentalReleaseVersion']);
     if (experimentalReleaseVersion != null) {
       List<String> split = experimentalReleaseVersion.split(".");
@@ -296,7 +294,7 @@
   return identifier.toString();
 }
 
-String getAsVersionNumberString(dynamic value) {
+String? getAsVersionNumberString(dynamic value) {
   if (value == null) return null;
   if (value is String) return value;
   if (value is double) return "$value";
diff --git a/pkg/front_end/tool/_fasta/generate_messages.dart b/pkg/front_end/tool/_fasta/generate_messages.dart
index 8ddafe5..3a971c3 100644
--- a/pkg/front_end/tool/_fasta/generate_messages.dart
+++ b/pkg/front_end/tool/_fasta/generate_messages.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:io' show File, exitCode;
 
 import "package:_fe_analyzer_shared/src/messages/severity.dart"
@@ -96,7 +94,7 @@
     while (description is String) {
       description = yaml[description];
     }
-    Map<dynamic, dynamic> map = description;
+    Map<dynamic, dynamic>? map = description;
     if (map == null) {
       throw "No 'template:' in key $name.";
     }
@@ -109,7 +107,7 @@
         index = -1;
         // Continue looking for other problems.
       } else {
-        String otherName = indexNameMap[index];
+        String? otherName = indexNameMap[index];
         if (otherName != null) {
           print('Error: The "index:" field must be unique, '
               'but is the same for $otherName and $name');
@@ -166,8 +164,8 @@
   Template(this.text, {this.isShared}) : assert(isShared != null);
 }
 
-Template compileTemplate(String name, int index, String template, String tip,
-    Object analyzerCode, String severity) {
+Template compileTemplate(String name, int? index, String? template, String? tip,
+    Object? analyzerCode, String? severity) {
   if (template == null) {
     print('Error: missing template for message: $name');
     exitCode = 1;
@@ -194,9 +192,9 @@
 
   for (Match match
       in placeholderPattern.allMatches("$template\n${tip ?? ''}")) {
-    String name = match[1];
-    String padding = match[2];
-    String fractionDigits = match[3];
+    String name = match[1]!;
+    String? padding = match[2];
+    String? fractionDigits = match[3];
 
     String format(String name) {
       String conversion;
@@ -205,7 +203,7 @@
       } else {
         conversion = "$name.toStringAsFixed($fractionDigits)";
       }
-      if (padding.isNotEmpty) {
+      if (padding!.isNotEmpty) {
         if (padding.startsWith("0")) {
           conversion += ".padLeft(${int.parse(padding)}, '0')";
         } else {
@@ -416,13 +414,13 @@
     if (analyzerCode is String) {
       analyzerCode = <String>[analyzerCode];
     }
-    List<Object> codes = analyzerCode;
+    List<Object> codes = analyzerCode as List<Object>;
     // If "index:" is defined, then "analyzerCode:" should not be generated
     // in the front end. See comment in messages.yaml
     codeArguments.add('analyzerCodes: <String>["${codes.join('", "')}"]');
   }
   if (severity != null) {
-    String severityEnumName = severityEnumNames[severity];
+    String? severityEnumName = severityEnumNames[severity];
     if (severityEnumName == null) {
       throw "Unknown severity '$severity'";
     }
@@ -430,6 +428,7 @@
   }
 
   if (parameters.isEmpty && conversions.isEmpty && arguments.isEmpty) {
+    // ignore: unnecessary_null_comparison
     if (template != null) {
       codeArguments.add('message: r"""$template"""');
     }
@@ -448,6 +447,7 @@
   }
 
   List<String> templateArguments = <String>[];
+  // ignore: unnecessary_null_comparison
   if (template != null) {
     templateArguments.add('messageTemplate: r"""$template"""');
   }
diff --git a/pkg/front_end/tool/_fasta/log_analyzer.dart b/pkg/front_end/tool/_fasta/log_analyzer.dart
index 1a794a0..c93e916 100644
--- a/pkg/front_end/tool/_fasta/log_analyzer.dart
+++ b/pkg/front_end/tool/_fasta/log_analyzer.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:convert' show jsonDecode, jsonEncode;
 
 import 'dart:io';
diff --git a/pkg/front_end/tool/_fasta/log_collector.dart b/pkg/front_end/tool/_fasta/log_collector.dart
index 95dc56f..01fac75 100644
--- a/pkg/front_end/tool/_fasta/log_collector.dart
+++ b/pkg/front_end/tool/_fasta/log_collector.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:convert' show jsonDecode, utf8;
 
 import 'dart:isolate' show RawReceivePort;
@@ -55,7 +53,7 @@
   String month = "${time.month}".padLeft(2, "0");
   String day = "${time.day}".padLeft(2, "0");
   String us = "${time.microsecondsSinceEpoch}".padLeft(19, '0');
-  Uri uri = Uri.base
+  Uri? uri = Uri.base
       .resolve("crash_logs/${data['client']}/$year-$month-$day/$us.log");
   File file = new File.fromUri(uri);
   await file.parent.create(recursive: true);
@@ -63,12 +61,12 @@
   print("Wrote ${uri.toFilePath()}");
 
   String type = data["type"];
-  String text = data["uri"];
+  String? text = data["uri"];
   uri = text == null ? null : Uri.parse(text);
   int charOffset = data["offset"];
   var error = data["error"];
   text = data["trace"];
-  StackTrace trace = text == null ? null : new StackTrace.fromString(text);
+  StackTrace? trace = text == null ? null : new StackTrace.fromString(text);
   String client = data["client"];
   print("""
 date: ${time}
diff --git a/pkg/front_end/tool/ast_model.dart b/pkg/front_end/tool/ast_model.dart
new file mode 100644
index 0000000..14f981f
--- /dev/null
+++ b/pkg/front_end/tool/ast_model.dart
@@ -0,0 +1,771 @@
+// 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 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart';
+import 'package:front_end/src/api_prototype/front_end.dart';
+import 'package:front_end/src/api_prototype/kernel_generator.dart';
+import 'package:front_end/src/api_prototype/terminal_color_support.dart';
+import 'package:front_end/src/api_unstable/ddc.dart';
+import 'package:front_end/src/compute_platform_binaries_location.dart';
+import 'package:front_end/src/fasta/kernel/kernel_api.dart';
+import 'package:front_end/src/kernel_generator_impl.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/src/printer.dart';
+import 'package:kernel/type_environment.dart';
+
+final Uri astLibraryUri = Uri.parse('package:kernel/ast.dart');
+final Uri canonicalNameLibraryUri =
+    Uri.parse('package:kernel/canonical_name.dart');
+Uri computePackageConfig(Uri repoDir) =>
+    repoDir.resolve('.dart_tool/package_config.json');
+
+/// Map from names of node classes that declares nominal entities that are _not_
+/// referenced through a [Reference] to their identifying name, if any.
+///
+/// For these classes, [_fieldRuleMap] must defined whether fields of these
+/// types should be consider declarations or references to the declarations.
+///
+/// If the identifying name is non-null, this is used to determine the
+/// nominality. For instance the name of a variable declaration is taking as
+/// defining its identity.
+const Map<String, String> _declarativeClassesNames = const {
+  'VariableDeclaration': 'name',
+  'TypeParameter': 'name',
+  'LabeledStatement': null,
+  'SwitchCase': null,
+};
+
+/// Names of non-node, non-enum classes that should be treated as atomic
+/// values.
+const Set<String> _utilityClassesAsValues = const {
+  'Version',
+};
+
+/// Names of subclasses of [Node] that do _not_ have `visitX` or `defaultX`
+/// methods.
+const Set<String> _classesWithoutVisitMethods = const {
+  'InvocationExpression',
+  'InstanceInvocationExpression',
+  'NamedNode',
+  'PrimitiveConstant',
+};
+
+/// Names of subclasses of [NamedNode] that do _not_ have `visitXReference` or
+/// `defaultXReference` methods.
+const Set<String> _classesWithoutVisitReference = const {
+  'NamedNode',
+  'Library',
+  'PrimitiveConstant',
+};
+
+/// Map of [FieldRule]s. These consist of a map for each class name, with
+/// `null` used for "any class". For each class, a map from field names to
+/// [FieldRule] define exceptions to how a field should be treated.
+///
+/// If a field name maps to `null`, the field is not included in the [AstModel].
+const Map<String /*?*/, Map<String, FieldRule /*?*/ >> _fieldRuleMap = {
+  null: {
+    'hashCode': null,
+    'parent': null,
+  },
+  'Component': {
+    'root': null,
+    '_mainMethodName': FieldRule(name: 'mainMethodName'),
+    '_mode': FieldRule(name: 'mode'),
+  },
+  'Library': {
+    '_languageVersion': FieldRule(name: 'languageVersion'),
+    '_libraryId': null,
+    '_classes': FieldRule(name: 'classes'),
+    '_typedefs': FieldRule(name: 'typedefs'),
+    '_extensions': FieldRule(name: 'extensions'),
+    '_fields': FieldRule(name: 'fields'),
+    '_procedures': FieldRule(name: 'procedures'),
+  },
+  'Class': {
+    'typeParameters': FieldRule(isDeclaration: true),
+    '_constructorsView': null,
+    '_constructorsInternal': FieldRule(name: 'constructors'),
+    '_fieldsView': null,
+    '_fieldsInternal': FieldRule(name: 'fields'),
+    '_proceduresView': null,
+    '_proceduresInternal': FieldRule(name: 'procedures'),
+    '_redirectingFactoriesView': null,
+    '_redirectingFactoriesInternal':
+        FieldRule(name: 'redirectingFactories'),
+    'lazyBuilder': null,
+    'dirty': null,
+  },
+  'Extension': {
+    'typeParameters': FieldRule(isDeclaration: true),
+  },
+  'Field': {
+    'reference': FieldRule(name: 'getterReference'),
+  },
+  'TypeParameter': {
+    '_variance': FieldRule(name: 'variance'),
+  },
+  'FunctionNode': {
+    '_body': FieldRule(name: 'body'),
+    'typeParameters': FieldRule(isDeclaration: true),
+    'positionalParameters': FieldRule(isDeclaration: true),
+    'namedParameters': FieldRule(isDeclaration: true),
+  },
+  'Typedef': {
+    'typeParameters': FieldRule(isDeclaration: true),
+    'typeParametersOfFunctionType': FieldRule(isDeclaration: false),
+    'positionalParameters': FieldRule(isDeclaration: false),
+    'namedParameters': FieldRule(isDeclaration: false),
+  },
+  'TypedefTearOff': {
+    'typeParameters': FieldRule(isDeclaration: true),
+  },
+  'TypedefTearOffConstant': {
+    'parameters': FieldRule(isDeclaration: true),
+  },
+  'LocalInitializer': {
+    'variable': FieldRule(isDeclaration: true),
+  },
+  'Let': {
+    'variable': FieldRule(isDeclaration: true),
+  },
+  'VariableGet': {
+    'variable': FieldRule(isDeclaration: false),
+  },
+  'VariableSet': {
+    'variable': FieldRule(isDeclaration: false),
+  },
+  'LocalFunctionInvocation': {
+    'variable': FieldRule(isDeclaration: false),
+  },
+  'BreakStatement': {
+    'target': FieldRule(isDeclaration: false),
+  },
+  'ForStatement': {
+    'variables': FieldRule(isDeclaration: true),
+  },
+  'ForInStatement': {
+    'variable': FieldRule(isDeclaration: true),
+  },
+  'SwitchStatement': {
+    'cases': FieldRule(isDeclaration: true),
+  },
+  'ContinueSwitchStatement': {
+    'target': FieldRule(isDeclaration: false),
+  },
+  'Catch': {
+    'exception': FieldRule(isDeclaration: true),
+    'stackTrace': FieldRule(isDeclaration: true),
+  },
+  'FunctionDeclaration': {
+    'variable': FieldRule(isDeclaration: true),
+  },
+  'FunctionType': {
+    'typeParameters': FieldRule(isDeclaration: true),
+  },
+  'TypeParameterType': {
+    'parameter': FieldRule(isDeclaration: false),
+  },
+};
+
+/// Data that determines exceptions to how fields are used.
+class FieldRule {
+  /// If non-null, the field should be accessed by this name.
+  ///
+  /// This is for instance used for private fields accessed through a public
+  /// getter.
+  final String name;
+
+  /// For fields contain ast class of kind `AstClassKind.declarative`, this
+  /// value defines whether the field should be treated as a declaration or
+  /// a reference to the declaration.
+  final bool isDeclaration;
+
+  const FieldRule({this.name, this.isDeclaration});
+}
+
+/// Return the [FieldRule] to use for the [field] in [AstClass].
+FieldRule getFieldRule(AstClass astClass, Field field) {
+  String name = field.name.text;
+  Map<String, FieldRule> leafClassMap = _fieldRuleMap[astClass.name];
+  if (leafClassMap != null && leafClassMap.containsKey(name)) {
+    return leafClassMap[name];
+  }
+  Map<String, FieldRule> enclosingClassMap =
+      _fieldRuleMap[field.enclosingClass.name];
+  if (enclosingClassMap != null && enclosingClassMap.containsKey(name)) {
+    return enclosingClassMap[name];
+  }
+  Map<String, FieldRule> defaultClassMap = _fieldRuleMap[null];
+  if (defaultClassMap != null && defaultClassMap.containsKey(name)) {
+    return defaultClassMap[name];
+  }
+  return new FieldRule(name: name);
+}
+
+/// Categorization of classes declared in 'package:kernel/ast.dart'.
+enum AstClassKind {
+  /// The root [Node] class.
+  root,
+
+  /// An abstract node class that is a superclass of a public class. Most of
+  /// these have a corresponding `defaultX` visitor method.
+  ///
+  /// For instance [Statement] and [Expression].
+  inner,
+
+  /// A concrete node class. These are the classes for which we have `visitX`
+  /// methods.
+  ///
+  /// For instance [Procedure] and [VariableGet].
+  public,
+
+  /// A concrete node class that serves only as an implementation of public
+  /// node class.
+  ///
+  /// For instance [PrivateName] and [PublicName] that implements the public
+  /// node [Name].
+  implementation,
+
+  /// A node class that serves as an interface.
+  ///
+  /// For instance `FileUriNode`.
+  interface,
+
+  /// A named node class that declares a nominal entity that is used with a
+  /// reference.
+  named,
+
+  /// A node class that declares a nominal entity but used without reference.
+  ///
+  /// For instance [VariableDeclaration] which introduces a new entity when it
+  /// occurs in a [Block] but is used as a reference when it occurs in a
+  /// [VariableGet].
+  declarative,
+
+  /// A none-node class that should be treated as a composite structure.
+  ///
+  /// For instance [ConstantMapEntry] which is a tuple of a [Constant] key and
+  /// a [Constant] value.
+  utilityAsStructure,
+
+  /// A none-node class that should be treated as an atomic value.
+  ///
+  /// For instance enum classes.
+  utilityAsValue,
+}
+
+class AstClass {
+  final Class node;
+  AstClassKind _kind;
+  final String declarativeName;
+
+  AstClass superclass;
+  List<AstClass> interfaces = [];
+  List<AstClass> subclasses = [];
+  List<AstClass> subtypes = [];
+
+  List<AstField> fields = [];
+
+  AstClass(this.node,
+      {this.superclass, AstClassKind kind, this.declarativeName})
+      : _kind = kind {
+    if (superclass != null) {
+      superclass.subclasses.add(this);
+    }
+  }
+
+  String get name => node.name;
+
+  AstClassKind get kind {
+    if (_kind == null) {
+      if (node.isAbstract) {
+        if (subclasses.isNotEmpty) {
+          if (subclasses.every(
+              (element) => element.kind == AstClassKind.implementation)) {
+            _kind = AstClassKind.public;
+          } else {
+            _kind = AstClassKind.inner;
+          }
+        } else {
+          _kind = AstClassKind.interface;
+        }
+      } else {
+        if (node.name.startsWith('_')) {
+          _kind = AstClassKind.implementation;
+        } else {
+          _kind = AstClassKind.public;
+        }
+      }
+    }
+    return _kind;
+  }
+
+  /// Returns `true` if this class has a `visitX` or `defaultX` method.
+  ///
+  /// This is only valid for subclass of [Node].
+  bool get hasVisitMethod {
+    switch (kind) {
+      case AstClassKind.root:
+      case AstClassKind.inner:
+      case AstClassKind.public:
+      case AstClassKind.named:
+      case AstClassKind.declarative:
+        return !_classesWithoutVisitMethods.contains(name);
+      case AstClassKind.implementation:
+      case AstClassKind.interface:
+      case AstClassKind.utilityAsStructure:
+      case AstClassKind.utilityAsValue:
+        return false;
+    }
+    throw new UnsupportedError("Unexpected $kind");
+  }
+
+  /// Returns `true` if this class has a `visitXReference` or
+  /// `defaultXReference` method.
+  ///
+  /// This is only valid for subclass of [NamedNode] or [Constant].
+  bool get hasVisitReferenceMethod {
+    switch (kind) {
+      case AstClassKind.root:
+      case AstClassKind.inner:
+      case AstClassKind.public:
+      case AstClassKind.named:
+      case AstClassKind.declarative:
+        return !_classesWithoutVisitReference.contains(name);
+      case AstClassKind.implementation:
+      case AstClassKind.interface:
+      case AstClassKind.utilityAsStructure:
+      case AstClassKind.utilityAsValue:
+        return false;
+    }
+    throw new UnsupportedError("Unexpected $kind");
+  }
+
+  String dump([String indent = ""]) {
+    StringBuffer sb = new StringBuffer();
+    sb.writeln('${indent}${node.name} ($kind)');
+    for (AstField field in fields) {
+      sb.write(field.dump('${indent}    '));
+    }
+    for (AstClass subclass in subclasses) {
+      sb.write(subclass.dump('${indent}  '));
+    }
+    return sb.toString();
+  }
+
+  String toString() => '${runtimeType}(${name})';
+}
+
+/// Categorization of field types.
+enum AstFieldKind {
+  /// An atomic non-node value.
+  ///
+  /// For instance an [int] value.
+  value,
+
+  /// A [Node] value that is part of the tree.
+  ///
+  /// For instance an [Expression] value.
+  node,
+
+  /// A [Reference] value.
+  reference,
+
+  /// A reference to a declarative [Node].
+  ///
+  /// For instance the reference to [VariableDeclaration] in [VariableGet].
+  use,
+
+  /// A list of values.
+  list,
+
+  /// A set of values.
+  set,
+
+  /// A map of values.
+  map,
+
+  /// A non-node composite value.
+  ///
+  /// For instance a [ConstantMapEntry] that must be treat as a tuple of
+  /// a [Constant] key and a [Constant] value.
+  utility,
+}
+
+/// Structural description of a field type.
+class FieldType {
+  final DartType type;
+  final AstFieldKind kind;
+
+  FieldType(this.type, this.kind);
+
+  String toString() => 'FieldType($type,$kind)';
+}
+
+class ListFieldType extends FieldType {
+  final FieldType elementType;
+
+  ListFieldType(DartType type, this.elementType)
+      : super(type, AstFieldKind.list);
+
+  String toString() => 'ListFieldType($type,$elementType)';
+}
+
+class SetFieldType extends FieldType {
+  final FieldType elementType;
+
+  SetFieldType(DartType type, this.elementType) : super(type, AstFieldKind.set);
+
+  String toString() => 'SetFieldType($type,$elementType)';
+}
+
+class MapFieldType extends FieldType {
+  final FieldType keyType;
+  final FieldType valueType;
+
+  MapFieldType(DartType type, this.keyType, this.valueType)
+      : super(type, AstFieldKind.map);
+
+  String toString() => 'MapFieldType($type,$keyType,$valueType)';
+}
+
+class UtilityFieldType extends FieldType {
+  final AstClass astClass;
+
+  UtilityFieldType(DartType type, this.astClass)
+      : super(type, AstFieldKind.utility);
+
+  String toString() => 'UtilityFieldType($type,$astClass)';
+}
+
+class AstField {
+  final Field node;
+  final String name;
+  final FieldType type;
+
+  AstField(this.node, this.name, this.type);
+
+  String dump([String indent = ""]) {
+    StringBuffer sb = new StringBuffer();
+    sb.writeln('$indent$name $type');
+    return sb.toString();
+  }
+
+  String toString() => '${runtimeType}(${name})';
+}
+
+class AstModel {
+  final AstClass nodeClass;
+  final AstClass namedNodeClass;
+  final AstClass constantClass;
+
+  AstModel(this.nodeClass, this.namedNodeClass, this.constantClass);
+
+  /// Returns an [Iterable] for all declarative [Node] classes in the AST model.
+  Iterable<AstClass> get declarativeClasses {
+    return classes.where((cls) => cls.kind == AstClassKind.declarative);
+  }
+
+  /// Returns an [Iterable] for all [Node] (sub)classes in the AST model.
+  Iterable<AstClass> get classes sync* {
+    Iterable<AstClass> visitClass(AstClass cls) sync* {
+      yield cls;
+      for (AstClass subclass in cls.subclasses) {
+        yield* visitClass(subclass);
+      }
+    }
+
+    yield* visitClass(nodeClass);
+  }
+}
+
+/// Computes the [AstModel] from 'package:kernel/ast' using [repoDir] to locate
+/// the package config file.
+///
+/// If [printDump] is `true`, a dump of the model printed to stdout.
+Future<AstModel> deriveAstModel(Uri repoDir, {bool printDump: false}) async {
+  CompilerOptions options = new CompilerOptions();
+  options.sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
+  options.packagesFileUri = computePackageConfig(repoDir);
+  options.onDiagnostic = (DiagnosticMessage message) {
+    printDiagnosticMessage(message, print);
+  };
+
+  InternalCompilerResult compilerResult = await kernelForProgramInternal(
+      astLibraryUri, options,
+      retainDataForTesting: true, requireMain: false);
+  ClassHierarchy classHierarchy = compilerResult.classHierarchy;
+  CoreTypes coreTypes = compilerResult.coreTypes;
+  TypeEnvironment typeEnvironment =
+      new TypeEnvironment(coreTypes, classHierarchy);
+
+  Library astLibrary = compilerResult.component.libraries
+      .singleWhere((library) => library.importUri == astLibraryUri);
+
+  bool errorsFound = false;
+  void reportError(String message) {
+    print(message);
+    errorsFound = true;
+  }
+
+  Map<String, String> declarativeClassesNames = {..._declarativeClassesNames};
+  Set<String> classesWithoutVisitMethods = _classesWithoutVisitMethods.toSet();
+  Set<String> classesWithoutVisitReference =
+      _classesWithoutVisitReference.toSet();
+  Map<String, Map<String, FieldRule>> fieldRuleMap = {..._fieldRuleMap};
+  Map<String, FieldRule> nullFieldRules = {...?fieldRuleMap.remove(null)};
+  for (Class cls in astLibrary.classes) {
+    declarativeClassesNames.remove(cls.name);
+    classesWithoutVisitMethods.remove(cls.name);
+    classesWithoutVisitReference.remove(cls.name);
+    Map<String, FieldRule> fieldRules = {...?fieldRuleMap.remove(cls.name)};
+    Set<String> renames = {};
+    Class parent = cls;
+    while (parent != null && parent.enclosingLibrary == astLibrary) {
+      for (Field field in parent.fields) {
+        bool hasFieldRule = fieldRules.containsKey(field.name.text);
+        FieldRule fieldRule = fieldRules.remove(field.name.text);
+        if (fieldRule != null) {
+          if (fieldRule.name != null) {
+            renames.add(fieldRule.name);
+          }
+        }
+        if (!hasFieldRule) {
+          if (!cls.isEnum && !field.isStatic && field.name.isPrivate) {
+            reportError(
+                'Private field `${field.name.text}` in ${parent.name} must '
+                'have a field rule.');
+          }
+        }
+        if (nullFieldRules.containsKey(field.name.text)) {
+          FieldRule nullFieldRule = nullFieldRules.remove(field.name.text);
+          if (nullFieldRule != null) {
+            reportError('Only `null` is allowed for class `null`.');
+          }
+        }
+      }
+      parent = parent.superclass;
+    }
+    for (Procedure procedure in cls.procedures) {
+      renames.remove(procedure.name.text);
+    }
+    if (renames.isNotEmpty) {
+      reportError('Unknown procedure(s) for field redirections in '
+          '${cls.name}: ${renames}');
+    }
+    if (fieldRules.isNotEmpty) {
+      reportError(
+          'Unknown field(s) for rules in ${cls.name}: ${fieldRules.keys}');
+    }
+  }
+  if (declarativeClassesNames.isNotEmpty) {
+    reportError('Unknown declarative classes: ${declarativeClassesNames}');
+  }
+  if (classesWithoutVisitMethods.isNotEmpty) {
+    reportError('Unknown classes without visit methods: '
+        '${classesWithoutVisitMethods}');
+  }
+  if (classesWithoutVisitReference.isNotEmpty) {
+    reportError('Unknown classes without visit reference methods: '
+        '${classesWithoutVisitReference}');
+  }
+  if (fieldRuleMap.isNotEmpty) {
+    reportError('Unknown classes with field rules: ${fieldRuleMap.keys}');
+  }
+
+  Class classNode = astLibrary.classes.singleWhere((cls) => cls.name == 'Node');
+  DartType nullableNodeType =
+      classNode.getThisType(coreTypes, Nullability.nullable);
+
+  Class classNamedNode =
+      astLibrary.classes.singleWhere((cls) => cls.name == 'NamedNode');
+
+  Class classConstant =
+      astLibrary.classes.singleWhere((cls) => cls.name == 'Constant');
+
+  Library canonicalNameLibrary = compilerResult.component.libraries
+      .singleWhere((library) => library.importUri == canonicalNameLibraryUri);
+
+  Class referenceClass = canonicalNameLibrary.classes
+      .singleWhere((cls) => cls.name == 'Reference');
+  DartType nullableReferenceType =
+      referenceClass.getThisType(coreTypes, Nullability.nullable);
+
+  Set<Class> declarativeClasses = {};
+  Set<DartType> declarativeTypes = {};
+  for (String name in _declarativeClassesNames.keys) {
+    Class cls = astLibrary.classes.singleWhere((cls) => cls.name == name);
+    declarativeClasses.add(cls);
+    declarativeTypes.add(cls.getThisType(coreTypes, Nullability.nullable));
+  }
+
+  Map<Class, AstClass> classMap = {};
+
+  /// Computes the [AstClass] corresponding to [node] if [node] is declared in
+  /// 'package:kernel/ast.dart'.
+  AstClass computeAstClass(Class node) {
+    if (node == null) return null;
+    if (node.enclosingLibrary != astLibrary) return null;
+
+    AstClass astClass = classMap[node];
+    if (astClass == null) {
+      if (node == classNode) {
+        astClass = new AstClass(node, kind: AstClassKind.root);
+      } else if (classHierarchy.isSubtypeOf(node, classNode)) {
+        AstClass superclass = computeAstClass(node.superclass);
+        AstClassKind kind;
+        String declarativeName;
+        if (!node.isAbstract &&
+            classHierarchy.isSubtypeOf(node, classNamedNode)) {
+          kind = AstClassKind.named;
+        } else if (declarativeClasses.contains(node)) {
+          kind = AstClassKind.declarative;
+          declarativeName = _declarativeClassesNames[node.name];
+        }
+        astClass = new AstClass(node,
+            superclass: superclass,
+            kind: kind,
+            declarativeName: declarativeName);
+        for (Supertype supertype in node.implementedTypes) {
+          AstClass astSupertype = computeAstClass(supertype.classNode);
+          if (astSupertype != null) {
+            astClass.interfaces.add(astSupertype);
+            astSupertype.subtypes.add(astClass);
+          }
+        }
+      } else if (node.isEnum || _utilityClassesAsValues.contains(node.name)) {
+        astClass = new AstClass(node, kind: AstClassKind.utilityAsValue);
+      } else {
+        AstClass superclass = computeAstClass(node.superclass);
+        astClass = new AstClass(node,
+            superclass: superclass, kind: AstClassKind.utilityAsStructure);
+      }
+      if (astClass != null) {
+        classMap[node] = astClass;
+      }
+    }
+    return astClass;
+  }
+
+  for (Class cls in astLibrary.classes) {
+    computeAstClass(cls);
+  }
+
+  for (AstClass astClass in classMap.values) {
+    void computeAstField(Field field, Substitution substitution) {
+      if (field.isStatic) {
+        return;
+      }
+      FieldRule rule = getFieldRule(astClass, field);
+      if (rule == null) {
+        return;
+      }
+      DartType type = substitution.substituteType(field.type);
+
+      FieldType computeFieldType(DartType type) {
+        bool isDeclarativeType = false;
+        for (InterfaceType declarativeType in declarativeTypes) {
+          if (type is InterfaceType &&
+              typeEnvironment.isSubtypeOf(
+                  type, declarativeType, SubtypeCheckMode.withNullabilities)) {
+            isDeclarativeType = true;
+            break;
+          }
+        }
+        if (isDeclarativeType) {
+          if (rule.isDeclaration == null) {
+            reportError(
+                "No field rule for '${field.name}' in ${astClass.name}.\n"
+                "The field type contains the declarative type "
+                "'${type.toText(defaultAstTextStrategy)}' "
+                "and a rule must therefore specify "
+                "whether this constitutes declarative or referential use.");
+          }
+          if (!rule.isDeclaration) {
+            return new FieldType(type, AstFieldKind.use);
+          }
+        }
+        if (type is InterfaceType &&
+            typeEnvironment.isSubtypeOf(type, coreTypes.listNullableRawType,
+                SubtypeCheckMode.withNullabilities)) {
+          DartType elementType = typeEnvironment
+              .getTypeArgumentsAsInstanceOf(type, coreTypes.listClass)
+              .single;
+          return new ListFieldType(type, computeFieldType(elementType));
+        } else if (type is InterfaceType &&
+            typeEnvironment.isSubtypeOf(type, coreTypes.setNullableRawType,
+                SubtypeCheckMode.withNullabilities)) {
+          DartType elementType = typeEnvironment
+              .getTypeArgumentsAsInstanceOf(type, coreTypes.setClass)
+              .single;
+          return new SetFieldType(type, computeFieldType(elementType));
+        } else if (type is InterfaceType &&
+            typeEnvironment.isSubtypeOf(type, coreTypes.mapNullableRawType,
+                SubtypeCheckMode.withNullabilities)) {
+          List<DartType> typeArguments = typeEnvironment
+              .getTypeArgumentsAsInstanceOf(type, coreTypes.mapClass);
+          return new MapFieldType(type, computeFieldType(typeArguments[0]),
+              computeFieldType(typeArguments[1]));
+        } else if (type is InterfaceType &&
+            typeEnvironment.isSubtypeOf(
+                type, nullableNodeType, SubtypeCheckMode.withNullabilities)) {
+          return new FieldType(type, AstFieldKind.node);
+        } else if (type is InterfaceType &&
+            typeEnvironment.isSubtypeOf(type, nullableReferenceType,
+                SubtypeCheckMode.withNullabilities)) {
+          return new FieldType(type, AstFieldKind.reference);
+        } else {
+          if (type is InterfaceType) {
+            AstClass astClass = classMap[type.classNode];
+            if (astClass != null &&
+                astClass.kind == AstClassKind.utilityAsStructure) {
+              return new UtilityFieldType(type, astClass);
+            }
+          }
+          return new FieldType(type, AstFieldKind.value);
+        }
+      }
+
+      FieldType fieldType;
+      fieldType ??= computeFieldType(type);
+      astClass.fields
+          .add(new AstField(field, rule.name ?? field.name.text, fieldType));
+    }
+
+    AstClass parent = astClass;
+    Substitution substitution = Substitution.empty;
+    while (parent != null) {
+      for (Field field in parent.node.fields) {
+        computeAstField(field, substitution);
+      }
+      parent = parent.superclass;
+      if (parent != null) {
+        substitution = Substitution.fromSupertype(
+            classHierarchy.getClassAsInstanceOf(astClass.node, parent.node));
+      }
+    }
+  }
+
+  AstClass astClassNode = classMap[classNode];
+  AstClass astClassNamedNode = classMap[classNamedNode];
+  AstClass astClassConstant = classMap[classConstant];
+
+  if (printDump) {
+    print(classMap[classNode].dump());
+    for (AstClass astClass in classMap.values) {
+      if (astClass != astClassNode && astClass.superclass == null) {
+        print(astClass.dump());
+      }
+    }
+  }
+  if (errorsFound) {
+    throw 'Errors found';
+  }
+  return new AstModel(astClassNode, astClassNamedNode, astClassConstant);
+}
diff --git a/pkg/front_end/tool/dart_doctest_impl.dart b/pkg/front_end/tool/dart_doctest_impl.dart
index 3051c00e..38e9a55 100644
--- a/pkg/front_end/tool/dart_doctest_impl.dart
+++ b/pkg/front_end/tool/dart_doctest_impl.dart
@@ -789,7 +789,7 @@
       LibraryBuilder libraryBuilder = userCode!.loader
           .read(libraryUri, -1, accessor: userCode!.loader.first);
 
-      userCode!.loader.seenMessages.clear();
+      userCode!.loader.resetSeenMessages();
 
       _dartDocTestLibraryBuilder = libraryBuilder;
       _dartDocTestCode = dartDocTestCode;
diff --git a/pkg/front_end/tool/fasta.dart b/pkg/front_end/tool/fasta.dart
index b2b8d26..af6094b 100644
--- a/pkg/front_end/tool/fasta.dart
+++ b/pkg/front_end/tool/fasta.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:io';
 
 import '../test/utils/io_utils.dart' show computeRepoDir;
@@ -95,7 +93,7 @@
   exitCode = await process.exitCode;
 }
 
-void stop(String message) {
+Never stop(String message) {
   stderr.write(message);
   exit(2);
 }
diff --git a/pkg/front_end/tool/generate_ast_equivalence.dart b/pkg/front_end/tool/generate_ast_equivalence.dart
new file mode 100644
index 0000000..87349d6
--- /dev/null
+++ b/pkg/front_end/tool/generate_ast_equivalence.dart
@@ -0,0 +1,956 @@
+// 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:io';
+
+import 'ast_model.dart';
+import 'visitor_generator.dart';
+
+Uri computeEquivalenceUri(Uri repoDir) {
+  return repoDir.resolve('pkg/kernel/lib/src/equivalence.dart');
+}
+
+main(List<String> args) async {
+  Uri output = args.isEmpty
+      ? computeEquivalenceUri(Uri.base)
+      : new File(args[0]).absolute.uri;
+  String result = await generateAstEquivalence(Uri.base);
+  new File.fromUri(output).writeAsStringSync(result);
+}
+
+Future<String> generateAstEquivalence(Uri repoDir) async {
+  AstModel astModel = await deriveAstModel(repoDir);
+  return generateVisitor(astModel, new EquivalenceVisitorStrategy());
+}
+
+class EquivalenceVisitorStrategy extends Visitor1Strategy {
+  Map<AstClass, String> _classStrategyMembers = {};
+  Map<AstField, String> _fieldStrategyMembers = {};
+
+  EquivalenceVisitorStrategy();
+
+  @override
+  String get argumentType => 'Node';
+
+  @override
+  String get argumentName => 'other';
+
+  @override
+  String get returnType => 'bool';
+
+  @override
+  String get visitorName => 'EquivalenceVisitor';
+
+  String get strategyName => 'EquivalenceStrategy';
+
+  String get internalCheckValues => '_checkValues';
+
+  String get checkValues => 'checkValues';
+
+  String get matchValues => 'matchValues';
+
+  String get internalCheckNodes => '_checkNodes';
+
+  String get checkNodes => 'checkNodes';
+
+  String get shallowMatchNodes => 'shallowMatchNodes';
+
+  String get deepMatchNodes => 'deepMatchNodes';
+
+  String get internalCheckReferences => '_checkReferences';
+
+  String get checkReferences => 'checkReferences';
+
+  String get matchReferences => 'matchReferences';
+
+  String get deepMatchReferences => 'deeplyMatchReferences';
+
+  String get matchNamedNodes => 'matchNamedNodes';
+
+  String get assumeReferences => 'assumeReferences';
+
+  String get checkAssumedReferences => 'checkAssumedReferences';
+
+  String get checkDeclarations => 'checkDeclarations';
+
+  String get internalCheckDeclarations => '_checkDeclarations';
+
+  String get shallowMatchDeclarations => 'matchDeclarations';
+
+  String get deepMatchDeclarations => 'deepMatchDeclarations';
+
+  String get assumeDeclarations => 'assumeDeclarations';
+
+  String get checkAssumedDeclarations => 'checkAssumedDeclarations';
+
+  String get checkLists => 'checkLists';
+
+  String get matchLists => 'matchLists';
+
+  String get checkSets => 'checkSets';
+
+  String get matchSets => 'matchSets';
+
+  String get checkMaps => 'checkMaps';
+
+  String get matchMaps => 'matchMaps';
+
+  String get checkingState => '_checkingState';
+
+  String get resultOnInequivalence => 'resultOnInequivalence';
+
+  String get registerInequivalence => 'registerInequivalence';
+
+  String classCheckName(AstClass astClass) => 'check${astClass.name}';
+
+  String fieldCheckName(AstClass astClass, AstField field) =>
+      'check${astClass.name}_${field.name}';
+
+  @override
+  void handleDefaultVisit(AstClass astClass, StringBuffer sb) {
+    sb.writeln('''
+    return false;''');
+  }
+
+  /// Compute the expression code for shallow matching two values of type
+  /// [fieldType].
+  ///
+  /// Shallow matching is used to pair value when checking sets and maps. The
+  /// checking doesn't traverse the AST deeply and inequivalences are not
+  /// registered.
+  ///
+  /// [prefix] is used as the receiver of the invocation.
+  String computeMatchingHelper(FieldType fieldType, [String prefix = '']) {
+    String thisName = 'a';
+    String otherName = 'b';
+    switch (fieldType.kind) {
+      case AstFieldKind.value:
+        return '$prefix$matchValues';
+      case AstFieldKind.node:
+        return '$prefix$shallowMatchNodes';
+      case AstFieldKind.reference:
+        return '$prefix$matchReferences';
+      case AstFieldKind.use:
+        return '$prefix$shallowMatchDeclarations';
+      case AstFieldKind.list:
+        ListFieldType listFieldType = fieldType;
+        String elementEquivalence =
+            computeMatchingHelper(listFieldType.elementType);
+        return '($thisName, $otherName) => $prefix$matchLists('
+            '$thisName, $otherName, $elementEquivalence)';
+      case AstFieldKind.set:
+        SetFieldType setFieldType = fieldType;
+        String elementMatching =
+            computeMatchingHelper(setFieldType.elementType);
+        String elementEquivalence =
+            computeEquivalenceHelper(setFieldType.elementType);
+        return '($thisName, $otherName) => $prefix$checkSets('
+            '$thisName, $otherName, $elementMatching, $elementEquivalence)';
+      case AstFieldKind.map:
+        MapFieldType mapFieldType = fieldType;
+        String keyMatching = computeMatchingHelper(mapFieldType.keyType);
+        String keyEquivalence = computeEquivalenceHelper(mapFieldType.keyType);
+        String valueEquivalence =
+            computeEquivalenceHelper(mapFieldType.valueType);
+        return '($thisName,  $otherName) => $prefix$checkMaps('
+            '$thisName, $otherName, $keyMatching, '
+            '$keyEquivalence, $valueEquivalence)';
+      case AstFieldKind.utility:
+        StringBuffer sb = new StringBuffer();
+        UtilityFieldType utilityFieldType = fieldType;
+        registerAstClassEquivalence(utilityFieldType.astClass);
+        sb.writeln('''($thisName, $otherName, _) {
+    if (identical($thisName, $otherName)) return true;
+    if ($thisName is! ${utilityFieldType.astClass.name}) return false;
+    if ($otherName is! ${utilityFieldType.astClass.name}) return false;
+    return ${classCheckName(utilityFieldType.astClass)}(
+        visitor,
+        $thisName,
+        $otherName);
+  }''');
+        return sb.toString();
+    }
+    throw ArgumentError("Unexpected field type ${fieldType}");
+  }
+
+  /// Computes the expression code for checking the equivalence of two fields
+  /// of type [fieldType].
+  ///
+  /// Checking is used to check the AST for equivalence and inequivalences are
+  /// registered.
+  ///
+  /// [prefix] is used as the receiver of the invocation.
+  String computeEquivalenceHelper(FieldType fieldType, [String prefix = '']) {
+    String thisName = 'a';
+    String otherName = 'b';
+    switch (fieldType.kind) {
+      case AstFieldKind.value:
+        return '$prefix$checkValues';
+      case AstFieldKind.node:
+        return '$prefix$checkNodes';
+      case AstFieldKind.reference:
+        return '$prefix$checkReferences';
+      case AstFieldKind.use:
+        return '$prefix$checkDeclarations';
+      case AstFieldKind.list:
+        ListFieldType listFieldType = fieldType;
+        String elementEquivalence =
+            computeEquivalenceHelper(listFieldType.elementType);
+        return '($thisName, $otherName) => $prefix$checkLists('
+            '$thisName, $otherName, $elementEquivalence)';
+      case AstFieldKind.set:
+        SetFieldType setFieldType = fieldType;
+        String elementMatching =
+            computeMatchingHelper(setFieldType.elementType);
+        String elementEquivalence =
+            computeEquivalenceHelper(setFieldType.elementType);
+        return '($thisName, $otherName) => $prefix$checkSets('
+            '$thisName, $otherName, $elementMatching, $elementEquivalence)';
+      case AstFieldKind.map:
+        MapFieldType mapFieldType = fieldType;
+        String keyMatching = computeMatchingHelper(mapFieldType.keyType);
+        String keyEquivalence = computeEquivalenceHelper(mapFieldType.keyType);
+        String valueEquivalence =
+            computeEquivalenceHelper(mapFieldType.valueType);
+        return '($thisName, $otherName) => $prefix$checkMaps('
+            '$thisName, $otherName, $keyMatching, '
+            '$keyEquivalence, $valueEquivalence)';
+      case AstFieldKind.utility:
+        StringBuffer sb = new StringBuffer();
+        UtilityFieldType utilityFieldType = fieldType;
+        registerAstClassEquivalence(utilityFieldType.astClass);
+        sb.writeln('''($thisName, $otherName, _) {
+    if (identical($thisName, $otherName)) return true;
+    if ($thisName is! ${utilityFieldType.astClass.name}) return false;
+    if ($otherName is! ${utilityFieldType.astClass.name}) return false;
+    return ${classCheckName(utilityFieldType.astClass)}(
+        visitor,
+        $thisName,
+        $otherName);
+  }''');
+        return sb.toString();
+    }
+    throw ArgumentError("Unexpected field type ${fieldType}");
+  }
+
+  /// Registers that a strategy method is needed for checking [astClass].
+  ///
+  /// If the method has not already been generated, it is generated and stored
+  /// in [_classStrategyMembers].
+  void registerAstClassEquivalence(AstClass astClass) {
+    if (_classStrategyMembers.containsKey(astClass)) return;
+
+    String thisName = 'node';
+    String otherName = 'other';
+    StringBuffer classStrategy = new StringBuffer();
+    classStrategy.writeln('''
+  bool ${classCheckName(astClass)}(
+      $visitorName visitor,
+      ${astClass.name}? $thisName,
+      Object? $otherName) {''');
+
+    classStrategy.writeln('''
+    if (identical($thisName, $otherName)) return true;
+    if ($thisName is! ${astClass.name}) return false;
+    if ($otherName is! ${astClass.name}) return false;''');
+    if (astClass.kind == AstClassKind.named) {
+      classStrategy.writeln('''
+    if (!visitor.$matchNamedNodes($thisName, $otherName)) {
+      return false;
+    }''');
+    } else if (astClass.kind == AstClassKind.declarative) {
+      classStrategy.writeln('''
+    if (!visitor.$checkDeclarations($thisName, $otherName, '')) {
+      return false;
+    }''');
+    }
+
+    if (astClass.kind != AstClassKind.utilityAsStructure) {
+      classStrategy.writeln('''
+    visitor.pushNodeState($thisName, $otherName);''');
+    }
+    classStrategy.writeln('''
+    bool result = true;''');
+    for (AstField field in astClass.fields) {
+      registerAstFieldEquivalence(astClass, field);
+      classStrategy.writeln('''
+    if (!${fieldCheckName(astClass, field)}(visitor, $thisName, $otherName)) {
+      result = visitor.$resultOnInequivalence;
+    }''');
+    }
+
+    if (astClass.kind != AstClassKind.utilityAsStructure) {
+      classStrategy.writeln('''
+    visitor.popState();''');
+    }
+
+    classStrategy.writeln('''
+    return result;
+  }''');
+
+    _classStrategyMembers[astClass] = classStrategy.toString();
+  }
+
+  /// Registers that a strategy method is needed for checking [field] in
+  /// [astClass].
+  ///
+  /// If the method has not already been generated, it is generated and stored
+  /// in [_fieldStrategyMembers].
+  void registerAstFieldEquivalence(AstClass astClass, AstField field) {
+    if (_fieldStrategyMembers.containsKey(field)) return;
+
+    String thisName = 'node';
+    String otherName = 'other';
+    StringBuffer fieldStrategy = new StringBuffer();
+    fieldStrategy.writeln('''
+  bool ${fieldCheckName(astClass, field)}(
+      $visitorName visitor,
+      ${astClass.name} $thisName,
+      ${astClass.name} $otherName) {''');
+
+    switch (field.type.kind) {
+      case AstFieldKind.value:
+        fieldStrategy.writeln('''
+    return visitor.$checkValues(
+        $thisName.${field.name},
+        $otherName.${field.name},
+        '${field.name}');''');
+        break;
+      case AstFieldKind.node:
+        fieldStrategy.writeln('''
+    return visitor.$checkNodes(
+        $thisName.${field.name},
+        $otherName.${field.name},
+        '${field.name}');''');
+        break;
+      case AstFieldKind.reference:
+        fieldStrategy.writeln('''
+    return visitor.$checkReferences(
+        $thisName.${field.name},
+        $otherName.${field.name},
+        '${field.name}');''');
+        break;
+      case AstFieldKind.use:
+        fieldStrategy.writeln('''
+    return visitor.$checkDeclarations(
+        $thisName.${field.name},
+        $otherName.${field.name},
+        '${field.name}');''');
+        break;
+      case AstFieldKind.list:
+        ListFieldType listFieldType = field.type;
+        fieldStrategy.writeln('''
+    return visitor.$checkLists(
+        $thisName.${field.name},
+        $otherName.${field.name},
+        ${computeEquivalenceHelper(listFieldType.elementType, 'visitor.')},
+        '${field.name}');''');
+        break;
+      case AstFieldKind.set:
+        SetFieldType setFieldType = field.type;
+        fieldStrategy.writeln('''
+    return visitor.$checkSets(
+        $thisName.${field.name},
+        $otherName.${field.name},
+        ${computeMatchingHelper(setFieldType.elementType, 'visitor.')},
+        ${computeEquivalenceHelper(setFieldType.elementType, 'visitor.')},
+        '${field.name}');''');
+        break;
+      case AstFieldKind.map:
+        MapFieldType mapFieldType = field.type;
+        fieldStrategy.writeln('''
+    return visitor.$checkMaps(
+        $thisName.${field.name},
+        $otherName.${field.name},
+        ${computeMatchingHelper(mapFieldType.keyType, 'visitor.')},
+        ${computeEquivalenceHelper(mapFieldType.keyType, 'visitor.')},
+        ${computeEquivalenceHelper(mapFieldType.valueType, 'visitor.')},
+        '${field.name}');''');
+        break;
+      case AstFieldKind.utility:
+        UtilityFieldType utilityFieldType = field.type;
+        registerAstClassEquivalence(utilityFieldType.astClass);
+        fieldStrategy.writeln('''
+    '${field.name}';
+    return ${classCheckName(utilityFieldType.astClass)}(
+        visitor,
+        $thisName.${field.name},
+        $otherName.${field.name});''');
+        break;
+    }
+    fieldStrategy.writeln('''
+  }''');
+    _fieldStrategyMembers[field] = fieldStrategy.toString();
+  }
+
+  @override
+  void handleVisit(AstClass astClass, StringBuffer sb) {
+    registerAstClassEquivalence(astClass);
+    sb.writeln('''
+    return strategy.${classCheckName(astClass)}(
+        this, node, $argumentName);''');
+  }
+
+  @override
+  void handleDefaultVisitReference(AstClass astClass, StringBuffer sb) {
+    sb.writeln('''
+    return false;''');
+  }
+
+  @override
+  void handleVisitReference(AstClass astClass, StringBuffer sb) {
+    sb.writeln('''
+    return false;''');
+  }
+
+  void generateHeader(AstModel astModel, StringBuffer sb) {
+    sb.writeln('''
+// 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.
+
+// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Run 'dart pkg/front_end/tool/generate_ast_equivalence.dart' to update.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/src/printer.dart';
+import 'union_find.dart';
+
+part 'equivalence_helpers.dart';
+
+/// Visitor that uses a $strategyName to compute AST node equivalence.
+///
+/// The visitor hold a current state that collects found inequivalences and
+/// current assumptions. The current state has two modes. In the asserting mode,
+/// the default, inequivalences are registered when found. In the non-asserting
+/// mode, inequivalences are _not_ registered. The latter is used to compute
+/// equivalences in sand boxed state, for instance to determine which elements
+/// to pair when checking equivalence of two sets.
+class $visitorName$visitorTypeParameters
+    implements Visitor1<$returnType, $argumentType> {
+  final $strategyName strategy;
+
+  $visitorName({
+      this.strategy: const $strategyName()});
+''');
+  }
+
+  @override
+  void generateFooter(AstModel astModel, StringBuffer sb) {
+    sb.writeln('''
+  /// Returns `true` if [a] and [b] are identical or equal.
+  bool $internalCheckValues<T>(T? a, T? b) {
+    return identical(a, b) || a == b;
+  }
+
+  /// Returns `true` if [a] and [b] are identical or equal and registers the
+  /// inequivalence otherwise.
+  bool $checkValues<T>(T? a, T? b, String propertyName) {
+    bool result = $internalCheckValues(a, b);
+    if (!result) {
+      registerInequivalence(
+          propertyName, 'Values \${a} and \${b} are not equivalent');
+    }
+    return result;
+  }
+
+  /// Returns `true` if [a] and [b] are identical or equal. Inequivalence is
+  /// _not_ registered.
+  bool $matchValues<T>(T? a, T? b) {
+    return $internalCheckValues(a, b);
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent.
+  bool $internalCheckNodes<T extends Node>(T? a, T? b) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) {
+      return false;
+    } else {
+      return a.accept1(this, b);
+    }
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, as defined by the current
+  /// strategy, and registers the inequivalence otherwise.
+  bool $checkNodes<T extends Node>(T? a, T? b,
+      [String propertyName = '']) {
+    $checkingState.pushPropertyState(propertyName);
+    bool result = $internalCheckNodes(a, b);
+    $checkingState.popState();
+    if (!result) {
+      $registerInequivalence(
+          propertyName, 'Inequivalent nodes\\n1: \${a}\\n2: \${b}');
+    }
+    return result;
+  }
+
+  /// Returns `true` if [a] and [b] are identical or equal. Inequivalence is
+  /// _not_ registered.
+  bool $shallowMatchNodes<T extends Node>(T? a, T? b) {
+    return $internalCheckValues(a, b);
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, as defined by the current
+  /// strategy. Inequivalence is _not_ registered.
+  bool $deepMatchNodes<T extends Node>(T? a, T? b) {
+    CheckingState oldState = $checkingState;
+    $checkingState = $checkingState.toMatchingState();
+    bool result = $checkNodes(a, b);
+    $checkingState = oldState;
+    return result;
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, as defined by their
+  /// corresponding canonical names. Inequivalence is _not_ registered.
+  bool $matchNamedNodes(NamedNode? a, NamedNode? b) {
+    return identical(a, b) ||
+        a == null ||
+        b == null ||
+        new ReferenceName.fromNamedNode(a) ==
+            new ReferenceName.fromNamedNode(b);
+  }
+
+  /// Returns `true` if [a] and [b] are currently assumed to be equivalent.
+  bool $checkAssumedReferences(Reference? a, Reference? b) {
+    return $checkingState.$checkAssumedReferences(a, b);
+  }
+
+  /// Assume that [a] and [b] are equivalent, if possible.
+  ///
+  /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+  /// would not be the case if [a] xor [b] is `null`.
+  bool $assumeReferences(Reference? a, Reference? b) {
+    return $checkingState.$assumeReferences(a, b);
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, as defined by their
+  /// corresponding canonical names. Inequivalence is _not_ registered.
+  bool $matchReferences(Reference? a, Reference? b) {
+    return identical(a, b) ||
+        ReferenceName.fromReference(a) ==
+            ReferenceName.fromReference(b);
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, either by their
+  /// corresponding canonical names or by assumption. Inequivalence is _not_
+  /// registered.
+  bool $internalCheckReferences(Reference? a, Reference? b) {
+    if (identical(a, b)) {
+      return true;
+    } else if (a == null || b == null) {
+      return false;
+    } else if ($matchReferences(a, b)) {
+      return true;
+    } else if ($checkAssumedReferences(a, b)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, either by their
+  /// corresponding canonical names or by assumption. Inequivalence is _not_
+  /// registered.
+  bool $deepMatchReferences(Reference? a, Reference? b) {
+    CheckingState oldState = $checkingState;
+    $checkingState = $checkingState.toMatchingState();
+    bool result = $checkReferences(a, b);
+    $checkingState = oldState;
+    return result;
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, either by their
+  /// corresponding canonical names or by assumption, and registers the
+  /// inequivalence otherwise.
+  bool $checkReferences(
+      Reference? a,
+      Reference? b,
+      [String propertyName = '']) {
+    bool result = $internalCheckReferences(a, b);
+    if (!result) {
+      $registerInequivalence(
+          propertyName, 'Inequivalent references:\\n1: \${a}\\n2: \${b}');
+    }
+    return result;
+  }
+
+  /// Returns `true` if declarations [a] and [b] are currently assumed to be
+  /// equivalent.
+  bool $checkAssumedDeclarations(dynamic a, dynamic b) {
+    return $checkingState.$checkAssumedDeclarations(a, b);
+  }
+
+  /// Assume that [a] and [b] are equivalent, if possible.
+  ///
+  /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+  /// would not be the case if [a] is already assumed to be equivalent to
+  /// another declaration.
+  bool $assumeDeclarations(dynamic a, dynamic b) {
+    return $checkingState.$assumeDeclarations(a, b);
+  }
+
+  bool $shallowMatchDeclarations(dynamic a, dynamic b) {''');
+
+    for (AstClass cls in astModel.declarativeClasses) {
+      if (cls.declarativeName != null) {
+        sb.write('''
+    if (a is ${cls.name}) {
+      return b is ${cls.name} &&
+          a.${cls.declarativeName} == b.${cls.declarativeName};
+    }
+''');
+      } else {
+        sb.write('''
+    if (a is ${cls.name}) {
+      return b is ${cls.name};
+    }
+''');
+      }
+    }
+    try {
+      try {
+        try {
+          sb.writeln('''
+          return false;
+  }
+
+  bool $internalCheckDeclarations(dynamic a, dynamic b) {
+          if (identical(a, b)) {
+            return true;
+          } else if (a == null || b == null) {
+            return false;
+          } else if ($checkAssumedDeclarations(a, b)) {
+            return true;
+          } else if ($shallowMatchDeclarations(a, b)) {
+            return $assumeDeclarations(a, b);
+          } else {
+            return false;
+          }
+  }
+
+  bool $deepMatchDeclarations(dynamic a, dynamic b) {
+          CheckingState oldState = $checkingState;
+          $checkingState = $checkingState.toMatchingState();
+          bool result = $checkDeclarations(a, b);
+          $checkingState = oldState;
+          return result;
+  }
+
+  bool $checkDeclarations(dynamic a, dynamic b,
+            [String propertyName = '']) {
+          bool result = $internalCheckDeclarations(a, b);
+          if (!result) {
+            result = $assumeDeclarations(a, b);
+          }
+          if (!result) {
+            $registerInequivalence(
+                propertyName, 'Declarations \${a} and \${b} are not equivalent');
+          }
+          return result;
+  }
+
+  /// Returns `true` if lists [a] and [b] are equivalent, using
+  /// [equivalentValues] to determine element-wise equivalence.
+  ///
+  /// If run in a checking state, the [propertyName] is used for registering
+  /// inequivalences.
+  bool $checkLists<E>(
+            List<E>? a,
+            List<E>? b,
+            bool Function(E?, E?, String) equivalentValues,
+            [String propertyName = '']) {
+          if (identical(a, b)) return true;
+          if (a == null || b == null) return false;
+          if (a.length != b.length) {
+            $registerInequivalence(
+              '\${propertyName}.length', 'Lists \${a} and \${b} are not equivalent');
+            return false;
+          }
+          for (int i = 0; i < a.length; i++) {
+            if (!equivalentValues(a[i], b[i], '\${propertyName}[\${i}]')) {
+              return false;
+            }
+          }
+          return true;
+  }
+
+  /// Returns `true` if lists [a] and [b] are equivalent, using
+  /// [equivalentValues] to determine element-wise equivalence.
+  ///
+  /// Inequivalence is _not_ registered.
+  bool $matchLists<E>(
+            List<E>? a,
+            List<E>? b,
+            bool Function(E?, E?, String) equivalentValues) {
+          CheckingState oldState = $checkingState;
+          $checkingState = $checkingState.toMatchingState();
+          bool result = $checkLists(a, b, equivalentValues);
+          $checkingState = oldState;
+          return result;
+  }
+
+  /// Returns `true` if sets [a] and [b] are equivalent, using
+  /// [matchingValues] to determine which elements that should be checked for
+  /// element-wise equivalence using [equivalentValues].
+  ///
+  /// If run in a checking state, the [propertyName] is used for registering
+  /// inequivalences.
+  bool $checkSets<E>(
+            Set<E>? a,
+            Set<E>? b,
+            bool Function(E?, E?) matchingValues,
+            bool Function(E?, E?, String) equivalentValues,
+            [String propertyName = '']) {
+          if (identical(a, b)) return true;
+          if (a == null || b == null) return false;
+          if (a.length != b.length) {
+            $registerInequivalence(
+                '\${propertyName}.length', 'Sets \${a} and \${b} are not equivalent');
+            return false;
+          }
+          b = b.toSet();
+          for (E aValue in a) {
+            bool hasFoundValue = false;
+            E? foundValue;
+            for (E bValue in b) {
+              if (matchingValues(aValue, bValue)) {
+                foundValue = bValue;
+                hasFoundValue = true;
+                if (!equivalentValues(aValue, bValue,
+                    '\${propertyName}[\${aValue}]')) {
+                  $registerInequivalence(
+                      '\${propertyName}[\${aValue}]',
+                      'Elements \${aValue} and \${bValue} are not equivalent');
+                  return false;
+                }
+                break;
+              }
+            }
+            if (hasFoundValue) {
+              b.remove(foundValue);
+            } else {
+              $registerInequivalence(
+                  '\${propertyName}[\${aValue}]',
+                  'Sets \${a} and \${b} are not equivalent, no equivalent value '
+                  'found for \$aValue');
+              return false;
+            }
+          }
+          return true;
+  }
+
+  /// Returns `true` if sets [a] and [b] are equivalent, using
+  /// [matchingValues] to determine which elements that should be checked for
+  /// element-wise equivalence using [equivalentValues].
+  ///
+  /// Inequivalence is _not_registered.
+  bool $matchSets<E>(
+            Set<E>? a,
+            Set<E>? b,
+            bool Function(E?, E?) matchingValues,
+            bool Function(E?, E?, String) equivalentValues) {
+          CheckingState oldState = $checkingState;
+          $checkingState = $checkingState.toMatchingState();
+          bool result = $checkSets(a, b, matchingValues, equivalentValues);
+          $checkingState = oldState;
+          return result;
+  }
+
+  /// Returns `true` if maps [a] and [b] are equivalent, using
+  /// [matchingKeys] to determine which entries that should be checked for
+  /// entry-wise equivalence using [equivalentKeys] and [equivalentValues] to
+  /// determine key and value equivalences, respectively.
+  ///
+  /// If run in a checking state, the [propertyName] is used for registering
+  /// inequivalences.
+  bool $checkMaps<K, V>(
+            Map<K, V>? a,
+            Map<K, V>? b,
+            bool Function(K?, K?) matchingKeys,
+            bool Function(K?, K?, String) equivalentKeys,
+            bool Function(V?, V?, String) equivalentValues,
+            [String propertyName = '']) {
+          if (identical(a, b)) return true;
+          if (a == null || b == null) return false;
+          if (a.length != b.length) {
+            $registerInequivalence(
+              '\${propertyName}.length',
+              'Maps \${a} and \${b} are not equivalent');
+            return false;
+          }
+          Set<K> bKeys = b.keys.toSet();
+          for (K aKey in a.keys) {
+            bool hasFoundKey = false;
+            K? foundKey;
+            for (K bKey in bKeys) {
+              if (matchingKeys(aKey, bKey)) {
+                foundKey = bKey;
+                hasFoundKey = true;
+                if (!equivalentKeys(aKey, bKey, '\${propertyName}[\${aKey}]')) {
+                  $registerInequivalence(
+                      '\${propertyName}[\${aKey}]',
+                      'Keys \${aKey} and \${bKey} are not equivalent');
+                  return false;
+                }
+                break;
+              }
+            }
+            if (hasFoundKey) {
+              bKeys.remove(foundKey);
+              if (!equivalentValues(a[aKey], b[foundKey],
+                  '\${propertyName}[\${aKey}]')) {
+                return false;
+              }
+            } else {
+              $registerInequivalence(
+                '\${propertyName}[\${aKey}]',
+                'Maps \${a} and \${b} are not equivalent, no equivalent key '
+                    'found for \$aKey');
+              return false;
+            }
+          }
+          return true;
+  }
+
+  /// Returns `true` if maps [a] and [b] are equivalent, using
+  /// [matchingKeys] to determine which entries that should be checked for
+  /// entry-wise equivalence using [equivalentKeys] and [equivalentValues] to
+  /// determine key and value equivalences, respectively.
+  ///
+  /// Inequivalence is _not_ registered.
+  bool $matchMaps<K, V>(
+            Map<K, V>? a,
+            Map<K, V>? b,
+            bool Function(K?, K?) matchingKeys,
+            bool Function(K?, K?, String) equivalentKeys,
+            bool Function(V?, V?, String) equivalentValues) {
+          CheckingState oldState = $checkingState;
+          $checkingState = $checkingState.toMatchingState();
+          bool result = $checkMaps(a, b, matchingKeys, equivalentKeys,
+              equivalentValues);
+          $checkingState = oldState;
+          return result;
+  }
+
+  /// The current state of the visitor.
+  ///
+  /// This holds the current assumptions, found inequivalences, and whether
+  /// inequivalences are currently registered.
+  CheckingState $checkingState = new CheckingState();
+
+  /// Runs [f] in a new state that holds all current assumptions. If
+  /// [isAsserting] is `true`, inequivalences are registered. Returns the
+  /// collected inequivalences.
+  ///
+  /// If [f] returns `false`, the returned result is marked as having
+  /// inequivalences even when non have being registered.
+  EquivalenceResult inSubState(bool Function() f, {bool isAsserting: false}) {
+    CheckingState _oldState = $checkingState;
+    $checkingState = $checkingState.createSubState(isAsserting: isAsserting);
+    bool hasInequivalences = f();
+    EquivalenceResult result =
+        $checkingState.toResult(hasInequivalences: hasInequivalences);
+    $checkingState = _oldState;
+    return result;
+  }
+
+  /// Registers that the visitor enters the property named [propertyName] and
+  /// the currently visited node.
+  void pushPropertyState(String propertyName) {
+    $checkingState.pushPropertyState(propertyName);
+  }
+
+  /// Registers that the visitor enters nodes [a] and [b].
+  void pushNodeState(Node a, Node b) {
+    $checkingState.pushNodeState(a, b);
+  }
+
+  /// Register that the visitor leave the current node or property.
+  void popState() {
+    $checkingState.popState();
+  }
+
+  /// Returns the value used as the result for property inequivalences.
+  ///
+  /// When inequivalences are currently registered, this is `true`, so that the
+  /// visitor will continue find inequivalences that are not directly related.
+  ///
+  /// An example is finding several child inequivalences on otherwise equivalent
+  /// nodes, like finding inequivalences deeply in the members of the second
+  /// library of a component even when inequivalences deeply in the members of
+  /// the first library. Had the return value been `false`, signaling that the
+  /// first libraries were inequivalent, which they technically are, given that
+  /// the contain inequivalent subnodes, the visitor would have stopped short in
+  /// checking the list of libraries, and the inequivalences in the second
+  /// library would not have been found.
+  ///
+  /// When inequivalences are _not_ currently registered, i.e. we are only
+  /// interested in the true/false value of the equivalence test, `false` is
+  /// used as the result value to stop the equivalence checking short.
+  bool get $resultOnInequivalence =>
+            $checkingState.$resultOnInequivalence;
+
+  /// Registers an equivalence on the [propertyName] with a detailed description
+  /// in [message].
+  void $registerInequivalence(String propertyName, String message) {
+          $checkingState.registerInequivalence(propertyName, message);
+  }
+
+  /// Returns the inequivalences found by the visitor.
+  EquivalenceResult toResult() => $checkingState.toResult();
+
+  ''');
+        } catch (e, s) {
+          print(s);
+        }
+      } catch (e, s) {
+        print(s);
+      }
+    } catch (e, s) {
+      print(s);
+    }
+    super.generateFooter(astModel, sb);
+    sb.writeln('''
+/// Checks [a] and [b] be for equivalence using [strategy].
+///
+/// Returns an [EquivalenceResult] containing the found inequivalences.
+EquivalenceResult checkEquivalence(
+    Node a,
+    Node b,
+    {$strategyName strategy: const $strategyName()}) {
+  EquivalenceVisitor visitor = new EquivalenceVisitor(
+      strategy: strategy);
+  visitor.$checkNodes(a, b, 'root');
+  return visitor.toResult();
+}
+''');
+
+    sb.writeln('''
+/// Strategy used for determining equivalence of AST nodes.
+///
+/// The strategy has a method for determining the equivalence of each AST node
+/// class, and a method for determining the equivalence of each property on each
+/// AST node class.
+///
+/// The base implementation enforces a full structural equivalence.
+///
+/// Custom strategies can be made by extending this strategy and override
+/// methods where exceptions to the structural equivalence are needed.
+class $strategyName {
+  const $strategyName();
+''');
+    _classStrategyMembers.forEach((key, value) {
+      sb.write(value);
+    });
+    _fieldStrategyMembers.forEach((key, value) {
+      sb.write(value);
+    });
+    sb.writeln(r'''
+}
+''');
+  }
+}
diff --git a/pkg/front_end/tool/smoke_test_quick.dart b/pkg/front_end/tool/smoke_test_quick.dart
index 9c60324..9e7d790 100644
--- a/pkg/front_end/tool/smoke_test_quick.dart
+++ b/pkg/front_end/tool/smoke_test_quick.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:io' show Platform, Process, ProcessResult, exitCode;
 
 import '../test/utils/io_utils.dart' show computeRepoDir;
diff --git a/pkg/front_end/tool/stat_on_dash_v.dart b/pkg/front_end/tool/stat_on_dash_v.dart
index c0ac7b4..7040540 100644
--- a/pkg/front_end/tool/stat_on_dash_v.dart
+++ b/pkg/front_end/tool/stat_on_dash_v.dart
@@ -2,13 +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.
 
-// @dart=2.9
-
 import "dart:io";
 
 import "../test/simple_stats.dart";
 
-void usage([String extraMessage]) {
+void usage([String? extraMessage]) {
   print("Usage:");
   print("On Linux via bash you can do something like");
   print("dart pkg/front_end/tool/stat_on_dash_v.dart \ "
@@ -68,12 +66,12 @@
 
   bool printedAnything = false;
   for (String part in data.keys) {
-    Map<String, List<int>> partData = data[part];
-    List<int> prevRuntimes;
-    String prevGroup;
+    Map<String, List<int>> partData = data[part]!;
+    List<int>? prevRuntimes;
+    String? prevGroup;
     bool printed = false;
     for (String group in allGroups) {
-      List<int> runtimes = partData[group];
+      List<int>? runtimes = partData[group];
       if (runtimes == null) {
         // Fake it to be a small list of 0s.
         runtimes = new List<int>.filled(5, 0);
@@ -101,7 +99,8 @@
             leastConfidentChange = result.diff - result.confidence;
           }
 
-          combinedChange["$prevGroup => $group"] += leastConfidentChange;
+          combinedChange["$prevGroup => $group"] =
+              combinedChange["$prevGroup => $group"]! + leastConfidentChange;
         }
       }
       prevRuntimes = runtimes;
@@ -115,7 +114,7 @@
   if (printedAnything) {
     for (String part in combinedChange.keys) {
       print("Combined least change for $part: "
-          "${combinedChange[part].toStringAsFixed(2)} ms.");
+          "${combinedChange[part]!.toStringAsFixed(2)} ms.");
     }
   } else {
     print("Nothing significant found.");
diff --git a/pkg/front_end/tool/update_all.dart b/pkg/front_end/tool/update_all.dart
index c25162c..3f9bfd1 100644
--- a/pkg/front_end/tool/update_all.dart
+++ b/pkg/front_end/tool/update_all.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 'package:_fe_analyzer_shared/src/testing/id_testing.dart' as id;
 import 'update_expectations.dart' as expectations;
 
diff --git a/pkg/front_end/tool/update_expectations.dart b/pkg/front_end/tool/update_expectations.dart
index 4ea0272..bd97672 100644
--- a/pkg/front_end/tool/update_expectations.dart
+++ b/pkg/front_end/tool/update_expectations.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 'fasta.dart' as fasta;
 
 const List<String> standardSuites = <String>[
@@ -19,7 +17,7 @@
   'incremental',
 ];
 
-Future<void> runStandardSuites([List<String> args]) async {
+Future<void> runStandardSuites([List<String>? args]) async {
   // Assert that 'strong' is the first suite - we use the assumption below.
   assert(standardSuites.first == 'weak', "Suite 'weak' most be the first.");
   bool first = true;
diff --git a/pkg/front_end/tool/visitor_generator.dart b/pkg/front_end/tool/visitor_generator.dart
new file mode 100644
index 0000000..ff3bace
--- /dev/null
+++ b/pkg/front_end/tool/visitor_generator.dart
@@ -0,0 +1,304 @@
+// 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 'package:dart_style/dart_style.dart' show DartFormatter;
+
+import 'ast_model.dart';
+
+/// Generates a visitor library into [sb] based on [astModel] and [strategy].
+String generateVisitor(AstModel astModel, VisitorStrategy strategy) {
+  StringBuffer sb = new StringBuffer();
+  strategy.generateHeader(astModel, sb);
+
+  void addVisitNode(AstClass astClass) {
+    switch (astClass.kind) {
+      case AstClassKind.root:
+      case AstClassKind.inner:
+        if (astClass.hasVisitMethod) {
+          strategy.generateDefaultVisit(astClass, sb);
+        }
+        for (AstClass subclass in astClass.subclasses) {
+          addVisitNode(subclass);
+        }
+        break;
+      case AstClassKind.public:
+      case AstClassKind.named:
+      case AstClassKind.declarative:
+        if (astClass.hasVisitMethod) {
+          strategy.generateVisit(astClass, sb);
+        }
+        break;
+      case AstClassKind.implementation:
+      case AstClassKind.interface:
+      case AstClassKind.utilityAsStructure:
+      case AstClassKind.utilityAsValue:
+        break;
+    }
+  }
+
+  void addVisitReference(AstClass astClass) {
+    switch (astClass.kind) {
+      case AstClassKind.root:
+      case AstClassKind.inner:
+        if (astClass.hasVisitReferenceMethod) {
+          strategy.generateDefaultVisitReference(astClass, sb);
+        }
+        for (AstClass subclass in astClass.subclasses) {
+          addVisitReference(subclass);
+        }
+        break;
+      case AstClassKind.public:
+      case AstClassKind.named:
+      case AstClassKind.declarative:
+        if (astClass.hasVisitReferenceMethod) {
+          strategy.generateVisitReference(astClass, sb);
+        }
+        break;
+      case AstClassKind.implementation:
+      case AstClassKind.interface:
+      case AstClassKind.utilityAsStructure:
+      case AstClassKind.utilityAsValue:
+        break;
+    }
+  }
+
+  addVisitNode(astModel.nodeClass);
+  addVisitReference(astModel.namedNodeClass);
+  addVisitReference(astModel.constantClass);
+  strategy.generateFooter(astModel, sb);
+
+  String result = sb.toString();
+  result = new DartFormatter().format(result);
+  return result;
+}
+
+/// Strategy for generating a visitor in its own library based on an [AstModel].
+abstract class VisitorStrategy {
+  const VisitorStrategy();
+
+  /// Generates the header of the visitor library, including preamble, imports
+  /// and visitor class declaration start.
+  void generateHeader(AstModel astModel, StringBuffer sb);
+
+  /// Generates a `defaultX` visitor method for [astClass].
+  void generateDefaultVisit(AstClass astClass, StringBuffer sb);
+
+  /// Generates a `visitX` visitor method for [astClass].
+  void generateVisit(AstClass astClass, StringBuffer sb);
+
+  /// Generates a `defaultXReference` visitor method for [astClass].
+  void generateDefaultVisitReference(AstClass astClass, StringBuffer sb);
+
+  /// Generates a `visitXReference` visitor method for [astClass].
+  void generateVisitReference(AstClass astClass, StringBuffer sb);
+
+  /// Generates the footer of the visitor library, including the visitor class
+  /// declaration end.
+  void generateFooter(AstModel astModel, StringBuffer sb);
+}
+
+/// Base strategy for creating a [Visitor] implementation.
+abstract class Visitor0Strategy extends VisitorStrategy {
+  const Visitor0Strategy();
+
+  /// The name of the generated visitor class.
+  String get visitorName;
+
+  /// The type parameters of the generated visitor class.
+  String get visitorTypeParameters => '';
+
+  /// The return type for the visitor methods.
+  ///
+  /// The generated visitor will implement `Visitor<$returnType>`.
+  String get returnType;
+
+  void generateHeader(AstModel astModel, StringBuffer sb) {
+    sb.writeln('''
+import 'package:kernel/ast.dart';
+
+class $visitorName$visitorTypeParameters implements Visitor<$returnType> {''');
+  }
+
+  void generateFooter(AstModel astModel, StringBuffer sb) {
+    sb.writeln('''
+}''');
+  }
+
+  @override
+  void generateDefaultVisit(AstClass astClass, StringBuffer sb) {
+    sb.writeln('''
+  @override
+  ${returnType} default${astClass.name}(
+      ${astClass.name} node) {''');
+    handleDefaultVisit(astClass, sb);
+    sb.writeln('}');
+  }
+
+  /// Generates the body of a `defaultX` visitor method of [astClass].
+  void handleDefaultVisit(AstClass astClass, StringBuffer sb) {}
+
+  @override
+  void generateVisit(AstClass astClass, StringBuffer sb) {
+    sb.writeln('''
+  @override
+  ${returnType} visit${astClass.name}(
+      ${astClass.name} node) {''');
+    handleVisit(astClass, sb);
+    sb.writeln('}');
+  }
+
+  /// Generates the body of a `visitX` visitor method of [astClass].
+  void handleVisit(AstClass astClass, StringBuffer sb) {}
+
+  @override
+  void generateDefaultVisitReference(AstClass astClass, StringBuffer sb) {
+    sb.writeln(''''
+  @override
+  ${returnType} default${astClass.name}Reference(
+      '${astClass.name} node) {''');
+    handleDefaultVisitReference(astClass, sb);
+    sb.writeln('}');
+  }
+
+  /// Generates the body of a `defaultXReference` visitor method of [astClass].
+  void handleDefaultVisitReference(AstClass astClass, StringBuffer sb) {}
+
+  @override
+  void generateVisitReference(AstClass astClass, StringBuffer sb) {
+    sb.writeln('''
+  @override
+  ${returnType} visit${astClass.name}Reference(
+      ${astClass.name} node) {''');
+    handleVisitReference(astClass, sb);
+    sb.writeln('}');
+  }
+
+  /// Generates the body of a `visitXReference` visitor method of [astClass].
+  void handleVisitReference(AstClass astClass, StringBuffer sb) {}
+}
+
+/// Strategy for creating an empty `Visitor<void>` implementation.
+class VoidVisitor0Strategy extends Visitor0Strategy {
+  const VoidVisitor0Strategy();
+
+  @override
+  String get visitorName => 'VoidVisitor';
+
+  @override
+  String get returnType => 'void';
+}
+
+/// Base strategy for creating a [Visitor1] implementation.
+abstract class Visitor1Strategy extends VisitorStrategy {
+  const Visitor1Strategy();
+
+  /// The name of the generated visitor class.
+  String get visitorName;
+
+  /// The type parameters of the generated visitor class.
+  String get visitorTypeParameters => '';
+
+  /// The type of the argument of the visitor methods.
+  ///
+  /// The generated visitor will implement
+  /// `Visitor1<$returnType, $argumentType>`.
+  String get argumentType;
+
+  /// The name of the argument parameter name.
+  String get argumentName => 'arg';
+
+  /// The return type for the visitor methods.
+  ///
+  /// The generated visitor will implement
+  /// `Visitor1<$returnType, $argumentType>`.
+  String get returnType;
+
+  void generateHeader(AstModel astModel, StringBuffer sb) {
+    sb.writeln('''
+import 'package:kernel/ast.dart';
+
+class $visitorName$visitorTypeParameters
+    implements Visitor1<$returnType, $argumentType> {''');
+  }
+
+  void generateFooter(AstModel astModel, StringBuffer sb) {
+    sb.writeln('''
+}''');
+  }
+
+  @override
+  void generateDefaultVisit(AstClass astClass, StringBuffer sb) {
+    sb.writeln('''
+  @override
+  ${returnType} default${astClass.name}(
+      ${astClass.name} node, $argumentType $argumentName) {''');
+    handleDefaultVisit(astClass, sb);
+    sb.writeln('''
+  }''');
+  }
+
+  /// Generates the body of a `defaultX` visitor method of [astClass].
+  void handleDefaultVisit(AstClass astClass, StringBuffer sb) {}
+
+  @override
+  void generateVisit(AstClass astClass, StringBuffer sb) {
+    sb.writeln('''
+  @override
+  ${returnType} visit${astClass.name}(
+      ${astClass.name} node, $argumentType $argumentName) {''');
+    handleVisit(astClass, sb);
+    sb.writeln('''
+  }''');
+  }
+
+  /// Generates the body of a `visitX` visitor method of [astClass].
+  void handleVisit(AstClass astClass, StringBuffer sb) {}
+
+  @override
+  void generateDefaultVisitReference(AstClass astClass, StringBuffer sb) {
+    sb.writeln('''
+  @override
+  ${returnType} default${astClass.name}Reference(
+      ${astClass.name} node, $argumentType $argumentName) {''');
+    handleDefaultVisitReference(astClass, sb);
+    sb.writeln('''
+  }''');
+  }
+
+  /// Generates the body of a `defaultXReference` visitor method of [astClass].
+  void handleDefaultVisitReference(AstClass astClass, StringBuffer sb) {}
+
+  @override
+  void generateVisitReference(AstClass astClass, StringBuffer sb) {
+    sb.writeln('''
+  @override
+  ${returnType} visit${astClass.name}Reference(
+      ${astClass.name} node, $argumentType $argumentName) {''');
+    handleVisitReference(astClass, sb);
+    sb.writeln('''
+  }''');
+  }
+
+  /// Generates the body of a `visitXReference` visitor method of [astClass].
+  void handleVisitReference(AstClass astClass, StringBuffer sb) {}
+}
+
+/// Strategy for creating an empty `Visitor1<void,Null>` implementation.
+class VoidVisitor1Strategy extends Visitor1Strategy {
+  const VoidVisitor1Strategy();
+
+  @override
+  String get visitorName => 'VoidVisitor';
+
+  @override
+  String get returnType => 'void';
+
+  @override
+  String get argumentType => 'Null';
+
+  @override
+  String get argumentName => '_';
+}
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 4dd9aa7..e013be5 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -147,7 +147,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 67;
+  UInt32 formatVersion = 69;
   Byte[10] shortSdkHash;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
@@ -328,7 +328,7 @@
   List<Field> fields;
   List<Constructor> constructors;
   List<Procedure> procedures;
-  List<RedirectingFactoryConstructor> redirectingFactoryConstructors;
+  List<RedirectingFactory> redirectingFactories;
 
   // Class index. Offsets are used to get start (inclusive) and end (exclusive) byte positions for
   // a specific procedure. Note the "+1" to account for needing the end of the last entry.
@@ -424,7 +424,7 @@
   Byte kind; // Index into the ProcedureKind enum above.
   Byte stubKind; // Index into the ProcedureStubKind enum above.
   UInt flags (isStatic, isAbstract, isExternal, isConst,
-              isRedirectingFactoryConstructor, isExtensionMember,
+              isRedirectingFactory, isExtensionMember,
               isNonNullableByDefault);
   Name name;
   List<Expression> annotations;
@@ -432,7 +432,7 @@
   FunctionNode function;
 }
 
-type RedirectingFactoryConstructor extends Member {
+type RedirectingFactory extends Member {
   Byte tag = 108;
   CanonicalNameReference canonicalName;
   UriReference fileUri;
@@ -584,25 +584,6 @@
   // Equivalent to VariableSet with index N.
 }
 
-type PropertyGet extends Expression {
-  Byte tag = 22;
-  FileOffset fileOffset;
-  Expression receiver;
-  Name name;
-  MemberReference interfaceTarget; // May be NullReference.
-  MemberReference interfaceTargetOrigin; // May be NullReference.
-}
-
-type PropertySet extends Expression {
-  Byte tag = 23;
-  FileOffset fileOffset;
-  Expression receiver;
-  Name name;
-  Expression value;
-  MemberReference interfaceTarget; // May be NullReference.
-  MemberReference interfaceTargetOrigin; // May be NullReference.
-}
-
 type SuperPropertyGet extends Expression {
   Byte tag = 24;
   FileOffset fileOffset;
@@ -703,8 +684,13 @@
 type ConstructorTearOff extends Expression {
   Byte tag = 60;
   FileOffset fileOffset;
-  ConstructorReference constructor;
-  Option<List<DartType>> typeArguments;
+  MemberReference target;
+}
+
+type RedirectingFactoryTearOff extends Expression {
+  Byte tag = 84;
+  FileOffset fileOffset;
+  MemberReference target;
 }
 
 type TypedefTearOff extends Expression {
@@ -735,17 +721,6 @@
   Expression value;
 }
 
-type MethodInvocation extends Expression {
-  Byte tag = 28;
-  Byte flags (isInvariant, isBoundsSafe);
-  FileOffset fileOffset;
-  Expression receiver;
-  Name name;
-  Arguments arguments;
-  MemberReference interfaceTarget; // May be NullReference.
-  MemberReference interfaceTargetOrigin; // May be NullReference.
-}
-
 type InstanceInvocation extends Expression {
   Byte tag = 120;
   Byte kind; // Index into InstanceAccessKind above.
@@ -1219,6 +1194,11 @@
   CanonicalNameReference constructorReference;
 }
 
+type RedirectingFactoryTearOffConstant extends Constant {
+  Byte tag = 16;
+  CanonicalNameReference constructorReference;
+}
+
 abstract type Statement extends Node {}
 
 type ExpressionStatement extends Statement {
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 4c7f24f..69df63a 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -92,6 +92,7 @@
   const Node();
 
   R accept<R>(Visitor<R> v);
+  R accept1<R, A>(Visitor1<R, A> v, A arg);
   void visitChildren(Visitor v);
 
   /// Returns the textual representation of this node for use in debugging.
@@ -1190,19 +1191,18 @@
     _proceduresView = null;
   }
 
-  List<RedirectingFactoryConstructor> _redirectingFactoryConstructorsInternal;
-  DirtifyingList<RedirectingFactoryConstructor>?
-      _redirectingFactoryConstructorsView;
+  List<RedirectingFactory> _redirectingFactoriesInternal;
+  DirtifyingList<RedirectingFactory>? _redirectingFactoriesView;
 
   /// Redirecting factory constructors declared in the class.
   ///
   /// For mixin applications this should be empty.
-  List<RedirectingFactoryConstructor> get redirectingFactoryConstructors {
+  List<RedirectingFactory> get redirectingFactories {
     ensureLoaded();
     // If already dirty the caller just might as well add stuff directly too.
-    if (dirty) return _redirectingFactoryConstructorsInternal;
-    return _redirectingFactoryConstructorsView ??=
-        new DirtifyingList(this, _redirectingFactoryConstructorsInternal);
+    if (dirty) return _redirectingFactoriesInternal;
+    return _redirectingFactoriesView ??=
+        new DirtifyingList(this, _redirectingFactoriesInternal);
   }
 
   /// Internal. Should *ONLY* be used from within kernel.
@@ -1210,9 +1210,9 @@
   /// Used for adding redirecting factory constructor when reading the dill
   /// file.
   void set redirectingFactoryConstructorsInternal(
-      List<RedirectingFactoryConstructor> redirectingFactoryConstructors) {
-    _redirectingFactoryConstructorsInternal = redirectingFactoryConstructors;
-    _redirectingFactoryConstructorsView = null;
+      List<RedirectingFactory> redirectingFactoryConstructors) {
+    _redirectingFactoriesInternal = redirectingFactoryConstructors;
+    _redirectingFactoriesView = null;
   }
 
   Class(
@@ -1226,7 +1226,7 @@
       List<Constructor>? constructors,
       List<Procedure>? procedures,
       List<Field>? fields,
-      List<RedirectingFactoryConstructor>? redirectingFactoryConstructors,
+      List<RedirectingFactory>? redirectingFactoryConstructors,
       required this.fileUri,
       Reference? reference})
       // ignore: unnecessary_null_comparison
@@ -1238,14 +1238,14 @@
         this._fieldsInternal = fields ?? <Field>[],
         this._constructorsInternal = constructors ?? <Constructor>[],
         this._proceduresInternal = procedures ?? <Procedure>[],
-        this._redirectingFactoryConstructorsInternal =
-            redirectingFactoryConstructors ?? <RedirectingFactoryConstructor>[],
+        this._redirectingFactoriesInternal =
+            redirectingFactoryConstructors ?? <RedirectingFactory>[],
         super(reference) {
     setParents(this.typeParameters, this);
     setParents(this._constructorsInternal, this);
     setParents(this._proceduresInternal, this);
     setParents(this._fieldsInternal, this);
-    setParents(this._redirectingFactoryConstructorsInternal, this);
+    setParents(this._redirectingFactoriesInternal, this);
     this.isAbstract = isAbstract;
     this.isAnonymousMixin = isAnonymousMixin;
   }
@@ -1270,10 +1270,10 @@
       Constructor member = constructors[i];
       canonicalName.getChildFromConstructor(member).bindTo(member.reference);
     }
-    for (int i = 0; i < redirectingFactoryConstructors.length; ++i) {
-      RedirectingFactoryConstructor member = redirectingFactoryConstructors[i];
+    for (int i = 0; i < redirectingFactories.length; ++i) {
+      RedirectingFactory member = redirectingFactories[i];
       canonicalName
-          .getChildFromRedirectingFactoryConstructor(member)
+          .getChildFromRedirectingFactory(member)
           .bindTo(member.reference);
     }
     dirty = false;
@@ -1300,8 +1300,8 @@
       Constructor member = constructors[i];
       member._relinkNode();
     }
-    for (int i = 0; i < redirectingFactoryConstructors.length; ++i) {
-      RedirectingFactoryConstructor member = redirectingFactoryConstructors[i];
+    for (int i = 0; i < redirectingFactories.length; ++i) {
+      RedirectingFactory member = redirectingFactories[i];
       member._relinkNode();
     }
     dirty = false;
@@ -1345,7 +1345,7 @@
         fields,
         constructors,
         procedures,
-        redirectingFactoryConstructors
+        redirectingFactories
       ].expand((x) => x);
 
   /// The immediately extended, mixed-in, and implemented types.
@@ -1389,11 +1389,10 @@
   }
 
   /// Adds a field to this class.
-  void addRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor redirectingFactoryConstructor) {
+  void addRedirectingFactory(RedirectingFactory redirectingFactory) {
     dirty = true;
-    redirectingFactoryConstructor.parent = this;
-    _redirectingFactoryConstructorsInternal.add(redirectingFactoryConstructor);
+    redirectingFactory.parent = this;
+    _redirectingFactoriesInternal.add(redirectingFactory);
   }
 
   @override
@@ -1446,7 +1445,7 @@
     visitList(constructors, v);
     visitList(procedures, v);
     visitList(fields, v);
-    visitList(redirectingFactoryConstructors, v);
+    visitList(redirectingFactories, v);
   }
 
   @override
@@ -1463,7 +1462,7 @@
     v.transformList(constructors, this);
     v.transformList(procedures, this);
     v.transformList(fields, this);
-    v.transformList(redirectingFactoryConstructors, this);
+    v.transformList(redirectingFactories, this);
   }
 
   @override
@@ -1490,8 +1489,7 @@
     v.transformConstructorList(constructors, this);
     v.transformProcedureList(procedures, this);
     v.transformFieldList(fields, this);
-    v.transformRedirectingFactoryConstructorList(
-        redirectingFactoryConstructors, this);
+    v.transformRedirectingFactoryList(redirectingFactories, this);
   }
 
   @override
@@ -2237,64 +2235,45 @@
 /// be removed from the class.  However, it is needed during the linking phase,
 /// because other modules can refer to that constructor.
 ///
-/// [RedirectingFactoryConstructor]s contain the necessary information for
+/// [RedirectingFactory]s contain the necessary information for
 /// linking and are treated as non-runnable members of classes that merely serve
 /// as containers for that information.
 ///
 /// Redirecting factory constructors can be unnamed.  In this case, the name is
 /// an empty string (in a [Name]).
-class RedirectingFactoryConstructor extends Member {
+class RedirectingFactory extends Member {
   int flags = 0;
 
-  /// [RedirectingFactoryConstructor]s may redirect to constructors or factories
+  /// [RedirectingFactory]s may redirect to constructors or factories
   /// of instantiated generic types, that is, generic types with supplied type
   /// arguments.  The supplied type arguments are stored in this field.
   final List<DartType> typeArguments;
 
   /// Reference to the constructor or the factory that this
-  /// [RedirectingFactoryConstructor] redirects to.
+  /// [RedirectingFactory] redirects to.
   // TODO(johnniwinther): Make this non-nullable.
   Reference? targetReference;
 
-  /// [typeParameters] are duplicates of the type parameters of the enclosing
-  /// class.  Because [RedirectingFactoryConstructor]s aren't instance members,
-  /// references to the type parameters of the enclosing class in the
-  /// redirection target description are encoded with references to the elements
-  /// of [typeParameters].
-  List<TypeParameter> typeParameters;
+  /// [FunctionNode] that holds the type parameters, copied from the enclosing
+  /// class, and the parameters defined on the redirecting factory.
+  ///
+  /// The `FunctionNode.body` is `null` or a synthesized [ConstructorInvocation]
+  /// of the [targetReference] constructor using the [typeArguments] and
+  /// [VariableGet] of the parameters.
+  FunctionNode function;
 
-  /// Positional parameters of [RedirectingFactoryConstructor]s should be
-  /// compatible with that of the target constructor.
-  List<VariableDeclaration> positionalParameters;
-  int requiredParameterCount;
-
-  /// Named parameters of [RedirectingFactoryConstructor]s should be compatible
-  /// with that of the target constructor.
-  List<VariableDeclaration> namedParameters;
-
-  RedirectingFactoryConstructor(this.targetReference,
+  RedirectingFactory(this.targetReference,
       {required Name name,
       bool isConst: false,
       bool isExternal: false,
       int transformerFlags: 0,
       List<DartType>? typeArguments,
-      List<TypeParameter>? typeParameters,
-      List<VariableDeclaration>? positionalParameters,
-      List<VariableDeclaration>? namedParameters,
-      int? requiredParameterCount,
+      required this.function,
       required Uri fileUri,
       Reference? reference})
       : this.typeArguments = typeArguments ?? <DartType>[],
-        this.typeParameters = typeParameters ?? <TypeParameter>[],
-        this.positionalParameters =
-            positionalParameters ?? <VariableDeclaration>[],
-        this.namedParameters = namedParameters ?? <VariableDeclaration>[],
-        this.requiredParameterCount =
-            requiredParameterCount ?? positionalParameters?.length ?? 0,
         super(name, fileUri, reference) {
-    setParents(this.typeParameters, this);
-    setParents(this.positionalParameters, this);
-    setParents(this.namedParameters, this);
+    function.parent = this;
     this.isConst = isConst;
     this.isExternal = isExternal;
     this.transformerFlags = transformerFlags;
@@ -2355,15 +2334,15 @@
   }
 
   @override
-  R accept<R>(MemberVisitor<R> v) => v.visitRedirectingFactoryConstructor(this);
+  R accept<R>(MemberVisitor<R> v) => v.visitRedirectingFactory(this);
 
   @override
   R accept1<R, A>(MemberVisitor1<R, A> v, A arg) =>
-      v.visitRedirectingFactoryConstructor(this, arg);
+      v.visitRedirectingFactory(this, arg);
 
   @override
   R acceptReference<R>(MemberReferenceVisitor<R> v) =>
-      v.visitRedirectingFactoryConstructorReference(this);
+      v.visitRedirectingFactoryReference(this);
 
   @override
   void visitChildren(Visitor v) {
@@ -2371,18 +2350,21 @@
     target?.acceptReference(v);
     visitList(typeArguments, v);
     name.accept(v);
+    function.accept(v);
   }
 
   @override
   void transformChildren(Transformer v) {
     v.transformList(annotations, this);
     v.transformDartTypeList(typeArguments);
+    function = v.transform(function)..parent = this;
   }
 
   @override
   void transformOrRemoveChildren(RemovingTransformer v) {
     v.transformExpressionList(annotations, this);
     v.transformDartTypeList(typeArguments);
+    function = v.transform(function)..parent = this;
   }
 
   @override
@@ -2705,7 +2687,7 @@
   static const int FlagExternal = 1 << 2;
   static const int FlagConst = 1 << 3; // Only for external const factories.
   // TODO(29841): Remove this flag after the issue is resolved.
-  static const int FlagRedirectingFactoryConstructor = 1 << 4;
+  static const int FlagRedirectingFactory = 1 << 4;
   static const int FlagExtensionMember = 1 << 5;
   static const int FlagNonNullableByDefault = 1 << 6;
   static const int FlagSynthetic = 1 << 7;
@@ -2750,8 +2732,8 @@
 
   // Indicates if this [Procedure] represents a redirecting factory constructor
   // and doesn't have a runnable body.
-  bool get isRedirectingFactoryConstructor {
-    return flags & FlagRedirectingFactoryConstructor != 0;
+  bool get isRedirectingFactory {
+    return flags & FlagRedirectingFactory != 0;
   }
 
   /// If set, this flag indicates that this function was not present in the
@@ -2783,10 +2765,10 @@
     flags = value ? (flags | FlagConst) : (flags & ~FlagConst);
   }
 
-  void set isRedirectingFactoryConstructor(bool value) {
+  void set isRedirectingFactory(bool value) {
     flags = value
-        ? (flags | FlagRedirectingFactoryConstructor)
-        : (flags & ~FlagRedirectingFactoryConstructor);
+        ? (flags | FlagRedirectingFactory)
+        : (flags & ~FlagRedirectingFactory);
   }
 
   void set isExtensionMember(bool value) {
@@ -3101,7 +3083,12 @@
 
   @override
   void toTextInternal(AstPrinter printer) {
-    // TODO(johnniwinther): Implement this.
+    printer.write('super');
+    if (target.name.text.isNotEmpty) {
+      printer.write('.');
+      printer.write(target.name.text);
+    }
+    printer.writeArguments(arguments, includeTypeArguments: false);
   }
 }
 
@@ -3405,6 +3392,14 @@
   /// resulting function type is generic, a fresh set of type parameters is used
   /// in it.
   FunctionType computeFunctionType(Nullability nullability) {
+    TreeNode? parent = this.parent;
+    List<TypeParameter> typeParameters;
+    if (parent is Constructor) {
+      assert(this.typeParameters.isEmpty);
+      typeParameters = parent.enclosingClass.typeParameters;
+    } else {
+      typeParameters = this.typeParameters;
+    }
     return typeParameters.isEmpty
         ? computeThisFunctionType(nullability)
         : getFreshTypeParameters(typeParameters)
@@ -4233,96 +4228,6 @@
   }
 }
 
-/// Expression of form `x.field`.
-///
-/// This may invoke a getter, read a field, or tear off a method.
-class PropertyGet extends Expression {
-  Expression receiver;
-  Name name;
-
-  Reference? interfaceTargetReference;
-
-  PropertyGet(Expression receiver, Name name, [Member? interfaceTarget])
-      : this.byReference(
-            receiver, name, getMemberReferenceGetter(interfaceTarget));
-
-  PropertyGet.byReference(
-      this.receiver, this.name, this.interfaceTargetReference) {
-    receiver.parent = this;
-  }
-
-  Member? get interfaceTarget => interfaceTargetReference?.asMember;
-
-  void set interfaceTarget(Member? member) {
-    interfaceTargetReference = getMemberReferenceGetter(member);
-  }
-
-  @override
-  DartType getStaticTypeInternal(StaticTypeContext context) {
-    Member? interfaceTarget = this.interfaceTarget;
-    if (interfaceTarget != null) {
-      Class superclass = interfaceTarget.enclosingClass!;
-      InterfaceType receiverType =
-          receiver.getStaticTypeAsInstanceOf(superclass, context);
-      return Substitution.fromInterfaceType(receiverType)
-          .substituteType(interfaceTarget.getterType);
-    }
-    // Treat the properties of Object specially.
-    String nameString = name.text;
-    if (nameString == 'hashCode') {
-      return context.typeEnvironment.coreTypes.intRawType(context.nonNullable);
-    } else if (nameString == 'runtimeType') {
-      return context.typeEnvironment.coreTypes.typeRawType(context.nonNullable);
-    }
-    return const DynamicType();
-  }
-
-  @override
-  R accept<R>(ExpressionVisitor<R> v) => v.visitPropertyGet(this);
-
-  @override
-  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
-      v.visitPropertyGet(this, arg);
-
-  @override
-  void visitChildren(Visitor v) {
-    receiver.accept(v);
-    interfaceTarget?.acceptReference(v);
-    name.accept(v);
-  }
-
-  @override
-  void transformChildren(Transformer v) {
-    // ignore: unnecessary_null_comparison
-    if (receiver != null) {
-      receiver = v.transform(receiver);
-      receiver.parent = this;
-    }
-  }
-
-  @override
-  void transformOrRemoveChildren(RemovingTransformer v) {
-    // ignore: unnecessary_null_comparison
-    if (receiver != null) {
-      receiver = v.transform(receiver);
-      receiver.parent = this;
-    }
-  }
-
-  @override
-  String toString() {
-    return "PropertyGet(${toStringInternal()})";
-  }
-
-  @override
-  void toTextInternal(AstPrinter printer) {
-    printer.writeExpression(receiver,
-        minimumPrecedence: astToText.Precedence.PRIMARY);
-    printer.write('.');
-    printer.writeInterfaceMemberName(interfaceTargetReference, name);
-  }
-}
-
 class DynamicSet extends Expression {
   final DynamicAccessKind kind;
   Expression receiver;
@@ -4490,98 +4395,6 @@
   }
 }
 
-/// Expression of form `x.field = value`.
-///
-/// This may invoke a setter or assign a field.
-///
-/// Evaluates to the value of [value].
-class PropertySet extends Expression {
-  Expression receiver;
-  Name name;
-  Expression value;
-
-  Reference? interfaceTargetReference;
-
-  PropertySet(Expression receiver, Name name, Expression value,
-      [Member? interfaceTarget])
-      : this.byReference(
-            receiver, name, value, getMemberReferenceSetter(interfaceTarget));
-
-  PropertySet.byReference(
-      this.receiver, this.name, this.value, this.interfaceTargetReference) {
-    receiver.parent = this;
-    value.parent = this;
-  }
-
-  Member? get interfaceTarget => interfaceTargetReference?.asMember;
-
-  void set interfaceTarget(Member? member) {
-    interfaceTargetReference = getMemberReferenceSetter(member);
-  }
-
-  @override
-  DartType getStaticTypeInternal(StaticTypeContext context) =>
-      value.getStaticType(context);
-
-  @override
-  R accept<R>(ExpressionVisitor<R> v) => v.visitPropertySet(this);
-
-  @override
-  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
-      v.visitPropertySet(this, arg);
-
-  @override
-  void visitChildren(Visitor v) {
-    receiver.accept(v);
-    interfaceTarget?.acceptReference(v);
-    name.accept(v);
-    value.accept(v);
-  }
-
-  @override
-  void transformChildren(Transformer v) {
-    // ignore: unnecessary_null_comparison
-    if (receiver != null) {
-      receiver = v.transform(receiver);
-      receiver.parent = this;
-    }
-    // ignore: unnecessary_null_comparison
-    if (value != null) {
-      value = v.transform(value);
-      value.parent = this;
-    }
-  }
-
-  @override
-  void transformOrRemoveChildren(RemovingTransformer v) {
-    // ignore: unnecessary_null_comparison
-    if (receiver != null) {
-      receiver = v.transform(receiver);
-      receiver.parent = this;
-    }
-    // ignore: unnecessary_null_comparison
-    if (value != null) {
-      value = v.transform(value);
-      value.parent = this;
-    }
-  }
-
-  @override
-  String toString() {
-    return "PropertySet(${toStringInternal()})";
-  }
-
-  @override
-  void toTextInternal(AstPrinter printer) {
-    printer.writeExpression(receiver,
-        minimumPrecedence: astToText.Precedence.PRIMARY);
-    printer.write('.');
-    printer.writeInterfaceMemberName(interfaceTargetReference, name);
-    printer.write(' = ');
-    printer.writeExpression(value);
-  }
-}
-
 /// Expression of form `super.field`.
 ///
 /// This may invoke a getter, read a field, or tear off a method.
@@ -5954,210 +5767,6 @@
   }
 }
 
-/// Expression of form `x.foo(y)`.
-class MethodInvocation extends InstanceInvocationExpression {
-  // Must match serialized bit positions.
-  static const int FlagInvariant = 1 << 0;
-  static const int FlagBoundsSafe = 1 << 1;
-
-  @override
-  Expression receiver;
-
-  @override
-  Name name;
-
-  @override
-  Arguments arguments;
-
-  int flags = 0;
-
-  Reference? interfaceTargetReference;
-
-  MethodInvocation(Expression receiver, Name name, Arguments arguments,
-      [Member? interfaceTarget])
-      : this.byReference(
-            receiver,
-            name,
-            arguments,
-            // An invocation doesn't refer to the setter.
-            getMemberReferenceGetter(interfaceTarget));
-
-  MethodInvocation.byReference(
-      this.receiver, this.name, this.arguments, this.interfaceTargetReference) {
-    receiver.parent = this;
-    arguments.parent = this;
-  }
-
-  Member? get interfaceTarget => interfaceTargetReference?.asMember;
-
-  void set interfaceTarget(Member? target) {
-    // An invocation doesn't refer to the setter.
-    interfaceTargetReference = getMemberReferenceGetter(target);
-  }
-
-  /// If `true`, this call is known to be safe wrt. parameter covariance checks.
-  ///
-  /// This is for instance the case in code patterns like this
-  ///
-  ///     List<int> list = <int>[];
-  ///     list.add(0);
-  ///
-  /// where the `list` variable is known to hold a value of the same type as
-  /// the static type. In contrast the would not be the case in code patterns
-  /// like this
-  ///
-  ///     List<num> list = <double>[];
-  ///     list.add(0); // Runtime error `int` is not a subtype of `double`.
-  ///
-  bool get isInvariant => flags & FlagInvariant != 0;
-
-  void set isInvariant(bool value) {
-    flags = value ? (flags | FlagInvariant) : (flags & ~FlagInvariant);
-  }
-
-  /// If `true`, this call is known to be safe wrt. parameter covariance checks.
-  ///
-  /// This is for instance the case in code patterns like this
-  ///
-  ///     List list = new List.filled(2, 0);
-  ///     list[1] = 42;
-  ///
-  /// where the `list` is known to have a sufficient length for the update
-  /// in `list[1] = 42`.
-  bool get isBoundsSafe => flags & FlagBoundsSafe != 0;
-
-  void set isBoundsSafe(bool value) {
-    flags = value ? (flags | FlagBoundsSafe) : (flags & ~FlagBoundsSafe);
-  }
-
-  @override
-  DartType getStaticTypeInternal(StaticTypeContext context) {
-    Member? interfaceTarget = this.interfaceTarget;
-    if (interfaceTarget != null) {
-      if (interfaceTarget is Procedure &&
-          context.typeEnvironment
-              .isSpecialCasedBinaryOperator(interfaceTarget)) {
-        return context.typeEnvironment.getTypeOfSpecialCasedBinaryOperator(
-            receiver.getStaticType(context),
-            arguments.positional[0].getStaticType(context));
-      }
-      Class superclass = interfaceTarget.enclosingClass!;
-      InterfaceType receiverType =
-          receiver.getStaticTypeAsInstanceOf(superclass, context);
-      DartType getterType = Substitution.fromInterfaceType(receiverType)
-          .substituteType(interfaceTarget.getterType);
-      if (getterType is FunctionType) {
-        Substitution substitution;
-        if (getterType.typeParameters.length == arguments.types.length) {
-          substitution = Substitution.fromPairs(
-              getterType.typeParameters, arguments.types);
-        } else {
-          // TODO(johnniwinther): The front end should normalize the type
-          //  argument count or create an invalid expression in case of method
-          //  invocations with invalid type argument count.
-          substitution = Substitution.fromPairs(
-              getterType.typeParameters,
-              getterType.typeParameters
-                  .map((TypeParameter typeParameter) =>
-                      typeParameter.defaultType)
-                  .toList());
-        }
-        return substitution.substituteType(getterType.returnType);
-      }
-      // The front end currently do not replace a property call `o.foo()`, where
-      // `foo` is a field or getter, with a function call on the property,
-      // `o.foo.call()`, so we look up the call method explicitly here.
-      // TODO(johnniwinther): Remove this when the front end performs the
-      // correct replacement.
-      if (getterType is InterfaceType) {
-        Member? member = context.typeEnvironment
-            .getInterfaceMember(getterType.classNode, new Name('call'));
-        if (member != null) {
-          DartType callType = member.getterType;
-          if (callType is FunctionType) {
-            return Substitution.fromInterfaceType(getterType)
-                .substituteType(callType.returnType);
-          }
-        }
-      }
-      return const DynamicType();
-    }
-    if (name.text == 'call') {
-      DartType receiverType = receiver.getStaticType(context);
-      if (receiverType is FunctionType) {
-        if (receiverType.typeParameters.length != arguments.types.length) {
-          return const NeverType.nonNullable();
-        }
-        return Substitution.fromPairs(
-                receiverType.typeParameters, arguments.types)
-            .substituteType(receiverType.returnType);
-      }
-    }
-    if (name.text == '==') {
-      // We use this special case to simplify generation of '==' checks.
-      return context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
-    }
-    return const DynamicType();
-  }
-
-  @override
-  R accept<R>(ExpressionVisitor<R> v) => v.visitMethodInvocation(this);
-
-  @override
-  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
-      v.visitMethodInvocation(this, arg);
-
-  @override
-  void visitChildren(Visitor v) {
-    receiver.accept(v);
-    interfaceTarget?.acceptReference(v);
-    name.accept(v);
-    arguments.accept(v);
-  }
-
-  @override
-  void transformChildren(Transformer v) {
-    // ignore: unnecessary_null_comparison
-    if (receiver != null) {
-      receiver = v.transform(receiver);
-      receiver.parent = this;
-    }
-    // ignore: unnecessary_null_comparison
-    if (arguments != null) {
-      arguments = v.transform(arguments);
-      arguments.parent = this;
-    }
-  }
-
-  @override
-  void transformOrRemoveChildren(RemovingTransformer v) {
-    // ignore: unnecessary_null_comparison
-    if (receiver != null) {
-      receiver = v.transform(receiver);
-      receiver.parent = this;
-    }
-    // ignore: unnecessary_null_comparison
-    if (arguments != null) {
-      arguments = v.transform(arguments);
-      arguments.parent = this;
-    }
-  }
-
-  @override
-  String toString() {
-    return "MethodInvocation(${toStringInternal()})";
-  }
-
-  @override
-  void toTextInternal(AstPrinter printer) {
-    printer.writeExpression(receiver,
-        minimumPrecedence: astToText.Precedence.PRIMARY);
-    printer.write('.');
-    printer.writeInterfaceMemberName(interfaceTargetReference, name);
-    printer.writeArguments(arguments);
-  }
-}
-
 /// Expression of form `super.foo(x)`.
 ///
 /// The provided arguments might not match the parameters of the target.
@@ -8611,23 +8220,28 @@
 /// Tearing off a constructor of a class.
 class ConstructorTearOff extends Expression {
   /// The reference to the constructor being torn off.
-  Reference constructorReference;
+  Reference targetReference;
 
-  ConstructorTearOff(Constructor constructor)
-      : this.byReference(getNonNullableMemberReferenceGetter(constructor));
+  ConstructorTearOff(Member target)
+      : assert(target is Constructor ||
+            (target is Procedure && target.kind == ProcedureKind.Factory)),
+        this.targetReference = getNonNullableMemberReferenceGetter(target);
 
-  ConstructorTearOff.byReference(this.constructorReference);
+  ConstructorTearOff.byReference(this.targetReference);
 
-  Constructor get constructor => constructorReference.asConstructor;
+  Member get target => targetReference.asMember;
 
-  void set constructor(Constructor constructor) {
-    constructorReference = getNonNullableMemberReferenceGetter(constructor);
+  FunctionNode get function => target.function!;
+
+  void set target(Member member) {
+    assert(member is Constructor ||
+        (member is Procedure && member.kind == ProcedureKind.Factory));
+    targetReference = getNonNullableMemberReferenceGetter(member);
   }
 
   @override
   DartType getStaticTypeInternal(StaticTypeContext context) {
-    return constructorReference.asConstructor.function
-        .computeFunctionType(Nullability.nonNullable);
+    return target.function!.computeFunctionType(Nullability.nonNullable);
   }
 
   @override
@@ -8639,7 +8253,7 @@
 
   @override
   void visitChildren(Visitor v) {
-    constructor.acceptReference(v);
+    target.acceptReference(v);
   }
 
   @override
@@ -8655,7 +8269,60 @@
 
   @override
   void toTextInternal(AstPrinter printer) {
-    printer.writeMemberName(constructorReference);
+    printer.writeMemberName(targetReference);
+  }
+}
+
+/// Tearing off a redirecting factory constructor of a class.
+class RedirectingFactoryTearOff extends Expression {
+  /// The reference to the redirecting factory constructor being torn off.
+  Reference targetReference;
+
+  RedirectingFactoryTearOff(Procedure target)
+      : assert(target.isRedirectingFactory),
+        this.targetReference = getNonNullableMemberReferenceGetter(target);
+
+  RedirectingFactoryTearOff.byReference(this.targetReference);
+
+  Procedure get target => targetReference.asProcedure;
+
+  void set target(Procedure target) {
+    targetReference = getNonNullableMemberReferenceGetter(target);
+  }
+
+  FunctionNode get function => target.function;
+
+  @override
+  DartType getStaticTypeInternal(StaticTypeContext context) {
+    return target.function.computeFunctionType(Nullability.nonNullable);
+  }
+
+  @override
+  R accept<R>(ExpressionVisitor<R> v) => v.visitRedirectingFactoryTearOff(this);
+
+  @override
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitRedirectingFactoryTearOff(this, arg);
+
+  @override
+  void visitChildren(Visitor v) {
+    target.acceptReference(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {}
+
+  @override
+  void transformOrRemoveChildren(RemovingTransformer v) {}
+
+  @override
+  String toString() {
+    return "RedirectingFactoryTearOff(${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeMemberName(targetReference);
   }
 }
 
@@ -8674,10 +8341,9 @@
     FreshTypeParameters freshTypeParameters =
         getFreshTypeParameters(typeParameters);
     FunctionType type = expression.getStaticType(context) as FunctionType;
-    type = Substitution.combine(
-            Substitution.fromPairs(type.typeParameters, typeArguments),
-            freshTypeParameters.substitution)
-        .substituteType(type.withoutTypeParameters) as FunctionType;
+    type = freshTypeParameters.substitute(
+        Substitution.fromPairs(type.typeParameters, typeArguments)
+            .substituteType(type.withoutTypeParameters)) as FunctionType;
     return new FunctionType(
         type.positionalParameters, type.returnType, type.declaredNullability,
         namedParameters: type.namedParameters,
@@ -8729,9 +8395,11 @@
 
   @override
   void toTextInternal(AstPrinter printer) {
-    printer.writeExpression(expression);
     printer.writeTypeParameters(typeParameters);
+    printer.write(".(");
+    printer.writeExpression(expression);
     printer.writeTypeArguments(typeArguments);
+    printer.write(")");
   }
 }
 
@@ -10534,6 +10202,9 @@
   R accept<R>(Visitor<R> v) => v.visitName(this);
 
   @override
+  R accept1<R, A>(Visitor1<R, A> v, A arg) => v.visitName(this, arg);
+
+  @override
   void visitChildren(Visitor v) {
     // DESIGN TODO: Should we visit the library as a library reference?
   }
@@ -11637,6 +11308,9 @@
   R accept<R>(Visitor<R> v) => v.visitNamedType(this);
 
   @override
+  R accept1<R, A>(Visitor1<R, A> v, A arg) => v.visitNamedType(this, arg);
+
+  @override
   void visitChildren(Visitor v) {
     type.accept(v);
   }
@@ -12392,6 +12066,9 @@
 
   R accept<R>(Visitor<R> v) => v.visitSupertype(this);
 
+  @override
+  R accept1<R, A>(Visitor1<R, A> v, A arg) => v.visitSupertype(this, arg);
+
   visitChildren(Visitor v) {
     classNode.acceptReference(v);
     visitList(typeArguments, v);
@@ -12445,31 +12122,46 @@
   ///
   /// (Note that a constant can be seen as a DAG (directed acyclic graph) and
   ///  not a tree!)
-  visitChildren(Visitor v);
+  @override
+  void visitChildren(Visitor v);
 
   /// Calls the `visit*Constant()` method on the visitor [v].
+  @override
   R accept<R>(ConstantVisitor<R> v);
 
+  /// Calls the `visit*Constant()` method on the visitor [v].
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg);
+
   /// Calls the `visit*ConstantReference()` method on the visitor [v].
   R acceptReference<R>(Visitor<R> v);
 
+  /// Calls the `visit*ConstantReference()` method on the visitor [v].
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg);
+
   /// The Kernel AST will reference [Constant]s via [ConstantExpression]s.  The
   /// constants are not required to be canonicalized, but they have to be deeply
   /// comparable via hashCode/==!
+  @override
   int get hashCode;
+
+  @override
   bool operator ==(Object other);
 
+  @override
   String toString() => throw '$runtimeType';
 
   /// Returns a textual representation of the this constant.
   ///
   /// If [verbose] is `true`, qualified names will include the library name/uri.
+  @override
   String toText(AstTextStrategy strategy) {
     AstPrinter printer = new AstPrinter(strategy);
     printer.writeConstant(this);
     return printer.getText();
   }
 
+  @override
   void toTextInternal(AstPrinter printer);
 
   /// Gets the type of this constant.
@@ -12485,8 +12177,10 @@
 
   PrimitiveConstant(this.value);
 
+  @override
   int get hashCode => value.hashCode;
 
+  @override
   bool operator ==(Object other) =>
       other is PrimitiveConstant<T> && other.value == value;
 
@@ -12499,10 +12193,24 @@
 class NullConstant extends PrimitiveConstant<Null> {
   NullConstant() : super(null);
 
-  visitChildren(Visitor v) {}
+  @override
+  void visitChildren(Visitor v) {}
+
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitNullConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitNullConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) => v.visitNullConstantReference(this);
 
+  @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitNullConstantReference(this, arg);
+
+  @override
   DartType getType(StaticTypeContext context) => const NullType();
 
   @override
@@ -12512,10 +12220,24 @@
 class BoolConstant extends PrimitiveConstant<bool> {
   BoolConstant(bool value) : super(value);
 
-  visitChildren(Visitor v) {}
+  @override
+  void visitChildren(Visitor v) {}
+
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitBoolConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitBoolConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) => v.visitBoolConstantReference(this);
 
+  @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitBoolConstantReference(this, arg);
+
+  @override
   DartType getType(StaticTypeContext context) =>
       context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
 
@@ -12527,10 +12249,24 @@
 class IntConstant extends PrimitiveConstant<int> {
   IntConstant(int value) : super(value);
 
-  visitChildren(Visitor v) {}
+  @override
+  void visitChildren(Visitor v) {}
+
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitIntConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitIntConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) => v.visitIntConstantReference(this);
 
+  @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitIntConstantReference(this, arg);
+
+  @override
   DartType getType(StaticTypeContext context) =>
       context.typeEnvironment.coreTypes.intRawType(context.nonNullable);
 
@@ -12542,14 +12278,31 @@
 class DoubleConstant extends PrimitiveConstant<double> {
   DoubleConstant(double value) : super(value);
 
-  visitChildren(Visitor v) {}
+  @override
+  void visitChildren(Visitor v) {}
+
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitDoubleConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitDoubleConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) => v.visitDoubleConstantReference(this);
 
+  @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitDoubleConstantReference(this, arg);
+
+  @override
   int get hashCode => value.isNaN ? 199 : super.hashCode;
+
+  @override
   bool operator ==(Object other) =>
       other is DoubleConstant && identical(value, other.value);
 
+  @override
   DartType getType(StaticTypeContext context) =>
       context.typeEnvironment.coreTypes.doubleRawType(context.nonNullable);
 
@@ -12563,11 +12316,24 @@
     assert(value != null);
   }
 
-  visitChildren(Visitor v) {}
+  @override
+  void visitChildren(Visitor v) {}
+
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitStringConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitStringConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) => v.visitStringConstantReference(this);
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitStringConstantReference(this, arg);
+
+  @override
   DartType getType(StaticTypeContext context) =>
       context.typeEnvironment.coreTypes.stringRawType(context.nonNullable);
 
@@ -12578,6 +12344,7 @@
     printer.write('"');
   }
 
+  @override
   String toString() => 'StringConstant(${toStringInternal()})';
 }
 
@@ -12587,22 +12354,37 @@
 
   SymbolConstant(this.name, this.libraryReference);
 
-  visitChildren(Visitor v) {}
+  @override
+  void visitChildren(Visitor v) {}
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitSymbolConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitSymbolConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) => v.visitSymbolConstantReference(this);
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitSymbolConstantReference(this, arg);
+
+  @override
   String toString() => 'SymbolConstant(${toStringInternal()})';
 
+  @override
   int get hashCode => _Hash.hash2(name, libraryReference);
 
+  @override
   bool operator ==(Object other) =>
       identical(this, other) ||
       (other is SymbolConstant &&
           other.name == name &&
           other.libraryReference == libraryReference);
 
+  @override
   DartType getType(StaticTypeContext context) =>
       context.typeEnvironment.coreTypes.symbolRawType(context.nonNullable);
 
@@ -12624,7 +12406,8 @@
 
   MapConstant(this.keyType, this.valueType, this.entries);
 
-  visitChildren(Visitor v) {
+  @override
+  void visitChildren(Visitor v) {
     keyType.accept(v);
     valueType.accept(v);
     for (final ConstantMapEntry entry in entries) {
@@ -12633,10 +12416,21 @@
     }
   }
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitMapConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitMapConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) => v.visitMapConstantReference(this);
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitMapConstantReference(this, arg);
+
+  @override
   void toTextInternal(AstPrinter printer) {
     printer.write('const <');
     printer.writeType(keyType);
@@ -12659,6 +12453,7 @@
   late final int hashCode = _Hash.combine2Finish(
       keyType.hashCode, valueType.hashCode, _Hash.combineListHash(entries));
 
+  @override
   bool operator ==(Object other) =>
       identical(this, other) ||
       (other is MapConstant &&
@@ -12666,6 +12461,7 @@
           other.valueType == valueType &&
           listEquals(other.entries, entries));
 
+  @override
   DartType getType(StaticTypeContext context) =>
       context.typeEnvironment.mapType(keyType, valueType, context.nonNullable);
 }
@@ -12706,17 +12502,29 @@
 
   ListConstant(this.typeArgument, this.entries);
 
-  visitChildren(Visitor v) {
+  @override
+  void visitChildren(Visitor v) {
     typeArgument.accept(v);
     for (final Constant constant in entries) {
       constant.acceptReference(v);
     }
   }
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitListConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitListConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) => v.visitListConstantReference(this);
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitListConstantReference(this, arg);
+
+  @override
   void toTextInternal(AstPrinter printer) {
     printer.write('const <');
     printer.writeType(typeArgument);
@@ -12737,12 +12545,14 @@
   late final int hashCode = _Hash.combineFinish(
       typeArgument.hashCode, _Hash.combineListHash(entries));
 
+  @override
   bool operator ==(Object other) =>
       identical(this, other) ||
       (other is ListConstant &&
           other.typeArgument == typeArgument &&
           listEquals(other.entries, entries));
 
+  @override
   DartType getType(StaticTypeContext context) =>
       context.typeEnvironment.listType(typeArgument, context.nonNullable);
 }
@@ -12753,17 +12563,29 @@
 
   SetConstant(this.typeArgument, this.entries);
 
-  visitChildren(Visitor v) {
+  @override
+  void visitChildren(Visitor v) {
     typeArgument.accept(v);
     for (final Constant constant in entries) {
       constant.acceptReference(v);
     }
   }
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitSetConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitSetConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) => v.visitSetConstantReference(this);
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitSetConstantReference(this, arg);
+
+  @override
   void toTextInternal(AstPrinter printer) {
     printer.write('const <');
     printer.writeType(typeArgument);
@@ -12784,12 +12606,14 @@
   late final int hashCode = _Hash.combineFinish(
       typeArgument.hashCode, _Hash.combineListHash(entries));
 
+  @override
   bool operator ==(Object other) =>
       identical(this, other) ||
       (other is SetConstant &&
           other.typeArgument == typeArgument &&
           listEquals(other.entries, entries));
 
+  @override
   DartType getType(StaticTypeContext context) =>
       context.typeEnvironment.setType(typeArgument, context.nonNullable);
 }
@@ -12815,9 +12639,19 @@
   }
 
   R accept<R>(ConstantVisitor<R> v) => v.visitInstanceConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitInstanceConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) => v.visitInstanceConstantReference(this);
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitInstanceConstantReference(this, arg);
+
+  @override
   void toTextInternal(AstPrinter printer) {
     printer.write('const ');
     printer.writeClassName(classReference);
@@ -12841,6 +12675,7 @@
   late final int hashCode = _Hash.combine2Finish(classReference.hashCode,
       listHashCode(typeArguments), _Hash.combineMapHashUnordered(fieldValues));
 
+  @override
   bool operator ==(Object other) {
     return identical(this, other) ||
         (other is InstanceConstant &&
@@ -12849,26 +12684,39 @@
             mapEquals(other.fieldValues, fieldValues));
   }
 
+  @override
   DartType getType(StaticTypeContext context) =>
       new InterfaceType(classNode, context.nonNullable, typeArguments);
 }
 
 class InstantiationConstant extends Constant {
-  final TearOffConstant tearOffConstant;
+  final Constant tearOffConstant;
   final List<DartType> types;
 
   InstantiationConstant(this.tearOffConstant, this.types);
 
-  visitChildren(Visitor v) {
+  @override
+  void visitChildren(Visitor v) {
     tearOffConstant.acceptReference(v);
     visitList(types, v);
   }
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitInstantiationConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitInstantiationConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) =>
       v.visitInstantiationConstantReference(this);
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitInstantiationConstantReference(this, arg);
+
+  @override
   void toTextInternal(AstPrinter printer) {
     printer.writeConstant(tearOffConstant);
     printer.writeTypeArguments(types);
@@ -12877,15 +12725,18 @@
   @override
   String toString() => 'InstantiationConstant(${toStringInternal()})';
 
+  @override
   int get hashCode => _Hash.combineFinish(
       tearOffConstant.hashCode, _Hash.combineListHash(types));
 
+  @override
   bool operator ==(Object other) {
     return other is InstantiationConstant &&
         other.tearOffConstant == tearOffConstant &&
         listEquals(other.types, types);
   }
 
+  @override
   DartType getType(StaticTypeContext context) {
     final FunctionType type = tearOffConstant.getType(context) as FunctionType;
     final Map<TypeParameter, DartType> mapping = <TypeParameter, DartType>{};
@@ -12897,100 +12748,184 @@
 }
 
 abstract class TearOffConstant implements Constant {
-  Reference get memberReference;
-  Member get member;
+  Reference get targetReference;
+  Member get target;
   FunctionNode get function;
 }
 
 class StaticTearOffConstant extends Constant implements TearOffConstant {
   @override
-  final Reference memberReference;
+  final Reference targetReference;
 
   StaticTearOffConstant(Procedure procedure)
-      : memberReference = procedure.reference {
+      : targetReference = procedure.reference {
     assert(procedure.isStatic);
   }
 
-  StaticTearOffConstant.byReference(this.memberReference);
+  StaticTearOffConstant.byReference(this.targetReference);
 
   @override
-  Member get member => memberReference.asMember;
+  Procedure get target => targetReference.asProcedure;
 
   @override
-  FunctionNode get function => procedure.function;
+  FunctionNode get function => target.function;
 
-  Procedure get procedure => memberReference.asProcedure;
-
-  visitChildren(Visitor v) {
-    memberReference.asProcedure.acceptReference(v);
+  @override
+  void visitChildren(Visitor v) {
+    target.acceptReference(v);
   }
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitStaticTearOffConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitStaticTearOffConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) =>
       v.visitStaticTearOffConstantReference(this);
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitStaticTearOffConstantReference(this, arg);
+
+  @override
   void toTextInternal(AstPrinter printer) {
-    printer.writeMemberName(memberReference);
+    printer.writeMemberName(targetReference);
   }
 
   @override
   String toString() => 'StaticTearOffConstant(${toStringInternal()})';
 
-  int get hashCode => memberReference.hashCode;
+  @override
+  int get hashCode => targetReference.hashCode;
 
+  @override
   bool operator ==(Object other) {
     return other is StaticTearOffConstant &&
-        other.memberReference == memberReference;
+        other.targetReference == targetReference;
   }
 
+  @override
   FunctionType getType(StaticTypeContext context) {
-    return procedure.function.computeFunctionType(context.nonNullable);
+    return target.function.computeFunctionType(context.nonNullable);
   }
 }
 
 class ConstructorTearOffConstant extends Constant implements TearOffConstant {
   @override
-  final Reference memberReference;
+  final Reference targetReference;
 
-  ConstructorTearOffConstant(Constructor constructor)
-      : memberReference = constructor.reference;
+  ConstructorTearOffConstant(Member target)
+      : assert(target is Constructor ||
+            (target is Procedure && target.kind == ProcedureKind.Factory)),
+        this.targetReference = getNonNullableMemberReferenceGetter(target);
 
-  ConstructorTearOffConstant.byReference(this.memberReference);
+  ConstructorTearOffConstant.byReference(this.targetReference);
 
   @override
-  Member get member => memberReference.asMember;
+  Member get target => targetReference.asMember;
 
   @override
-  FunctionNode get function => constructor.function;
+  FunctionNode get function => target.function!;
 
-  Constructor get constructor => memberReference.asConstructor;
-
-  visitChildren(Visitor v) {
-    memberReference.asProcedure.acceptReference(v);
+  @override
+  void visitChildren(Visitor v) {
+    target.acceptReference(v);
   }
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitConstructorTearOffConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitConstructorTearOffConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) =>
       v.visitConstructorTearOffConstantReference(this);
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitConstructorTearOffConstantReference(this, arg);
+
+  @override
   void toTextInternal(AstPrinter printer) {
-    printer.writeMemberName(memberReference);
+    printer.writeMemberName(targetReference);
   }
 
   @override
   String toString() => 'ConstructorTearOffConstant(${toStringInternal()})';
 
-  int get hashCode => memberReference.hashCode;
+  int get hashCode => targetReference.hashCode;
 
   bool operator ==(Object other) {
-    return other is StaticTearOffConstant &&
-        other.memberReference == memberReference;
+    return other is ConstructorTearOffConstant &&
+        other.targetReference == targetReference;
   }
 
   FunctionType getType(StaticTypeContext context) {
-    return constructor.function.computeFunctionType(context.nonNullable);
+    return function.computeFunctionType(context.nonNullable);
+  }
+}
+
+class RedirectingFactoryTearOffConstant extends Constant
+    implements TearOffConstant {
+  @override
+  final Reference targetReference;
+
+  RedirectingFactoryTearOffConstant(Procedure target)
+      : assert(target.isRedirectingFactory),
+        this.targetReference = getNonNullableMemberReferenceGetter(target);
+
+  RedirectingFactoryTearOffConstant.byReference(this.targetReference);
+
+  @override
+  Procedure get target => targetReference.asProcedure;
+
+  @override
+  FunctionNode get function => target.function;
+
+  @override
+  void visitChildren(Visitor v) {
+    target.acceptReference(v);
+  }
+
+  @override
+  R accept<R>(ConstantVisitor<R> v) =>
+      v.visitRedirectingFactoryTearOffConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitRedirectingFactoryTearOffConstant(this, arg);
+
+  @override
+  R acceptReference<R>(Visitor<R> v) =>
+      v.visitRedirectingFactoryTearOffConstantReference(this);
+
+  @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitRedirectingFactoryTearOffConstantReference(this, arg);
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeMemberName(targetReference);
+  }
+
+  @override
+  String toString() =>
+      'RedirectingFactoryTearOffConstant(${toStringInternal()})';
+
+  int get hashCode => targetReference.hashCode;
+
+  bool operator ==(Object other) {
+    return other is RedirectingFactoryTearOffConstant &&
+        other.targetReference == targetReference;
+  }
+
+  FunctionType getType(StaticTypeContext context) {
+    return function.computeFunctionType(context.nonNullable);
   }
 }
 
@@ -12999,21 +12934,36 @@
   final TearOffConstant tearOffConstant;
   final List<DartType> types;
 
+  late final int hashCode = _computeHashCode();
+
   TypedefTearOffConstant(this.parameters, this.tearOffConstant, this.types);
 
-  visitChildren(Visitor v) {
+  @override
+  void visitChildren(Visitor v) {
     visitList(parameters, v);
     tearOffConstant.acceptReference(v);
     visitList(types, v);
   }
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitTypedefTearOffConstant(this);
-  R acceptReference<R>(Visitor<R> v) => v.visitTypedefTearOffConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitTypedefTearOffConstant(this, arg);
+
+  @override
+  R acceptReference<R>(Visitor<R> v) =>
+      v.visitTypedefTearOffConstantReference(this);
+
+  @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitTypedefTearOffConstantReference(this, arg);
 
   @override
   void toTextInternal(AstPrinter printer) {
-    printer.writeConstant(tearOffConstant);
     printer.writeTypeParameters(parameters);
+    printer.writeConstant(tearOffConstant);
     printer.writeTypeArguments(types);
   }
 
@@ -13045,13 +12995,26 @@
     return true;
   }
 
+  int _computeHashCode() {
+    int hash = 1237;
+    for (int i = 0; i < parameters.length; ++i) {
+      TypeParameter parameter = parameters[i];
+      hash = 0x3fffffff & (hash * 31 + parameter.bound.hashCode);
+    }
+    for (int i = 0; i < types.length; ++i) {
+      hash = 0x3fffffff & (hash * 31 + types[i].hashCode);
+    }
+    hash = 0x3fffffff & (hash * 31 + tearOffConstant.hashCode);
+    return hash;
+  }
+
   DartType getType(StaticTypeContext context) {
     FunctionType type = tearOffConstant.getType(context) as FunctionType;
     FreshTypeParameters freshTypeParameters =
         getFreshTypeParameters(parameters);
     type = freshTypeParameters.substitute(
-            Substitution.fromPairs(parameters, types).substituteType(type))
-        as FunctionType;
+        Substitution.fromPairs(type.typeParameters, types)
+            .substituteType(type.withoutTypeParameters)) as FunctionType;
     return new FunctionType(
         type.positionalParameters, type.returnType, type.declaredNullability,
         namedParameters: type.namedParameters,
@@ -13066,15 +13029,27 @@
 
   TypeLiteralConstant(this.type);
 
-  visitChildren(Visitor v) {
+  @override
+  void visitChildren(Visitor v) {
     type.accept(v);
   }
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitTypeLiteralConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitTypeLiteralConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) =>
       v.visitTypeLiteralConstantReference(this);
 
   @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitTypeLiteralConstantReference(this, arg);
+
+  @override
   void toTextInternal(AstPrinter printer) {
     printer.writeType(type);
   }
@@ -13082,8 +13057,10 @@
   @override
   String toString() => 'TypeLiteralConstant(${toStringInternal()})';
 
+  @override
   int get hashCode => type.hashCode;
 
+  @override
   bool operator ==(Object other) {
     return other is TypeLiteralConstant && other.type == type;
   }
@@ -13099,14 +13076,26 @@
     expression.parent = null;
   }
 
-  visitChildren(Visitor v) {
+  @override
+  void visitChildren(Visitor v) {
     expression.accept(v);
   }
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitUnevaluatedConstant(this);
+
+  @override
+  R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+      v.visitUnevaluatedConstant(this, arg);
+
+  @override
   R acceptReference<R>(Visitor<R> v) =>
       v.visitUnevaluatedConstantReference(this);
 
+  @override
+  R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+      v.visitUnevaluatedConstantReference(this, arg);
+
   DartType getType(StaticTypeContext context) =>
       expression.getStaticType(context);
 
@@ -13383,7 +13372,7 @@
   /// Write List<Byte> into the sink.
   void writeByteList(List<int> bytes);
 
-  void writeNullAllowedCanonicalNameReference(CanonicalName name);
+  void writeNullAllowedCanonicalNameReference(CanonicalName? name);
   void writeStringReference(String str);
   void writeName(Name node);
   void writeDartType(DartType type);
@@ -14037,12 +14026,11 @@
 final List<Constructor> emptyListOfConstructor =
     List.filled(0, dummyConstructor, growable: false);
 
-/// Almost const <RedirectingFactoryConstructor>[], but not const in an attempt
-/// to avoid polymorphism. See
+/// Almost const <RedirectingFactory>[], but not const in an attempt to avoid
+/// polymorphism. See
 /// https://dart-review.googlesource.com/c/sdk/+/185828.
-final List<RedirectingFactoryConstructor>
-    emptyListOfRedirectingFactoryConstructor =
-    List.filled(0, dummyRedirectingFactoryConstructor, growable: false);
+final List<RedirectingFactory> emptyListOfRedirectingFactory =
+    List.filled(0, dummyRedirectingFactory, growable: false);
 
 /// Almost const <Initializer>[], but not const in an attempt to avoid
 /// polymorphism. See https://dart-review.googlesource.com/c/sdk/+/185828.
@@ -14170,13 +14158,13 @@
 /// constructor.
 final Field dummyField = new Field.mutable(dummyName, fileUri: dummyUri);
 
-/// Non-nullable [RedirectingFactoryConstructor] dummy value.
+/// Non-nullable [RedirectingFactory] dummy value.
 ///
 /// This is used as the removal sentinel in [RemovingTransformer] and can be
 /// used for instance as a dummy initial value for the `List.filled`
 /// constructor.
-final RedirectingFactoryConstructor dummyRedirectingFactoryConstructor =
-    new RedirectingFactoryConstructor(null, name: dummyName, fileUri: dummyUri);
+final RedirectingFactory dummyRedirectingFactory = new RedirectingFactory(null,
+    name: dummyName, fileUri: dummyUri, function: dummyFunctionNode);
 
 /// Non-nullable [Typedef] dummy value.
 ///
@@ -14307,7 +14295,7 @@
   dummyMember,
   dummyProcedure,
   dummyField,
-  dummyRedirectingFactoryConstructor,
+  dummyRedirectingFactory,
   dummyTypedef,
   dummyInitializer,
   dummyFunctionNode,
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index a257708..80b2979 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -373,6 +373,8 @@
         return _readStaticTearOffConstant();
       case ConstantTag.ConstructorTearOffConstant:
         return _readConstructorTearOffConstant();
+      case ConstantTag.RedirectingFactoryTearOffConstant:
+        return _readRedirectingFactoryTearOffConstant();
       case ConstantTag.TypeLiteralConstant:
         return _readTypeLiteralConstant();
       case ConstantTag.UnevaluatedConstant:
@@ -446,17 +448,17 @@
   }
 
   Constant _readInstantiationConstant() {
-    final StaticTearOffConstant tearOffConstant =
-        readConstantReference() as StaticTearOffConstant;
+    final Constant tearOffConstant = readConstantReference();
     final List<DartType> types = readDartTypeList();
     return new InstantiationConstant(tearOffConstant, types);
   }
 
   Constant _readTypedefTearOffConstant() {
     final List<TypeParameter> parameters = readAndPushTypeParameterList();
-    final StaticTearOffConstant tearOffConstant =
-        readConstantReference() as StaticTearOffConstant;
+    final TearOffConstant tearOffConstant =
+        readConstantReference() as TearOffConstant;
     final List<DartType> types = readDartTypeList();
+    typeParameterStack.length -= parameters.length;
     return new TypedefTearOffConstant(parameters, tearOffConstant, types);
   }
 
@@ -470,6 +472,11 @@
     return new ConstructorTearOffConstant.byReference(reference);
   }
 
+  Constant _readRedirectingFactoryTearOffConstant() {
+    final Reference reference = readNonNullCanonicalNameReference().reference;
+    return new RedirectingFactoryTearOffConstant.byReference(reference);
+  }
+
   Constant _readTypeLiteralConstant() {
     final DartType type = readDartType();
     return new TypeLiteralConstant(type);
@@ -1478,7 +1485,7 @@
     node.fieldsInternal = _readFieldList(node);
     _readConstructorList(node);
     node.proceduresInternal = _readProcedureList(node, procedureOffsets);
-    _readRedirectingFactoryConstructorList(node);
+    _readRedirectingFactoryList(node);
   }
 
   void _readConstructorList(Class node) {
@@ -1494,17 +1501,17 @@
     }
   }
 
-  void _readRedirectingFactoryConstructorList(Class node) {
+  void _readRedirectingFactoryList(Class node) {
     int length = readUInt30();
     if (!useGrowableLists && length == 0) {
       // When lists don't have to be growable anyway, we might as well use a
       // constant one for the empty list.
       node.redirectingFactoryConstructorsInternal =
-          emptyListOfRedirectingFactoryConstructor;
+          emptyListOfRedirectingFactory;
     } else {
       node.redirectingFactoryConstructorsInternal =
-          new List<RedirectingFactoryConstructor>.generate(length,
-              (int index) => readRedirectingFactoryConstructor()..parent = node,
+          new List<RedirectingFactory>.generate(
+              length, (int index) => readRedirectingFactory()..parent = node,
               growable: useGrowableLists);
     }
   }
@@ -1690,13 +1697,12 @@
     return node;
   }
 
-  RedirectingFactoryConstructor readRedirectingFactoryConstructor() {
+  RedirectingFactory readRedirectingFactory() {
     int tag = readByte();
-    assert(tag == Tag.RedirectingFactoryConstructor);
+    assert(tag == Tag.RedirectingFactory);
     CanonicalName canonicalName = readNonNullCanonicalNameReference();
     Reference reference = canonicalName.reference;
-    RedirectingFactoryConstructor? node =
-        reference.node as RedirectingFactoryConstructor?;
+    RedirectingFactory? node = reference.node as RedirectingFactory?;
     if (alwaysCreateNewNamedNodes) {
       node = null;
     }
@@ -1705,39 +1711,34 @@
     int fileEndOffset = readOffset();
     int flags = readByte();
     Name name = readName();
-    if (node == null) {
-      node = new RedirectingFactoryConstructor(null,
-          reference: reference, name: name, fileUri: fileUri);
-    }
-    List<Expression> annotations = readAnnotationList(node);
     assert(() {
       debugPath.add(name.text);
       return true;
     }());
+    List<Expression> annotations = readAnnotationList();
     Reference targetReference = readNonNullMemberReference();
     List<DartType> typeArguments = readDartTypeList();
-    int typeParameterStackHeight = typeParameterStack.length;
-    List<TypeParameter> typeParameters = readAndPushTypeParameterList();
-    readUInt30(); // Total parameter count.
-    int requiredParameterCount = readUInt30();
-    int variableStackHeight = variableStack.length;
-    List<VariableDeclaration> positional = readAndPushVariableDeclarationList();
-    List<VariableDeclaration> named = readAndPushVariableDeclarationList();
-    variableStack.length = variableStackHeight;
-    typeParameterStack.length = typeParameterStackHeight;
-    debugPath.removeLast();
+    FunctionNode function = readFunctionNode(outerEndOffset: fileEndOffset);
+    if (node == null) {
+      node = new RedirectingFactory(targetReference,
+          reference: reference,
+          name: name,
+          fileUri: fileUri,
+          function: function,
+          typeArguments: typeArguments);
+    } else {
+      node.name = name;
+      node.fileUri = fileUri;
+      node.targetReference = targetReference;
+      node.typeArguments.addAll(typeArguments);
+      node.function = function..parent = node;
+    }
     node.fileOffset = fileOffset;
     node.fileEndOffset = fileEndOffset;
     node.flags = flags;
-    node.name = name;
-    node.fileUri = fileUri;
     node.annotations = annotations;
-    node.targetReference = targetReference;
-    node.typeArguments.addAll(typeArguments);
-    node.typeParameters = typeParameters;
-    node.requiredParameterCount = requiredParameterCount;
-    node.positionalParameters = positional;
-    node.namedParameters = named;
+    setParents(annotations, node);
+    debugPath.removeLast();
     return node;
   }
 
@@ -1959,16 +1960,12 @@
         return _readVariableSet();
       case Tag.SpecializedVariableSet:
         return _readSpecializedVariableSet(tagByte);
-      case Tag.PropertyGet:
-        return _readPropertyGet();
       case Tag.InstanceGet:
         return _readInstanceGet();
       case Tag.InstanceTearOff:
         return _readInstanceTearOff();
       case Tag.DynamicGet:
         return _readDynamicGet();
-      case Tag.PropertySet:
-        return _readPropertySet();
       case Tag.InstanceSet:
         return _readInstanceSet();
       case Tag.DynamicSet:
@@ -1987,8 +1984,8 @@
         return _readConstructorTearOff();
       case Tag.TypedefTearOff:
         return _readTypedefTearOff();
-      case Tag.MethodInvocation:
-        return _readMethodInvocation();
+      case Tag.RedirectingFactoryTearOff:
+        return _readRedirectingFactoryTearOff();
       case Tag.InstanceInvocation:
         return _readInstanceInvocation();
       case Tag.InstanceGetterInvocation:
@@ -2139,13 +2136,6 @@
       ..fileOffset = offset;
   }
 
-  Expression _readPropertyGet() {
-    int offset = readOffset();
-    return new PropertyGet.byReference(
-        readExpression(), readName(), readNullableInstanceMemberReference())
-      ..fileOffset = offset;
-  }
-
   Expression _readInstanceGet() {
     InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
     int offset = readOffset();
@@ -2171,13 +2161,6 @@
       ..fileOffset = offset;
   }
 
-  Expression _readPropertySet() {
-    int offset = readOffset();
-    return new PropertySet.byReference(readExpression(), readName(),
-        readExpression(), readNullableInstanceMemberReference())
-      ..fileOffset = offset;
-  }
-
   Expression _readInstanceSet() {
     InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
     int offset = readOffset();
@@ -2231,6 +2214,13 @@
     return new TypedefTearOff(typeParameters, expression, typeArguments);
   }
 
+  Expression _readRedirectingFactoryTearOff() {
+    int offset = readOffset();
+    Reference constructorReference = readNonNullMemberReference();
+    return new RedirectingFactoryTearOff.byReference(constructorReference)
+      ..fileOffset = offset;
+  }
+
   Expression _readStaticTearOff() {
     int offset = readOffset();
     return new StaticTearOff.byReference(readNonNullMemberReference())
@@ -2244,15 +2234,6 @@
       ..fileOffset = offset;
   }
 
-  Expression _readMethodInvocation() {
-    int flags = readByte();
-    int offset = readOffset();
-    return new MethodInvocation.byReference(readExpression(), readName(),
-        readArguments(), readNullableInstanceMemberReference())
-      ..fileOffset = offset
-      ..flags = flags;
-  }
-
   Expression _readInstanceInvocation() {
     InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
     int flags = readByte();
@@ -3372,10 +3353,9 @@
   }
 
   @override
-  RedirectingFactoryConstructor readRedirectingFactoryConstructor() {
+  RedirectingFactory readRedirectingFactory() {
     final int nodeOffset = _byteOffset;
-    final RedirectingFactoryConstructor result =
-        super.readRedirectingFactoryConstructor();
+    final RedirectingFactory result = super.readRedirectingFactory();
     return _associateMetadata(result, nodeOffset);
   }
 
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 5460a6e..aa211d3 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -25,8 +25,8 @@
   final ConstantIndexer _constantIndexer;
   final UriIndexer _sourceUriIndexer = new UriIndexer();
   bool _currentlyInNonimplementation = false;
-  final List<bool> _sourcesFromRealImplementation = <bool>[];
-  final List<bool> _sourcesUsedInLibrary = <bool>[];
+  final List<bool?> _sourcesFromRealImplementation = <bool?>[];
+  final List<bool?> _sourcesUsedInLibrary = <bool?>[];
   Map<LibraryDependency, int> _libraryDependencyIndex =
       <LibraryDependency, int>{};
   NonNullableByDefaultCompiledMode? compilationMode;
@@ -264,11 +264,15 @@
     } else if (constant is StaticTearOffConstant) {
       writeByte(ConstantTag.StaticTearOffConstant);
       writeNonNullCanonicalNameReference(
-          constant.procedure.reference.canonicalName!);
+          constant.targetReference.canonicalName!);
     } else if (constant is ConstructorTearOffConstant) {
       writeByte(ConstantTag.ConstructorTearOffConstant);
       writeNonNullCanonicalNameReference(
-          constant.constructor.reference.canonicalName!);
+          constant.targetReference.canonicalName!);
+    } else if (constant is RedirectingFactoryTearOffConstant) {
+      writeByte(ConstantTag.RedirectingFactoryTearOffConstant);
+      writeNonNullCanonicalNameReference(
+          constant.targetReference.canonicalName!);
     } else if (constant is TypeLiteralConstant) {
       writeByte(ConstantTag.TypeLiteralConstant);
       writeDartType(constant.type);
@@ -373,13 +377,12 @@
     }
   }
 
-  void writeRedirectingFactoryConstructorNodeList(
-      List<RedirectingFactoryConstructor> nodes) {
+  void writeRedirectingFactoryNodeList(List<RedirectingFactory> nodes) {
     final int len = nodes.length;
     writeUInt30(len);
     for (int i = 0; i < len; i++) {
-      final RedirectingFactoryConstructor node = nodes[i];
-      writeRedirectingFactoryConstructorNode(node);
+      final RedirectingFactory node = nodes[i];
+      writeRedirectingFactoryNode(node);
     }
   }
 
@@ -473,8 +476,7 @@
     node.accept(this);
   }
 
-  void writeRedirectingFactoryConstructorNode(
-      RedirectingFactoryConstructor node) {
+  void writeRedirectingFactoryNode(RedirectingFactory node) {
     if (_metadataSubsections != null) {
       _writeNodeMetadata(node);
     }
@@ -1205,8 +1207,7 @@
     procedureOffsets = <int>[];
     writeProcedureNodeList(node.procedures);
     procedureOffsets.add(getBufferOffset());
-    writeRedirectingFactoryConstructorNodeList(
-        node.redirectingFactoryConstructors);
+    writeRedirectingFactoryNodeList(node.redirectingFactories);
     leaveScope(typeParameters: node.typeParameters);
 
     assert(procedureOffsets.length > 0);
@@ -1366,35 +1367,21 @@
   }
 
   @override
-  void visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+  void visitRedirectingFactory(RedirectingFactory node) {
     if (node.reference.canonicalName == null) {
       throw new ArgumentError('Missing canonical name for $node');
     }
-    writeByte(Tag.RedirectingFactoryConstructor);
-    enterScope(
-        typeParameters: node.typeParameters,
-        memberScope: true,
-        variableScope: true);
+    writeByte(Tag.RedirectingFactory);
     writeNonNullCanonicalNameReference(getCanonicalNameOfMemberGetter(node));
     writeUriReference(node.fileUri);
     writeOffset(node.fileOffset);
     writeOffset(node.fileEndOffset);
     writeByte(node.flags);
     writeName(node.name);
-
     writeAnnotationList(node.annotations);
     writeNonNullReference(node.targetReference!);
     writeNodeList(node.typeArguments);
-    writeNodeList(node.typeParameters);
-    writeUInt30(node.positionalParameters.length + node.namedParameters.length);
-    writeUInt30(node.requiredParameterCount);
-    writeVariableDeclarationList(node.positionalParameters);
-    writeVariableDeclarationList(node.namedParameters);
-
-    leaveScope(
-        typeParameters: node.typeParameters,
-        memberScope: true,
-        variableScope: true);
+    writeFunctionNode(node.function);
   }
 
   @override
@@ -1542,15 +1529,6 @@
   }
 
   @override
-  void visitPropertyGet(PropertyGet node) {
-    writeByte(Tag.PropertyGet);
-    writeOffset(node.fileOffset);
-    writeNode(node.receiver);
-    writeName(node.name);
-    writeNullAllowedInstanceMemberReference(node.interfaceTargetReference);
-  }
-
-  @override
   void visitDynamicSet(DynamicSet node) {
     writeByte(Tag.DynamicSet);
     writeByte(node.kind.index);
@@ -1572,16 +1550,6 @@
   }
 
   @override
-  void visitPropertySet(PropertySet node) {
-    writeByte(Tag.PropertySet);
-    writeOffset(node.fileOffset);
-    writeNode(node.receiver);
-    writeName(node.name);
-    writeNode(node.value);
-    writeNullAllowedInstanceMemberReference(node.interfaceTargetReference);
-  }
-
-  @override
   void visitSuperPropertyGet(SuperPropertyGet node) {
     writeByte(Tag.SuperPropertyGet);
     writeOffset(node.fileOffset);
@@ -1609,15 +1577,24 @@
   void visitConstructorTearOff(ConstructorTearOff node) {
     writeByte(Tag.ConstructorTearOff);
     writeOffset(node.fileOffset);
-    writeNonNullReference(node.constructorReference);
+    writeNonNullReference(node.targetReference);
+  }
+
+  @override
+  void visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+    writeByte(Tag.RedirectingFactoryTearOff);
+    writeOffset(node.fileOffset);
+    writeNonNullReference(node.targetReference);
   }
 
   @override
   void visitTypedefTearOff(TypedefTearOff node) {
     writeByte(Tag.TypedefTearOff);
+    enterScope(typeParameters: node.typeParameters);
     writeNodeList(node.typeParameters);
     writeNode(node.expression);
     writeNodeList(node.typeArguments);
+    leaveScope(typeParameters: node.typeParameters);
   }
 
   @override
@@ -1712,17 +1689,6 @@
   }
 
   @override
-  void visitMethodInvocation(MethodInvocation node) {
-    writeByte(Tag.MethodInvocation);
-    writeByte(node.flags);
-    writeOffset(node.fileOffset);
-    writeNode(node.receiver);
-    writeName(node.name);
-    writeArgumentsNode(node.arguments);
-    writeNullAllowedInstanceMemberReference(node.interfaceTargetReference);
-  }
-
-  @override
   void visitSuperMethodInvocation(SuperMethodInvocation node) {
     writeByte(Tag.SuperMethodInvocation);
     writeOffset(node.fileOffset);
@@ -2685,10 +2651,9 @@
   }
 
   @override
-  void visitRedirectingFactoryConstructorReference(
-      RedirectingFactoryConstructor node) {
+  void visitRedirectingFactoryReference(RedirectingFactory node) {
     throw new UnsupportedError(
-        'serialization of RedirectingFactoryConstructor references');
+        'serialization of RedirectingFactory references');
   }
 
   @override
@@ -2738,6 +2703,13 @@
   }
 
   @override
+  void visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node) {
+    throw new UnsupportedError(
+        'serialization of RedirectingFactoryTearOffConstants ');
+  }
+
+  @override
   void visitStaticTearOffConstantReference(StaticTearOffConstant node) {
     throw new UnsupportedError(
         'serialization of StaticTearOffConstant references');
@@ -2751,6 +2723,18 @@
   }
 
   @override
+  void visitRedirectingFactoryTearOffConstantReference(
+      RedirectingFactoryTearOffConstant node) {
+    throw new UnsupportedError(
+        'serialization of RedirectingFactoryTearOffConstant references');
+  }
+
+  @override
+  void visitTypedefTearOffConstantReference(TypedefTearOffConstant node) {
+    throw new UnsupportedError('serialization of TypedefTearOffConstants ');
+  }
+
+  @override
   void visitTypeLiteralConstant(TypeLiteralConstant node) {
     throw new UnsupportedError('serialization of TypeLiteralConstants');
   }
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index e5291c5..d578618 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -17,7 +17,7 @@
   static const int Field = 4;
   static const int Constructor = 5;
   static const int Procedure = 6;
-  static const int RedirectingFactoryConstructor = 108;
+  static const int RedirectingFactory = 108;
 
   // Initializers
   static const int InvalidInitializer = 7;
@@ -37,13 +37,10 @@
   static const int InvalidExpression = 19;
   static const int VariableGet = 20;
   static const int VariableSet = 21;
-  static const int PropertyGet = 22;
-  static const int PropertySet = 23;
   static const int SuperPropertyGet = 24;
   static const int SuperPropertySet = 25;
   static const int StaticGet = 26;
   static const int StaticSet = 27;
-  static const int MethodInvocation = 28;
   static const int SuperMethodInvocation = 29;
   static const int StaticInvocation = 30;
   static const int ConstructorInvocation = 31;
@@ -78,6 +75,7 @@
   static const int ConstMapLiteral = 59;
   static const int ConstructorTearOff = 60;
   static const int TypedefTearOff = 83;
+  static const int RedirectingFactoryTearOff = 84;
 
   static const int SetLiteral = 109;
   static const int ConstSetLiteral = 110;
@@ -125,6 +123,7 @@
   static const int AssertBlock = 81;
   // 82 is occupied by [BlockExpression] (expression).
   // 83 is occupied by [TypedefTearOff] (expression).
+  // 84 is occupied by [RedirectingFactoryTearOff] (expression).
 
   // Types
   static const int TypedefType = 87;
@@ -141,7 +140,7 @@
 
   static const int ConstantExpression = 106;
 
-  /// 108 is occupied by [RedirectingFactoryConstructor] (member).
+  /// 108 is occupied by [RedirectingFactory] (member).
   /// 109 is occupied by [SetLiteral] (expression).
   /// 110 is occupied by [ConstSetLiteral] (expression).
   /// 111 is occupied by [ListConcatenation] (expression).
@@ -177,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 = 67;
+  static const int BinaryFormatVersion = 69;
 }
 
 abstract class ConstantTag {
@@ -198,6 +197,7 @@
   // 13 is occupied by [SetConstant]
   static const int TypedefTearOffConstant = 14;
   static const int ConstructorTearOffConstant = 15;
+  static const int RedirectingFactoryTearOffConstant = 16;
 }
 
 const int sdkHashLength = 10; // Bytes, a Git "short hash".
diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart
index 21eb6b3..6d7bd11 100644
--- a/pkg/kernel/lib/canonical_name.dart
+++ b/pkg/kernel/lib/canonical_name.dart
@@ -137,34 +137,34 @@
   }
 
   CanonicalName getChildFromField(Field field) {
-    return getChild('@getters').getChildFromQualifiedName(field.name);
+    return getChild(gettersName).getChildFromQualifiedName(field.name);
   }
 
   CanonicalName getChildFromFieldSetter(Field field) {
-    return getChild('@setters').getChildFromQualifiedName(field.name);
+    return getChild(settersName).getChildFromQualifiedName(field.name);
   }
 
   CanonicalName getChildFromConstructor(Constructor constructor) {
-    return getChild('@constructors')
+    return getChild(constructorsName)
         .getChildFromQualifiedName(constructor.name);
   }
 
-  CanonicalName getChildFromRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor redirectingFactoryConstructor) {
-    return getChild('@factories')
-        .getChildFromQualifiedName(redirectingFactoryConstructor.name);
+  CanonicalName getChildFromRedirectingFactory(
+      RedirectingFactory redirectingFactory) {
+    return getChild(factoriesName)
+        .getChildFromQualifiedName(redirectingFactory.name);
   }
 
   CanonicalName getChildFromFieldWithName(Name name) {
-    return getChild('@getters').getChildFromQualifiedName(name);
+    return getChild(gettersName).getChildFromQualifiedName(name);
   }
 
   CanonicalName getChildFromFieldSetterWithName(Name name) {
-    return getChild('@setters').getChildFromQualifiedName(name);
+    return getChild(settersName).getChildFromQualifiedName(name);
   }
 
   CanonicalName getChildFromTypedef(Typedef typedef_) {
-    return getChild('@typedefs').getChild(typedef_.name);
+    return getChild(typedefsName).getChild(typedef_.name);
   }
 
   /// Take ownership of a child canonical name and its subtree.
@@ -279,14 +279,7 @@
     Iterable<CanonicalName>? parentChildren = parent.childrenOrNull;
     if (parentChildren != null) {
       for (CanonicalName child in parentChildren) {
-        if (child.name != '@methods' &&
-            child.name != '@typedefs' &&
-            child.name != '@fields' &&
-            child.name != '@=fields' &&
-            child.name != '@getters' &&
-            child.name != '@setters' &&
-            child.name != '@factories' &&
-            child.name != '@constructors') {
+        if (!isSymbolicName(child.name)) {
           bool checkReferenceNode = true;
           if (child._reference == null) {
             // OK for "if private: URI of library" part of "Qualified name"...
@@ -333,11 +326,46 @@
     return sb.toString();
   }
 
+  /// Symbolic name used for the [CanonicalName] node that holds all
+  /// constructors within a class.
+  static const String constructorsName = '@constructors';
+
+  /// Symbolic name used for the [CanonicalName] node that holds all factories
+  /// within a class.
+  static const String factoriesName = '@factories';
+
+  /// Symbolic name used for the [CanonicalName] node that holds all methods
+  /// within a library or a class.
+  static const String methodsName = '@methods';
+
+  /// Symbolic name used for the [CanonicalName] node that holds all getters and
+  /// readable fields within a library or class.
+  static const String gettersName = '@getters';
+
+  /// Symbolic name used for the [CanonicalName] node that holds all setters and
+  /// writable fields within a library or class.
+  static const String settersName = '@setters';
+
+  /// Symbolic name used for the [CanonicalName] node that holds all typedefs
+  /// within a library.
+  static const String typedefsName = '@typedefs';
+
+  static const Set<String> symbolicNames = {
+    constructorsName,
+    factoriesName,
+    methodsName,
+    gettersName,
+    settersName,
+    typedefsName,
+  };
+
+  static bool isSymbolicName(String name) => symbolicNames.contains(name);
+
   static String getProcedureQualifier(Procedure procedure) {
-    if (procedure.isGetter) return '@getters';
-    if (procedure.isSetter) return '@setters';
-    if (procedure.isFactory) return '@factories';
-    return '@methods';
+    if (procedure.isGetter) return gettersName;
+    if (procedure.isSetter) return settersName;
+    if (procedure.isFactory) return factoriesName;
+    return methodsName;
   }
 
   /// Returns `true` if [node] is orphaned through its [reference].
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 86e78d6..9127088 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -81,8 +81,7 @@
     throw 'Cloning of fields is not implemented here';
   }
 
-  TreeNode visitRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor node) {
+  TreeNode visitRedirectingFactory(RedirectingFactory node) {
     throw 'Cloning of redirecting factory constructors is not implemented here';
   }
 
@@ -165,16 +164,6 @@
     return new VariableSet(getVariableClone(node.variable)!, clone(node.value));
   }
 
-  visitPropertyGet(PropertyGet node) {
-    return new PropertyGet.byReference(
-        clone(node.receiver), node.name, node.interfaceTargetReference);
-  }
-
-  visitPropertySet(PropertySet node) {
-    return new PropertySet.byReference(clone(node.receiver), node.name,
-        clone(node.value), node.interfaceTargetReference);
-  }
-
   visitSuperPropertyGet(SuperPropertyGet node) {
     return new SuperPropertyGet.byReference(
         node.name, node.interfaceTargetReference);
@@ -193,12 +182,6 @@
     return new StaticSet.byReference(node.targetReference, clone(node.value));
   }
 
-  visitMethodInvocation(MethodInvocation node) {
-    return new MethodInvocation.byReference(clone(node.receiver), node.name,
-        clone(node.arguments), node.interfaceTargetReference)
-      ..flags = node.flags;
-  }
-
   visitSuperMethodInvocation(SuperMethodInvocation node) {
     return new SuperMethodInvocation.byReference(
         node.name, clone(node.arguments), node.interfaceTargetReference);
@@ -738,7 +721,12 @@
 
   @override
   TreeNode visitConstructorTearOff(ConstructorTearOff node) {
-    return new ConstructorTearOff.byReference(node.constructorReference);
+    return new ConstructorTearOff.byReference(node.targetReference);
+  }
+
+  @override
+  TreeNode visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+    return new RedirectingFactoryTearOff.byReference(node.targetReference);
   }
 
   @override
@@ -856,24 +844,18 @@
     return result;
   }
 
-  RedirectingFactoryConstructor cloneRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor node, Reference? reference) {
+  RedirectingFactory cloneRedirectingFactory(
+      RedirectingFactory node, Reference? reference) {
     final Uri? activeFileUriSaved = _activeFileUri;
     _activeFileUri = node.fileUri;
 
-    prepareTypeParameters(node.typeParameters);
-    RedirectingFactoryConstructor result = new RedirectingFactoryConstructor(
-        node.targetReference,
+    RedirectingFactory result = new RedirectingFactory(node.targetReference,
         name: node.name,
         isConst: node.isConst,
         isExternal: node.isExternal,
         transformerFlags: node.transformerFlags,
         typeArguments: node.typeArguments.map(visitType).toList(),
-        typeParameters: node.typeParameters.map(super.clone).toList(),
-        positionalParameters:
-            node.positionalParameters.map(super.clone).toList(),
-        namedParameters: node.namedParameters.map(super.clone).toList(),
-        requiredParameterCount: node.requiredParameterCount,
+        function: super.clone(node.function),
         fileUri: node.fileUri,
         reference: reference)
       ..annotations = cloneAnnotations && !node.annotations.isEmpty
diff --git a/pkg/kernel/lib/naive_type_checker.dart b/pkg/kernel/lib/naive_type_checker.dart
index d3a6638..7470718 100644
--- a/pkg/kernel/lib/naive_type_checker.dart
+++ b/pkg/kernel/lib/naive_type_checker.dart
@@ -287,7 +287,6 @@
                 receiver == environment.coreTypes.functionNonNullableRawType ||
                 receiver is FunctionType) &&
             (where is InvocationExpression && where.name.text == 'call') ||
-        (where is PropertyGet && where.name.text == 'call') ||
         where is FunctionTearOff) {
       return;
     }
diff --git a/pkg/kernel/lib/src/equivalence.dart b/pkg/kernel/lib/src/equivalence.dart
new file mode 100644
index 0000000..a6667e8
--- /dev/null
+++ b/pkg/kernel/lib/src/equivalence.dart
@@ -0,0 +1,7220 @@
+// 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.
+
+// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Run 'dart pkg/front_end/tool/generate_ast_equivalence.dart' to update.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/src/printer.dart';
+import 'union_find.dart';
+
+part 'equivalence_helpers.dart';
+
+/// Visitor that uses a EquivalenceStrategy to compute AST node equivalence.
+///
+/// The visitor hold a current state that collects found inequivalences and
+/// current assumptions. The current state has two modes. In the asserting mode,
+/// the default, inequivalences are registered when found. In the non-asserting
+/// mode, inequivalences are _not_ registered. The latter is used to compute
+/// equivalences in sand boxed state, for instance to determine which elements
+/// to pair when checking equivalence of two sets.
+class EquivalenceVisitor implements Visitor1<bool, Node> {
+  final EquivalenceStrategy strategy;
+
+  EquivalenceVisitor({this.strategy: const EquivalenceStrategy()});
+
+  @override
+  bool defaultNode(Node node, Node other) {
+    return false;
+  }
+
+  @override
+  bool defaultTreeNode(TreeNode node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitLibrary(Library node, Node other) {
+    return strategy.checkLibrary(this, node, other);
+  }
+
+  @override
+  bool visitTypedef(Typedef node, Node other) {
+    return strategy.checkTypedef(this, node, other);
+  }
+
+  @override
+  bool visitClass(Class node, Node other) {
+    return strategy.checkClass(this, node, other);
+  }
+
+  @override
+  bool visitExtension(Extension node, Node other) {
+    return strategy.checkExtension(this, node, other);
+  }
+
+  @override
+  bool defaultMember(Member node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitField(Field node, Node other) {
+    return strategy.checkField(this, node, other);
+  }
+
+  @override
+  bool visitConstructor(Constructor node, Node other) {
+    return strategy.checkConstructor(this, node, other);
+  }
+
+  @override
+  bool visitRedirectingFactory(RedirectingFactory node, Node other) {
+    return strategy.checkRedirectingFactory(this, node, other);
+  }
+
+  @override
+  bool visitProcedure(Procedure node, Node other) {
+    return strategy.checkProcedure(this, node, other);
+  }
+
+  @override
+  bool visitLibraryDependency(LibraryDependency node, Node other) {
+    return strategy.checkLibraryDependency(this, node, other);
+  }
+
+  @override
+  bool visitLibraryPart(LibraryPart node, Node other) {
+    return strategy.checkLibraryPart(this, node, other);
+  }
+
+  @override
+  bool visitCombinator(Combinator node, Node other) {
+    return strategy.checkCombinator(this, node, other);
+  }
+
+  @override
+  bool defaultInitializer(Initializer node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitInvalidInitializer(InvalidInitializer node, Node other) {
+    return strategy.checkInvalidInitializer(this, node, other);
+  }
+
+  @override
+  bool visitFieldInitializer(FieldInitializer node, Node other) {
+    return strategy.checkFieldInitializer(this, node, other);
+  }
+
+  @override
+  bool visitSuperInitializer(SuperInitializer node, Node other) {
+    return strategy.checkSuperInitializer(this, node, other);
+  }
+
+  @override
+  bool visitRedirectingInitializer(RedirectingInitializer node, Node other) {
+    return strategy.checkRedirectingInitializer(this, node, other);
+  }
+
+  @override
+  bool visitLocalInitializer(LocalInitializer node, Node other) {
+    return strategy.checkLocalInitializer(this, node, other);
+  }
+
+  @override
+  bool visitAssertInitializer(AssertInitializer node, Node other) {
+    return strategy.checkAssertInitializer(this, node, other);
+  }
+
+  @override
+  bool visitFunctionNode(FunctionNode node, Node other) {
+    return strategy.checkFunctionNode(this, node, other);
+  }
+
+  @override
+  bool defaultExpression(Expression node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitInvalidExpression(InvalidExpression node, Node other) {
+    return strategy.checkInvalidExpression(this, node, other);
+  }
+
+  @override
+  bool visitVariableGet(VariableGet node, Node other) {
+    return strategy.checkVariableGet(this, node, other);
+  }
+
+  @override
+  bool visitVariableSet(VariableSet node, Node other) {
+    return strategy.checkVariableSet(this, node, other);
+  }
+
+  @override
+  bool visitDynamicGet(DynamicGet node, Node other) {
+    return strategy.checkDynamicGet(this, node, other);
+  }
+
+  @override
+  bool visitInstanceGet(InstanceGet node, Node other) {
+    return strategy.checkInstanceGet(this, node, other);
+  }
+
+  @override
+  bool visitFunctionTearOff(FunctionTearOff node, Node other) {
+    return strategy.checkFunctionTearOff(this, node, other);
+  }
+
+  @override
+  bool visitInstanceTearOff(InstanceTearOff node, Node other) {
+    return strategy.checkInstanceTearOff(this, node, other);
+  }
+
+  @override
+  bool visitDynamicSet(DynamicSet node, Node other) {
+    return strategy.checkDynamicSet(this, node, other);
+  }
+
+  @override
+  bool visitInstanceSet(InstanceSet node, Node other) {
+    return strategy.checkInstanceSet(this, node, other);
+  }
+
+  @override
+  bool visitSuperPropertyGet(SuperPropertyGet node, Node other) {
+    return strategy.checkSuperPropertyGet(this, node, other);
+  }
+
+  @override
+  bool visitSuperPropertySet(SuperPropertySet node, Node other) {
+    return strategy.checkSuperPropertySet(this, node, other);
+  }
+
+  @override
+  bool visitStaticGet(StaticGet node, Node other) {
+    return strategy.checkStaticGet(this, node, other);
+  }
+
+  @override
+  bool visitStaticTearOff(StaticTearOff node, Node other) {
+    return strategy.checkStaticTearOff(this, node, other);
+  }
+
+  @override
+  bool visitStaticSet(StaticSet node, Node other) {
+    return strategy.checkStaticSet(this, node, other);
+  }
+
+  @override
+  bool visitDynamicInvocation(DynamicInvocation node, Node other) {
+    return strategy.checkDynamicInvocation(this, node, other);
+  }
+
+  @override
+  bool visitInstanceInvocation(InstanceInvocation node, Node other) {
+    return strategy.checkInstanceInvocation(this, node, other);
+  }
+
+  @override
+  bool visitInstanceGetterInvocation(
+      InstanceGetterInvocation node, Node other) {
+    return strategy.checkInstanceGetterInvocation(this, node, other);
+  }
+
+  @override
+  bool visitFunctionInvocation(FunctionInvocation node, Node other) {
+    return strategy.checkFunctionInvocation(this, node, other);
+  }
+
+  @override
+  bool visitLocalFunctionInvocation(LocalFunctionInvocation node, Node other) {
+    return strategy.checkLocalFunctionInvocation(this, node, other);
+  }
+
+  @override
+  bool visitSuperMethodInvocation(SuperMethodInvocation node, Node other) {
+    return strategy.checkSuperMethodInvocation(this, node, other);
+  }
+
+  @override
+  bool visitStaticInvocation(StaticInvocation node, Node other) {
+    return strategy.checkStaticInvocation(this, node, other);
+  }
+
+  @override
+  bool visitConstructorInvocation(ConstructorInvocation node, Node other) {
+    return strategy.checkConstructorInvocation(this, node, other);
+  }
+
+  @override
+  bool visitEqualsNull(EqualsNull node, Node other) {
+    return strategy.checkEqualsNull(this, node, other);
+  }
+
+  @override
+  bool visitEqualsCall(EqualsCall node, Node other) {
+    return strategy.checkEqualsCall(this, node, other);
+  }
+
+  @override
+  bool visitInstantiation(Instantiation node, Node other) {
+    return strategy.checkInstantiation(this, node, other);
+  }
+
+  @override
+  bool visitNot(Not node, Node other) {
+    return strategy.checkNot(this, node, other);
+  }
+
+  @override
+  bool visitLogicalExpression(LogicalExpression node, Node other) {
+    return strategy.checkLogicalExpression(this, node, other);
+  }
+
+  @override
+  bool visitConditionalExpression(ConditionalExpression node, Node other) {
+    return strategy.checkConditionalExpression(this, node, other);
+  }
+
+  @override
+  bool visitStringConcatenation(StringConcatenation node, Node other) {
+    return strategy.checkStringConcatenation(this, node, other);
+  }
+
+  @override
+  bool visitListConcatenation(ListConcatenation node, Node other) {
+    return strategy.checkListConcatenation(this, node, other);
+  }
+
+  @override
+  bool visitSetConcatenation(SetConcatenation node, Node other) {
+    return strategy.checkSetConcatenation(this, node, other);
+  }
+
+  @override
+  bool visitMapConcatenation(MapConcatenation node, Node other) {
+    return strategy.checkMapConcatenation(this, node, other);
+  }
+
+  @override
+  bool visitInstanceCreation(InstanceCreation node, Node other) {
+    return strategy.checkInstanceCreation(this, node, other);
+  }
+
+  @override
+  bool visitFileUriExpression(FileUriExpression node, Node other) {
+    return strategy.checkFileUriExpression(this, node, other);
+  }
+
+  @override
+  bool visitIsExpression(IsExpression node, Node other) {
+    return strategy.checkIsExpression(this, node, other);
+  }
+
+  @override
+  bool visitAsExpression(AsExpression node, Node other) {
+    return strategy.checkAsExpression(this, node, other);
+  }
+
+  @override
+  bool visitNullCheck(NullCheck node, Node other) {
+    return strategy.checkNullCheck(this, node, other);
+  }
+
+  @override
+  bool defaultBasicLiteral(BasicLiteral node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitStringLiteral(StringLiteral node, Node other) {
+    return strategy.checkStringLiteral(this, node, other);
+  }
+
+  @override
+  bool visitIntLiteral(IntLiteral node, Node other) {
+    return strategy.checkIntLiteral(this, node, other);
+  }
+
+  @override
+  bool visitDoubleLiteral(DoubleLiteral node, Node other) {
+    return strategy.checkDoubleLiteral(this, node, other);
+  }
+
+  @override
+  bool visitBoolLiteral(BoolLiteral node, Node other) {
+    return strategy.checkBoolLiteral(this, node, other);
+  }
+
+  @override
+  bool visitNullLiteral(NullLiteral node, Node other) {
+    return strategy.checkNullLiteral(this, node, other);
+  }
+
+  @override
+  bool visitSymbolLiteral(SymbolLiteral node, Node other) {
+    return strategy.checkSymbolLiteral(this, node, other);
+  }
+
+  @override
+  bool visitTypeLiteral(TypeLiteral node, Node other) {
+    return strategy.checkTypeLiteral(this, node, other);
+  }
+
+  @override
+  bool visitThisExpression(ThisExpression node, Node other) {
+    return strategy.checkThisExpression(this, node, other);
+  }
+
+  @override
+  bool visitRethrow(Rethrow node, Node other) {
+    return strategy.checkRethrow(this, node, other);
+  }
+
+  @override
+  bool visitThrow(Throw node, Node other) {
+    return strategy.checkThrow(this, node, other);
+  }
+
+  @override
+  bool visitListLiteral(ListLiteral node, Node other) {
+    return strategy.checkListLiteral(this, node, other);
+  }
+
+  @override
+  bool visitSetLiteral(SetLiteral node, Node other) {
+    return strategy.checkSetLiteral(this, node, other);
+  }
+
+  @override
+  bool visitMapLiteral(MapLiteral node, Node other) {
+    return strategy.checkMapLiteral(this, node, other);
+  }
+
+  @override
+  bool visitAwaitExpression(AwaitExpression node, Node other) {
+    return strategy.checkAwaitExpression(this, node, other);
+  }
+
+  @override
+  bool visitFunctionExpression(FunctionExpression node, Node other) {
+    return strategy.checkFunctionExpression(this, node, other);
+  }
+
+  @override
+  bool visitConstantExpression(ConstantExpression node, Node other) {
+    return strategy.checkConstantExpression(this, node, other);
+  }
+
+  @override
+  bool visitLet(Let node, Node other) {
+    return strategy.checkLet(this, node, other);
+  }
+
+  @override
+  bool visitBlockExpression(BlockExpression node, Node other) {
+    return strategy.checkBlockExpression(this, node, other);
+  }
+
+  @override
+  bool visitLoadLibrary(LoadLibrary node, Node other) {
+    return strategy.checkLoadLibrary(this, node, other);
+  }
+
+  @override
+  bool visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node, Node other) {
+    return strategy.checkCheckLibraryIsLoaded(this, node, other);
+  }
+
+  @override
+  bool visitConstructorTearOff(ConstructorTearOff node, Node other) {
+    return strategy.checkConstructorTearOff(this, node, other);
+  }
+
+  @override
+  bool visitRedirectingFactoryTearOff(
+      RedirectingFactoryTearOff node, Node other) {
+    return strategy.checkRedirectingFactoryTearOff(this, node, other);
+  }
+
+  @override
+  bool visitTypedefTearOff(TypedefTearOff node, Node other) {
+    return strategy.checkTypedefTearOff(this, node, other);
+  }
+
+  @override
+  bool visitArguments(Arguments node, Node other) {
+    return strategy.checkArguments(this, node, other);
+  }
+
+  @override
+  bool visitNamedExpression(NamedExpression node, Node other) {
+    return strategy.checkNamedExpression(this, node, other);
+  }
+
+  @override
+  bool visitMapLiteralEntry(MapLiteralEntry node, Node other) {
+    return strategy.checkMapLiteralEntry(this, node, other);
+  }
+
+  @override
+  bool defaultStatement(Statement node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitExpressionStatement(ExpressionStatement node, Node other) {
+    return strategy.checkExpressionStatement(this, node, other);
+  }
+
+  @override
+  bool visitBlock(Block node, Node other) {
+    return strategy.checkBlock(this, node, other);
+  }
+
+  @override
+  bool visitAssertBlock(AssertBlock node, Node other) {
+    return strategy.checkAssertBlock(this, node, other);
+  }
+
+  @override
+  bool visitEmptyStatement(EmptyStatement node, Node other) {
+    return strategy.checkEmptyStatement(this, node, other);
+  }
+
+  @override
+  bool visitAssertStatement(AssertStatement node, Node other) {
+    return strategy.checkAssertStatement(this, node, other);
+  }
+
+  @override
+  bool visitLabeledStatement(LabeledStatement node, Node other) {
+    return strategy.checkLabeledStatement(this, node, other);
+  }
+
+  @override
+  bool visitBreakStatement(BreakStatement node, Node other) {
+    return strategy.checkBreakStatement(this, node, other);
+  }
+
+  @override
+  bool visitWhileStatement(WhileStatement node, Node other) {
+    return strategy.checkWhileStatement(this, node, other);
+  }
+
+  @override
+  bool visitDoStatement(DoStatement node, Node other) {
+    return strategy.checkDoStatement(this, node, other);
+  }
+
+  @override
+  bool visitForStatement(ForStatement node, Node other) {
+    return strategy.checkForStatement(this, node, other);
+  }
+
+  @override
+  bool visitForInStatement(ForInStatement node, Node other) {
+    return strategy.checkForInStatement(this, node, other);
+  }
+
+  @override
+  bool visitSwitchStatement(SwitchStatement node, Node other) {
+    return strategy.checkSwitchStatement(this, node, other);
+  }
+
+  @override
+  bool visitContinueSwitchStatement(ContinueSwitchStatement node, Node other) {
+    return strategy.checkContinueSwitchStatement(this, node, other);
+  }
+
+  @override
+  bool visitIfStatement(IfStatement node, Node other) {
+    return strategy.checkIfStatement(this, node, other);
+  }
+
+  @override
+  bool visitReturnStatement(ReturnStatement node, Node other) {
+    return strategy.checkReturnStatement(this, node, other);
+  }
+
+  @override
+  bool visitTryCatch(TryCatch node, Node other) {
+    return strategy.checkTryCatch(this, node, other);
+  }
+
+  @override
+  bool visitTryFinally(TryFinally node, Node other) {
+    return strategy.checkTryFinally(this, node, other);
+  }
+
+  @override
+  bool visitYieldStatement(YieldStatement node, Node other) {
+    return strategy.checkYieldStatement(this, node, other);
+  }
+
+  @override
+  bool visitVariableDeclaration(VariableDeclaration node, Node other) {
+    return strategy.checkVariableDeclaration(this, node, other);
+  }
+
+  @override
+  bool visitFunctionDeclaration(FunctionDeclaration node, Node other) {
+    return strategy.checkFunctionDeclaration(this, node, other);
+  }
+
+  @override
+  bool visitSwitchCase(SwitchCase node, Node other) {
+    return strategy.checkSwitchCase(this, node, other);
+  }
+
+  @override
+  bool visitCatch(Catch node, Node other) {
+    return strategy.checkCatch(this, node, other);
+  }
+
+  @override
+  bool visitTypeParameter(TypeParameter node, Node other) {
+    return strategy.checkTypeParameter(this, node, other);
+  }
+
+  @override
+  bool visitComponent(Component node, Node other) {
+    return strategy.checkComponent(this, node, other);
+  }
+
+  @override
+  bool visitName(Name node, Node other) {
+    return strategy.checkName(this, node, other);
+  }
+
+  @override
+  bool defaultDartType(DartType node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitInvalidType(InvalidType node, Node other) {
+    return strategy.checkInvalidType(this, node, other);
+  }
+
+  @override
+  bool visitDynamicType(DynamicType node, Node other) {
+    return strategy.checkDynamicType(this, node, other);
+  }
+
+  @override
+  bool visitVoidType(VoidType node, Node other) {
+    return strategy.checkVoidType(this, node, other);
+  }
+
+  @override
+  bool visitNeverType(NeverType node, Node other) {
+    return strategy.checkNeverType(this, node, other);
+  }
+
+  @override
+  bool visitNullType(NullType node, Node other) {
+    return strategy.checkNullType(this, node, other);
+  }
+
+  @override
+  bool visitInterfaceType(InterfaceType node, Node other) {
+    return strategy.checkInterfaceType(this, node, other);
+  }
+
+  @override
+  bool visitFunctionType(FunctionType node, Node other) {
+    return strategy.checkFunctionType(this, node, other);
+  }
+
+  @override
+  bool visitTypedefType(TypedefType node, Node other) {
+    return strategy.checkTypedefType(this, node, other);
+  }
+
+  @override
+  bool visitFutureOrType(FutureOrType node, Node other) {
+    return strategy.checkFutureOrType(this, node, other);
+  }
+
+  @override
+  bool visitExtensionType(ExtensionType node, Node other) {
+    return strategy.checkExtensionType(this, node, other);
+  }
+
+  @override
+  bool visitTypeParameterType(TypeParameterType node, Node other) {
+    return strategy.checkTypeParameterType(this, node, other);
+  }
+
+  @override
+  bool visitNamedType(NamedType node, Node other) {
+    return strategy.checkNamedType(this, node, other);
+  }
+
+  @override
+  bool visitSupertype(Supertype node, Node other) {
+    return strategy.checkSupertype(this, node, other);
+  }
+
+  @override
+  bool defaultConstant(Constant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitNullConstant(NullConstant node, Node other) {
+    return strategy.checkNullConstant(this, node, other);
+  }
+
+  @override
+  bool visitBoolConstant(BoolConstant node, Node other) {
+    return strategy.checkBoolConstant(this, node, other);
+  }
+
+  @override
+  bool visitIntConstant(IntConstant node, Node other) {
+    return strategy.checkIntConstant(this, node, other);
+  }
+
+  @override
+  bool visitDoubleConstant(DoubleConstant node, Node other) {
+    return strategy.checkDoubleConstant(this, node, other);
+  }
+
+  @override
+  bool visitStringConstant(StringConstant node, Node other) {
+    return strategy.checkStringConstant(this, node, other);
+  }
+
+  @override
+  bool visitSymbolConstant(SymbolConstant node, Node other) {
+    return strategy.checkSymbolConstant(this, node, other);
+  }
+
+  @override
+  bool visitMapConstant(MapConstant node, Node other) {
+    return strategy.checkMapConstant(this, node, other);
+  }
+
+  @override
+  bool visitListConstant(ListConstant node, Node other) {
+    return strategy.checkListConstant(this, node, other);
+  }
+
+  @override
+  bool visitSetConstant(SetConstant node, Node other) {
+    return strategy.checkSetConstant(this, node, other);
+  }
+
+  @override
+  bool visitInstanceConstant(InstanceConstant node, Node other) {
+    return strategy.checkInstanceConstant(this, node, other);
+  }
+
+  @override
+  bool visitInstantiationConstant(InstantiationConstant node, Node other) {
+    return strategy.checkInstantiationConstant(this, node, other);
+  }
+
+  @override
+  bool visitStaticTearOffConstant(StaticTearOffConstant node, Node other) {
+    return strategy.checkStaticTearOffConstant(this, node, other);
+  }
+
+  @override
+  bool visitConstructorTearOffConstant(
+      ConstructorTearOffConstant node, Node other) {
+    return strategy.checkConstructorTearOffConstant(this, node, other);
+  }
+
+  @override
+  bool visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node, Node other) {
+    return strategy.checkRedirectingFactoryTearOffConstant(this, node, other);
+  }
+
+  @override
+  bool visitTypedefTearOffConstant(TypedefTearOffConstant node, Node other) {
+    return strategy.checkTypedefTearOffConstant(this, node, other);
+  }
+
+  @override
+  bool visitTypeLiteralConstant(TypeLiteralConstant node, Node other) {
+    return strategy.checkTypeLiteralConstant(this, node, other);
+  }
+
+  @override
+  bool visitUnevaluatedConstant(UnevaluatedConstant node, Node other) {
+    return strategy.checkUnevaluatedConstant(this, node, other);
+  }
+
+  @override
+  bool visitTypedefReference(Typedef node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitClassReference(Class node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitExtensionReference(Extension node, Node other) {
+    return false;
+  }
+
+  @override
+  bool defaultMemberReference(Member node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitFieldReference(Field node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitConstructorReference(Constructor node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitRedirectingFactoryReference(RedirectingFactory node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitProcedureReference(Procedure node, Node other) {
+    return false;
+  }
+
+  @override
+  bool defaultConstantReference(Constant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitNullConstantReference(NullConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitBoolConstantReference(BoolConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitIntConstantReference(IntConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitDoubleConstantReference(DoubleConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitStringConstantReference(StringConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitSymbolConstantReference(SymbolConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitMapConstantReference(MapConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitListConstantReference(ListConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitSetConstantReference(SetConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitInstanceConstantReference(InstanceConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitInstantiationConstantReference(
+      InstantiationConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitStaticTearOffConstantReference(
+      StaticTearOffConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitConstructorTearOffConstantReference(
+      ConstructorTearOffConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitRedirectingFactoryTearOffConstantReference(
+      RedirectingFactoryTearOffConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitTypedefTearOffConstantReference(
+      TypedefTearOffConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitTypeLiteralConstantReference(TypeLiteralConstant node, Node other) {
+    return false;
+  }
+
+  @override
+  bool visitUnevaluatedConstantReference(UnevaluatedConstant node, Node other) {
+    return false;
+  }
+
+  /// Returns `true` if [a] and [b] are identical or equal.
+  bool _checkValues<T>(T? a, T? b) {
+    return identical(a, b) || a == b;
+  }
+
+  /// Returns `true` if [a] and [b] are identical or equal and registers the
+  /// inequivalence otherwise.
+  bool checkValues<T>(T? a, T? b, String propertyName) {
+    bool result = _checkValues(a, b);
+    if (!result) {
+      registerInequivalence(
+          propertyName, 'Values ${a} and ${b} are not equivalent');
+    }
+    return result;
+  }
+
+  /// Returns `true` if [a] and [b] are identical or equal. Inequivalence is
+  /// _not_ registered.
+  bool matchValues<T>(T? a, T? b) {
+    return _checkValues(a, b);
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent.
+  bool _checkNodes<T extends Node>(T? a, T? b) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) {
+      return false;
+    } else {
+      return a.accept1(this, b);
+    }
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, as defined by the current
+  /// strategy, and registers the inequivalence otherwise.
+  bool checkNodes<T extends Node>(T? a, T? b, [String propertyName = '']) {
+    _checkingState.pushPropertyState(propertyName);
+    bool result = _checkNodes(a, b);
+    _checkingState.popState();
+    if (!result) {
+      registerInequivalence(
+          propertyName, 'Inequivalent nodes\n1: ${a}\n2: ${b}');
+    }
+    return result;
+  }
+
+  /// Returns `true` if [a] and [b] are identical or equal. Inequivalence is
+  /// _not_ registered.
+  bool shallowMatchNodes<T extends Node>(T? a, T? b) {
+    return _checkValues(a, b);
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, as defined by the current
+  /// strategy. Inequivalence is _not_ registered.
+  bool deepMatchNodes<T extends Node>(T? a, T? b) {
+    CheckingState oldState = _checkingState;
+    _checkingState = _checkingState.toMatchingState();
+    bool result = checkNodes(a, b);
+    _checkingState = oldState;
+    return result;
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, as defined by their
+  /// corresponding canonical names. Inequivalence is _not_ registered.
+  bool matchNamedNodes(NamedNode? a, NamedNode? b) {
+    return identical(a, b) ||
+        a == null ||
+        b == null ||
+        new ReferenceName.fromNamedNode(a) ==
+            new ReferenceName.fromNamedNode(b);
+  }
+
+  /// Returns `true` if [a] and [b] are currently assumed to be equivalent.
+  bool checkAssumedReferences(Reference? a, Reference? b) {
+    return _checkingState.checkAssumedReferences(a, b);
+  }
+
+  /// Assume that [a] and [b] are equivalent, if possible.
+  ///
+  /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+  /// would not be the case if [a] xor [b] is `null`.
+  bool assumeReferences(Reference? a, Reference? b) {
+    return _checkingState.assumeReferences(a, b);
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, as defined by their
+  /// corresponding canonical names. Inequivalence is _not_ registered.
+  bool matchReferences(Reference? a, Reference? b) {
+    return identical(a, b) ||
+        ReferenceName.fromReference(a) == ReferenceName.fromReference(b);
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, either by their
+  /// corresponding canonical names or by assumption. Inequivalence is _not_
+  /// registered.
+  bool _checkReferences(Reference? a, Reference? b) {
+    if (identical(a, b)) {
+      return true;
+    } else if (a == null || b == null) {
+      return false;
+    } else if (matchReferences(a, b)) {
+      return true;
+    } else if (checkAssumedReferences(a, b)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, either by their
+  /// corresponding canonical names or by assumption. Inequivalence is _not_
+  /// registered.
+  bool deeplyMatchReferences(Reference? a, Reference? b) {
+    CheckingState oldState = _checkingState;
+    _checkingState = _checkingState.toMatchingState();
+    bool result = checkReferences(a, b);
+    _checkingState = oldState;
+    return result;
+  }
+
+  /// Returns `true` if [a] and [b] are equivalent, either by their
+  /// corresponding canonical names or by assumption, and registers the
+  /// inequivalence otherwise.
+  bool checkReferences(Reference? a, Reference? b, [String propertyName = '']) {
+    bool result = _checkReferences(a, b);
+    if (!result) {
+      registerInequivalence(
+          propertyName, 'Inequivalent references:\n1: ${a}\n2: ${b}');
+    }
+    return result;
+  }
+
+  /// Returns `true` if declarations [a] and [b] are currently assumed to be
+  /// equivalent.
+  bool checkAssumedDeclarations(dynamic a, dynamic b) {
+    return _checkingState.checkAssumedDeclarations(a, b);
+  }
+
+  /// Assume that [a] and [b] are equivalent, if possible.
+  ///
+  /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+  /// would not be the case if [a] is already assumed to be equivalent to
+  /// another declaration.
+  bool assumeDeclarations(dynamic a, dynamic b) {
+    return _checkingState.assumeDeclarations(a, b);
+  }
+
+  bool matchDeclarations(dynamic a, dynamic b) {
+    if (a is LabeledStatement) {
+      return b is LabeledStatement;
+    }
+    if (a is VariableDeclaration) {
+      return b is VariableDeclaration && a.name == b.name;
+    }
+    if (a is SwitchCase) {
+      return b is SwitchCase;
+    }
+    if (a is TypeParameter) {
+      return b is TypeParameter && a.name == b.name;
+    }
+    return false;
+  }
+
+  bool _checkDeclarations(dynamic a, dynamic b) {
+    if (identical(a, b)) {
+      return true;
+    } else if (a == null || b == null) {
+      return false;
+    } else if (checkAssumedDeclarations(a, b)) {
+      return true;
+    } else if (matchDeclarations(a, b)) {
+      return assumeDeclarations(a, b);
+    } else {
+      return false;
+    }
+  }
+
+  bool deepMatchDeclarations(dynamic a, dynamic b) {
+    CheckingState oldState = _checkingState;
+    _checkingState = _checkingState.toMatchingState();
+    bool result = checkDeclarations(a, b);
+    _checkingState = oldState;
+    return result;
+  }
+
+  bool checkDeclarations(dynamic a, dynamic b, [String propertyName = '']) {
+    bool result = _checkDeclarations(a, b);
+    if (!result) {
+      result = assumeDeclarations(a, b);
+    }
+    if (!result) {
+      registerInequivalence(
+          propertyName, 'Declarations ${a} and ${b} are not equivalent');
+    }
+    return result;
+  }
+
+  /// Returns `true` if lists [a] and [b] are equivalent, using
+  /// [equivalentValues] to determine element-wise equivalence.
+  ///
+  /// If run in a checking state, the [propertyName] is used for registering
+  /// inequivalences.
+  bool checkLists<E>(
+      List<E>? a, List<E>? b, bool Function(E?, E?, String) equivalentValues,
+      [String propertyName = '']) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) return false;
+    if (a.length != b.length) {
+      registerInequivalence(
+          '${propertyName}.length', 'Lists ${a} and ${b} are not equivalent');
+      return false;
+    }
+    for (int i = 0; i < a.length; i++) {
+      if (!equivalentValues(a[i], b[i], '${propertyName}[${i}]')) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /// Returns `true` if lists [a] and [b] are equivalent, using
+  /// [equivalentValues] to determine element-wise equivalence.
+  ///
+  /// Inequivalence is _not_ registered.
+  bool matchLists<E>(
+      List<E>? a, List<E>? b, bool Function(E?, E?, String) equivalentValues) {
+    CheckingState oldState = _checkingState;
+    _checkingState = _checkingState.toMatchingState();
+    bool result = checkLists(a, b, equivalentValues);
+    _checkingState = oldState;
+    return result;
+  }
+
+  /// Returns `true` if sets [a] and [b] are equivalent, using
+  /// [matchingValues] to determine which elements that should be checked for
+  /// element-wise equivalence using [equivalentValues].
+  ///
+  /// If run in a checking state, the [propertyName] is used for registering
+  /// inequivalences.
+  bool checkSets<E>(Set<E>? a, Set<E>? b, bool Function(E?, E?) matchingValues,
+      bool Function(E?, E?, String) equivalentValues,
+      [String propertyName = '']) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) return false;
+    if (a.length != b.length) {
+      registerInequivalence(
+          '${propertyName}.length', 'Sets ${a} and ${b} are not equivalent');
+      return false;
+    }
+    b = b.toSet();
+    for (E aValue in a) {
+      bool hasFoundValue = false;
+      E? foundValue;
+      for (E bValue in b) {
+        if (matchingValues(aValue, bValue)) {
+          foundValue = bValue;
+          hasFoundValue = true;
+          if (!equivalentValues(aValue, bValue, '${propertyName}[${aValue}]')) {
+            registerInequivalence('${propertyName}[${aValue}]',
+                'Elements ${aValue} and ${bValue} are not equivalent');
+            return false;
+          }
+          break;
+        }
+      }
+      if (hasFoundValue) {
+        b.remove(foundValue);
+      } else {
+        registerInequivalence(
+            '${propertyName}[${aValue}]',
+            'Sets ${a} and ${b} are not equivalent, no equivalent value '
+                'found for $aValue');
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /// Returns `true` if sets [a] and [b] are equivalent, using
+  /// [matchingValues] to determine which elements that should be checked for
+  /// element-wise equivalence using [equivalentValues].
+  ///
+  /// Inequivalence is _not_registered.
+  bool matchSets<E>(Set<E>? a, Set<E>? b, bool Function(E?, E?) matchingValues,
+      bool Function(E?, E?, String) equivalentValues) {
+    CheckingState oldState = _checkingState;
+    _checkingState = _checkingState.toMatchingState();
+    bool result = checkSets(a, b, matchingValues, equivalentValues);
+    _checkingState = oldState;
+    return result;
+  }
+
+  /// Returns `true` if maps [a] and [b] are equivalent, using
+  /// [matchingKeys] to determine which entries that should be checked for
+  /// entry-wise equivalence using [equivalentKeys] and [equivalentValues] to
+  /// determine key and value equivalences, respectively.
+  ///
+  /// If run in a checking state, the [propertyName] is used for registering
+  /// inequivalences.
+  bool checkMaps<K, V>(
+      Map<K, V>? a,
+      Map<K, V>? b,
+      bool Function(K?, K?) matchingKeys,
+      bool Function(K?, K?, String) equivalentKeys,
+      bool Function(V?, V?, String) equivalentValues,
+      [String propertyName = '']) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) return false;
+    if (a.length != b.length) {
+      registerInequivalence(
+          '${propertyName}.length', 'Maps ${a} and ${b} are not equivalent');
+      return false;
+    }
+    Set<K> bKeys = b.keys.toSet();
+    for (K aKey in a.keys) {
+      bool hasFoundKey = false;
+      K? foundKey;
+      for (K bKey in bKeys) {
+        if (matchingKeys(aKey, bKey)) {
+          foundKey = bKey;
+          hasFoundKey = true;
+          if (!equivalentKeys(aKey, bKey, '${propertyName}[${aKey}]')) {
+            registerInequivalence('${propertyName}[${aKey}]',
+                'Keys ${aKey} and ${bKey} are not equivalent');
+            return false;
+          }
+          break;
+        }
+      }
+      if (hasFoundKey) {
+        bKeys.remove(foundKey);
+        if (!equivalentValues(
+            a[aKey], b[foundKey], '${propertyName}[${aKey}]')) {
+          return false;
+        }
+      } else {
+        registerInequivalence(
+            '${propertyName}[${aKey}]',
+            'Maps ${a} and ${b} are not equivalent, no equivalent key '
+                'found for $aKey');
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /// Returns `true` if maps [a] and [b] are equivalent, using
+  /// [matchingKeys] to determine which entries that should be checked for
+  /// entry-wise equivalence using [equivalentKeys] and [equivalentValues] to
+  /// determine key and value equivalences, respectively.
+  ///
+  /// Inequivalence is _not_ registered.
+  bool matchMaps<K, V>(
+      Map<K, V>? a,
+      Map<K, V>? b,
+      bool Function(K?, K?) matchingKeys,
+      bool Function(K?, K?, String) equivalentKeys,
+      bool Function(V?, V?, String) equivalentValues) {
+    CheckingState oldState = _checkingState;
+    _checkingState = _checkingState.toMatchingState();
+    bool result =
+        checkMaps(a, b, matchingKeys, equivalentKeys, equivalentValues);
+    _checkingState = oldState;
+    return result;
+  }
+
+  /// The current state of the visitor.
+  ///
+  /// This holds the current assumptions, found inequivalences, and whether
+  /// inequivalences are currently registered.
+  CheckingState _checkingState = new CheckingState();
+
+  /// Runs [f] in a new state that holds all current assumptions. If
+  /// [isAsserting] is `true`, inequivalences are registered. Returns the
+  /// collected inequivalences.
+  ///
+  /// If [f] returns `false`, the returned result is marked as having
+  /// inequivalences even when non have being registered.
+  EquivalenceResult inSubState(bool Function() f, {bool isAsserting: false}) {
+    CheckingState _oldState = _checkingState;
+    _checkingState = _checkingState.createSubState(isAsserting: isAsserting);
+    bool hasInequivalences = f();
+    EquivalenceResult result =
+        _checkingState.toResult(hasInequivalences: hasInequivalences);
+    _checkingState = _oldState;
+    return result;
+  }
+
+  /// Registers that the visitor enters the property named [propertyName] and
+  /// the currently visited node.
+  void pushPropertyState(String propertyName) {
+    _checkingState.pushPropertyState(propertyName);
+  }
+
+  /// Registers that the visitor enters nodes [a] and [b].
+  void pushNodeState(Node a, Node b) {
+    _checkingState.pushNodeState(a, b);
+  }
+
+  /// Register that the visitor leave the current node or property.
+  void popState() {
+    _checkingState.popState();
+  }
+
+  /// Returns the value used as the result for property inequivalences.
+  ///
+  /// When inequivalences are currently registered, this is `true`, so that the
+  /// visitor will continue find inequivalences that are not directly related.
+  ///
+  /// An example is finding several child inequivalences on otherwise equivalent
+  /// nodes, like finding inequivalences deeply in the members of the second
+  /// library of a component even when inequivalences deeply in the members of
+  /// the first library. Had the return value been `false`, signaling that the
+  /// first libraries were inequivalent, which they technically are, given that
+  /// the contain inequivalent subnodes, the visitor would have stopped short in
+  /// checking the list of libraries, and the inequivalences in the second
+  /// library would not have been found.
+  ///
+  /// When inequivalences are _not_ currently registered, i.e. we are only
+  /// interested in the true/false value of the equivalence test, `false` is
+  /// used as the result value to stop the equivalence checking short.
+  bool get resultOnInequivalence => _checkingState.resultOnInequivalence;
+
+  /// Registers an equivalence on the [propertyName] with a detailed description
+  /// in [message].
+  void registerInequivalence(String propertyName, String message) {
+    _checkingState.registerInequivalence(propertyName, message);
+  }
+
+  /// Returns the inequivalences found by the visitor.
+  EquivalenceResult toResult() => _checkingState.toResult();
+}
+
+/// Checks [a] and [b] be for equivalence using [strategy].
+///
+/// Returns an [EquivalenceResult] containing the found inequivalences.
+EquivalenceResult checkEquivalence(Node a, Node b,
+    {EquivalenceStrategy strategy: const EquivalenceStrategy()}) {
+  EquivalenceVisitor visitor = new EquivalenceVisitor(strategy: strategy);
+  visitor.checkNodes(a, b, 'root');
+  return visitor.toResult();
+}
+
+/// Strategy used for determining equivalence of AST nodes.
+///
+/// The strategy has a method for determining the equivalence of each AST node
+/// class, and a method for determining the equivalence of each property on each
+/// AST node class.
+///
+/// The base implementation enforces a full structural equivalence.
+///
+/// Custom strategies can be made by extending this strategy and override
+/// methods where exceptions to the structural equivalence are needed.
+class EquivalenceStrategy {
+  const EquivalenceStrategy();
+
+  bool checkLibrary(EquivalenceVisitor visitor, Library? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Library) return false;
+    if (other is! Library) return false;
+    if (!visitor.matchNamedNodes(node, other)) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkLibrary_importUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_fileUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_languageVersion(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_problemsAsJson(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_dependencies(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_additionalExports(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_parts(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_typedefs(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_classes(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_extensions(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_procedures(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_fields(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_reference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibrary_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkTypedef(EquivalenceVisitor visitor, Typedef? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Typedef) return false;
+    if (other is! Typedef) return false;
+    if (!visitor.matchNamedNodes(node, other)) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkTypedef_fileUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedef_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedef_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedef_typeParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedef_type(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedef_typeParametersOfFunctionType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedef_positionalParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedef_namedParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedef_reference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedef_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkClass(EquivalenceVisitor visitor, Class? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Class) return false;
+    if (other is! Class) return false;
+    if (!visitor.matchNamedNodes(node, other)) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkClass_startFileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_fileEndOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_fileUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_typeParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_supertype(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_mixedInType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_implementedTypes(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_fields(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_constructors(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_procedures(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_redirectingFactories(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_reference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkClass_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkExtensionMemberDescriptor(EquivalenceVisitor visitor,
+      ExtensionMemberDescriptor? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ExtensionMemberDescriptor) return false;
+    if (other is! ExtensionMemberDescriptor) return false;
+    bool result = true;
+    if (!checkExtensionMemberDescriptor_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtensionMemberDescriptor_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtensionMemberDescriptor_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtensionMemberDescriptor_member(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    return result;
+  }
+
+  bool checkExtension(
+      EquivalenceVisitor visitor, Extension? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Extension) return false;
+    if (other is! Extension) return false;
+    if (!visitor.matchNamedNodes(node, other)) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkExtension_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtension_fileUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtension_typeParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtension_onType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtension_members(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtension_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtension_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtension_reference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtension_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkField(EquivalenceVisitor visitor, Field? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Field) return false;
+    if (other is! Field) return false;
+    if (!visitor.matchNamedNodes(node, other)) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkField_type(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkField_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkField_initializer(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkField_setterReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkField_fileEndOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkField_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkField_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkField_fileUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkField_transformerFlags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkField_getterReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkField_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkConstructor(
+      EquivalenceVisitor visitor, Constructor? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Constructor) return false;
+    if (other is! Constructor) return false;
+    if (!visitor.matchNamedNodes(node, other)) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkConstructor_startFileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructor_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructor_function(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructor_initializers(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructor_fileEndOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructor_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructor_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructor_fileUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructor_transformerFlags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructor_reference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructor_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkRedirectingFactory(
+      EquivalenceVisitor visitor, RedirectingFactory? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! RedirectingFactory) return false;
+    if (other is! RedirectingFactory) return false;
+    if (!visitor.matchNamedNodes(node, other)) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkRedirectingFactory_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactory_typeArguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactory_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactory_function(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactory_fileEndOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactory_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactory_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactory_fileUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactory_transformerFlags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactory_reference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactory_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkProcedure(
+      EquivalenceVisitor visitor, Procedure? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Procedure) return false;
+    if (other is! Procedure) return false;
+    if (!visitor.matchNamedNodes(node, other)) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkProcedure_startFileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_function(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_stubKind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_stubTargetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_fileEndOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_fileUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_transformerFlags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_reference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkProcedure_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkLibraryDependency(
+      EquivalenceVisitor visitor, LibraryDependency? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! LibraryDependency) return false;
+    if (other is! LibraryDependency) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkLibraryDependency_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibraryDependency_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibraryDependency_importedLibraryReference(
+        visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibraryDependency_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibraryDependency_combinators(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibraryDependency_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkLibraryPart(
+      EquivalenceVisitor visitor, LibraryPart? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! LibraryPart) return false;
+    if (other is! LibraryPart) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkLibraryPart_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibraryPart_partUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLibraryPart_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkCombinator(
+      EquivalenceVisitor visitor, Combinator? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Combinator) return false;
+    if (other is! Combinator) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkCombinator_isShow(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkCombinator_names(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkCombinator_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInvalidInitializer(
+      EquivalenceVisitor visitor, InvalidInitializer? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InvalidInitializer) return false;
+    if (other is! InvalidInitializer) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInvalidInitializer_isSynthetic(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInvalidInitializer_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkFieldInitializer(
+      EquivalenceVisitor visitor, FieldInitializer? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! FieldInitializer) return false;
+    if (other is! FieldInitializer) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkFieldInitializer_fieldReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFieldInitializer_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFieldInitializer_isSynthetic(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFieldInitializer_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSuperInitializer(
+      EquivalenceVisitor visitor, SuperInitializer? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SuperInitializer) return false;
+    if (other is! SuperInitializer) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSuperInitializer_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperInitializer_arguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperInitializer_isSynthetic(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperInitializer_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkRedirectingInitializer(
+      EquivalenceVisitor visitor, RedirectingInitializer? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! RedirectingInitializer) return false;
+    if (other is! RedirectingInitializer) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkRedirectingInitializer_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingInitializer_arguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingInitializer_isSynthetic(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingInitializer_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkLocalInitializer(
+      EquivalenceVisitor visitor, LocalInitializer? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! LocalInitializer) return false;
+    if (other is! LocalInitializer) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkLocalInitializer_variable(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLocalInitializer_isSynthetic(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLocalInitializer_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkAssertInitializer(
+      EquivalenceVisitor visitor, AssertInitializer? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! AssertInitializer) return false;
+    if (other is! AssertInitializer) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkAssertInitializer_statement(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAssertInitializer_isSynthetic(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAssertInitializer_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkFunctionNode(
+      EquivalenceVisitor visitor, FunctionNode? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! FunctionNode) return false;
+    if (other is! FunctionNode) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkFunctionNode_fileEndOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_asyncMarker(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_dartAsyncMarker(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_typeParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_requiredParameterCount(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_positionalParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_namedParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_returnType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_futureValueType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_lazyBuilder(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionNode_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInvalidExpression(
+      EquivalenceVisitor visitor, InvalidExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InvalidExpression) return false;
+    if (other is! InvalidExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInvalidExpression_message(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInvalidExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkVariableGet(
+      EquivalenceVisitor visitor, VariableGet? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! VariableGet) return false;
+    if (other is! VariableGet) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkVariableGet_variable(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableGet_promotedType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableGet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkVariableSet(
+      EquivalenceVisitor visitor, VariableSet? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! VariableSet) return false;
+    if (other is! VariableSet) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkVariableSet_variable(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableSet_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableSet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkDynamicGet(
+      EquivalenceVisitor visitor, DynamicGet? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! DynamicGet) return false;
+    if (other is! DynamicGet) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkDynamicGet_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicGet_receiver(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicGet_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicGet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInstanceGet(
+      EquivalenceVisitor visitor, InstanceGet? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InstanceGet) return false;
+    if (other is! InstanceGet) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInstanceGet_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGet_receiver(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGet_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGet_resultType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGet_interfaceTargetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkFunctionTearOff(
+      EquivalenceVisitor visitor, FunctionTearOff? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! FunctionTearOff) return false;
+    if (other is! FunctionTearOff) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkFunctionTearOff_receiver(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionTearOff_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInstanceTearOff(
+      EquivalenceVisitor visitor, InstanceTearOff? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InstanceTearOff) return false;
+    if (other is! InstanceTearOff) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInstanceTearOff_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceTearOff_receiver(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceTearOff_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceTearOff_resultType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceTearOff_interfaceTargetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceTearOff_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkDynamicSet(
+      EquivalenceVisitor visitor, DynamicSet? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! DynamicSet) return false;
+    if (other is! DynamicSet) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkDynamicSet_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicSet_receiver(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicSet_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicSet_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicSet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInstanceSet(
+      EquivalenceVisitor visitor, InstanceSet? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InstanceSet) return false;
+    if (other is! InstanceSet) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInstanceSet_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceSet_receiver(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceSet_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceSet_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceSet_interfaceTargetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceSet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSuperPropertyGet(
+      EquivalenceVisitor visitor, SuperPropertyGet? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SuperPropertyGet) return false;
+    if (other is! SuperPropertyGet) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSuperPropertyGet_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperPropertyGet_interfaceTargetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperPropertyGet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSuperPropertySet(
+      EquivalenceVisitor visitor, SuperPropertySet? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SuperPropertySet) return false;
+    if (other is! SuperPropertySet) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSuperPropertySet_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperPropertySet_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperPropertySet_interfaceTargetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperPropertySet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkStaticGet(
+      EquivalenceVisitor visitor, StaticGet? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! StaticGet) return false;
+    if (other is! StaticGet) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkStaticGet_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkStaticGet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkStaticTearOff(
+      EquivalenceVisitor visitor, StaticTearOff? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! StaticTearOff) return false;
+    if (other is! StaticTearOff) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkStaticTearOff_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkStaticTearOff_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkStaticSet(
+      EquivalenceVisitor visitor, StaticSet? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! StaticSet) return false;
+    if (other is! StaticSet) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkStaticSet_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkStaticSet_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkStaticSet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkDynamicInvocation(
+      EquivalenceVisitor visitor, DynamicInvocation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! DynamicInvocation) return false;
+    if (other is! DynamicInvocation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkDynamicInvocation_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicInvocation_receiver(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicInvocation_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicInvocation_arguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDynamicInvocation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInstanceInvocation(
+      EquivalenceVisitor visitor, InstanceInvocation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InstanceInvocation) return false;
+    if (other is! InstanceInvocation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInstanceInvocation_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceInvocation_receiver(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceInvocation_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceInvocation_arguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceInvocation_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceInvocation_functionType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceInvocation_interfaceTargetReference(
+        visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceInvocation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInstanceGetterInvocation(EquivalenceVisitor visitor,
+      InstanceGetterInvocation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InstanceGetterInvocation) return false;
+    if (other is! InstanceGetterInvocation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInstanceGetterInvocation_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGetterInvocation_receiver(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGetterInvocation_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGetterInvocation_arguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGetterInvocation_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGetterInvocation_functionType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGetterInvocation_interfaceTargetReference(
+        visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceGetterInvocation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkFunctionInvocation(
+      EquivalenceVisitor visitor, FunctionInvocation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! FunctionInvocation) return false;
+    if (other is! FunctionInvocation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkFunctionInvocation_kind(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionInvocation_receiver(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionInvocation_arguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionInvocation_functionType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionInvocation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkLocalFunctionInvocation(EquivalenceVisitor visitor,
+      LocalFunctionInvocation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! LocalFunctionInvocation) return false;
+    if (other is! LocalFunctionInvocation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkLocalFunctionInvocation_variable(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLocalFunctionInvocation_arguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLocalFunctionInvocation_functionType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLocalFunctionInvocation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSuperMethodInvocation(
+      EquivalenceVisitor visitor, SuperMethodInvocation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SuperMethodInvocation) return false;
+    if (other is! SuperMethodInvocation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSuperMethodInvocation_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperMethodInvocation_arguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperMethodInvocation_interfaceTargetReference(
+        visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSuperMethodInvocation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkStaticInvocation(
+      EquivalenceVisitor visitor, StaticInvocation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! StaticInvocation) return false;
+    if (other is! StaticInvocation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkStaticInvocation_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkStaticInvocation_arguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkStaticInvocation_isConst(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkStaticInvocation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkConstructorInvocation(
+      EquivalenceVisitor visitor, ConstructorInvocation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ConstructorInvocation) return false;
+    if (other is! ConstructorInvocation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkConstructorInvocation_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructorInvocation_arguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructorInvocation_isConst(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructorInvocation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkEqualsNull(
+      EquivalenceVisitor visitor, EqualsNull? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! EqualsNull) return false;
+    if (other is! EqualsNull) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkEqualsNull_expression(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkEqualsNull_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkEqualsCall(
+      EquivalenceVisitor visitor, EqualsCall? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! EqualsCall) return false;
+    if (other is! EqualsCall) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkEqualsCall_left(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkEqualsCall_right(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkEqualsCall_functionType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkEqualsCall_interfaceTargetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkEqualsCall_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInstantiation(
+      EquivalenceVisitor visitor, Instantiation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Instantiation) return false;
+    if (other is! Instantiation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInstantiation_expression(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstantiation_typeArguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstantiation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkNot(EquivalenceVisitor visitor, Not? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Not) return false;
+    if (other is! Not) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkNot_operand(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkNot_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkLogicalExpression(
+      EquivalenceVisitor visitor, LogicalExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! LogicalExpression) return false;
+    if (other is! LogicalExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkLogicalExpression_left(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLogicalExpression_operatorEnum(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLogicalExpression_right(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLogicalExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkConditionalExpression(
+      EquivalenceVisitor visitor, ConditionalExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ConditionalExpression) return false;
+    if (other is! ConditionalExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkConditionalExpression_condition(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConditionalExpression_then(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConditionalExpression_otherwise(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConditionalExpression_staticType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConditionalExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkStringConcatenation(
+      EquivalenceVisitor visitor, StringConcatenation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! StringConcatenation) return false;
+    if (other is! StringConcatenation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkStringConcatenation_expressions(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkStringConcatenation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkListConcatenation(
+      EquivalenceVisitor visitor, ListConcatenation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ListConcatenation) return false;
+    if (other is! ListConcatenation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkListConcatenation_typeArgument(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkListConcatenation_lists(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkListConcatenation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSetConcatenation(
+      EquivalenceVisitor visitor, SetConcatenation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SetConcatenation) return false;
+    if (other is! SetConcatenation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSetConcatenation_typeArgument(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSetConcatenation_sets(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSetConcatenation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkMapConcatenation(
+      EquivalenceVisitor visitor, MapConcatenation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! MapConcatenation) return false;
+    if (other is! MapConcatenation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkMapConcatenation_keyType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapConcatenation_valueType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapConcatenation_maps(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapConcatenation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInstanceCreation(
+      EquivalenceVisitor visitor, InstanceCreation? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InstanceCreation) return false;
+    if (other is! InstanceCreation) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInstanceCreation_classReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceCreation_typeArguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceCreation_fieldValues(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceCreation_asserts(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceCreation_unusedArguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceCreation_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkFileUriExpression(
+      EquivalenceVisitor visitor, FileUriExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! FileUriExpression) return false;
+    if (other is! FileUriExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkFileUriExpression_fileUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFileUriExpression_expression(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFileUriExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkIsExpression(
+      EquivalenceVisitor visitor, IsExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! IsExpression) return false;
+    if (other is! IsExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkIsExpression_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkIsExpression_operand(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkIsExpression_type(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkIsExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkAsExpression(
+      EquivalenceVisitor visitor, AsExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! AsExpression) return false;
+    if (other is! AsExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkAsExpression_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAsExpression_operand(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAsExpression_type(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAsExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkNullCheck(
+      EquivalenceVisitor visitor, NullCheck? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! NullCheck) return false;
+    if (other is! NullCheck) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkNullCheck_operand(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkNullCheck_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkStringLiteral(
+      EquivalenceVisitor visitor, StringLiteral? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! StringLiteral) return false;
+    if (other is! StringLiteral) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkStringLiteral_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkStringLiteral_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkIntLiteral(
+      EquivalenceVisitor visitor, IntLiteral? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! IntLiteral) return false;
+    if (other is! IntLiteral) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkIntLiteral_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkIntLiteral_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkDoubleLiteral(
+      EquivalenceVisitor visitor, DoubleLiteral? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! DoubleLiteral) return false;
+    if (other is! DoubleLiteral) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkDoubleLiteral_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDoubleLiteral_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkBoolLiteral(
+      EquivalenceVisitor visitor, BoolLiteral? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! BoolLiteral) return false;
+    if (other is! BoolLiteral) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkBoolLiteral_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkBoolLiteral_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkNullLiteral(
+      EquivalenceVisitor visitor, NullLiteral? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! NullLiteral) return false;
+    if (other is! NullLiteral) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkNullLiteral_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSymbolLiteral(
+      EquivalenceVisitor visitor, SymbolLiteral? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SymbolLiteral) return false;
+    if (other is! SymbolLiteral) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSymbolLiteral_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSymbolLiteral_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkTypeLiteral(
+      EquivalenceVisitor visitor, TypeLiteral? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! TypeLiteral) return false;
+    if (other is! TypeLiteral) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkTypeLiteral_type(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypeLiteral_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkThisExpression(
+      EquivalenceVisitor visitor, ThisExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ThisExpression) return false;
+    if (other is! ThisExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkThisExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkRethrow(EquivalenceVisitor visitor, Rethrow? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Rethrow) return false;
+    if (other is! Rethrow) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkRethrow_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkThrow(EquivalenceVisitor visitor, Throw? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Throw) return false;
+    if (other is! Throw) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkThrow_expression(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkThrow_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkListLiteral(
+      EquivalenceVisitor visitor, ListLiteral? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ListLiteral) return false;
+    if (other is! ListLiteral) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkListLiteral_isConst(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkListLiteral_typeArgument(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkListLiteral_expressions(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkListLiteral_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSetLiteral(
+      EquivalenceVisitor visitor, SetLiteral? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SetLiteral) return false;
+    if (other is! SetLiteral) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSetLiteral_isConst(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSetLiteral_typeArgument(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSetLiteral_expressions(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSetLiteral_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkMapLiteral(
+      EquivalenceVisitor visitor, MapLiteral? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! MapLiteral) return false;
+    if (other is! MapLiteral) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkMapLiteral_isConst(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapLiteral_keyType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapLiteral_valueType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapLiteral_entries(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapLiteral_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkAwaitExpression(
+      EquivalenceVisitor visitor, AwaitExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! AwaitExpression) return false;
+    if (other is! AwaitExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkAwaitExpression_operand(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAwaitExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkFunctionExpression(
+      EquivalenceVisitor visitor, FunctionExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! FunctionExpression) return false;
+    if (other is! FunctionExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkFunctionExpression_function(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkConstantExpression(
+      EquivalenceVisitor visitor, ConstantExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ConstantExpression) return false;
+    if (other is! ConstantExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkConstantExpression_constant(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstantExpression_type(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstantExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkLet(EquivalenceVisitor visitor, Let? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Let) return false;
+    if (other is! Let) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkLet_variable(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLet_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLet_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkBlockExpression(
+      EquivalenceVisitor visitor, BlockExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! BlockExpression) return false;
+    if (other is! BlockExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkBlockExpression_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkBlockExpression_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkBlockExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkLoadLibrary(
+      EquivalenceVisitor visitor, LoadLibrary? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! LoadLibrary) return false;
+    if (other is! LoadLibrary) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkLoadLibrary_import(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLoadLibrary_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkCheckLibraryIsLoaded(
+      EquivalenceVisitor visitor, CheckLibraryIsLoaded? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! CheckLibraryIsLoaded) return false;
+    if (other is! CheckLibraryIsLoaded) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkCheckLibraryIsLoaded_import(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkCheckLibraryIsLoaded_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkConstructorTearOff(
+      EquivalenceVisitor visitor, ConstructorTearOff? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ConstructorTearOff) return false;
+    if (other is! ConstructorTearOff) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkConstructorTearOff_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstructorTearOff_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkRedirectingFactoryTearOff(EquivalenceVisitor visitor,
+      RedirectingFactoryTearOff? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! RedirectingFactoryTearOff) return false;
+    if (other is! RedirectingFactoryTearOff) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkRedirectingFactoryTearOff_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkRedirectingFactoryTearOff_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkTypedefTearOff(
+      EquivalenceVisitor visitor, TypedefTearOff? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! TypedefTearOff) return false;
+    if (other is! TypedefTearOff) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkTypedefTearOff_typeParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedefTearOff_expression(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedefTearOff_typeArguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedefTearOff_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkArguments(
+      EquivalenceVisitor visitor, Arguments? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Arguments) return false;
+    if (other is! Arguments) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkArguments_types(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkArguments_positional(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkArguments_named(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkArguments_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkNamedExpression(
+      EquivalenceVisitor visitor, NamedExpression? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! NamedExpression) return false;
+    if (other is! NamedExpression) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkNamedExpression_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkNamedExpression_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkNamedExpression_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkMapLiteralEntry(
+      EquivalenceVisitor visitor, MapLiteralEntry? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! MapLiteralEntry) return false;
+    if (other is! MapLiteralEntry) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkMapLiteralEntry_key(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapLiteralEntry_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapLiteralEntry_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkExpressionStatement(
+      EquivalenceVisitor visitor, ExpressionStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ExpressionStatement) return false;
+    if (other is! ExpressionStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkExpressionStatement_expression(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExpressionStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkBlock(EquivalenceVisitor visitor, Block? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Block) return false;
+    if (other is! Block) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkBlock_statements(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkBlock_fileEndOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkBlock_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkAssertBlock(
+      EquivalenceVisitor visitor, AssertBlock? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! AssertBlock) return false;
+    if (other is! AssertBlock) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkAssertBlock_statements(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAssertBlock_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkEmptyStatement(
+      EquivalenceVisitor visitor, EmptyStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! EmptyStatement) return false;
+    if (other is! EmptyStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkEmptyStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkAssertStatement(
+      EquivalenceVisitor visitor, AssertStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! AssertStatement) return false;
+    if (other is! AssertStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkAssertStatement_condition(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAssertStatement_message(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAssertStatement_conditionStartOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAssertStatement_conditionEndOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkAssertStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkLabeledStatement(
+      EquivalenceVisitor visitor, LabeledStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! LabeledStatement) return false;
+    if (other is! LabeledStatement) return false;
+    if (!visitor.checkDeclarations(node, other, '')) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkLabeledStatement_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkLabeledStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkBreakStatement(
+      EquivalenceVisitor visitor, BreakStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! BreakStatement) return false;
+    if (other is! BreakStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkBreakStatement_target(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkBreakStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkWhileStatement(
+      EquivalenceVisitor visitor, WhileStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! WhileStatement) return false;
+    if (other is! WhileStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkWhileStatement_condition(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkWhileStatement_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkWhileStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkDoStatement(
+      EquivalenceVisitor visitor, DoStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! DoStatement) return false;
+    if (other is! DoStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkDoStatement_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDoStatement_condition(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkDoStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkForStatement(
+      EquivalenceVisitor visitor, ForStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ForStatement) return false;
+    if (other is! ForStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkForStatement_variables(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkForStatement_condition(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkForStatement_updates(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkForStatement_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkForStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkForInStatement(
+      EquivalenceVisitor visitor, ForInStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ForInStatement) return false;
+    if (other is! ForInStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkForInStatement_bodyOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkForInStatement_variable(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkForInStatement_iterable(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkForInStatement_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkForInStatement_isAsync(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkForInStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSwitchStatement(
+      EquivalenceVisitor visitor, SwitchStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SwitchStatement) return false;
+    if (other is! SwitchStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSwitchStatement_expression(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSwitchStatement_cases(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSwitchStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkContinueSwitchStatement(EquivalenceVisitor visitor,
+      ContinueSwitchStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ContinueSwitchStatement) return false;
+    if (other is! ContinueSwitchStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkContinueSwitchStatement_target(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkContinueSwitchStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkIfStatement(
+      EquivalenceVisitor visitor, IfStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! IfStatement) return false;
+    if (other is! IfStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkIfStatement_condition(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkIfStatement_then(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkIfStatement_otherwise(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkIfStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkReturnStatement(
+      EquivalenceVisitor visitor, ReturnStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ReturnStatement) return false;
+    if (other is! ReturnStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkReturnStatement_expression(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkReturnStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkTryCatch(
+      EquivalenceVisitor visitor, TryCatch? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! TryCatch) return false;
+    if (other is! TryCatch) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkTryCatch_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTryCatch_catches(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTryCatch_isSynthetic(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTryCatch_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkTryFinally(
+      EquivalenceVisitor visitor, TryFinally? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! TryFinally) return false;
+    if (other is! TryFinally) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkTryFinally_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTryFinally_finalizer(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTryFinally_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkYieldStatement(
+      EquivalenceVisitor visitor, YieldStatement? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! YieldStatement) return false;
+    if (other is! YieldStatement) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkYieldStatement_expression(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkYieldStatement_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkYieldStatement_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkVariableDeclaration(
+      EquivalenceVisitor visitor, VariableDeclaration? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! VariableDeclaration) return false;
+    if (other is! VariableDeclaration) return false;
+    if (!visitor.checkDeclarations(node, other, '')) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkVariableDeclaration_fileEqualsOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableDeclaration_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableDeclaration_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableDeclaration_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableDeclaration_type(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableDeclaration_binaryOffsetNoTag(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableDeclaration_initializer(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkVariableDeclaration_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkFunctionDeclaration(
+      EquivalenceVisitor visitor, FunctionDeclaration? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! FunctionDeclaration) return false;
+    if (other is! FunctionDeclaration) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkFunctionDeclaration_variable(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionDeclaration_function(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionDeclaration_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSwitchCase(
+      EquivalenceVisitor visitor, SwitchCase? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SwitchCase) return false;
+    if (other is! SwitchCase) return false;
+    if (!visitor.checkDeclarations(node, other, '')) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSwitchCase_expressions(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSwitchCase_expressionOffsets(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSwitchCase_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSwitchCase_isDefault(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSwitchCase_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkCatch(EquivalenceVisitor visitor, Catch? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Catch) return false;
+    if (other is! Catch) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkCatch_guard(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkCatch_exception(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkCatch_stackTrace(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkCatch_body(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkCatch_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkTypeParameter(
+      EquivalenceVisitor visitor, TypeParameter? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! TypeParameter) return false;
+    if (other is! TypeParameter) return false;
+    if (!visitor.checkDeclarations(node, other, '')) {
+      return false;
+    }
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkTypeParameter_flags(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypeParameter_annotations(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypeParameter_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypeParameter_bound(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypeParameter_defaultType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypeParameter_variance(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypeParameter_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSource(EquivalenceVisitor visitor, Source? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Source) return false;
+    if (other is! Source) return false;
+    bool result = true;
+    if (!checkSource_lineStarts(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSource_source(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSource_importUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSource_fileUri(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSource_constantCoverageConstructors(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSource_cachedText(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    return result;
+  }
+
+  bool checkMetadataRepository(
+      EquivalenceVisitor visitor, MetadataRepository? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! MetadataRepository) return false;
+    if (other is! MetadataRepository) return false;
+    bool result = true;
+    return result;
+  }
+
+  bool checkComponent(
+      EquivalenceVisitor visitor, Component? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Component) return false;
+    if (other is! Component) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkComponent_problemsAsJson(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkComponent_libraries(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkComponent_uriToSource(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkComponent_metadata(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkComponent_mainMethodName(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkComponent_mode(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkComponent_fileOffset(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkName(EquivalenceVisitor visitor, Name? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Name) return false;
+    if (other is! Name) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkName_text(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInvalidType(
+      EquivalenceVisitor visitor, InvalidType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InvalidType) return false;
+    if (other is! InvalidType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    visitor.popState();
+    return result;
+  }
+
+  bool checkDynamicType(
+      EquivalenceVisitor visitor, DynamicType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! DynamicType) return false;
+    if (other is! DynamicType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    visitor.popState();
+    return result;
+  }
+
+  bool checkVoidType(
+      EquivalenceVisitor visitor, VoidType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! VoidType) return false;
+    if (other is! VoidType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    visitor.popState();
+    return result;
+  }
+
+  bool checkNeverType(
+      EquivalenceVisitor visitor, NeverType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! NeverType) return false;
+    if (other is! NeverType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkNeverType_declaredNullability(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkNullType(
+      EquivalenceVisitor visitor, NullType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! NullType) return false;
+    if (other is! NullType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInterfaceType(
+      EquivalenceVisitor visitor, InterfaceType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InterfaceType) return false;
+    if (other is! InterfaceType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInterfaceType_className(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInterfaceType_declaredNullability(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInterfaceType_typeArguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkFunctionType(
+      EquivalenceVisitor visitor, FunctionType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! FunctionType) return false;
+    if (other is! FunctionType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkFunctionType_typeParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionType_requiredParameterCount(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionType_positionalParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionType_namedParameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionType_declaredNullability(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionType_typedefType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFunctionType_returnType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkTypedefType(
+      EquivalenceVisitor visitor, TypedefType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! TypedefType) return false;
+    if (other is! TypedefType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkTypedefType_declaredNullability(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedefType_typedefReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedefType_typeArguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkFutureOrType(
+      EquivalenceVisitor visitor, FutureOrType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! FutureOrType) return false;
+    if (other is! FutureOrType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkFutureOrType_typeArgument(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkFutureOrType_declaredNullability(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkExtensionType(
+      EquivalenceVisitor visitor, ExtensionType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ExtensionType) return false;
+    if (other is! ExtensionType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkExtensionType_extensionReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtensionType_declaredNullability(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtensionType_typeArguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkExtensionType_onType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkTypeParameterType(
+      EquivalenceVisitor visitor, TypeParameterType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! TypeParameterType) return false;
+    if (other is! TypeParameterType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkTypeParameterType_declaredNullability(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypeParameterType_parameter(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypeParameterType_promotedBound(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkNamedType(
+      EquivalenceVisitor visitor, NamedType? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! NamedType) return false;
+    if (other is! NamedType) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkNamedType_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkNamedType_type(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkNamedType_isRequired(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSupertype(
+      EquivalenceVisitor visitor, Supertype? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! Supertype) return false;
+    if (other is! Supertype) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSupertype_className(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSupertype_typeArguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkNullConstant(
+      EquivalenceVisitor visitor, NullConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! NullConstant) return false;
+    if (other is! NullConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkNullConstant_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkBoolConstant(
+      EquivalenceVisitor visitor, BoolConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! BoolConstant) return false;
+    if (other is! BoolConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkBoolConstant_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkIntConstant(
+      EquivalenceVisitor visitor, IntConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! IntConstant) return false;
+    if (other is! IntConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkIntConstant_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkDoubleConstant(
+      EquivalenceVisitor visitor, DoubleConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! DoubleConstant) return false;
+    if (other is! DoubleConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkDoubleConstant_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkStringConstant(
+      EquivalenceVisitor visitor, StringConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! StringConstant) return false;
+    if (other is! StringConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkStringConstant_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSymbolConstant(
+      EquivalenceVisitor visitor, SymbolConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SymbolConstant) return false;
+    if (other is! SymbolConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSymbolConstant_name(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSymbolConstant_libraryReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkConstantMapEntry(
+      EquivalenceVisitor visitor, ConstantMapEntry? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ConstantMapEntry) return false;
+    if (other is! ConstantMapEntry) return false;
+    bool result = true;
+    if (!checkConstantMapEntry_key(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkConstantMapEntry_value(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    return result;
+  }
+
+  bool checkMapConstant(
+      EquivalenceVisitor visitor, MapConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! MapConstant) return false;
+    if (other is! MapConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkMapConstant_keyType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapConstant_valueType(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkMapConstant_entries(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkListConstant(
+      EquivalenceVisitor visitor, ListConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ListConstant) return false;
+    if (other is! ListConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkListConstant_typeArgument(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkListConstant_entries(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkSetConstant(
+      EquivalenceVisitor visitor, SetConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! SetConstant) return false;
+    if (other is! SetConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkSetConstant_typeArgument(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkSetConstant_entries(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInstanceConstant(
+      EquivalenceVisitor visitor, InstanceConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InstanceConstant) return false;
+    if (other is! InstanceConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInstanceConstant_classReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceConstant_typeArguments(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstanceConstant_fieldValues(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkInstantiationConstant(
+      EquivalenceVisitor visitor, InstantiationConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! InstantiationConstant) return false;
+    if (other is! InstantiationConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkInstantiationConstant_tearOffConstant(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkInstantiationConstant_types(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkStaticTearOffConstant(
+      EquivalenceVisitor visitor, StaticTearOffConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! StaticTearOffConstant) return false;
+    if (other is! StaticTearOffConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkStaticTearOffConstant_targetReference(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkConstructorTearOffConstant(EquivalenceVisitor visitor,
+      ConstructorTearOffConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! ConstructorTearOffConstant) return false;
+    if (other is! ConstructorTearOffConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkConstructorTearOffConstant_targetReference(
+        visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkRedirectingFactoryTearOffConstant(EquivalenceVisitor visitor,
+      RedirectingFactoryTearOffConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! RedirectingFactoryTearOffConstant) return false;
+    if (other is! RedirectingFactoryTearOffConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkRedirectingFactoryTearOffConstant_targetReference(
+        visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkTypedefTearOffConstant(
+      EquivalenceVisitor visitor, TypedefTearOffConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! TypedefTearOffConstant) return false;
+    if (other is! TypedefTearOffConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkTypedefTearOffConstant_parameters(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedefTearOffConstant_tearOffConstant(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    if (!checkTypedefTearOffConstant_types(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkTypeLiteralConstant(
+      EquivalenceVisitor visitor, TypeLiteralConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! TypeLiteralConstant) return false;
+    if (other is! TypeLiteralConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkTypeLiteralConstant_type(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkUnevaluatedConstant(
+      EquivalenceVisitor visitor, UnevaluatedConstant? node, Object? other) {
+    if (identical(node, other)) return true;
+    if (node is! UnevaluatedConstant) return false;
+    if (other is! UnevaluatedConstant) return false;
+    visitor.pushNodeState(node, other);
+    bool result = true;
+    if (!checkUnevaluatedConstant_expression(visitor, node, other)) {
+      result = visitor.resultOnInequivalence;
+    }
+    visitor.popState();
+    return result;
+  }
+
+  bool checkLibrary_importUri(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkValues(node.importUri, other.importUri, 'importUri');
+  }
+
+  bool checkLibrary_fileUri(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+  }
+
+  bool checkLibrary_languageVersion(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkValues(
+        node.languageVersion, other.languageVersion, 'languageVersion');
+  }
+
+  bool checkLibrary_flags(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkLibrary_name(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkValues(node.name, other.name, 'name');
+  }
+
+  bool checkLibrary_problemsAsJson(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkLists(node.problemsAsJson, other.problemsAsJson,
+        visitor.checkValues, 'problemsAsJson');
+  }
+
+  bool checkLibrary_annotations(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkLibrary_dependencies(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkLists(node.dependencies, other.dependencies,
+        visitor.checkNodes, 'dependencies');
+  }
+
+  bool checkLibrary_additionalExports(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkLists(node.additionalExports, other.additionalExports,
+        visitor.checkReferences, 'additionalExports');
+  }
+
+  bool checkLibrary_parts(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkLists(
+        node.parts, other.parts, visitor.checkNodes, 'parts');
+  }
+
+  bool checkLibrary_typedefs(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkLists(
+        node.typedefs, other.typedefs, visitor.checkNodes, 'typedefs');
+  }
+
+  bool checkLibrary_classes(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkLists(
+        node.classes, other.classes, visitor.checkNodes, 'classes');
+  }
+
+  bool checkLibrary_extensions(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkLists(
+        node.extensions, other.extensions, visitor.checkNodes, 'extensions');
+  }
+
+  bool checkLibrary_procedures(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkLists(
+        node.procedures, other.procedures, visitor.checkNodes, 'procedures');
+  }
+
+  bool checkLibrary_fields(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkLists(
+        node.fields, other.fields, visitor.checkNodes, 'fields');
+  }
+
+  bool checkLibrary_reference(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkReferences(
+        node.reference, other.reference, 'reference');
+  }
+
+  bool checkLibrary_fileOffset(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkTypedef_fileUri(
+      EquivalenceVisitor visitor, Typedef node, Typedef other) {
+    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+  }
+
+  bool checkTypedef_annotations(
+      EquivalenceVisitor visitor, Typedef node, Typedef other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkTypedef_name(
+      EquivalenceVisitor visitor, Typedef node, Typedef other) {
+    return visitor.checkValues(node.name, other.name, 'name');
+  }
+
+  bool checkTypedef_typeParameters(
+      EquivalenceVisitor visitor, Typedef node, Typedef other) {
+    return visitor.checkLists(node.typeParameters, other.typeParameters,
+        visitor.checkNodes, 'typeParameters');
+  }
+
+  bool checkTypedef_type(
+      EquivalenceVisitor visitor, Typedef node, Typedef other) {
+    return visitor.checkNodes(node.type, other.type, 'type');
+  }
+
+  bool checkTypedef_typeParametersOfFunctionType(
+      EquivalenceVisitor visitor, Typedef node, Typedef other) {
+    return visitor.checkLists(
+        node.typeParametersOfFunctionType,
+        other.typeParametersOfFunctionType,
+        visitor.checkDeclarations,
+        'typeParametersOfFunctionType');
+  }
+
+  bool checkTypedef_positionalParameters(
+      EquivalenceVisitor visitor, Typedef node, Typedef other) {
+    return visitor.checkLists(
+        node.positionalParameters,
+        other.positionalParameters,
+        visitor.checkDeclarations,
+        'positionalParameters');
+  }
+
+  bool checkTypedef_namedParameters(
+      EquivalenceVisitor visitor, Typedef node, Typedef other) {
+    return visitor.checkLists(node.namedParameters, other.namedParameters,
+        visitor.checkDeclarations, 'namedParameters');
+  }
+
+  bool checkTypedef_reference(
+      EquivalenceVisitor visitor, Typedef node, Typedef other) {
+    return visitor.checkReferences(
+        node.reference, other.reference, 'reference');
+  }
+
+  bool checkTypedef_fileOffset(
+      EquivalenceVisitor visitor, Typedef node, Typedef other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkClass_startFileOffset(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkValues(
+        node.startFileOffset, other.startFileOffset, 'startFileOffset');
+  }
+
+  bool checkClass_fileEndOffset(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkValues(
+        node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+  }
+
+  bool checkClass_annotations(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkClass_name(EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkValues(node.name, other.name, 'name');
+  }
+
+  bool checkClass_flags(EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkClass_fileUri(EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+  }
+
+  bool checkClass_typeParameters(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkLists(node.typeParameters, other.typeParameters,
+        visitor.checkNodes, 'typeParameters');
+  }
+
+  bool checkClass_supertype(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkNodes(node.supertype, other.supertype, 'supertype');
+  }
+
+  bool checkClass_mixedInType(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkNodes(
+        node.mixedInType, other.mixedInType, 'mixedInType');
+  }
+
+  bool checkClass_implementedTypes(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkLists(node.implementedTypes, other.implementedTypes,
+        visitor.checkNodes, 'implementedTypes');
+  }
+
+  bool checkClass_fields(EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkLists(
+        node.fields, other.fields, visitor.checkNodes, 'fields');
+  }
+
+  bool checkClass_constructors(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkLists(node.constructors, other.constructors,
+        visitor.checkNodes, 'constructors');
+  }
+
+  bool checkClass_procedures(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkLists(
+        node.procedures, other.procedures, visitor.checkNodes, 'procedures');
+  }
+
+  bool checkClass_redirectingFactories(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkLists(node.redirectingFactories,
+        other.redirectingFactories, visitor.checkNodes, 'redirectingFactories');
+  }
+
+  bool checkClass_reference(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkReferences(
+        node.reference, other.reference, 'reference');
+  }
+
+  bool checkClass_fileOffset(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkExtension_name(
+      EquivalenceVisitor visitor, Extension node, Extension other) {
+    return visitor.checkValues(node.name, other.name, 'name');
+  }
+
+  bool checkExtension_fileUri(
+      EquivalenceVisitor visitor, Extension node, Extension other) {
+    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+  }
+
+  bool checkExtension_typeParameters(
+      EquivalenceVisitor visitor, Extension node, Extension other) {
+    return visitor.checkLists(node.typeParameters, other.typeParameters,
+        visitor.checkNodes, 'typeParameters');
+  }
+
+  bool checkExtension_onType(
+      EquivalenceVisitor visitor, Extension node, Extension other) {
+    return visitor.checkNodes(node.onType, other.onType, 'onType');
+  }
+
+  bool checkExtensionMemberDescriptor_name(EquivalenceVisitor visitor,
+      ExtensionMemberDescriptor node, ExtensionMemberDescriptor other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkExtensionMemberDescriptor_kind(EquivalenceVisitor visitor,
+      ExtensionMemberDescriptor node, ExtensionMemberDescriptor other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkExtensionMemberDescriptor_flags(EquivalenceVisitor visitor,
+      ExtensionMemberDescriptor node, ExtensionMemberDescriptor other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkExtensionMemberDescriptor_member(EquivalenceVisitor visitor,
+      ExtensionMemberDescriptor node, ExtensionMemberDescriptor other) {
+    return visitor.checkReferences(node.member, other.member, 'member');
+  }
+
+  bool checkExtension_members(
+      EquivalenceVisitor visitor, Extension node, Extension other) {
+    return visitor.checkLists(node.members, other.members, (a, b, _) {
+      if (identical(a, b)) return true;
+      if (a is! ExtensionMemberDescriptor) return false;
+      if (b is! ExtensionMemberDescriptor) return false;
+      return checkExtensionMemberDescriptor(visitor, a, b);
+    }, 'members');
+  }
+
+  bool checkExtension_annotations(
+      EquivalenceVisitor visitor, Extension node, Extension other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkExtension_flags(
+      EquivalenceVisitor visitor, Extension node, Extension other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkExtension_reference(
+      EquivalenceVisitor visitor, Extension node, Extension other) {
+    return visitor.checkReferences(
+        node.reference, other.reference, 'reference');
+  }
+
+  bool checkExtension_fileOffset(
+      EquivalenceVisitor visitor, Extension node, Extension other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkField_type(EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkNodes(node.type, other.type, 'type');
+  }
+
+  bool checkField_flags(EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkField_initializer(
+      EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkNodes(
+        node.initializer, other.initializer, 'initializer');
+  }
+
+  bool checkField_setterReference(
+      EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkReferences(
+        node.setterReference, other.setterReference, 'setterReference');
+  }
+
+  bool checkField_fileEndOffset(
+      EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkValues(
+        node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+  }
+
+  bool checkField_annotations(
+      EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkField_name(EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkField_fileUri(EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+  }
+
+  bool checkField_transformerFlags(
+      EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkValues(
+        node.transformerFlags, other.transformerFlags, 'transformerFlags');
+  }
+
+  bool checkField_getterReference(
+      EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkReferences(
+        node.getterReference, other.getterReference, 'getterReference');
+  }
+
+  bool checkField_fileOffset(
+      EquivalenceVisitor visitor, Field node, Field other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkConstructor_startFileOffset(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkValues(
+        node.startFileOffset, other.startFileOffset, 'startFileOffset');
+  }
+
+  bool checkConstructor_flags(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkConstructor_function(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkNodes(node.function, other.function, 'function');
+  }
+
+  bool checkConstructor_initializers(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkLists(node.initializers, other.initializers,
+        visitor.checkNodes, 'initializers');
+  }
+
+  bool checkConstructor_fileEndOffset(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkValues(
+        node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+  }
+
+  bool checkConstructor_annotations(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkConstructor_name(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkConstructor_fileUri(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+  }
+
+  bool checkConstructor_transformerFlags(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkValues(
+        node.transformerFlags, other.transformerFlags, 'transformerFlags');
+  }
+
+  bool checkConstructor_reference(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkReferences(
+        node.reference, other.reference, 'reference');
+  }
+
+  bool checkConstructor_fileOffset(
+      EquivalenceVisitor visitor, Constructor node, Constructor other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkRedirectingFactory_flags(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkRedirectingFactory_typeArguments(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkLists(node.typeArguments, other.typeArguments,
+        visitor.checkNodes, 'typeArguments');
+  }
+
+  bool checkRedirectingFactory_targetReference(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkRedirectingFactory_function(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkNodes(node.function, other.function, 'function');
+  }
+
+  bool checkRedirectingFactory_fileEndOffset(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkValues(
+        node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+  }
+
+  bool checkRedirectingFactory_annotations(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkRedirectingFactory_name(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkRedirectingFactory_fileUri(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+  }
+
+  bool checkRedirectingFactory_transformerFlags(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkValues(
+        node.transformerFlags, other.transformerFlags, 'transformerFlags');
+  }
+
+  bool checkRedirectingFactory_reference(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkReferences(
+        node.reference, other.reference, 'reference');
+  }
+
+  bool checkRedirectingFactory_fileOffset(EquivalenceVisitor visitor,
+      RedirectingFactory node, RedirectingFactory other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkProcedure_startFileOffset(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkValues(
+        node.startFileOffset, other.startFileOffset, 'startFileOffset');
+  }
+
+  bool checkProcedure_kind(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkProcedure_flags(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkProcedure_function(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkNodes(node.function, other.function, 'function');
+  }
+
+  bool checkProcedure_stubKind(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkValues(node.stubKind, other.stubKind, 'stubKind');
+  }
+
+  bool checkProcedure_stubTargetReference(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkReferences(node.stubTargetReference,
+        other.stubTargetReference, 'stubTargetReference');
+  }
+
+  bool checkProcedure_fileEndOffset(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkValues(
+        node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+  }
+
+  bool checkProcedure_annotations(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkProcedure_name(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkProcedure_fileUri(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+  }
+
+  bool checkProcedure_transformerFlags(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkValues(
+        node.transformerFlags, other.transformerFlags, 'transformerFlags');
+  }
+
+  bool checkProcedure_reference(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkReferences(
+        node.reference, other.reference, 'reference');
+  }
+
+  bool checkProcedure_fileOffset(
+      EquivalenceVisitor visitor, Procedure node, Procedure other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkLibraryDependency_flags(EquivalenceVisitor visitor,
+      LibraryDependency node, LibraryDependency other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkLibraryDependency_annotations(EquivalenceVisitor visitor,
+      LibraryDependency node, LibraryDependency other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkLibraryDependency_importedLibraryReference(
+      EquivalenceVisitor visitor,
+      LibraryDependency node,
+      LibraryDependency other) {
+    return visitor.checkReferences(node.importedLibraryReference,
+        other.importedLibraryReference, 'importedLibraryReference');
+  }
+
+  bool checkLibraryDependency_name(EquivalenceVisitor visitor,
+      LibraryDependency node, LibraryDependency other) {
+    return visitor.checkValues(node.name, other.name, 'name');
+  }
+
+  bool checkLibraryDependency_combinators(EquivalenceVisitor visitor,
+      LibraryDependency node, LibraryDependency other) {
+    return visitor.checkLists(
+        node.combinators, other.combinators, visitor.checkNodes, 'combinators');
+  }
+
+  bool checkLibraryDependency_fileOffset(EquivalenceVisitor visitor,
+      LibraryDependency node, LibraryDependency other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkLibraryPart_annotations(
+      EquivalenceVisitor visitor, LibraryPart node, LibraryPart other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkLibraryPart_partUri(
+      EquivalenceVisitor visitor, LibraryPart node, LibraryPart other) {
+    return visitor.checkValues(node.partUri, other.partUri, 'partUri');
+  }
+
+  bool checkLibraryPart_fileOffset(
+      EquivalenceVisitor visitor, LibraryPart node, LibraryPart other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkCombinator_isShow(
+      EquivalenceVisitor visitor, Combinator node, Combinator other) {
+    return visitor.checkValues(node.isShow, other.isShow, 'isShow');
+  }
+
+  bool checkCombinator_names(
+      EquivalenceVisitor visitor, Combinator node, Combinator other) {
+    return visitor.checkLists(
+        node.names, other.names, visitor.checkValues, 'names');
+  }
+
+  bool checkCombinator_fileOffset(
+      EquivalenceVisitor visitor, Combinator node, Combinator other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkInvalidInitializer_isSynthetic(EquivalenceVisitor visitor,
+      InvalidInitializer node, InvalidInitializer other) {
+    return visitor.checkValues(
+        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+  }
+
+  bool checkInvalidInitializer_fileOffset(EquivalenceVisitor visitor,
+      InvalidInitializer node, InvalidInitializer other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkFieldInitializer_fieldReference(EquivalenceVisitor visitor,
+      FieldInitializer node, FieldInitializer other) {
+    return visitor.checkReferences(
+        node.fieldReference, other.fieldReference, 'fieldReference');
+  }
+
+  bool checkFieldInitializer_value(EquivalenceVisitor visitor,
+      FieldInitializer node, FieldInitializer other) {
+    return visitor.checkNodes(node.value, other.value, 'value');
+  }
+
+  bool checkFieldInitializer_isSynthetic(EquivalenceVisitor visitor,
+      FieldInitializer node, FieldInitializer other) {
+    return visitor.checkValues(
+        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+  }
+
+  bool checkFieldInitializer_fileOffset(EquivalenceVisitor visitor,
+      FieldInitializer node, FieldInitializer other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkSuperInitializer_targetReference(EquivalenceVisitor visitor,
+      SuperInitializer node, SuperInitializer other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkSuperInitializer_arguments(EquivalenceVisitor visitor,
+      SuperInitializer node, SuperInitializer other) {
+    return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+  }
+
+  bool checkSuperInitializer_isSynthetic(EquivalenceVisitor visitor,
+      SuperInitializer node, SuperInitializer other) {
+    return visitor.checkValues(
+        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+  }
+
+  bool checkSuperInitializer_fileOffset(EquivalenceVisitor visitor,
+      SuperInitializer node, SuperInitializer other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkRedirectingInitializer_targetReference(EquivalenceVisitor visitor,
+      RedirectingInitializer node, RedirectingInitializer other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkRedirectingInitializer_arguments(EquivalenceVisitor visitor,
+      RedirectingInitializer node, RedirectingInitializer other) {
+    return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+  }
+
+  bool checkRedirectingInitializer_isSynthetic(EquivalenceVisitor visitor,
+      RedirectingInitializer node, RedirectingInitializer other) {
+    return visitor.checkValues(
+        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+  }
+
+  bool checkRedirectingInitializer_fileOffset(EquivalenceVisitor visitor,
+      RedirectingInitializer node, RedirectingInitializer other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkLocalInitializer_variable(EquivalenceVisitor visitor,
+      LocalInitializer node, LocalInitializer other) {
+    return visitor.checkNodes(node.variable, other.variable, 'variable');
+  }
+
+  bool checkLocalInitializer_isSynthetic(EquivalenceVisitor visitor,
+      LocalInitializer node, LocalInitializer other) {
+    return visitor.checkValues(
+        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+  }
+
+  bool checkLocalInitializer_fileOffset(EquivalenceVisitor visitor,
+      LocalInitializer node, LocalInitializer other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkAssertInitializer_statement(EquivalenceVisitor visitor,
+      AssertInitializer node, AssertInitializer other) {
+    return visitor.checkNodes(node.statement, other.statement, 'statement');
+  }
+
+  bool checkAssertInitializer_isSynthetic(EquivalenceVisitor visitor,
+      AssertInitializer node, AssertInitializer other) {
+    return visitor.checkValues(
+        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+  }
+
+  bool checkAssertInitializer_fileOffset(EquivalenceVisitor visitor,
+      AssertInitializer node, AssertInitializer other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkFunctionNode_fileEndOffset(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkValues(
+        node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+  }
+
+  bool checkFunctionNode_asyncMarker(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkValues(
+        node.asyncMarker, other.asyncMarker, 'asyncMarker');
+  }
+
+  bool checkFunctionNode_dartAsyncMarker(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkValues(
+        node.dartAsyncMarker, other.dartAsyncMarker, 'dartAsyncMarker');
+  }
+
+  bool checkFunctionNode_typeParameters(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkLists(node.typeParameters, other.typeParameters,
+        visitor.checkNodes, 'typeParameters');
+  }
+
+  bool checkFunctionNode_requiredParameterCount(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkValues(node.requiredParameterCount,
+        other.requiredParameterCount, 'requiredParameterCount');
+  }
+
+  bool checkFunctionNode_positionalParameters(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkLists(node.positionalParameters,
+        other.positionalParameters, visitor.checkNodes, 'positionalParameters');
+  }
+
+  bool checkFunctionNode_namedParameters(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkLists(node.namedParameters, other.namedParameters,
+        visitor.checkNodes, 'namedParameters');
+  }
+
+  bool checkFunctionNode_returnType(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkNodes(node.returnType, other.returnType, 'returnType');
+  }
+
+  bool checkFunctionNode_body(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkFunctionNode_futureValueType(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkNodes(
+        node.futureValueType, other.futureValueType, 'futureValueType');
+  }
+
+  bool checkFunctionNode_lazyBuilder(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkValues(
+        node.lazyBuilder, other.lazyBuilder, 'lazyBuilder');
+  }
+
+  bool checkFunctionNode_fileOffset(
+      EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkInvalidExpression_message(EquivalenceVisitor visitor,
+      InvalidExpression node, InvalidExpression other) {
+    return visitor.checkValues(node.message, other.message, 'message');
+  }
+
+  bool checkInvalidExpression_fileOffset(EquivalenceVisitor visitor,
+      InvalidExpression node, InvalidExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkVariableGet_variable(
+      EquivalenceVisitor visitor, VariableGet node, VariableGet other) {
+    return visitor.checkDeclarations(node.variable, other.variable, 'variable');
+  }
+
+  bool checkVariableGet_promotedType(
+      EquivalenceVisitor visitor, VariableGet node, VariableGet other) {
+    return visitor.checkNodes(
+        node.promotedType, other.promotedType, 'promotedType');
+  }
+
+  bool checkVariableGet_fileOffset(
+      EquivalenceVisitor visitor, VariableGet node, VariableGet other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkVariableSet_variable(
+      EquivalenceVisitor visitor, VariableSet node, VariableSet other) {
+    return visitor.checkDeclarations(node.variable, other.variable, 'variable');
+  }
+
+  bool checkVariableSet_value(
+      EquivalenceVisitor visitor, VariableSet node, VariableSet other) {
+    return visitor.checkNodes(node.value, other.value, 'value');
+  }
+
+  bool checkVariableSet_fileOffset(
+      EquivalenceVisitor visitor, VariableSet node, VariableSet other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkDynamicGet_kind(
+      EquivalenceVisitor visitor, DynamicGet node, DynamicGet other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkDynamicGet_receiver(
+      EquivalenceVisitor visitor, DynamicGet node, DynamicGet other) {
+    return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+  }
+
+  bool checkDynamicGet_name(
+      EquivalenceVisitor visitor, DynamicGet node, DynamicGet other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkDynamicGet_fileOffset(
+      EquivalenceVisitor visitor, DynamicGet node, DynamicGet other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkInstanceGet_kind(
+      EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkInstanceGet_receiver(
+      EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+    return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+  }
+
+  bool checkInstanceGet_name(
+      EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkInstanceGet_resultType(
+      EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+    return visitor.checkNodes(node.resultType, other.resultType, 'resultType');
+  }
+
+  bool checkInstanceGet_interfaceTargetReference(
+      EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+    return visitor.checkReferences(node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+
+  bool checkInstanceGet_fileOffset(
+      EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkFunctionTearOff_receiver(
+      EquivalenceVisitor visitor, FunctionTearOff node, FunctionTearOff other) {
+    return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+  }
+
+  bool checkFunctionTearOff_fileOffset(
+      EquivalenceVisitor visitor, FunctionTearOff node, FunctionTearOff other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkInstanceTearOff_kind(
+      EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkInstanceTearOff_receiver(
+      EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+    return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+  }
+
+  bool checkInstanceTearOff_name(
+      EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkInstanceTearOff_resultType(
+      EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+    return visitor.checkNodes(node.resultType, other.resultType, 'resultType');
+  }
+
+  bool checkInstanceTearOff_interfaceTargetReference(
+      EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+    return visitor.checkReferences(node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+
+  bool checkInstanceTearOff_fileOffset(
+      EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkDynamicSet_kind(
+      EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkDynamicSet_receiver(
+      EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
+    return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+  }
+
+  bool checkDynamicSet_name(
+      EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkDynamicSet_value(
+      EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
+    return visitor.checkNodes(node.value, other.value, 'value');
+  }
+
+  bool checkDynamicSet_fileOffset(
+      EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkInstanceSet_kind(
+      EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkInstanceSet_receiver(
+      EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+    return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+  }
+
+  bool checkInstanceSet_name(
+      EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkInstanceSet_value(
+      EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+    return visitor.checkNodes(node.value, other.value, 'value');
+  }
+
+  bool checkInstanceSet_interfaceTargetReference(
+      EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+    return visitor.checkReferences(node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+
+  bool checkInstanceSet_fileOffset(
+      EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkSuperPropertyGet_name(EquivalenceVisitor visitor,
+      SuperPropertyGet node, SuperPropertyGet other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkSuperPropertyGet_interfaceTargetReference(
+      EquivalenceVisitor visitor,
+      SuperPropertyGet node,
+      SuperPropertyGet other) {
+    return visitor.checkReferences(node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+
+  bool checkSuperPropertyGet_fileOffset(EquivalenceVisitor visitor,
+      SuperPropertyGet node, SuperPropertyGet other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkSuperPropertySet_name(EquivalenceVisitor visitor,
+      SuperPropertySet node, SuperPropertySet other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkSuperPropertySet_value(EquivalenceVisitor visitor,
+      SuperPropertySet node, SuperPropertySet other) {
+    return visitor.checkNodes(node.value, other.value, 'value');
+  }
+
+  bool checkSuperPropertySet_interfaceTargetReference(
+      EquivalenceVisitor visitor,
+      SuperPropertySet node,
+      SuperPropertySet other) {
+    return visitor.checkReferences(node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+
+  bool checkSuperPropertySet_fileOffset(EquivalenceVisitor visitor,
+      SuperPropertySet node, SuperPropertySet other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkStaticGet_targetReference(
+      EquivalenceVisitor visitor, StaticGet node, StaticGet other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkStaticGet_fileOffset(
+      EquivalenceVisitor visitor, StaticGet node, StaticGet other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkStaticTearOff_targetReference(
+      EquivalenceVisitor visitor, StaticTearOff node, StaticTearOff other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkStaticTearOff_fileOffset(
+      EquivalenceVisitor visitor, StaticTearOff node, StaticTearOff other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkStaticSet_targetReference(
+      EquivalenceVisitor visitor, StaticSet node, StaticSet other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkStaticSet_value(
+      EquivalenceVisitor visitor, StaticSet node, StaticSet other) {
+    return visitor.checkNodes(node.value, other.value, 'value');
+  }
+
+  bool checkStaticSet_fileOffset(
+      EquivalenceVisitor visitor, StaticSet node, StaticSet other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkDynamicInvocation_kind(EquivalenceVisitor visitor,
+      DynamicInvocation node, DynamicInvocation other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkDynamicInvocation_receiver(EquivalenceVisitor visitor,
+      DynamicInvocation node, DynamicInvocation other) {
+    return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+  }
+
+  bool checkDynamicInvocation_name(EquivalenceVisitor visitor,
+      DynamicInvocation node, DynamicInvocation other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkDynamicInvocation_arguments(EquivalenceVisitor visitor,
+      DynamicInvocation node, DynamicInvocation other) {
+    return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+  }
+
+  bool checkDynamicInvocation_fileOffset(EquivalenceVisitor visitor,
+      DynamicInvocation node, DynamicInvocation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkInstanceInvocation_kind(EquivalenceVisitor visitor,
+      InstanceInvocation node, InstanceInvocation other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkInstanceInvocation_receiver(EquivalenceVisitor visitor,
+      InstanceInvocation node, InstanceInvocation other) {
+    return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+  }
+
+  bool checkInstanceInvocation_name(EquivalenceVisitor visitor,
+      InstanceInvocation node, InstanceInvocation other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkInstanceInvocation_arguments(EquivalenceVisitor visitor,
+      InstanceInvocation node, InstanceInvocation other) {
+    return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+  }
+
+  bool checkInstanceInvocation_flags(EquivalenceVisitor visitor,
+      InstanceInvocation node, InstanceInvocation other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkInstanceInvocation_functionType(EquivalenceVisitor visitor,
+      InstanceInvocation node, InstanceInvocation other) {
+    return visitor.checkNodes(
+        node.functionType, other.functionType, 'functionType');
+  }
+
+  bool checkInstanceInvocation_interfaceTargetReference(
+      EquivalenceVisitor visitor,
+      InstanceInvocation node,
+      InstanceInvocation other) {
+    return visitor.checkReferences(node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+
+  bool checkInstanceInvocation_fileOffset(EquivalenceVisitor visitor,
+      InstanceInvocation node, InstanceInvocation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkInstanceGetterInvocation_kind(EquivalenceVisitor visitor,
+      InstanceGetterInvocation node, InstanceGetterInvocation other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkInstanceGetterInvocation_receiver(EquivalenceVisitor visitor,
+      InstanceGetterInvocation node, InstanceGetterInvocation other) {
+    return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+  }
+
+  bool checkInstanceGetterInvocation_name(EquivalenceVisitor visitor,
+      InstanceGetterInvocation node, InstanceGetterInvocation other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkInstanceGetterInvocation_arguments(EquivalenceVisitor visitor,
+      InstanceGetterInvocation node, InstanceGetterInvocation other) {
+    return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+  }
+
+  bool checkInstanceGetterInvocation_flags(EquivalenceVisitor visitor,
+      InstanceGetterInvocation node, InstanceGetterInvocation other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkInstanceGetterInvocation_functionType(EquivalenceVisitor visitor,
+      InstanceGetterInvocation node, InstanceGetterInvocation other) {
+    return visitor.checkNodes(
+        node.functionType, other.functionType, 'functionType');
+  }
+
+  bool checkInstanceGetterInvocation_interfaceTargetReference(
+      EquivalenceVisitor visitor,
+      InstanceGetterInvocation node,
+      InstanceGetterInvocation other) {
+    return visitor.checkReferences(node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+
+  bool checkInstanceGetterInvocation_fileOffset(EquivalenceVisitor visitor,
+      InstanceGetterInvocation node, InstanceGetterInvocation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkFunctionInvocation_kind(EquivalenceVisitor visitor,
+      FunctionInvocation node, FunctionInvocation other) {
+    return visitor.checkValues(node.kind, other.kind, 'kind');
+  }
+
+  bool checkFunctionInvocation_receiver(EquivalenceVisitor visitor,
+      FunctionInvocation node, FunctionInvocation other) {
+    return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+  }
+
+  bool checkFunctionInvocation_arguments(EquivalenceVisitor visitor,
+      FunctionInvocation node, FunctionInvocation other) {
+    return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+  }
+
+  bool checkFunctionInvocation_functionType(EquivalenceVisitor visitor,
+      FunctionInvocation node, FunctionInvocation other) {
+    return visitor.checkNodes(
+        node.functionType, other.functionType, 'functionType');
+  }
+
+  bool checkFunctionInvocation_fileOffset(EquivalenceVisitor visitor,
+      FunctionInvocation node, FunctionInvocation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkLocalFunctionInvocation_variable(EquivalenceVisitor visitor,
+      LocalFunctionInvocation node, LocalFunctionInvocation other) {
+    return visitor.checkDeclarations(node.variable, other.variable, 'variable');
+  }
+
+  bool checkLocalFunctionInvocation_arguments(EquivalenceVisitor visitor,
+      LocalFunctionInvocation node, LocalFunctionInvocation other) {
+    return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+  }
+
+  bool checkLocalFunctionInvocation_functionType(EquivalenceVisitor visitor,
+      LocalFunctionInvocation node, LocalFunctionInvocation other) {
+    return visitor.checkNodes(
+        node.functionType, other.functionType, 'functionType');
+  }
+
+  bool checkLocalFunctionInvocation_fileOffset(EquivalenceVisitor visitor,
+      LocalFunctionInvocation node, LocalFunctionInvocation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkSuperMethodInvocation_name(EquivalenceVisitor visitor,
+      SuperMethodInvocation node, SuperMethodInvocation other) {
+    return visitor.checkNodes(node.name, other.name, 'name');
+  }
+
+  bool checkSuperMethodInvocation_arguments(EquivalenceVisitor visitor,
+      SuperMethodInvocation node, SuperMethodInvocation other) {
+    return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+  }
+
+  bool checkSuperMethodInvocation_interfaceTargetReference(
+      EquivalenceVisitor visitor,
+      SuperMethodInvocation node,
+      SuperMethodInvocation other) {
+    return visitor.checkReferences(node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+
+  bool checkSuperMethodInvocation_fileOffset(EquivalenceVisitor visitor,
+      SuperMethodInvocation node, SuperMethodInvocation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkStaticInvocation_targetReference(EquivalenceVisitor visitor,
+      StaticInvocation node, StaticInvocation other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkStaticInvocation_arguments(EquivalenceVisitor visitor,
+      StaticInvocation node, StaticInvocation other) {
+    return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+  }
+
+  bool checkStaticInvocation_isConst(EquivalenceVisitor visitor,
+      StaticInvocation node, StaticInvocation other) {
+    return visitor.checkValues(node.isConst, other.isConst, 'isConst');
+  }
+
+  bool checkStaticInvocation_fileOffset(EquivalenceVisitor visitor,
+      StaticInvocation node, StaticInvocation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkConstructorInvocation_targetReference(EquivalenceVisitor visitor,
+      ConstructorInvocation node, ConstructorInvocation other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkConstructorInvocation_arguments(EquivalenceVisitor visitor,
+      ConstructorInvocation node, ConstructorInvocation other) {
+    return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+  }
+
+  bool checkConstructorInvocation_isConst(EquivalenceVisitor visitor,
+      ConstructorInvocation node, ConstructorInvocation other) {
+    return visitor.checkValues(node.isConst, other.isConst, 'isConst');
+  }
+
+  bool checkConstructorInvocation_fileOffset(EquivalenceVisitor visitor,
+      ConstructorInvocation node, ConstructorInvocation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkEqualsNull_expression(
+      EquivalenceVisitor visitor, EqualsNull node, EqualsNull other) {
+    return visitor.checkNodes(node.expression, other.expression, 'expression');
+  }
+
+  bool checkEqualsNull_fileOffset(
+      EquivalenceVisitor visitor, EqualsNull node, EqualsNull other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkEqualsCall_left(
+      EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
+    return visitor.checkNodes(node.left, other.left, 'left');
+  }
+
+  bool checkEqualsCall_right(
+      EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
+    return visitor.checkNodes(node.right, other.right, 'right');
+  }
+
+  bool checkEqualsCall_functionType(
+      EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
+    return visitor.checkNodes(
+        node.functionType, other.functionType, 'functionType');
+  }
+
+  bool checkEqualsCall_interfaceTargetReference(
+      EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
+    return visitor.checkReferences(node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+
+  bool checkEqualsCall_fileOffset(
+      EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkInstantiation_expression(
+      EquivalenceVisitor visitor, Instantiation node, Instantiation other) {
+    return visitor.checkNodes(node.expression, other.expression, 'expression');
+  }
+
+  bool checkInstantiation_typeArguments(
+      EquivalenceVisitor visitor, Instantiation node, Instantiation other) {
+    return visitor.checkLists(node.typeArguments, other.typeArguments,
+        visitor.checkNodes, 'typeArguments');
+  }
+
+  bool checkInstantiation_fileOffset(
+      EquivalenceVisitor visitor, Instantiation node, Instantiation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkNot_operand(EquivalenceVisitor visitor, Not node, Not other) {
+    return visitor.checkNodes(node.operand, other.operand, 'operand');
+  }
+
+  bool checkNot_fileOffset(EquivalenceVisitor visitor, Not node, Not other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkLogicalExpression_left(EquivalenceVisitor visitor,
+      LogicalExpression node, LogicalExpression other) {
+    return visitor.checkNodes(node.left, other.left, 'left');
+  }
+
+  bool checkLogicalExpression_operatorEnum(EquivalenceVisitor visitor,
+      LogicalExpression node, LogicalExpression other) {
+    return visitor.checkValues(
+        node.operatorEnum, other.operatorEnum, 'operatorEnum');
+  }
+
+  bool checkLogicalExpression_right(EquivalenceVisitor visitor,
+      LogicalExpression node, LogicalExpression other) {
+    return visitor.checkNodes(node.right, other.right, 'right');
+  }
+
+  bool checkLogicalExpression_fileOffset(EquivalenceVisitor visitor,
+      LogicalExpression node, LogicalExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkConditionalExpression_condition(EquivalenceVisitor visitor,
+      ConditionalExpression node, ConditionalExpression other) {
+    return visitor.checkNodes(node.condition, other.condition, 'condition');
+  }
+
+  bool checkConditionalExpression_then(EquivalenceVisitor visitor,
+      ConditionalExpression node, ConditionalExpression other) {
+    return visitor.checkNodes(node.then, other.then, 'then');
+  }
+
+  bool checkConditionalExpression_otherwise(EquivalenceVisitor visitor,
+      ConditionalExpression node, ConditionalExpression other) {
+    return visitor.checkNodes(node.otherwise, other.otherwise, 'otherwise');
+  }
+
+  bool checkConditionalExpression_staticType(EquivalenceVisitor visitor,
+      ConditionalExpression node, ConditionalExpression other) {
+    return visitor.checkNodes(node.staticType, other.staticType, 'staticType');
+  }
+
+  bool checkConditionalExpression_fileOffset(EquivalenceVisitor visitor,
+      ConditionalExpression node, ConditionalExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkStringConcatenation_expressions(EquivalenceVisitor visitor,
+      StringConcatenation node, StringConcatenation other) {
+    return visitor.checkLists(
+        node.expressions, other.expressions, visitor.checkNodes, 'expressions');
+  }
+
+  bool checkStringConcatenation_fileOffset(EquivalenceVisitor visitor,
+      StringConcatenation node, StringConcatenation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkListConcatenation_typeArgument(EquivalenceVisitor visitor,
+      ListConcatenation node, ListConcatenation other) {
+    return visitor.checkNodes(
+        node.typeArgument, other.typeArgument, 'typeArgument');
+  }
+
+  bool checkListConcatenation_lists(EquivalenceVisitor visitor,
+      ListConcatenation node, ListConcatenation other) {
+    return visitor.checkLists(
+        node.lists, other.lists, visitor.checkNodes, 'lists');
+  }
+
+  bool checkListConcatenation_fileOffset(EquivalenceVisitor visitor,
+      ListConcatenation node, ListConcatenation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkSetConcatenation_typeArgument(EquivalenceVisitor visitor,
+      SetConcatenation node, SetConcatenation other) {
+    return visitor.checkNodes(
+        node.typeArgument, other.typeArgument, 'typeArgument');
+  }
+
+  bool checkSetConcatenation_sets(EquivalenceVisitor visitor,
+      SetConcatenation node, SetConcatenation other) {
+    return visitor.checkLists(
+        node.sets, other.sets, visitor.checkNodes, 'sets');
+  }
+
+  bool checkSetConcatenation_fileOffset(EquivalenceVisitor visitor,
+      SetConcatenation node, SetConcatenation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkMapConcatenation_keyType(EquivalenceVisitor visitor,
+      MapConcatenation node, MapConcatenation other) {
+    return visitor.checkNodes(node.keyType, other.keyType, 'keyType');
+  }
+
+  bool checkMapConcatenation_valueType(EquivalenceVisitor visitor,
+      MapConcatenation node, MapConcatenation other) {
+    return visitor.checkNodes(node.valueType, other.valueType, 'valueType');
+  }
+
+  bool checkMapConcatenation_maps(EquivalenceVisitor visitor,
+      MapConcatenation node, MapConcatenation other) {
+    return visitor.checkLists(
+        node.maps, other.maps, visitor.checkNodes, 'maps');
+  }
+
+  bool checkMapConcatenation_fileOffset(EquivalenceVisitor visitor,
+      MapConcatenation node, MapConcatenation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkInstanceCreation_classReference(EquivalenceVisitor visitor,
+      InstanceCreation node, InstanceCreation other) {
+    return visitor.checkReferences(
+        node.classReference, other.classReference, 'classReference');
+  }
+
+  bool checkInstanceCreation_typeArguments(EquivalenceVisitor visitor,
+      InstanceCreation node, InstanceCreation other) {
+    return visitor.checkLists(node.typeArguments, other.typeArguments,
+        visitor.checkNodes, 'typeArguments');
+  }
+
+  bool checkInstanceCreation_fieldValues(EquivalenceVisitor visitor,
+      InstanceCreation node, InstanceCreation other) {
+    return visitor.checkMaps(
+        node.fieldValues,
+        other.fieldValues,
+        visitor.matchReferences,
+        visitor.checkReferences,
+        visitor.checkNodes,
+        'fieldValues');
+  }
+
+  bool checkInstanceCreation_asserts(EquivalenceVisitor visitor,
+      InstanceCreation node, InstanceCreation other) {
+    return visitor.checkLists(
+        node.asserts, other.asserts, visitor.checkNodes, 'asserts');
+  }
+
+  bool checkInstanceCreation_unusedArguments(EquivalenceVisitor visitor,
+      InstanceCreation node, InstanceCreation other) {
+    return visitor.checkLists(node.unusedArguments, other.unusedArguments,
+        visitor.checkNodes, 'unusedArguments');
+  }
+
+  bool checkInstanceCreation_fileOffset(EquivalenceVisitor visitor,
+      InstanceCreation node, InstanceCreation other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkFileUriExpression_fileUri(EquivalenceVisitor visitor,
+      FileUriExpression node, FileUriExpression other) {
+    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+  }
+
+  bool checkFileUriExpression_expression(EquivalenceVisitor visitor,
+      FileUriExpression node, FileUriExpression other) {
+    return visitor.checkNodes(node.expression, other.expression, 'expression');
+  }
+
+  bool checkFileUriExpression_fileOffset(EquivalenceVisitor visitor,
+      FileUriExpression node, FileUriExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkIsExpression_flags(
+      EquivalenceVisitor visitor, IsExpression node, IsExpression other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkIsExpression_operand(
+      EquivalenceVisitor visitor, IsExpression node, IsExpression other) {
+    return visitor.checkNodes(node.operand, other.operand, 'operand');
+  }
+
+  bool checkIsExpression_type(
+      EquivalenceVisitor visitor, IsExpression node, IsExpression other) {
+    return visitor.checkNodes(node.type, other.type, 'type');
+  }
+
+  bool checkIsExpression_fileOffset(
+      EquivalenceVisitor visitor, IsExpression node, IsExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkAsExpression_flags(
+      EquivalenceVisitor visitor, AsExpression node, AsExpression other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkAsExpression_operand(
+      EquivalenceVisitor visitor, AsExpression node, AsExpression other) {
+    return visitor.checkNodes(node.operand, other.operand, 'operand');
+  }
+
+  bool checkAsExpression_type(
+      EquivalenceVisitor visitor, AsExpression node, AsExpression other) {
+    return visitor.checkNodes(node.type, other.type, 'type');
+  }
+
+  bool checkAsExpression_fileOffset(
+      EquivalenceVisitor visitor, AsExpression node, AsExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkNullCheck_operand(
+      EquivalenceVisitor visitor, NullCheck node, NullCheck other) {
+    return visitor.checkNodes(node.operand, other.operand, 'operand');
+  }
+
+  bool checkNullCheck_fileOffset(
+      EquivalenceVisitor visitor, NullCheck node, NullCheck other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkStringLiteral_value(
+      EquivalenceVisitor visitor, StringLiteral node, StringLiteral other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
+  bool checkStringLiteral_fileOffset(
+      EquivalenceVisitor visitor, StringLiteral node, StringLiteral other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkIntLiteral_value(
+      EquivalenceVisitor visitor, IntLiteral node, IntLiteral other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
+  bool checkIntLiteral_fileOffset(
+      EquivalenceVisitor visitor, IntLiteral node, IntLiteral other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkDoubleLiteral_value(
+      EquivalenceVisitor visitor, DoubleLiteral node, DoubleLiteral other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
+  bool checkDoubleLiteral_fileOffset(
+      EquivalenceVisitor visitor, DoubleLiteral node, DoubleLiteral other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkBoolLiteral_value(
+      EquivalenceVisitor visitor, BoolLiteral node, BoolLiteral other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
+  bool checkBoolLiteral_fileOffset(
+      EquivalenceVisitor visitor, BoolLiteral node, BoolLiteral other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkNullLiteral_fileOffset(
+      EquivalenceVisitor visitor, NullLiteral node, NullLiteral other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkSymbolLiteral_value(
+      EquivalenceVisitor visitor, SymbolLiteral node, SymbolLiteral other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
+  bool checkSymbolLiteral_fileOffset(
+      EquivalenceVisitor visitor, SymbolLiteral node, SymbolLiteral other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkTypeLiteral_type(
+      EquivalenceVisitor visitor, TypeLiteral node, TypeLiteral other) {
+    return visitor.checkNodes(node.type, other.type, 'type');
+  }
+
+  bool checkTypeLiteral_fileOffset(
+      EquivalenceVisitor visitor, TypeLiteral node, TypeLiteral other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkThisExpression_fileOffset(
+      EquivalenceVisitor visitor, ThisExpression node, ThisExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkRethrow_fileOffset(
+      EquivalenceVisitor visitor, Rethrow node, Rethrow other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkThrow_expression(
+      EquivalenceVisitor visitor, Throw node, Throw other) {
+    return visitor.checkNodes(node.expression, other.expression, 'expression');
+  }
+
+  bool checkThrow_fileOffset(
+      EquivalenceVisitor visitor, Throw node, Throw other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkListLiteral_isConst(
+      EquivalenceVisitor visitor, ListLiteral node, ListLiteral other) {
+    return visitor.checkValues(node.isConst, other.isConst, 'isConst');
+  }
+
+  bool checkListLiteral_typeArgument(
+      EquivalenceVisitor visitor, ListLiteral node, ListLiteral other) {
+    return visitor.checkNodes(
+        node.typeArgument, other.typeArgument, 'typeArgument');
+  }
+
+  bool checkListLiteral_expressions(
+      EquivalenceVisitor visitor, ListLiteral node, ListLiteral other) {
+    return visitor.checkLists(
+        node.expressions, other.expressions, visitor.checkNodes, 'expressions');
+  }
+
+  bool checkListLiteral_fileOffset(
+      EquivalenceVisitor visitor, ListLiteral node, ListLiteral other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkSetLiteral_isConst(
+      EquivalenceVisitor visitor, SetLiteral node, SetLiteral other) {
+    return visitor.checkValues(node.isConst, other.isConst, 'isConst');
+  }
+
+  bool checkSetLiteral_typeArgument(
+      EquivalenceVisitor visitor, SetLiteral node, SetLiteral other) {
+    return visitor.checkNodes(
+        node.typeArgument, other.typeArgument, 'typeArgument');
+  }
+
+  bool checkSetLiteral_expressions(
+      EquivalenceVisitor visitor, SetLiteral node, SetLiteral other) {
+    return visitor.checkLists(
+        node.expressions, other.expressions, visitor.checkNodes, 'expressions');
+  }
+
+  bool checkSetLiteral_fileOffset(
+      EquivalenceVisitor visitor, SetLiteral node, SetLiteral other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkMapLiteral_isConst(
+      EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
+    return visitor.checkValues(node.isConst, other.isConst, 'isConst');
+  }
+
+  bool checkMapLiteral_keyType(
+      EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
+    return visitor.checkNodes(node.keyType, other.keyType, 'keyType');
+  }
+
+  bool checkMapLiteral_valueType(
+      EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
+    return visitor.checkNodes(node.valueType, other.valueType, 'valueType');
+  }
+
+  bool checkMapLiteral_entries(
+      EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
+    return visitor.checkLists(
+        node.entries, other.entries, visitor.checkNodes, 'entries');
+  }
+
+  bool checkMapLiteral_fileOffset(
+      EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkAwaitExpression_operand(
+      EquivalenceVisitor visitor, AwaitExpression node, AwaitExpression other) {
+    return visitor.checkNodes(node.operand, other.operand, 'operand');
+  }
+
+  bool checkAwaitExpression_fileOffset(
+      EquivalenceVisitor visitor, AwaitExpression node, AwaitExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkFunctionExpression_function(EquivalenceVisitor visitor,
+      FunctionExpression node, FunctionExpression other) {
+    return visitor.checkNodes(node.function, other.function, 'function');
+  }
+
+  bool checkFunctionExpression_fileOffset(EquivalenceVisitor visitor,
+      FunctionExpression node, FunctionExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkConstantExpression_constant(EquivalenceVisitor visitor,
+      ConstantExpression node, ConstantExpression other) {
+    return visitor.checkNodes(node.constant, other.constant, 'constant');
+  }
+
+  bool checkConstantExpression_type(EquivalenceVisitor visitor,
+      ConstantExpression node, ConstantExpression other) {
+    return visitor.checkNodes(node.type, other.type, 'type');
+  }
+
+  bool checkConstantExpression_fileOffset(EquivalenceVisitor visitor,
+      ConstantExpression node, ConstantExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkLet_variable(EquivalenceVisitor visitor, Let node, Let other) {
+    return visitor.checkNodes(node.variable, other.variable, 'variable');
+  }
+
+  bool checkLet_body(EquivalenceVisitor visitor, Let node, Let other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkLet_fileOffset(EquivalenceVisitor visitor, Let node, Let other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkBlockExpression_body(
+      EquivalenceVisitor visitor, BlockExpression node, BlockExpression other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkBlockExpression_value(
+      EquivalenceVisitor visitor, BlockExpression node, BlockExpression other) {
+    return visitor.checkNodes(node.value, other.value, 'value');
+  }
+
+  bool checkBlockExpression_fileOffset(
+      EquivalenceVisitor visitor, BlockExpression node, BlockExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkLoadLibrary_import(
+      EquivalenceVisitor visitor, LoadLibrary node, LoadLibrary other) {
+    return visitor.checkNodes(node.import, other.import, 'import');
+  }
+
+  bool checkLoadLibrary_fileOffset(
+      EquivalenceVisitor visitor, LoadLibrary node, LoadLibrary other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkCheckLibraryIsLoaded_import(EquivalenceVisitor visitor,
+      CheckLibraryIsLoaded node, CheckLibraryIsLoaded other) {
+    return visitor.checkNodes(node.import, other.import, 'import');
+  }
+
+  bool checkCheckLibraryIsLoaded_fileOffset(EquivalenceVisitor visitor,
+      CheckLibraryIsLoaded node, CheckLibraryIsLoaded other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkConstructorTearOff_targetReference(EquivalenceVisitor visitor,
+      ConstructorTearOff node, ConstructorTearOff other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkConstructorTearOff_fileOffset(EquivalenceVisitor visitor,
+      ConstructorTearOff node, ConstructorTearOff other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkRedirectingFactoryTearOff_targetReference(
+      EquivalenceVisitor visitor,
+      RedirectingFactoryTearOff node,
+      RedirectingFactoryTearOff other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkRedirectingFactoryTearOff_fileOffset(EquivalenceVisitor visitor,
+      RedirectingFactoryTearOff node, RedirectingFactoryTearOff other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkTypedefTearOff_typeParameters(
+      EquivalenceVisitor visitor, TypedefTearOff node, TypedefTearOff other) {
+    return visitor.checkLists(node.typeParameters, other.typeParameters,
+        visitor.checkNodes, 'typeParameters');
+  }
+
+  bool checkTypedefTearOff_expression(
+      EquivalenceVisitor visitor, TypedefTearOff node, TypedefTearOff other) {
+    return visitor.checkNodes(node.expression, other.expression, 'expression');
+  }
+
+  bool checkTypedefTearOff_typeArguments(
+      EquivalenceVisitor visitor, TypedefTearOff node, TypedefTearOff other) {
+    return visitor.checkLists(node.typeArguments, other.typeArguments,
+        visitor.checkNodes, 'typeArguments');
+  }
+
+  bool checkTypedefTearOff_fileOffset(
+      EquivalenceVisitor visitor, TypedefTearOff node, TypedefTearOff other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkArguments_types(
+      EquivalenceVisitor visitor, Arguments node, Arguments other) {
+    return visitor.checkLists(
+        node.types, other.types, visitor.checkNodes, 'types');
+  }
+
+  bool checkArguments_positional(
+      EquivalenceVisitor visitor, Arguments node, Arguments other) {
+    return visitor.checkLists(
+        node.positional, other.positional, visitor.checkNodes, 'positional');
+  }
+
+  bool checkArguments_named(
+      EquivalenceVisitor visitor, Arguments node, Arguments other) {
+    return visitor.checkLists(
+        node.named, other.named, visitor.checkNodes, 'named');
+  }
+
+  bool checkArguments_fileOffset(
+      EquivalenceVisitor visitor, Arguments node, Arguments other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkNamedExpression_name(
+      EquivalenceVisitor visitor, NamedExpression node, NamedExpression other) {
+    return visitor.checkValues(node.name, other.name, 'name');
+  }
+
+  bool checkNamedExpression_value(
+      EquivalenceVisitor visitor, NamedExpression node, NamedExpression other) {
+    return visitor.checkNodes(node.value, other.value, 'value');
+  }
+
+  bool checkNamedExpression_fileOffset(
+      EquivalenceVisitor visitor, NamedExpression node, NamedExpression other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkMapLiteralEntry_key(
+      EquivalenceVisitor visitor, MapLiteralEntry node, MapLiteralEntry other) {
+    return visitor.checkNodes(node.key, other.key, 'key');
+  }
+
+  bool checkMapLiteralEntry_value(
+      EquivalenceVisitor visitor, MapLiteralEntry node, MapLiteralEntry other) {
+    return visitor.checkNodes(node.value, other.value, 'value');
+  }
+
+  bool checkMapLiteralEntry_fileOffset(
+      EquivalenceVisitor visitor, MapLiteralEntry node, MapLiteralEntry other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkExpressionStatement_expression(EquivalenceVisitor visitor,
+      ExpressionStatement node, ExpressionStatement other) {
+    return visitor.checkNodes(node.expression, other.expression, 'expression');
+  }
+
+  bool checkExpressionStatement_fileOffset(EquivalenceVisitor visitor,
+      ExpressionStatement node, ExpressionStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkBlock_statements(
+      EquivalenceVisitor visitor, Block node, Block other) {
+    return visitor.checkLists(
+        node.statements, other.statements, visitor.checkNodes, 'statements');
+  }
+
+  bool checkBlock_fileEndOffset(
+      EquivalenceVisitor visitor, Block node, Block other) {
+    return visitor.checkValues(
+        node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+  }
+
+  bool checkBlock_fileOffset(
+      EquivalenceVisitor visitor, Block node, Block other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkAssertBlock_statements(
+      EquivalenceVisitor visitor, AssertBlock node, AssertBlock other) {
+    return visitor.checkLists(
+        node.statements, other.statements, visitor.checkNodes, 'statements');
+  }
+
+  bool checkAssertBlock_fileOffset(
+      EquivalenceVisitor visitor, AssertBlock node, AssertBlock other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkEmptyStatement_fileOffset(
+      EquivalenceVisitor visitor, EmptyStatement node, EmptyStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkAssertStatement_condition(
+      EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
+    return visitor.checkNodes(node.condition, other.condition, 'condition');
+  }
+
+  bool checkAssertStatement_message(
+      EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
+    return visitor.checkNodes(node.message, other.message, 'message');
+  }
+
+  bool checkAssertStatement_conditionStartOffset(
+      EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
+    return visitor.checkValues(node.conditionStartOffset,
+        other.conditionStartOffset, 'conditionStartOffset');
+  }
+
+  bool checkAssertStatement_conditionEndOffset(
+      EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
+    return visitor.checkValues(node.conditionEndOffset,
+        other.conditionEndOffset, 'conditionEndOffset');
+  }
+
+  bool checkAssertStatement_fileOffset(
+      EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkLabeledStatement_body(EquivalenceVisitor visitor,
+      LabeledStatement node, LabeledStatement other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkLabeledStatement_fileOffset(EquivalenceVisitor visitor,
+      LabeledStatement node, LabeledStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkBreakStatement_target(
+      EquivalenceVisitor visitor, BreakStatement node, BreakStatement other) {
+    return visitor.checkDeclarations(node.target, other.target, 'target');
+  }
+
+  bool checkBreakStatement_fileOffset(
+      EquivalenceVisitor visitor, BreakStatement node, BreakStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkWhileStatement_condition(
+      EquivalenceVisitor visitor, WhileStatement node, WhileStatement other) {
+    return visitor.checkNodes(node.condition, other.condition, 'condition');
+  }
+
+  bool checkWhileStatement_body(
+      EquivalenceVisitor visitor, WhileStatement node, WhileStatement other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkWhileStatement_fileOffset(
+      EquivalenceVisitor visitor, WhileStatement node, WhileStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkDoStatement_body(
+      EquivalenceVisitor visitor, DoStatement node, DoStatement other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkDoStatement_condition(
+      EquivalenceVisitor visitor, DoStatement node, DoStatement other) {
+    return visitor.checkNodes(node.condition, other.condition, 'condition');
+  }
+
+  bool checkDoStatement_fileOffset(
+      EquivalenceVisitor visitor, DoStatement node, DoStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkForStatement_variables(
+      EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
+    return visitor.checkLists(
+        node.variables, other.variables, visitor.checkNodes, 'variables');
+  }
+
+  bool checkForStatement_condition(
+      EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
+    return visitor.checkNodes(node.condition, other.condition, 'condition');
+  }
+
+  bool checkForStatement_updates(
+      EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
+    return visitor.checkLists(
+        node.updates, other.updates, visitor.checkNodes, 'updates');
+  }
+
+  bool checkForStatement_body(
+      EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkForStatement_fileOffset(
+      EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkForInStatement_bodyOffset(
+      EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+    return visitor.checkValues(node.bodyOffset, other.bodyOffset, 'bodyOffset');
+  }
+
+  bool checkForInStatement_variable(
+      EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+    return visitor.checkNodes(node.variable, other.variable, 'variable');
+  }
+
+  bool checkForInStatement_iterable(
+      EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+    return visitor.checkNodes(node.iterable, other.iterable, 'iterable');
+  }
+
+  bool checkForInStatement_body(
+      EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkForInStatement_isAsync(
+      EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+    return visitor.checkValues(node.isAsync, other.isAsync, 'isAsync');
+  }
+
+  bool checkForInStatement_fileOffset(
+      EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkSwitchStatement_expression(
+      EquivalenceVisitor visitor, SwitchStatement node, SwitchStatement other) {
+    return visitor.checkNodes(node.expression, other.expression, 'expression');
+  }
+
+  bool checkSwitchStatement_cases(
+      EquivalenceVisitor visitor, SwitchStatement node, SwitchStatement other) {
+    return visitor.checkLists(
+        node.cases, other.cases, visitor.checkNodes, 'cases');
+  }
+
+  bool checkSwitchStatement_fileOffset(
+      EquivalenceVisitor visitor, SwitchStatement node, SwitchStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkContinueSwitchStatement_target(EquivalenceVisitor visitor,
+      ContinueSwitchStatement node, ContinueSwitchStatement other) {
+    return visitor.checkDeclarations(node.target, other.target, 'target');
+  }
+
+  bool checkContinueSwitchStatement_fileOffset(EquivalenceVisitor visitor,
+      ContinueSwitchStatement node, ContinueSwitchStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkIfStatement_condition(
+      EquivalenceVisitor visitor, IfStatement node, IfStatement other) {
+    return visitor.checkNodes(node.condition, other.condition, 'condition');
+  }
+
+  bool checkIfStatement_then(
+      EquivalenceVisitor visitor, IfStatement node, IfStatement other) {
+    return visitor.checkNodes(node.then, other.then, 'then');
+  }
+
+  bool checkIfStatement_otherwise(
+      EquivalenceVisitor visitor, IfStatement node, IfStatement other) {
+    return visitor.checkNodes(node.otherwise, other.otherwise, 'otherwise');
+  }
+
+  bool checkIfStatement_fileOffset(
+      EquivalenceVisitor visitor, IfStatement node, IfStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkReturnStatement_expression(
+      EquivalenceVisitor visitor, ReturnStatement node, ReturnStatement other) {
+    return visitor.checkNodes(node.expression, other.expression, 'expression');
+  }
+
+  bool checkReturnStatement_fileOffset(
+      EquivalenceVisitor visitor, ReturnStatement node, ReturnStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkTryCatch_body(
+      EquivalenceVisitor visitor, TryCatch node, TryCatch other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkTryCatch_catches(
+      EquivalenceVisitor visitor, TryCatch node, TryCatch other) {
+    return visitor.checkLists(
+        node.catches, other.catches, visitor.checkNodes, 'catches');
+  }
+
+  bool checkTryCatch_isSynthetic(
+      EquivalenceVisitor visitor, TryCatch node, TryCatch other) {
+    return visitor.checkValues(
+        node.isSynthetic, other.isSynthetic, 'isSynthetic');
+  }
+
+  bool checkTryCatch_fileOffset(
+      EquivalenceVisitor visitor, TryCatch node, TryCatch other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkTryFinally_body(
+      EquivalenceVisitor visitor, TryFinally node, TryFinally other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkTryFinally_finalizer(
+      EquivalenceVisitor visitor, TryFinally node, TryFinally other) {
+    return visitor.checkNodes(node.finalizer, other.finalizer, 'finalizer');
+  }
+
+  bool checkTryFinally_fileOffset(
+      EquivalenceVisitor visitor, TryFinally node, TryFinally other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkYieldStatement_expression(
+      EquivalenceVisitor visitor, YieldStatement node, YieldStatement other) {
+    return visitor.checkNodes(node.expression, other.expression, 'expression');
+  }
+
+  bool checkYieldStatement_flags(
+      EquivalenceVisitor visitor, YieldStatement node, YieldStatement other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkYieldStatement_fileOffset(
+      EquivalenceVisitor visitor, YieldStatement node, YieldStatement other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkVariableDeclaration_fileEqualsOffset(EquivalenceVisitor visitor,
+      VariableDeclaration node, VariableDeclaration other) {
+    return visitor.checkValues(
+        node.fileEqualsOffset, other.fileEqualsOffset, 'fileEqualsOffset');
+  }
+
+  bool checkVariableDeclaration_annotations(EquivalenceVisitor visitor,
+      VariableDeclaration node, VariableDeclaration other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkVariableDeclaration_name(EquivalenceVisitor visitor,
+      VariableDeclaration node, VariableDeclaration other) {
+    return visitor.checkValues(node.name, other.name, 'name');
+  }
+
+  bool checkVariableDeclaration_flags(EquivalenceVisitor visitor,
+      VariableDeclaration node, VariableDeclaration other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkVariableDeclaration_type(EquivalenceVisitor visitor,
+      VariableDeclaration node, VariableDeclaration other) {
+    return visitor.checkNodes(node.type, other.type, 'type');
+  }
+
+  bool checkVariableDeclaration_binaryOffsetNoTag(EquivalenceVisitor visitor,
+      VariableDeclaration node, VariableDeclaration other) {
+    return visitor.checkValues(
+        node.binaryOffsetNoTag, other.binaryOffsetNoTag, 'binaryOffsetNoTag');
+  }
+
+  bool checkVariableDeclaration_initializer(EquivalenceVisitor visitor,
+      VariableDeclaration node, VariableDeclaration other) {
+    return visitor.checkNodes(
+        node.initializer, other.initializer, 'initializer');
+  }
+
+  bool checkVariableDeclaration_fileOffset(EquivalenceVisitor visitor,
+      VariableDeclaration node, VariableDeclaration other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkFunctionDeclaration_variable(EquivalenceVisitor visitor,
+      FunctionDeclaration node, FunctionDeclaration other) {
+    return visitor.checkNodes(node.variable, other.variable, 'variable');
+  }
+
+  bool checkFunctionDeclaration_function(EquivalenceVisitor visitor,
+      FunctionDeclaration node, FunctionDeclaration other) {
+    return visitor.checkNodes(node.function, other.function, 'function');
+  }
+
+  bool checkFunctionDeclaration_fileOffset(EquivalenceVisitor visitor,
+      FunctionDeclaration node, FunctionDeclaration other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkSwitchCase_expressions(
+      EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
+    return visitor.checkLists(
+        node.expressions, other.expressions, visitor.checkNodes, 'expressions');
+  }
+
+  bool checkSwitchCase_expressionOffsets(
+      EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
+    return visitor.checkLists(node.expressionOffsets, other.expressionOffsets,
+        visitor.checkValues, 'expressionOffsets');
+  }
+
+  bool checkSwitchCase_body(
+      EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkSwitchCase_isDefault(
+      EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
+    return visitor.checkValues(node.isDefault, other.isDefault, 'isDefault');
+  }
+
+  bool checkSwitchCase_fileOffset(
+      EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkCatch_guard(EquivalenceVisitor visitor, Catch node, Catch other) {
+    return visitor.checkNodes(node.guard, other.guard, 'guard');
+  }
+
+  bool checkCatch_exception(
+      EquivalenceVisitor visitor, Catch node, Catch other) {
+    return visitor.checkNodes(node.exception, other.exception, 'exception');
+  }
+
+  bool checkCatch_stackTrace(
+      EquivalenceVisitor visitor, Catch node, Catch other) {
+    return visitor.checkNodes(node.stackTrace, other.stackTrace, 'stackTrace');
+  }
+
+  bool checkCatch_body(EquivalenceVisitor visitor, Catch node, Catch other) {
+    return visitor.checkNodes(node.body, other.body, 'body');
+  }
+
+  bool checkCatch_fileOffset(
+      EquivalenceVisitor visitor, Catch node, Catch other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkTypeParameter_flags(
+      EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+    return visitor.checkValues(node.flags, other.flags, 'flags');
+  }
+
+  bool checkTypeParameter_annotations(
+      EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+    return visitor.checkLists(
+        node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+  }
+
+  bool checkTypeParameter_name(
+      EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+    return visitor.checkValues(node.name, other.name, 'name');
+  }
+
+  bool checkTypeParameter_bound(
+      EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+    return visitor.checkNodes(node.bound, other.bound, 'bound');
+  }
+
+  bool checkTypeParameter_defaultType(
+      EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+    return visitor.checkNodes(
+        node.defaultType, other.defaultType, 'defaultType');
+  }
+
+  bool checkTypeParameter_variance(
+      EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+    return visitor.checkValues(node.variance, other.variance, 'variance');
+  }
+
+  bool checkTypeParameter_fileOffset(
+      EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkComponent_problemsAsJson(
+      EquivalenceVisitor visitor, Component node, Component other) {
+    return visitor.checkLists(node.problemsAsJson, other.problemsAsJson,
+        visitor.checkValues, 'problemsAsJson');
+  }
+
+  bool checkComponent_libraries(
+      EquivalenceVisitor visitor, Component node, Component other) {
+    return visitor.checkLists(
+        node.libraries, other.libraries, visitor.checkNodes, 'libraries');
+  }
+
+  bool checkSource_lineStarts(
+      EquivalenceVisitor visitor, Source node, Source other) {
+    return visitor.checkLists(
+        node.lineStarts, other.lineStarts, visitor.checkValues, 'lineStarts');
+  }
+
+  bool checkSource_source(
+      EquivalenceVisitor visitor, Source node, Source other) {
+    return visitor.checkLists(
+        node.source, other.source, visitor.checkValues, 'source');
+  }
+
+  bool checkSource_importUri(
+      EquivalenceVisitor visitor, Source node, Source other) {
+    return visitor.checkValues(node.importUri, other.importUri, 'importUri');
+  }
+
+  bool checkSource_fileUri(
+      EquivalenceVisitor visitor, Source node, Source other) {
+    return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+  }
+
+  bool checkSource_constantCoverageConstructors(
+      EquivalenceVisitor visitor, Source node, Source other) {
+    return visitor.checkSets(
+        node.constantCoverageConstructors,
+        other.constantCoverageConstructors,
+        visitor.matchReferences,
+        visitor.checkReferences,
+        'constantCoverageConstructors');
+  }
+
+  bool checkSource_cachedText(
+      EquivalenceVisitor visitor, Source node, Source other) {
+    return visitor.checkValues(node.cachedText, other.cachedText, 'cachedText');
+  }
+
+  bool checkComponent_uriToSource(
+      EquivalenceVisitor visitor, Component node, Component other) {
+    return visitor.checkMaps(node.uriToSource, other.uriToSource,
+        visitor.matchValues, visitor.checkValues, (a, b, _) {
+      if (identical(a, b)) return true;
+      if (a is! Source) return false;
+      if (b is! Source) return false;
+      return checkSource(visitor, a, b);
+    }, 'uriToSource');
+  }
+
+  bool checkComponent_metadata(
+      EquivalenceVisitor visitor, Component node, Component other) {
+    return visitor.checkMaps(
+        node.metadata, other.metadata, visitor.matchValues, visitor.checkValues,
+        (a, b, _) {
+      if (identical(a, b)) return true;
+      if (a is! MetadataRepository) return false;
+      if (b is! MetadataRepository) return false;
+      return checkMetadataRepository(visitor, a, b);
+    }, 'metadata');
+  }
+
+  bool checkComponent_mainMethodName(
+      EquivalenceVisitor visitor, Component node, Component other) {
+    return visitor.checkReferences(
+        node.mainMethodName, other.mainMethodName, 'mainMethodName');
+  }
+
+  bool checkComponent_mode(
+      EquivalenceVisitor visitor, Component node, Component other) {
+    return visitor.checkValues(node.mode, other.mode, 'mode');
+  }
+
+  bool checkComponent_fileOffset(
+      EquivalenceVisitor visitor, Component node, Component other) {
+    return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+  }
+
+  bool checkName_text(EquivalenceVisitor visitor, Name node, Name other) {
+    return visitor.checkValues(node.text, other.text, 'text');
+  }
+
+  bool checkNeverType_declaredNullability(
+      EquivalenceVisitor visitor, NeverType node, NeverType other) {
+    return visitor.checkValues(node.declaredNullability,
+        other.declaredNullability, 'declaredNullability');
+  }
+
+  bool checkInterfaceType_className(
+      EquivalenceVisitor visitor, InterfaceType node, InterfaceType other) {
+    return visitor.checkReferences(
+        node.className, other.className, 'className');
+  }
+
+  bool checkInterfaceType_declaredNullability(
+      EquivalenceVisitor visitor, InterfaceType node, InterfaceType other) {
+    return visitor.checkValues(node.declaredNullability,
+        other.declaredNullability, 'declaredNullability');
+  }
+
+  bool checkInterfaceType_typeArguments(
+      EquivalenceVisitor visitor, InterfaceType node, InterfaceType other) {
+    return visitor.checkLists(node.typeArguments, other.typeArguments,
+        visitor.checkNodes, 'typeArguments');
+  }
+
+  bool checkFunctionType_typeParameters(
+      EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+    return visitor.checkLists(node.typeParameters, other.typeParameters,
+        visitor.checkNodes, 'typeParameters');
+  }
+
+  bool checkFunctionType_requiredParameterCount(
+      EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+    return visitor.checkValues(node.requiredParameterCount,
+        other.requiredParameterCount, 'requiredParameterCount');
+  }
+
+  bool checkFunctionType_positionalParameters(
+      EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+    return visitor.checkLists(node.positionalParameters,
+        other.positionalParameters, visitor.checkNodes, 'positionalParameters');
+  }
+
+  bool checkFunctionType_namedParameters(
+      EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+    return visitor.checkLists(node.namedParameters, other.namedParameters,
+        visitor.checkNodes, 'namedParameters');
+  }
+
+  bool checkFunctionType_declaredNullability(
+      EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+    return visitor.checkValues(node.declaredNullability,
+        other.declaredNullability, 'declaredNullability');
+  }
+
+  bool checkFunctionType_typedefType(
+      EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+    return visitor.checkNodes(
+        node.typedefType, other.typedefType, 'typedefType');
+  }
+
+  bool checkFunctionType_returnType(
+      EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+    return visitor.checkNodes(node.returnType, other.returnType, 'returnType');
+  }
+
+  bool checkTypedefType_declaredNullability(
+      EquivalenceVisitor visitor, TypedefType node, TypedefType other) {
+    return visitor.checkValues(node.declaredNullability,
+        other.declaredNullability, 'declaredNullability');
+  }
+
+  bool checkTypedefType_typedefReference(
+      EquivalenceVisitor visitor, TypedefType node, TypedefType other) {
+    return visitor.checkReferences(
+        node.typedefReference, other.typedefReference, 'typedefReference');
+  }
+
+  bool checkTypedefType_typeArguments(
+      EquivalenceVisitor visitor, TypedefType node, TypedefType other) {
+    return visitor.checkLists(node.typeArguments, other.typeArguments,
+        visitor.checkNodes, 'typeArguments');
+  }
+
+  bool checkFutureOrType_typeArgument(
+      EquivalenceVisitor visitor, FutureOrType node, FutureOrType other) {
+    return visitor.checkNodes(
+        node.typeArgument, other.typeArgument, 'typeArgument');
+  }
+
+  bool checkFutureOrType_declaredNullability(
+      EquivalenceVisitor visitor, FutureOrType node, FutureOrType other) {
+    return visitor.checkValues(node.declaredNullability,
+        other.declaredNullability, 'declaredNullability');
+  }
+
+  bool checkExtensionType_extensionReference(
+      EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
+    return visitor.checkReferences(node.extensionReference,
+        other.extensionReference, 'extensionReference');
+  }
+
+  bool checkExtensionType_declaredNullability(
+      EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
+    return visitor.checkValues(node.declaredNullability,
+        other.declaredNullability, 'declaredNullability');
+  }
+
+  bool checkExtensionType_typeArguments(
+      EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
+    return visitor.checkLists(node.typeArguments, other.typeArguments,
+        visitor.checkNodes, 'typeArguments');
+  }
+
+  bool checkExtensionType_onType(
+      EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
+    return visitor.checkNodes(node.onType, other.onType, 'onType');
+  }
+
+  bool checkTypeParameterType_declaredNullability(EquivalenceVisitor visitor,
+      TypeParameterType node, TypeParameterType other) {
+    return visitor.checkValues(node.declaredNullability,
+        other.declaredNullability, 'declaredNullability');
+  }
+
+  bool checkTypeParameterType_parameter(EquivalenceVisitor visitor,
+      TypeParameterType node, TypeParameterType other) {
+    return visitor.checkDeclarations(
+        node.parameter, other.parameter, 'parameter');
+  }
+
+  bool checkTypeParameterType_promotedBound(EquivalenceVisitor visitor,
+      TypeParameterType node, TypeParameterType other) {
+    return visitor.checkNodes(
+        node.promotedBound, other.promotedBound, 'promotedBound');
+  }
+
+  bool checkNamedType_name(
+      EquivalenceVisitor visitor, NamedType node, NamedType other) {
+    return visitor.checkValues(node.name, other.name, 'name');
+  }
+
+  bool checkNamedType_type(
+      EquivalenceVisitor visitor, NamedType node, NamedType other) {
+    return visitor.checkNodes(node.type, other.type, 'type');
+  }
+
+  bool checkNamedType_isRequired(
+      EquivalenceVisitor visitor, NamedType node, NamedType other) {
+    return visitor.checkValues(node.isRequired, other.isRequired, 'isRequired');
+  }
+
+  bool checkSupertype_className(
+      EquivalenceVisitor visitor, Supertype node, Supertype other) {
+    return visitor.checkReferences(
+        node.className, other.className, 'className');
+  }
+
+  bool checkSupertype_typeArguments(
+      EquivalenceVisitor visitor, Supertype node, Supertype other) {
+    return visitor.checkLists(node.typeArguments, other.typeArguments,
+        visitor.checkNodes, 'typeArguments');
+  }
+
+  bool checkNullConstant_value(
+      EquivalenceVisitor visitor, NullConstant node, NullConstant other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
+  bool checkBoolConstant_value(
+      EquivalenceVisitor visitor, BoolConstant node, BoolConstant other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
+  bool checkIntConstant_value(
+      EquivalenceVisitor visitor, IntConstant node, IntConstant other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
+  bool checkDoubleConstant_value(
+      EquivalenceVisitor visitor, DoubleConstant node, DoubleConstant other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
+  bool checkStringConstant_value(
+      EquivalenceVisitor visitor, StringConstant node, StringConstant other) {
+    return visitor.checkValues(node.value, other.value, 'value');
+  }
+
+  bool checkSymbolConstant_name(
+      EquivalenceVisitor visitor, SymbolConstant node, SymbolConstant other) {
+    return visitor.checkValues(node.name, other.name, 'name');
+  }
+
+  bool checkSymbolConstant_libraryReference(
+      EquivalenceVisitor visitor, SymbolConstant node, SymbolConstant other) {
+    return visitor.checkReferences(
+        node.libraryReference, other.libraryReference, 'libraryReference');
+  }
+
+  bool checkMapConstant_keyType(
+      EquivalenceVisitor visitor, MapConstant node, MapConstant other) {
+    return visitor.checkNodes(node.keyType, other.keyType, 'keyType');
+  }
+
+  bool checkMapConstant_valueType(
+      EquivalenceVisitor visitor, MapConstant node, MapConstant other) {
+    return visitor.checkNodes(node.valueType, other.valueType, 'valueType');
+  }
+
+  bool checkConstantMapEntry_key(EquivalenceVisitor visitor,
+      ConstantMapEntry node, ConstantMapEntry other) {
+    return visitor.checkNodes(node.key, other.key, 'key');
+  }
+
+  bool checkConstantMapEntry_value(EquivalenceVisitor visitor,
+      ConstantMapEntry node, ConstantMapEntry other) {
+    return visitor.checkNodes(node.value, other.value, 'value');
+  }
+
+  bool checkMapConstant_entries(
+      EquivalenceVisitor visitor, MapConstant node, MapConstant other) {
+    return visitor.checkLists(node.entries, other.entries, (a, b, _) {
+      if (identical(a, b)) return true;
+      if (a is! ConstantMapEntry) return false;
+      if (b is! ConstantMapEntry) return false;
+      return checkConstantMapEntry(visitor, a, b);
+    }, 'entries');
+  }
+
+  bool checkListConstant_typeArgument(
+      EquivalenceVisitor visitor, ListConstant node, ListConstant other) {
+    return visitor.checkNodes(
+        node.typeArgument, other.typeArgument, 'typeArgument');
+  }
+
+  bool checkListConstant_entries(
+      EquivalenceVisitor visitor, ListConstant node, ListConstant other) {
+    return visitor.checkLists(
+        node.entries, other.entries, visitor.checkNodes, 'entries');
+  }
+
+  bool checkSetConstant_typeArgument(
+      EquivalenceVisitor visitor, SetConstant node, SetConstant other) {
+    return visitor.checkNodes(
+        node.typeArgument, other.typeArgument, 'typeArgument');
+  }
+
+  bool checkSetConstant_entries(
+      EquivalenceVisitor visitor, SetConstant node, SetConstant other) {
+    return visitor.checkLists(
+        node.entries, other.entries, visitor.checkNodes, 'entries');
+  }
+
+  bool checkInstanceConstant_classReference(EquivalenceVisitor visitor,
+      InstanceConstant node, InstanceConstant other) {
+    return visitor.checkReferences(
+        node.classReference, other.classReference, 'classReference');
+  }
+
+  bool checkInstanceConstant_typeArguments(EquivalenceVisitor visitor,
+      InstanceConstant node, InstanceConstant other) {
+    return visitor.checkLists(node.typeArguments, other.typeArguments,
+        visitor.checkNodes, 'typeArguments');
+  }
+
+  bool checkInstanceConstant_fieldValues(EquivalenceVisitor visitor,
+      InstanceConstant node, InstanceConstant other) {
+    return visitor.checkMaps(
+        node.fieldValues,
+        other.fieldValues,
+        visitor.matchReferences,
+        visitor.checkReferences,
+        visitor.checkNodes,
+        'fieldValues');
+  }
+
+  bool checkInstantiationConstant_tearOffConstant(EquivalenceVisitor visitor,
+      InstantiationConstant node, InstantiationConstant other) {
+    return visitor.checkNodes(
+        node.tearOffConstant, other.tearOffConstant, 'tearOffConstant');
+  }
+
+  bool checkInstantiationConstant_types(EquivalenceVisitor visitor,
+      InstantiationConstant node, InstantiationConstant other) {
+    return visitor.checkLists(
+        node.types, other.types, visitor.checkNodes, 'types');
+  }
+
+  bool checkStaticTearOffConstant_targetReference(EquivalenceVisitor visitor,
+      StaticTearOffConstant node, StaticTearOffConstant other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkConstructorTearOffConstant_targetReference(
+      EquivalenceVisitor visitor,
+      ConstructorTearOffConstant node,
+      ConstructorTearOffConstant other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkRedirectingFactoryTearOffConstant_targetReference(
+      EquivalenceVisitor visitor,
+      RedirectingFactoryTearOffConstant node,
+      RedirectingFactoryTearOffConstant other) {
+    return visitor.checkReferences(
+        node.targetReference, other.targetReference, 'targetReference');
+  }
+
+  bool checkTypedefTearOffConstant_parameters(EquivalenceVisitor visitor,
+      TypedefTearOffConstant node, TypedefTearOffConstant other) {
+    return visitor.checkLists(
+        node.parameters, other.parameters, visitor.checkNodes, 'parameters');
+  }
+
+  bool checkTypedefTearOffConstant_tearOffConstant(EquivalenceVisitor visitor,
+      TypedefTearOffConstant node, TypedefTearOffConstant other) {
+    return visitor.checkNodes(
+        node.tearOffConstant, other.tearOffConstant, 'tearOffConstant');
+  }
+
+  bool checkTypedefTearOffConstant_types(EquivalenceVisitor visitor,
+      TypedefTearOffConstant node, TypedefTearOffConstant other) {
+    return visitor.checkLists(
+        node.types, other.types, visitor.checkNodes, 'types');
+  }
+
+  bool checkTypeLiteralConstant_type(EquivalenceVisitor visitor,
+      TypeLiteralConstant node, TypeLiteralConstant other) {
+    return visitor.checkNodes(node.type, other.type, 'type');
+  }
+
+  bool checkUnevaluatedConstant_expression(EquivalenceVisitor visitor,
+      UnevaluatedConstant node, UnevaluatedConstant other) {
+    return visitor.checkNodes(node.expression, other.expression, 'expression');
+  }
+}
diff --git a/pkg/kernel/lib/src/equivalence_helpers.dart b/pkg/kernel/lib/src/equivalence_helpers.dart
new file mode 100644
index 0000000..a7ccb27
--- /dev/null
+++ b/pkg/kernel/lib/src/equivalence_helpers.dart
@@ -0,0 +1,400 @@
+// 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.
+
+part of 'equivalence.dart';
+
+/// The node or property currently visited by the [EquivalenceVisitor].
+abstract class State {
+  const State();
+
+  State? get parent;
+}
+
+/// State for visiting two AST nodes in [EquivalenceVisitor].
+class NodeState extends State {
+  final State? parent;
+  final Node a;
+  final Node b;
+
+  NodeState(this.a, this.b, [this.parent]);
+}
+
+/// State for visiting an AST property in [EquivalenceVisitor]
+class PropertyState extends State {
+  final State? parent;
+  final String name;
+
+  PropertyState(this.name, [this.parent]);
+}
+
+/// The state of the equivalence visitor.
+///
+/// This holds the currently found inequivalences and the current assumptions.
+/// This also determines whether inequivalence are currently reported.
+class CheckingState {
+  /// If `true`, inequivalences are currently reported.
+  final bool isAsserting;
+
+  CheckingState(
+      {this.isAsserting: true,
+      UnionFind<Reference>? assumedReferences,
+      State? currentState})
+      : _assumedReferences = assumedReferences ?? new UnionFind<Reference>(),
+        _currentState = currentState;
+
+  /// Create a new [CheckingState] that inherits the [_currentState] and a copy
+  /// of the current assumptions. If [isAsserting] is `true`, the new state
+  /// will register inequivalences.
+  CheckingState createSubState({bool isAsserting: false}) {
+    return new CheckingState(
+        isAsserting: isAsserting,
+        assumedReferences: _assumedReferences.clone(),
+        currentState: _currentState)
+      .._assumedDeclarationMap.addAll(_assumedDeclarationMap);
+  }
+
+  /// Returns a state corresponding to the state which does _not_ register
+  /// inequivalences. If this state is already not registering inequivalences,
+  /// `this` is returned.
+  CheckingState toMatchingState() {
+    if (!isAsserting) return this;
+    return createSubState(isAsserting: false);
+  }
+
+  /// Returns that value that should be used as the result value when
+  /// inequivalence are found.
+  ///
+  /// See [EquivalenceVisitor.resultOnInequivalence] for details.
+  bool get resultOnInequivalence => isAsserting;
+
+  /// Map of [Reference]s that are assumed to be equivalent. The keys are
+  /// the [Reference]s on the left side of the equivalence relation.
+  UnionFind<Reference> _assumedReferences;
+
+  /// Returns `true` if [a] and [b] are currently assumed to be equivalent.
+  bool checkAssumedReferences(Reference? a, Reference? b) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) return false;
+    return _assumedReferences.valuesInSameSet(a, b);
+  }
+
+  /// Assume that [a] and [b] are equivalent, if possible.
+  ///
+  /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+  /// is not the case if either [a] or [b] is `null`.
+  bool assumeReferences(Reference? a, Reference? b) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) return false;
+    _assumedReferences.unionOfValues(a, b);
+    return true;
+  }
+
+  /// Map of declarations that are assumed to be equivalent.
+  Map<dynamic, dynamic> _assumedDeclarationMap = {};
+
+  /// Returns `true` if [a] and [b] are currently assumed to be equivalent.
+  bool checkAssumedDeclarations(dynamic a, dynamic b) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) return false;
+    return _assumedDeclarationMap.containsKey(a) &&
+        _assumedDeclarationMap[a] == b;
+  }
+
+  /// Assume that [a] and [b] are equivalent, if possible.
+  ///
+  /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+  /// would not be the case if [a] is already assumed to be equivalent to
+  /// another declaration.
+  bool assumeDeclarations(dynamic a, dynamic b) {
+    if (identical(a, b)) return true;
+    if (a == null || b == null) return false;
+    if (_assumedDeclarationMap.containsKey(a)) {
+      return _assumedDeclarationMap[a] == b;
+    } else {
+      _assumedDeclarationMap[a] = b;
+      return true;
+    }
+  }
+
+  /// The currently visited node or property.
+  State? _currentState;
+
+  /// Enters a new property state of a property named [propertyName].
+  void pushPropertyState(String propertyName) {
+    _currentState = new PropertyState(propertyName, _currentState);
+  }
+
+  /// Enters a new node state of nodes [a] and [b].
+  void pushNodeState(Node a, Node b) {
+    _currentState = new NodeState(a, b, _currentState);
+  }
+
+  /// Leaves the current node or property.
+  void popState() {
+    _currentState = _currentState?.parent;
+  }
+
+  /// List of registered inequivalences.
+  List<Inequivalence> _inequivalences = [];
+
+  /// Registers the inequivalence [message] on [propertyName].
+  void registerInequivalence(String propertyName, String message) {
+    _inequivalences.add(new Inequivalence(
+        new PropertyState(propertyName, _currentState), message));
+  }
+
+  /// Returns `true` if inequivalences have been registered.
+  bool get hasInequivalences => _inequivalences.isNotEmpty;
+
+  /// Returns the [EquivalenceResult] for the registered inequivalences. If
+  /// [hasInequivalences] is `true`, the result is marked has having
+  /// inequivalences, even when none have been registered.
+  EquivalenceResult toResult({bool hasInequivalences: false}) =>
+      new EquivalenceResult(
+          hasInequivalences: hasInequivalences,
+          registeredInequivalences: _inequivalences.toList());
+}
+
+/// The result of performing equivalence checking.
+class EquivalenceResult {
+  final bool hasInequivalences;
+  final List<Inequivalence> registeredInequivalences;
+
+  EquivalenceResult(
+      {this.hasInequivalences: false, required this.registeredInequivalences});
+
+  bool get isEquivalent =>
+      !hasInequivalences && registeredInequivalences.isEmpty;
+
+  @override
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    for (Inequivalence inequivalence in registeredInequivalences) {
+      sb.writeln(inequivalence);
+    }
+    return sb.toString();
+  }
+}
+
+/// A registered inequivalence holding the [state] at which is was found and
+/// details about the inequivalence.
+class Inequivalence {
+  final State state;
+  final String message;
+
+  Inequivalence(this.state, this.message);
+
+  @override
+  String toString() {
+    List<State> states = [];
+    State? state = this.state;
+    while (state != null) {
+      states.add(state);
+      state = state.parent;
+    }
+    StringBuffer sb = new StringBuffer();
+    sb.writeln(message);
+    String indent = ' ';
+    for (State state in states.reversed) {
+      if (state is NodeState) {
+        sb.writeln();
+        sb.write(indent);
+        indent = ' $indent';
+        if (state.a.runtimeType == state.b.runtimeType) {
+          if (state.a is NamedNode) {
+            sb.write(state.a.runtimeType);
+            sb.write('(');
+            sb.write(state.a.toText(defaultAstTextStrategy));
+            sb.write(')');
+          } else {
+            sb.write(state.a.runtimeType);
+          }
+        } else {
+          sb.write('(${state.a.runtimeType}/${state.b.runtimeType})');
+        }
+      } else if (state is PropertyState) {
+        sb.write('.${state.name}');
+      } else {
+        throw new UnsupportedError('Unexpected state ${state.runtimeType}');
+      }
+    }
+    return sb.toString();
+  }
+}
+
+/// Enum for different kinds of [ReferenceName]s.
+enum ReferenceNameKind {
+  /// A reference name without information.
+  Unknown,
+
+  /// A reference name of a library.
+  Library,
+
+  /// A reference name of a class or extension.
+  Declaration,
+
+  /// A reference name of a typedef or member.
+  Member,
+}
+
+/// Abstract representation of a [Reference] or [CanonicalName].
+///
+/// This is used to determine nominality of [Reference]s consistently,
+/// regardless of whether the [Reference] has an attached node or canonical
+/// name.
+class ReferenceName {
+  final ReferenceNameKind kind;
+  final ReferenceName? parent;
+  final String? name;
+  final String? uri;
+
+  ReferenceName.internal(this.kind, this.name, [this.parent, this.uri]);
+
+  factory ReferenceName.fromNamedNode(NamedNode node) {
+    if (node is Library) {
+      return new ReferenceName.internal(
+          ReferenceNameKind.Library, node.importUri.toString());
+    } else if (node is Extension) {
+      return new ReferenceName.internal(ReferenceNameKind.Declaration,
+          node.name, new ReferenceName.fromNamedNode(node.enclosingLibrary));
+    } else if (node is Class) {
+      return new ReferenceName.internal(ReferenceNameKind.Declaration,
+          node.name, new ReferenceName.fromNamedNode(node.enclosingLibrary));
+    } else if (node is Typedef) {
+      return new ReferenceName.internal(ReferenceNameKind.Member, node.name,
+          new ReferenceName.fromNamedNode(node.enclosingLibrary));
+    } else if (node is Member) {
+      Class? enclosingClass = node.enclosingClass;
+      Reference? libraryReference = node.name.libraryName;
+      String? uri;
+      if (libraryReference != null) {
+        Library? library = libraryReference.node as Library?;
+        if (library != null) {
+          uri = library.importUri.toString();
+        } else {
+          uri = libraryReference.canonicalName?.name;
+        }
+      }
+      if (enclosingClass != null) {
+        return new ReferenceName.internal(
+            ReferenceNameKind.Member,
+            node.name.text,
+            new ReferenceName.fromNamedNode(enclosingClass),
+            uri);
+      } else {
+        return new ReferenceName.internal(
+            ReferenceNameKind.Member,
+            node.name.text,
+            new ReferenceName.fromNamedNode(node.enclosingLibrary),
+            uri);
+      }
+    } else {
+      throw new ArgumentError(
+          'Unexpected named node ${node} (${node.runtimeType})');
+    }
+  }
+
+  factory ReferenceName.fromCanonicalName(CanonicalName canonicalName) {
+    List<CanonicalName> parents = [];
+    CanonicalName? parent = canonicalName;
+    while (parent != null) {
+      parents.add(parent);
+      parent = parent.parent;
+    }
+    parents = parents.reversed.toList();
+    ReferenceName? referenceName;
+    ReferenceNameKind kind = ReferenceNameKind.Declaration;
+    for (int index = 1; index < parents.length; index++) {
+      if (index == 1) {
+        // Library reference.
+        referenceName = new ReferenceName.internal(
+            ReferenceNameKind.Library, parents[index].name);
+      } else if (CanonicalName.isSymbolicName(parents[index].name)) {
+        // Skip symbolic names
+        kind = ReferenceNameKind.Member;
+      } else {
+        if (index + 2 == parents.length) {
+          // This is a private name.
+          referenceName = new ReferenceName.internal(ReferenceNameKind.Member,
+              parents[index + 1].name, referenceName, parents[index].name);
+          break;
+        } else {
+          referenceName = new ReferenceName.internal(
+              kind, parents[index].name, referenceName);
+        }
+      }
+    }
+    return referenceName ??
+        new ReferenceName.internal(ReferenceNameKind.Unknown, null);
+  }
+
+  String? get libraryUri {
+    if (kind == ReferenceNameKind.Library) {
+      return name;
+    } else {
+      return parent?.libraryUri;
+    }
+  }
+
+  String? get declarationName {
+    if (kind == ReferenceNameKind.Declaration) {
+      return name;
+    } else {
+      return parent?.declarationName;
+    }
+  }
+
+  String? get memberName {
+    if (kind == ReferenceNameKind.Member) {
+      return name;
+    }
+    return null;
+  }
+
+  String? get memberUri {
+    if (kind == ReferenceNameKind.Member) {
+      return uri;
+    }
+    return null;
+  }
+
+  static ReferenceName? fromReference(Reference? reference) {
+    if (reference == null) {
+      return null;
+    }
+    NamedNode? node = reference.node;
+    if (node != null) {
+      return new ReferenceName.fromNamedNode(node);
+    }
+    CanonicalName? canonicalName = reference.canonicalName;
+    if (canonicalName != null) {
+      return new ReferenceName.fromCanonicalName(canonicalName);
+    }
+    return new ReferenceName.internal(ReferenceNameKind.Unknown, null);
+  }
+
+  @override
+  int get hashCode =>
+      name.hashCode * 13 + uri.hashCode * 17 + parent.hashCode * 19;
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is ReferenceName &&
+        name == other.name &&
+        uri == other.uri &&
+        parent == other.parent;
+  }
+
+  @override
+  String toString() {
+    if (parent != null) {
+      return '${parent}/$name';
+    } else if (name != null) {
+      return '/$name';
+    } else {
+      return '<null>';
+    }
+  }
+}
diff --git a/pkg/kernel/lib/src/heap.dart b/pkg/kernel/lib/src/heap.dart
index ecb3f0a..5cbeeab 100644
--- a/pkg/kernel/lib/src/heap.dart
+++ b/pkg/kernel/lib/src/heap.dart
@@ -12,7 +12,7 @@
 
   void add(T item) {
     int index = _items.length;
-    _items.length += 1;
+    _items.add(item);
     while (index > 0) {
       T parent = _items[_parentIndex(index)];
       if (sortsBefore(parent, item)) break;
diff --git a/pkg/kernel/lib/src/union_find.dart b/pkg/kernel/lib/src/union_find.dart
new file mode 100644
index 0000000..4dffab0
--- /dev/null
+++ b/pkg/kernel/lib/src/union_find.dart
@@ -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.
+
+import 'dart:collection';
+
+class UnionFindNode<T> {
+  final T value;
+  UnionFindNode<T>? parent;
+
+  UnionFindNode(this.value);
+}
+
+class UnionFind<T> {
+  final bool _useIdentity;
+  final Map<T, UnionFindNode<T>> _nodeMap;
+
+  UnionFind({bool useIdentity: false})
+      : _nodeMap = useIdentity ? new LinkedHashMap.identity() : {},
+        _useIdentity = useIdentity;
+
+  UnionFind<T> clone() {
+    UnionFind<T> newUnionFind = new UnionFind<T>(useIdentity: _useIdentity);
+    Map<UnionFindNode<T>, UnionFindNode<T>> oldToNewMap = {};
+
+    UnionFindNode<T> getNewNode(UnionFindNode<T> oldNode) {
+      UnionFindNode<T> newNode = newUnionFind[oldNode.value];
+      return oldToNewMap[oldNode] = newNode;
+    }
+
+    for (UnionFindNode<T> oldNode in _nodeMap.values) {
+      UnionFindNode<T> newNode = getNewNode(oldNode);
+      if (oldNode.parent != null) {
+        newNode.parent = getNewNode(oldNode.parent!);
+      }
+    }
+    return newUnionFind;
+  }
+
+  UnionFindNode<T> operator [](T value) =>
+      _nodeMap[value] ??= new UnionFindNode<T>(value);
+
+  Iterable<UnionFindNode<T>> get nodes => _nodeMap.values;
+
+  Iterable<T> get values => nodes.map((n) => n.value);
+
+  UnionFindNode<T> findNode(UnionFindNode<T> node) {
+    if (node.parent != null) {
+      return node.parent = findNode(node.parent!);
+    }
+    return node;
+  }
+
+  void unionOfValues(T a, T b) {
+    unionOfNodes(this[a], this[b]);
+  }
+
+  UnionFindNode<T> unionOfNodes(UnionFindNode<T> a, UnionFindNode<T> b) {
+    UnionFindNode<T> rootA = findNode(a);
+    UnionFindNode<T> rootB = findNode(b);
+    if (rootA != rootB) {
+      return rootB.parent = rootA;
+    }
+    return rootA;
+  }
+
+  bool valuesInSameSet(T a, T b) {
+    UnionFindNode<T>? node1 = _nodeMap[a];
+    UnionFindNode<T>? node2 = _nodeMap[b];
+    return node1 != null && node2 != null && nodesInSameSet(node1, node2);
+  }
+
+  bool nodesInSameSet(UnionFindNode<T> a, UnionFindNode<T> b) {
+    return findNode(a) == findNode(b);
+  }
+}
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 90615e8..55a69cd 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -74,7 +74,7 @@
 }
 
 abstract class DiagnosticReporter<M, C> {
-  void report(M message, int charOffset, int length, Uri fileUri,
+  void report(M message, int charOffset, int length, Uri? fileUri,
       {List<C> context});
 }
 
@@ -256,7 +256,7 @@
       Map<String, String>? environmentDefines,
       DiagnosticReporter diagnosticReporter,
       ReferenceFromIndex? referenceFromIndex,
-      {void logger(String msg),
+      {void Function(String msg)? logger,
       ChangedStructureNotifier? changedStructureNotifier});
 
   /// Perform target-specific modular transformations on the given program.
@@ -354,7 +354,7 @@
   /// synthesized top level functions.
   int get enabledConstructorTearOffLowerings;
 
-  /// Returns `true` if lowering of constructor tear offs is enabled.
+  /// Returns `true` if lowering of generative constructor tear offs is enabled.
   ///
   /// This is determined by the [enabledConstructorTearOffLowerings] mask.
   bool get isConstructorTearOffLoweringEnabled =>
@@ -362,6 +362,23 @@
           ConstructorTearOffLowering.constructors) !=
       0;
 
+  /// Returns `true` if lowering of non-redirecting factory tear offs is
+  /// enabled.
+  ///
+  /// This is determined by the [enabledConstructorTearOffLowerings] mask.
+  bool get isFactoryTearOffLoweringEnabled =>
+      (enabledConstructorTearOffLowerings &
+          ConstructorTearOffLowering.factories) !=
+      0;
+
+  /// Returns `true` if lowering of redirecting factory tear offs is enabled.
+  ///
+  /// This is determined by the [enabledConstructorTearOffLowerings] mask.
+  bool get isRedirectingFactoryTearOffLoweringEnabled =>
+      (enabledConstructorTearOffLowerings &
+          ConstructorTearOffLowering.redirectingFactories) !=
+      0;
+
   /// Returns `true` if lowering of typedef tear offs is enabled.
   ///
   /// This is determined by the [enabledConstructorTearOffLowerings] mask.
@@ -409,8 +426,6 @@
   /// with the accessed getter or field as the interface target.
   bool get supportsExplicitGetterCalls;
 
-  bool get supportsNewMethodInvocationEncoding;
-
   /// Builds an expression that instantiates an [Invocation] that can be passed
   /// to [noSuchMethod].
   Expression instantiateInvocation(CoreTypes coreTypes, Expression receiver,
@@ -478,9 +493,6 @@
       !flags.forceNoExplicitGetterCallsForTesting;
 
   @override
-  bool get supportsNewMethodInvocationEncoding => true;
-
-  @override
   int get enabledConstructorTearOffLowerings =>
       flags.forceConstructorTearOffLoweringForTesting;
 
@@ -635,13 +647,19 @@
 }
 
 class ConstructorTearOffLowering {
-  /// Create top level functions to use as tear offs of constructors.
+  /// Create static functions to use as tear offs of generative constructors.
   static const int constructors = 1 << 0;
 
-  /// Create top level functions to use as tear offs of non trivial redirecting
-  /// factory constructors and typedefs.
-  static const int typedefs = 1 << 1;
+  /// Create static functions to use as tear offs of non-redirecting factories.
+  static const int factories = 1 << 1;
+
+  /// Create static functions to use as tear offs of redirecting factories.
+  static const int redirectingFactories = 1 << 2;
+
+  /// Create top level functions to use as tear offs of typedefs that are not
+  /// proper renames.
+  static const int typedefs = 1 << 3;
 
   static const int none = 0;
-  static const int all = (1 << 2) - 1;
+  static const int all = (1 << 4) - 1;
 }
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 197bdfa..eacfa1e 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1243,20 +1243,13 @@
         name: node.name, initializers: node.initializers);
   }
 
-  visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+  visitRedirectingFactory(RedirectingFactory node) {
     writeAnnotationList(node.annotations);
     writeIndentation();
     writeModifier(node.isExternal, 'external');
     writeModifier(node.isConst, 'const');
     writeWord('redirecting_factory');
-
-    // ignore: unnecessary_null_comparison
-    if (node.name != null) {
-      writeName(node.name);
-    }
-    writeTypeParameterList(node.typeParameters);
-    writeParameterList(node.positionalParameters, node.namedParameters,
-        node.requiredParameterCount);
+    writeFunction(node.function, name: node.name);
     writeSpaced('=');
     writeMemberReferenceFromReference(node.targetReference!);
     if (node.typeArguments.isNotEmpty) {
@@ -1327,7 +1320,7 @@
     node.fields.forEach(writeNode);
     node.constructors.forEach(writeNode);
     node.procedures.forEach(writeNode);
-    node.redirectingFactoryConstructors.forEach(writeNode);
+    node.redirectingFactories.forEach(writeNode);
     --indentation;
     writeIndentation();
     endLine('}');
@@ -1545,23 +1538,6 @@
     writeSymbol('null');
   }
 
-  visitMethodInvocation(MethodInvocation node) {
-    writeExpression(node.receiver, Precedence.PRIMARY);
-    writeSymbol('.');
-    writeInterfaceTarget(node.name, node.interfaceTargetReference);
-    List<String> flags = <String>[];
-    if (node.isInvariant) {
-      flags.add('Invariant');
-    }
-    if (node.isBoundsSafe) {
-      flags.add('BoundsSafe');
-    }
-    if (flags.isNotEmpty) {
-      write('{${flags.join(',')}}');
-    }
-    writeNode(node.arguments);
-  }
-
   visitSuperMethodInvocation(SuperMethodInvocation node) {
     writeWord('super');
     writeSymbol('.');
@@ -1992,12 +1968,6 @@
     writeSymbol('}');
   }
 
-  visitPropertyGet(PropertyGet node) {
-    writeExpression(node.receiver, Precedence.PRIMARY);
-    writeSymbol('.');
-    writeInterfaceTarget(node.name, node.interfaceTargetReference);
-  }
-
   visitDynamicSet(DynamicSet node) {
     writeExpression(node.receiver, Precedence.PRIMARY);
     _writeDynamicAccessKind(node.kind);
@@ -2015,14 +1985,6 @@
     writeExpression(node.value);
   }
 
-  visitPropertySet(PropertySet node) {
-    writeExpression(node.receiver, Precedence.PRIMARY);
-    writeSymbol('.');
-    writeInterfaceTarget(node.name, node.interfaceTargetReference);
-    writeSpaced('=');
-    writeExpression(node.value);
-  }
-
   visitSuperPropertyGet(SuperPropertyGet node) {
     writeWord('super');
     writeSymbol('.');
@@ -2052,7 +2014,25 @@
   }
 
   visitConstructorTearOff(ConstructorTearOff node) {
-    writeMemberReferenceFromReference(node.constructorReference);
+    writeMemberReferenceFromReference(node.targetReference);
+  }
+
+  visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+    writeMemberReferenceFromReference(node.targetReference);
+  }
+
+  visitTypedefTearOff(TypedefTearOff node) {
+    writeTypeParameterList(node.typeParameters);
+    state = SYMBOL;
+    writeSymbol('.(');
+    writeNode(node.expression);
+    if (node.typeArguments.isNotEmpty) {
+      writeSymbol('<');
+      writeList(node.typeArguments, writeType);
+      writeSymbol('>');
+    }
+    writeSymbol(')');
+    state = WORD;
   }
 
   visitExpressionStatement(ExpressionStatement node) {
@@ -2667,9 +2647,14 @@
     writeIndentation();
     writeConstantReference(node);
     writeSpaced('=');
-    writeWord('partial-instantiation');
+    writeWord('instantiation');
     writeSpace();
-    writeMemberReferenceFromReference(node.tearOffConstant.memberReference);
+    Constant tearOffConstant = node.tearOffConstant;
+    if (tearOffConstant is TearOffConstant) {
+      writeMemberReferenceFromReference(tearOffConstant.targetReference);
+    } else {
+      writeConstantReference(tearOffConstant);
+    }
     writeSpace();
     writeSymbol('<');
     writeList(node.types, writeType);
@@ -2688,9 +2673,29 @@
     writeIndentation();
     writeConstantReference(node);
     writeSpaced('=');
-    writeWord('tearoff');
+    writeWord('static-tearoff');
     writeSpace();
-    writeMemberReferenceFromReference(node.memberReference);
+    writeMemberReferenceFromReference(node.targetReference);
+    endLine();
+  }
+
+  visitTypedefTearOffConstant(TypedefTearOffConstant node) {
+    writeIndentation();
+    writeConstantReference(node);
+    writeSpaced('=');
+    writeWord('typedef-tearoff');
+    writeSpace();
+    writeTypeParameterList(node.parameters);
+    state = SYMBOL;
+    writeSymbol('.(');
+    writeConstantReference(node.tearOffConstant);
+    if (node.types.isNotEmpty) {
+      writeSymbol('<');
+      writeList(node.types, writeType);
+      writeSymbol('>');
+    }
+    writeSymbol(')');
+    state = WORD;
     endLine();
   }
 
@@ -2704,6 +2709,27 @@
     endLine();
   }
 
+  visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
+    writeIndentation();
+    writeConstantReference(node);
+    writeSpaced('=');
+    writeWord('constructor-tearoff');
+    writeSpace();
+    writeMemberReferenceFromReference(node.targetReference);
+    endLine();
+  }
+
+  visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node) {
+    writeIndentation();
+    writeConstantReference(node);
+    writeSpaced('=');
+    writeWord('redirecting-factory-tearoff');
+    writeSpace();
+    writeMemberReferenceFromReference(node.targetReference);
+    endLine();
+  }
+
   defaultNode(Node node) {
     write('<${node.runtimeType}>');
   }
@@ -2768,9 +2794,6 @@
   int visitInvalidExpression(InvalidExpression node) => CALLEE;
 
   @override
-  int visitMethodInvocation(MethodInvocation node) => CALLEE;
-
-  @override
   int visitInstanceInvocation(InstanceInvocation node) => CALLEE;
 
   @override
@@ -2874,9 +2897,6 @@
   int visitVariableSet(VariableSet node) => EXPRESSION;
 
   @override
-  int visitPropertyGet(PropertyGet node) => PRIMARY;
-
-  @override
   int visitInstanceGet(InstanceGet node) => PRIMARY;
 
   @override
@@ -2889,9 +2909,6 @@
   int visitFunctionTearOff(FunctionTearOff node) => PRIMARY;
 
   @override
-  int visitPropertySet(PropertySet node) => EXPRESSION;
-
-  @override
   int visitSuperPropertyGet(SuperPropertyGet node) => PRIMARY;
 
   @override
@@ -2910,6 +2927,9 @@
   int visitConstructorTearOff(ConstructorTearOff node) => PRIMARY;
 
   @override
+  int visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) => PRIMARY;
+
+  @override
   int visitTypedefTearOff(TypedefTearOff node) => EXPRESSION;
 
   @override
diff --git a/pkg/compiler/lib/src/ir/debug.dart b/pkg/kernel/lib/text/debug_printer.dart
similarity index 93%
rename from pkg/compiler/lib/src/ir/debug.dart
rename to pkg/kernel/lib/text/debug_printer.dart
index 3b9e11a..fa700c1 100644
--- a/pkg/compiler/lib/src/ir/debug.dart
+++ b/pkg/kernel/lib/text/debug_printer.dart
@@ -8,14 +8,14 @@
 
 import 'package:kernel/ast.dart';
 
-import '../util/util.dart' show Indentation, Tagging;
+import 'indentation.dart' show Indentation, Tagging;
 
 class DebugPrinter extends Visitor<void>
     with Indentation, Tagging<Node>, VisitorVoidMixin {
   @override
   StringBuffer sb = new StringBuffer();
 
-  void visitNodeWithChildren(Node node, String type, [Map params]) {
+  void visitNodeWithChildren(Node node, String type, [Map? params]) {
     openNode(node, type, params);
     node.visitChildren(this);
     closeNode();
@@ -102,7 +102,7 @@
 
   /// Pretty-prints given node tree into string.
   static String prettyPrint(Node node) {
-    var p = new DebugPrinter();
+    DebugPrinter p = new DebugPrinter();
     node.accept(p);
     return p.sb.toString();
   }
diff --git a/pkg/compiler/lib/src/util/indentation.dart b/pkg/kernel/lib/text/indentation.dart
similarity index 88%
rename from pkg/compiler/lib/src/util/indentation.dart
rename to pkg/kernel/lib/text/indentation.dart
index fb7cc21..4c9c344 100644
--- a/pkg/compiler/lib/src/util/indentation.dart
+++ b/pkg/kernel/lib/text/indentation.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.
 
-part of dart2js.util;
-
 /// Indentation utility class. Should be used as a mixin in most cases.
 class Indentation {
   /// The current indentation string.
@@ -46,7 +44,7 @@
   /// upon return of [f] and returning its result.
   indentBlock(Function f) {
     indentMore();
-    var result = f();
+    dynamic result = f();
     indentLess();
     return result;
   }
@@ -54,19 +52,17 @@
 
 abstract class Tagging<N> implements Indentation {
   StringBuffer sb = new StringBuffer();
-  Link<String> tagStack = const Link<String>();
+  List<String> tagStack = [];
 
   void pushTag(String tag) {
-    tagStack = tagStack.prepend(tag);
+    tagStack.add(tag);
     indentMore();
   }
 
   String popTag() {
     assert(!tagStack.isEmpty);
-    String tag = tagStack.head;
-    tagStack = tagStack.tail;
     indentLess();
-    return tag;
+    return tagStack.removeLast();
   }
 
   /// Adds given string to result string.
@@ -81,7 +77,7 @@
   /// The method "opens" the node, meaning that all output after calling
   /// this method and before calling closeNode() will represent contents
   /// of given node.
-  void openNode(N node, String type, [Map params]) {
+  void openNode(N node, String type, [Map? params]) {
     if (params == null) params = new Map();
     addCurrentIndent();
     sb.write("<");
@@ -92,7 +88,7 @@
   }
 
   /// Adds given node to result string.
-  void openAndCloseNode(N node, String type, [Map params]) {
+  void openAndCloseNode(N node, String type, [Map? params]) {
     if (params == null) params = {};
     addCurrentIndent();
     sb.write("<");
@@ -110,7 +106,7 @@
     sb.write(">\n");
   }
 
-  void addTypeWithParams(String type, [Map params]) {
+  void addTypeWithParams(String type, [Map? params]) {
     if (params == null) params = new Map();
     sb.write("${type}");
     params.forEach((k, v) {
@@ -133,5 +129,5 @@
   }
 
   /// Converts a parameter value into a string.
-  String valueToString(var value) => value;
+  String valueToString(dynamic value) => value;
 }
diff --git a/pkg/kernel/lib/text/serializer_combinators.dart b/pkg/kernel/lib/text/serializer_combinators.dart
index 7af498e..aae9ea2 100644
--- a/pkg/kernel/lib/text/serializer_combinators.dart
+++ b/pkg/kernel/lib/text/serializer_combinators.dart
@@ -714,7 +714,7 @@
 /// Serializes an object and uses it as a binder for the name that is retrieved
 /// from the object using [nameGetter] and (temporarily) modified using
 /// [nameSetter].  The binder is added to the enclosing environment.
-class Binder<T extends Node> extends TextSerializer<Tuple2<String, T>> {
+class Binder<T extends Node> extends TextSerializer<Tuple2<String?, T>> {
   final Tuple2Serializer<String, T> namedContents;
 
   Binder(TextSerializer<T> contents)
@@ -733,13 +733,13 @@
     return new Tuple2(name, object);
   }
 
-  void writeTo(StringBuffer buffer, Tuple2<String, T> namedObject,
+  void writeTo(StringBuffer buffer, Tuple2<String?, T> namedObject,
       SerializationState? state) {
     if (state == null) {
       throw StateError(
           "No serialization state provided for ${runtimeType}.writeTo.");
     }
-    String nameClue = namedObject.first;
+    String? nameClue = namedObject.first;
     T object = namedObject.second;
     String distinctName =
         state.environment.addBinder(object, nameClue: nameClue);
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index 0c4f26e..5d740c4 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -70,8 +70,6 @@
 
   String visitLet(Let _) => "let";
 
-  String visitPropertyGet(PropertyGet _) => "get-prop";
-  String visitPropertySet(PropertySet _) => "set-prop";
   String visitInstanceGet(InstanceGet _) => "get-instance";
   String visitInstanceSet(InstanceSet _) => "set-instance";
   String visitDynamicGet(DynamicGet _) => "get-dynamic";
@@ -80,7 +78,6 @@
   String visitFunctionTearOff(FunctionTearOff _) => "tearoff-function";
   String visitSuperPropertyGet(SuperPropertyGet _) => "get-super";
   String visitSuperPropertySet(SuperPropertySet _) => "set-super";
-  String visitMethodInvocation(MethodInvocation _) => "invoke-method";
   String visitInstanceInvocation(InstanceInvocation _) => "invoke-instance";
   String visitInstanceGetterInvocation(InstanceGetterInvocation _) =>
       "invoke-instance-getter";
@@ -97,6 +94,10 @@
   String visitStaticGet(StaticGet _) => "get-static";
   String visitStaticSet(StaticSet _) => "set-static";
   String visitStaticTearOff(StaticTearOff _) => "tearoff-static";
+  String visitConstructorTearOff(ConstructorTearOff _) => "tearoff-constructor";
+  String visitRedirectingFactoryTearOff(RedirectingFactoryTearOff _) =>
+      "tearoff-redirecting-factory";
+  String visitTypedefTearOff(TypedefTearOff _) => "tearoff-typedef";
   String visitStaticInvocation(StaticInvocation expression) {
     return expression.isConst ? "invoke-const-static" : "invoke-static";
   }
@@ -415,33 +416,6 @@
   return new Let(tuple.first, tuple.second);
 }
 
-TextSerializer<PropertyGet> propertyGetSerializer = new Wrapped(
-    unwrapPropertyGet,
-    wrapPropertyGet,
-    new Tuple2Serializer(expressionSerializer, nameSerializer));
-
-Tuple2<Expression, Name> unwrapPropertyGet(PropertyGet expression) {
-  return new Tuple2(expression.receiver, expression.name);
-}
-
-PropertyGet wrapPropertyGet(Tuple2<Expression, Name> tuple) {
-  return new PropertyGet(tuple.first, tuple.second);
-}
-
-TextSerializer<PropertySet> propertySetSerializer = new Wrapped(
-    unwrapPropertySet,
-    wrapPropertySet,
-    new Tuple3Serializer(
-        expressionSerializer, nameSerializer, expressionSerializer));
-
-Tuple3<Expression, Name, Expression> unwrapPropertySet(PropertySet expression) {
-  return new Tuple3(expression.receiver, expression.name, expression.value);
-}
-
-PropertySet wrapPropertySet(Tuple3<Expression, Name, Expression> tuple) {
-  return new PropertySet(tuple.first, tuple.second, tuple.third);
-}
-
 TextSerializer<InstanceGet> instanceGetSerializer = new Wrapped<
         Tuple5<InstanceAccessKind, Expression, Name, CanonicalName, DartType>,
         InstanceGet>(
@@ -586,22 +560,6 @@
   return new SuperPropertySet(tuple.first, tuple.second, null);
 }
 
-TextSerializer<MethodInvocation> methodInvocationSerializer = new Wrapped(
-    unwrapMethodInvocation,
-    wrapMethodInvocation,
-    new Tuple3Serializer(
-        expressionSerializer, nameSerializer, argumentsSerializer));
-
-Tuple3<Expression, Name, Arguments> unwrapMethodInvocation(
-    MethodInvocation expression) {
-  return new Tuple3(expression.receiver, expression.name, expression.arguments);
-}
-
-MethodInvocation wrapMethodInvocation(
-    Tuple3<Expression, Name, Arguments> tuple) {
-  return new MethodInvocation(tuple.first, tuple.second, tuple.third);
-}
-
 const Map<InstanceAccessKind, String> instanceAccessKindToName = const {
   InstanceAccessKind.Instance: "instance",
   InstanceAccessKind.Object: "object",
@@ -931,6 +889,55 @@
   return new StaticTearOff.byReference(name.reference);
 }
 
+const TextSerializer<ConstructorTearOff> constructorTearOffSerializer =
+    const Wrapped(unwrapConstructorTearOff, wrapConstructorTearOff,
+        canonicalNameSerializer);
+
+CanonicalName unwrapConstructorTearOff(ConstructorTearOff expression) {
+  return expression.targetReference.canonicalName!;
+}
+
+ConstructorTearOff wrapConstructorTearOff(CanonicalName name) {
+  return new ConstructorTearOff.byReference(name.reference);
+}
+
+const TextSerializer<RedirectingFactoryTearOff>
+    redirectingFactoryTearOffSerializer = const Wrapped(
+        unwrapRedirectingFactoryTearOff,
+        wrapRedirectingFactoryTearOff,
+        canonicalNameSerializer);
+
+CanonicalName unwrapRedirectingFactoryTearOff(
+    RedirectingFactoryTearOff expression) {
+  return expression.targetReference.canonicalName!;
+}
+
+RedirectingFactoryTearOff wrapRedirectingFactoryTearOff(CanonicalName name) {
+  return new RedirectingFactoryTearOff.byReference(name.reference);
+}
+
+final TextSerializer<TypedefTearOff> typedefTearOffSerializer = new Wrapped<
+        Tuple2<List<TypeParameter>, Tuple2<Expression, List<DartType>>>,
+        TypedefTearOff>(
+    unwrapTypedefTearOff,
+    wrapTypedefTearOff,
+    Bind(
+        typeParametersSerializer,
+        Tuple2Serializer(
+            expressionSerializer, ListSerializer(dartTypeSerializer))));
+
+Tuple2<List<TypeParameter>, Tuple2<Expression, List<DartType>>>
+    unwrapTypedefTearOff(TypedefTearOff node) {
+  return new Tuple2(
+      node.typeParameters, new Tuple2(node.expression, node.typeArguments));
+}
+
+TypedefTearOff wrapTypedefTearOff(
+    Tuple2<List<TypeParameter>, Tuple2<Expression, List<DartType>>> tuple) {
+  return new TypedefTearOff(
+      tuple.first, tuple.second.first, tuple.second.second);
+}
+
 TextSerializer<StaticSet> staticSetSerializer = new Wrapped(
     unwrapStaticSet,
     wrapStaticSet,
@@ -1653,7 +1660,7 @@
         (ls) => Tuple2(ls, ls.body),
         (t) => t.first..body = t.second,
         Bind(
-            Wrapped<Tuple2<String, LabeledStatement>, LabeledStatement>(
+            Wrapped<Tuple2<String?, LabeledStatement>, LabeledStatement>(
                 (ls) => Tuple2("L", ls),
                 (t) => t.second,
                 Binder(Wrapped(
@@ -1722,7 +1729,7 @@
 }
 
 TextSerializer<SwitchCase> switchCaseCaseSerializer =
-    Wrapped<Tuple2<String, SwitchCase>, SwitchCase>(
+    Wrapped<Tuple2<String?, SwitchCase>, SwitchCase>(
         (w) => Tuple2("L", w),
         (u) => u.second,
         Binder(Wrapped<List<Expression>, SwitchCase>(
@@ -1731,7 +1738,7 @@
             ListSerializer(expressionSerializer))));
 
 TextSerializer<SwitchCase> switchCaseDefaultSerializer = Wrapped<
-        Tuple2<String, SwitchCase>, SwitchCase>(
+        Tuple2<String?, SwitchCase>, SwitchCase>(
     (w) => Tuple2("L", w),
     (u) => u.second,
     Binder(
@@ -1836,8 +1843,7 @@
   Procedure.FlagAbstract: "abstract",
   Procedure.FlagExternal: "external",
   Procedure.FlagConst: "const",
-  Procedure.FlagRedirectingFactoryConstructor:
-      "redirecting-factory-constructor",
+  Procedure.FlagRedirectingFactory: "redirecting-factory-constructor",
   Procedure.FlagExtensionMember: "extension-member",
   Procedure.FlagNonNullableByDefault: "non-nullable-by-default",
   Procedure.FlagSynthetic: "synthetic",
@@ -1906,20 +1912,18 @@
     ListSerializer(
         Case(ConstructorFlagTagger(), convertFlagsMap(constructorFlagToName))));
 
-const Map<int, String> redirectingFactoryConstructorFlagToName = const {
-  RedirectingFactoryConstructor.FlagConst: "const",
-  RedirectingFactoryConstructor.FlagExternal: "external",
-  RedirectingFactoryConstructor.FlagNonNullableByDefault:
-      "non-nullable-by-default",
+const Map<int, String> redirectingFactoryFlagToName = const {
+  RedirectingFactory.FlagConst: "const",
+  RedirectingFactory.FlagExternal: "external",
+  RedirectingFactory.FlagNonNullableByDefault: "non-nullable-by-default",
 };
 
-class RedirectingFactoryConstructorFlagTagger implements Tagger<int> {
-  const RedirectingFactoryConstructorFlagTagger();
+class RedirectingFactoryFlagTagger implements Tagger<int> {
+  const RedirectingFactoryFlagTagger();
 
   String tag(int flag) {
-    return redirectingFactoryConstructorFlagToName[flag] ??
-        (throw StateError(
-            "Unknown RedirectingFactoryConstructor flag value: ${flag}."));
+    return redirectingFactoryFlagToName[flag] ??
+        (throw StateError("Unknown RedirectingFactory flag value: ${flag}."));
   }
 }
 
@@ -1929,8 +1933,8 @@
             .where((f) => f != 0)
             .toList(),
         (u) => u.fold(0, (fs, f) => fs |= f),
-        ListSerializer(Case(RedirectingFactoryConstructorFlagTagger(),
-            convertFlagsMap(redirectingFactoryConstructorFlagToName))));
+        ListSerializer(Case(RedirectingFactoryFlagTagger(),
+            convertFlagsMap(redirectingFactoryFlagToName))));
 
 class MemberTagger implements Tagger<Member> {
   const MemberTagger();
@@ -1940,7 +1944,7 @@
       return node.hasSetter ? "mutable-field" : "immutable-field";
     } else if (node is Constructor) {
       return "constructor";
-    } else if (node is RedirectingFactoryConstructor) {
+    } else if (node is RedirectingFactory) {
       return "redirecting-factory-constructor";
     } else if (node is Procedure) {
       switch (node.kind) {
@@ -2036,57 +2040,25 @@
     Tuple4Serializer(nameSerializer, constructorFlagsSerializer,
         functionNodeWithInitializersSerializer, UriSerializer()));
 
-TextSerializer<RedirectingFactoryConstructor>
-    redirectingFactoryConstructorSerializer
+TextSerializer<RedirectingFactory> redirectingFactoryConstructorSerializer
     // Comment added to direct formatter.
     = Wrapped<
-            Tuple5<
-                Name,
-                int,
-                CanonicalName,
-                Tuple2<
-                    List<TypeParameter>,
-                    Tuple4<List<VariableDeclaration>, List<VariableDeclaration>,
-                        List<VariableDeclaration>, List<DartType>>>,
-                Uri>,
-            RedirectingFactoryConstructor>(
-        (w) => Tuple5(
-            w.name,
-            w.flags,
-            w.targetReference!.canonicalName!,
-            Tuple2(
-                w.typeParameters,
-                Tuple4(
-                    w.positionalParameters
-                        .take(w.requiredParameterCount)
-                        .toList(),
-                    w.positionalParameters
-                        .skip(w.requiredParameterCount)
-                        .toList(),
-                    w.namedParameters,
-                    w.typeArguments)),
-            w.fileUri),
-        (u) => RedirectingFactoryConstructor(u.third.reference,
+            Tuple6<Name, int, FunctionNode, CanonicalName, List<DartType>, Uri>,
+            RedirectingFactory>(
+        (w) => Tuple6(w.name, w.flags, w.function,
+            w.targetReference!.canonicalName!, w.typeArguments, w.fileUri),
+        (u) => RedirectingFactory(u.fourth.reference,
             name: u.first,
-            typeParameters: u.fourth.first,
-            positionalParameters:
-                u.fourth.second.first + u.fourth.second.second,
-            requiredParameterCount: u.fourth.second.first.length,
-            namedParameters: u.fourth.second.third,
-            typeArguments: u.fourth.second.fourth,
-            fileUri: u.fifth)
+            function: u.third,
+            typeArguments: u.fifth,
+            fileUri: u.sixth)
           ..flags = u.second,
-        Tuple5Serializer(
+        Tuple6Serializer(
             nameSerializer,
             redirectingFactoryConstructorFlagsSerializer,
+            functionNodeSerializer,
             CanonicalNameSerializer(),
-            Bind(
-                typeParametersSerializer,
-                Tuple4Serializer(
-                    ListSerializer(variableDeclarationSerializer),
-                    ListSerializer(variableDeclarationSerializer),
-                    ListSerializer(variableDeclarationSerializer),
-                    ListSerializer(dartTypeSerializer))),
+            ListSerializer(dartTypeSerializer),
             UriSerializer()));
 
 Case<Member> memberSerializer = new Case.uninitialized(const MemberTagger());
@@ -2210,7 +2182,14 @@
   String visitStringConstant(StringConstant node) => "const-string";
   String visitSymbolConstant(SymbolConstant node) => "const-symbol";
   String visitStaticTearOffConstant(StaticTearOffConstant node) =>
-      "const-tearoff";
+      "const-tearoff-static";
+  String visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
+      "const-tearoff-constructor";
+  String visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      "const-tearoff-redirecting-factory";
+  String visitTypedefTearOffConstant(TypedefTearOffConstant node) =>
+      "const-tearoff-typedef";
   String visitTypeLiteralConstant(TypeLiteralConstant node) => "const-type";
   String visitUnevaluatedConstant(UnevaluatedConstant node) => "const-expr";
 
@@ -2256,11 +2235,11 @@
     Wrapped<void, NullConstant>((w) => null, (u) => NullConstant(), Nothing());
 
 TextSerializer<InstantiationConstant> instantiationConstantSerializer =
-    Wrapped<Tuple2<TearOffConstant, List<DartType>>, InstantiationConstant>(
+    Wrapped<Tuple2<Constant, List<DartType>>, InstantiationConstant>(
         (w) => Tuple2(w.tearOffConstant, w.types),
         (u) => InstantiationConstant(u.first, u.second),
         Tuple2Serializer(
-            tearOffConstantSerializer, ListSerializer(dartTypeSerializer)));
+            constantSerializer, ListSerializer(dartTypeSerializer)));
 
 TextSerializer<SetConstant> setConstantSerializer =
     Wrapped<Tuple2<DartType, List<Constant>>, SetConstant>(
@@ -2279,12 +2258,48 @@
         (u) => SymbolConstant(u.first, u.second?.reference),
         Tuple2Serializer(DartString(), Optional(CanonicalNameSerializer())));
 
-TextSerializer<StaticTearOffConstant> tearOffConstantSerializer =
+TextSerializer<StaticTearOffConstant> staticTearOffConstantSerializer =
     Wrapped<CanonicalName, StaticTearOffConstant>(
-        (w) => w.memberReference.canonicalName!,
+        (w) => w.targetReference.canonicalName!,
         (u) => StaticTearOffConstant.byReference(u.reference),
         CanonicalNameSerializer());
 
+TextSerializer<ConstructorTearOffConstant>
+    constructorTearOffConstantSerializer =
+    Wrapped<CanonicalName, ConstructorTearOffConstant>(
+        (w) => w.targetReference.canonicalName!,
+        (u) => ConstructorTearOffConstant.byReference(u.reference),
+        CanonicalNameSerializer());
+
+TextSerializer<RedirectingFactoryTearOffConstant>
+    redirectingFactoryTearOffConstantSerializer =
+    Wrapped<CanonicalName, RedirectingFactoryTearOffConstant>(
+        (w) => w.targetReference.canonicalName!,
+        (u) => RedirectingFactoryTearOffConstant.byReference(u.reference),
+        CanonicalNameSerializer());
+
+final TextSerializer<TypedefTearOffConstant> typedefTearOffConstantSerializer =
+    new Wrapped<Tuple2<List<TypeParameter>, Tuple2<Constant, List<DartType>>>,
+            TypedefTearOffConstant>(
+        unwrapTypedefTearOffConstant,
+        wrapTypedefTearOffConstant,
+        Bind(
+            typeParametersSerializer,
+            Tuple2Serializer(
+                constantSerializer, ListSerializer(dartTypeSerializer))));
+
+Tuple2<List<TypeParameter>, Tuple2<Constant, List<DartType>>>
+    unwrapTypedefTearOffConstant(TypedefTearOffConstant node) {
+  return new Tuple2(
+      node.parameters, new Tuple2(node.tearOffConstant, node.types));
+}
+
+TypedefTearOffConstant wrapTypedefTearOffConstant(
+    Tuple2<List<TypeParameter>, Tuple2<Constant, List<DartType>>> tuple) {
+  return new TypedefTearOffConstant(
+      tuple.first, tuple.second.first as TearOffConstant, tuple.second.second);
+}
+
 TextSerializer<TypeLiteralConstant> typeLiteralConstantSerializer =
     Wrapped<DartType, TypeLiteralConstant>(
         (w) => w.type, (u) => TypeLiteralConstant(u), dartTypeSerializer);
@@ -2559,8 +2574,6 @@
     "map": mapLiteralSerializer,
     "const-map": constMapLiteralSerializer,
     "let": letSerializer,
-    "get-prop": propertyGetSerializer,
-    "set-prop": propertySetSerializer,
     "get-instance": instanceGetSerializer,
     "set-instance": instanceSetSerializer,
     "get-dynamic": dynamicGetSerializer,
@@ -2569,7 +2582,6 @@
     "tearoff-function": functionTearOffSerializer,
     "get-super": superPropertyGetSerializer,
     "set-super": superPropertySetSerializer,
-    "invoke-method": methodInvocationSerializer,
     "invoke-instance": instanceInvocationSerializer,
     "invoke-instance-getter": instanceGetterInvocationSerializer,
     "invoke-dynamic": dynamicInvocationSerializer,
@@ -2582,7 +2594,10 @@
     "set-var": variableSetSerializer,
     "get-static": staticGetSerializer,
     "set-static": staticSetSerializer,
-    "tearoff-static": staticGetSerializer,
+    "tearoff-static": staticTearOffSerializer,
+    "tearoff-constructor": constructorTearOffSerializer,
+    "tearoff-redirecting-factory": redirectingFactoryTearOffSerializer,
+    "tearoff-typedef": typedefTearOffSerializer,
     "invoke-static": staticInvocationSerializer,
     "invoke-const-static": constStaticInvocationSerializer,
     "invoke-constructor": constructorInvocationSerializer,
@@ -2659,7 +2674,11 @@
     "const-set": setConstantSerializer,
     "const-string": stringConstantSerializer,
     "const-symbol": symbolConstantSerializer,
-    "const-tearoff": tearOffConstantSerializer,
+    "const-tearoff-static": staticTearOffConstantSerializer,
+    "const-tearoff-constructor": constructorTearOffConstantSerializer,
+    "const-tearoff-redirecting-factory":
+        redirectingFactoryTearOffConstantSerializer,
+    "const-tearoff-typedef": typedefTearOffConstantSerializer,
     "const-type": typeLiteralConstantSerializer,
     "const-expr": unevaluatedConstantSerializer,
     "const-object": instanceConstantSerializer,
diff --git a/pkg/kernel/lib/transformations/async.dart b/pkg/kernel/lib/transformations/async.dart
index b18d98f..43fca30 100644
--- a/pkg/kernel/lib/transformations/async.dart
+++ b/pkg/kernel/lib/transformations/async.dart
@@ -115,21 +115,40 @@
     return result;
   }
 
+  // Wraps VariableGet in an unsafeCast if `type` isn't dynamic.
+  Expression unsafeCastVariableGet(
+      VariableDeclaration variable, DartType type) {
+    if (type != const DynamicType()) {
+      return StaticInvocation(
+          continuationRewriter.helper.unsafeCast,
+          Arguments(<Expression>[VariableGet(variable)],
+              types: <DartType>[type]));
+    }
+    return VariableGet(variable);
+  }
+
   // Name an expression by emitting an assignment to a temporary variable.
   Expression name(Expression expr) {
-    // Allocate as dynamic as temps might be reused with different types.
-    VariableDeclaration temp =
-        allocateTemporary(nameIndex, const DynamicType());
-    statements.add(ExpressionStatement(VariableSet(temp, expr)));
-    // Type annotate the get via an unsafe cast since all temps are allocated
-    // as dynamic.
     DartType type = expr.getStaticType(_staticTypeContext);
-    return StaticInvocation(continuationRewriter.helper.unsafeCast,
-        Arguments(<Expression>[VariableGet(temp)], types: <DartType>[type]));
+    VariableDeclaration temp = allocateTemporary(nameIndex, type);
+    statements.add(ExpressionStatement(VariableSet(temp, expr)));
+    // Wrap in unsafeCast to make sure we pass type information even if we later
+    // have to re-type the temporary variable to dynamic.
+    return unsafeCastVariableGet(temp, type);
   }
 
   VariableDeclaration allocateTemporary(int index,
       [DartType type = const DynamicType()]) {
+    if (variables.length > index) {
+      // Re-type temporary to dynamic if we detect reuse with different type.
+      // Note: We should make sure all uses use `unsafeCast(...)` to pass their
+      // type information on, as that is lost otherwise.
+      if (variables[index].type != const DynamicType() &&
+          variables[index].type != type) {
+        variables[index].type = const DynamicType();
+      }
+      return variables[index];
+    }
     for (var i = variables.length; i <= index; i++) {
       variables.add(VariableDeclaration(":async_temporary_${i}", type: type));
     }
@@ -384,10 +403,9 @@
     // so any statements it emits occur after in the accumulated list (that is,
     // so they occur before in the corresponding block).
     var rightBody = blockOf(rightStatements);
-    var result = allocateTemporary(
-        nameIndex,
-        _staticTypeContext.typeEnvironment.coreTypes
-            .boolRawType(_staticTypeContext.nonNullable));
+    final type = _staticTypeContext.typeEnvironment.coreTypes
+        .boolRawType(_staticTypeContext.nonNullable);
+    final result = allocateTemporary(nameIndex, type);
     final objectEquals = continuationRewriter.helper.coreTypes.objectEquals;
     rightBody.addStatement(new ExpressionStatement(new VariableSet(
         result,
@@ -402,7 +420,8 @@
       then = new EmptyStatement();
       otherwise = rightBody;
     }
-    statements.add(new IfStatement(new VariableGet(result), then, otherwise));
+    statements.add(
+        new IfStatement(unsafeCastVariableGet(result, type), then, otherwise));
 
     final test = new EqualsCall(expr.left, new BoolLiteral(true),
         interfaceTarget: objectEquals,
@@ -414,7 +433,7 @@
 
     ++nameIndex;
     seenAwait = seenAwait || rightAwait;
-    return new VariableGet(result);
+    return unsafeCastVariableGet(result, type);
   }
 
   TreeNode visitConditionalExpression(ConditionalExpression expr) {
@@ -455,15 +474,15 @@
       });
     }
 
-    // If then or otherwise has emitted statements we will produce a temporary t
-    // and emit:
+    // If `then` or `otherwise` has emitted statements we will produce a
+    // temporary t and emit:
     //
     // if ([condition]) {
     //   t = [left];
     // } else {
     //   t = [right];
     // }
-    var result = allocateTemporary(nameIndex, expr.staticType);
+    final result = allocateTemporary(nameIndex, expr.staticType);
     var thenBody = blockOf(thenStatements);
     var otherwiseBody = blockOf(otherwiseStatements);
     thenBody.addStatement(
@@ -478,7 +497,7 @@
 
     ++nameIndex;
     seenAwait = seenAwait || thenAwait || otherwiseAwait;
-    return new VariableGet(result);
+    return unsafeCastVariableGet(result, expr.staticType);
   }
 
   // Others.
diff --git a/pkg/kernel/lib/transformations/scanner.dart b/pkg/kernel/lib/transformations/scanner.dart
index d80aa65..18c7814 100644
--- a/pkg/kernel/lib/transformations/scanner.dart
+++ b/pkg/kernel/lib/transformations/scanner.dart
@@ -260,7 +260,7 @@
     return result;
   }
 
-  void visitMethodInvocation(MethodInvocation node) {
+  void visitInstanceInvocation(InstanceInvocation node) {
     if (predicate(node)) {
       _result!.targets[node] = next?.scan(node);
       // TODO: Update result.errors.
diff --git a/pkg/kernel/lib/transformations/value_class.dart b/pkg/kernel/lib/transformations/value_class.dart
index 014256c..61481e5 100644
--- a/pkg/kernel/lib/transformations/value_class.dart
+++ b/pkg/kernel/lib/transformations/value_class.dart
@@ -61,17 +61,14 @@
 }
 
 void transformComponent(Component node, CoreTypes coreTypes,
-    ClassHierarchy hierarchy, TypeEnvironment typeEnvironment,
-    {required bool useNewMethodInvocationEncoding}) {
+    ClassHierarchy hierarchy, TypeEnvironment typeEnvironment) {
   ValueClassScanner scanner = new ValueClassScanner();
   ScanResult<Class, Null> valueClasses = scanner.scan(node);
   for (Class valueClass in valueClasses.targets.keys) {
-    transformValueClass(valueClass, coreTypes, hierarchy, typeEnvironment,
-        useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
+    transformValueClass(valueClass, coreTypes, hierarchy, typeEnvironment);
   }
 
-  treatCopyWithCallSites(node, coreTypes, typeEnvironment, hierarchy,
-      useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
+  treatCopyWithCallSites(node, coreTypes, typeEnvironment, hierarchy);
 
   for (Class valueClass in valueClasses.targets.keys) {
     removeValueClassAnnotation(valueClass);
@@ -79,8 +76,7 @@
 }
 
 void transformValueClass(Class cls, CoreTypes coreTypes,
-    ClassHierarchy hierarchy, TypeEnvironment typeEnvironment,
-    {required bool useNewMethodInvocationEncoding}) {
+    ClassHierarchy hierarchy, TypeEnvironment typeEnvironment) {
   Constructor? syntheticConstructor = null;
   for (Constructor constructor in cls.constructors) {
     if (constructor.isSynthetic) {
@@ -93,12 +89,9 @@
   allVariablesList.sort((a, b) => a.name!.compareTo(b.name!));
 
   addConstructor(cls, coreTypes, syntheticConstructor!);
-  addEqualsOperator(cls, coreTypes, hierarchy, allVariablesList,
-      useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
-  addHashCode(cls, coreTypes, hierarchy, allVariablesList,
-      useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
-  addToString(cls, coreTypes, hierarchy, allVariablesList,
-      useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
+  addEqualsOperator(cls, coreTypes, hierarchy, allVariablesList);
+  addHashCode(cls, coreTypes, hierarchy, allVariablesList);
+  addToString(cls, coreTypes, hierarchy, allVariablesList);
   addCopyWith(cls, coreTypes, hierarchy, allVariablesList, syntheticConstructor,
       typeEnvironment);
 }
@@ -140,8 +133,7 @@
 }
 
 void addEqualsOperator(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
-    List<VariableDeclaration> allVariablesList,
-    {required bool useNewMethodInvocationEncoding}) {
+    List<VariableDeclaration> allVariablesList) {
   List<VariableDeclaration> allVariables = allVariablesList.toList();
   for (Procedure procedure in cls.procedures) {
     if (procedure.kind == ProcedureKind.Operator &&
@@ -178,16 +170,10 @@
           ReturnStatement(allVariables
               .map((f) => _createEquals(
                   _createGet(ThisExpression(), Name(f.name!),
-                      interfaceTarget: targets[f],
-                      useNewMethodInvocationEncoding:
-                          useNewMethodInvocationEncoding),
+                      interfaceTarget: targets[f]),
                   _createGet(VariableGet(other, myType), Name(f.name!),
-                      interfaceTarget: targets[f],
-                      useNewMethodInvocationEncoding:
-                          useNewMethodInvocationEncoding),
-                  interfaceTarget: targetsEquals[f] as Procedure,
-                  useNewMethodInvocationEncoding:
-                      useNewMethodInvocationEncoding))
+                      interfaceTarget: targets[f]),
+                  interfaceTarget: targetsEquals[f] as Procedure))
               .fold(
                   IsExpression(VariableGet(other), myType),
                   (previousValue, element) => LogicalExpression(
@@ -200,8 +186,7 @@
 }
 
 void addHashCode(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
-    List<VariableDeclaration> allVariablesList,
-    {required bool useNewMethodInvocationEncoding}) {
+    List<VariableDeclaration> allVariablesList) {
   List<VariableDeclaration> allVariables = allVariablesList.toList();
   for (Procedure procedure in cls.procedures) {
     if (procedure.kind == ProcedureKind.Getter &&
@@ -255,13 +240,9 @@
                 allVariables
                     .map((f) => (_createGet(
                         _createGet(ThisExpression(), Name(f.name!),
-                            interfaceTarget: targets[f],
-                            useNewMethodInvocationEncoding:
-                                useNewMethodInvocationEncoding),
+                            interfaceTarget: targets[f]),
                         Name("hashCode"),
-                        interfaceTarget: targetsHashcode[f],
-                        useNewMethodInvocationEncoding:
-                            useNewMethodInvocationEncoding)))
+                        interfaceTarget: targetsHashcode[f])))
                     .fold(
                         _createGet(
                             StringLiteral(
@@ -269,9 +250,7 @@
                                     cls.name),
                             Name("hashCode"),
                             interfaceTarget: hierarchy.getInterfaceMember(
-                                coreTypes.stringClass, Name("hashCode")),
-                            useNewMethodInvocationEncoding:
-                                useNewMethodInvocationEncoding),
+                                coreTypes.stringClass, Name("hashCode"))),
                         (previousValue, element) => StaticInvocation(
                             hashCombine!, Arguments([previousValue, element])))
               ]))),
@@ -281,8 +260,7 @@
 }
 
 void addToString(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
-    List<VariableDeclaration> allVariablesList,
-    {required bool useNewMethodInvocationEncoding}) {
+    List<VariableDeclaration> allVariablesList) {
   List<Expression> wording = [StringLiteral("${cls.name}(")];
 
   for (VariableDeclaration variable in allVariablesList) {
@@ -296,12 +274,10 @@
         Name("toString")) as Procedure;
     wording.add(_createInvocation(
         _createGet(ThisExpression(), Name(variable.name!),
-            interfaceTarget: variableTarget,
-            useNewMethodInvocationEncoding: useNewMethodInvocationEncoding),
+            interfaceTarget: variableTarget),
         Name("toString"),
         Arguments([]),
-        interfaceTarget: toStringTarget,
-        useNewMethodInvocationEncoding: useNewMethodInvocationEncoding));
+        interfaceTarget: toStringTarget));
     wording.add(StringLiteral(", "));
   }
   if (allVariablesList.length != 0) {
@@ -392,8 +368,7 @@
 }
 
 void treatCopyWithCallSites(Component component, CoreTypes coreTypes,
-    TypeEnvironment typeEnvironment, ClassHierarchy hierarchy,
-    {required bool useNewMethodInvocationEncoding}) {
+    TypeEnvironment typeEnvironment, ClassHierarchy hierarchy) {
   ValueClassCopyWithScanner valueCopyWithScanner =
       new ValueClassCopyWithScanner();
   AllMemberScanner copyWithScanner = AllMemberScanner(valueCopyWithScanner);
@@ -415,8 +390,7 @@
           Class valueClass = valueClassType.classNode;
           if (isValueClass(valueClass)) {
             treatCopyWithCallSite(
-                valueClass, copyWithCall, coreTypes, hierarchy,
-                useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
+                valueClass, copyWithCall, coreTypes, hierarchy);
           }
         }
       }
@@ -428,8 +402,7 @@
     Class valueClass,
     InstanceInvocationExpression copyWithCall,
     CoreTypes coreTypes,
-    ClassHierarchy hierarchy,
-    {required bool useNewMethodInvocationEncoding}) {
+    ClassHierarchy hierarchy) {
   Map<String, Expression> preTransformationArguments = new Map();
   for (NamedExpression argument in copyWithCall.arguments.named) {
     preTransformationArguments[argument.name] = argument.value;
@@ -452,18 +425,15 @@
           argument.name!, preTransformationArguments[argument.name]!)
         ..parent = postTransformationArguments);
     } else {
-      postTransformationArguments.named.add(NamedExpression(
-          argument.name!,
-          _createGet(VariableGet(letVariable), Name(argument.name!),
-              useNewMethodInvocationEncoding: useNewMethodInvocationEncoding))
+      postTransformationArguments.named.add(NamedExpression(argument.name!,
+          _createGet(VariableGet(letVariable), Name(argument.name!)))
         ..parent = postTransformationArguments);
     }
   }
   copyWithCall.replaceWith(Let(
       letVariable,
       _createInvocation(VariableGet(letVariable), Name("copyWith"),
-          postTransformationArguments,
-          useNewMethodInvocationEncoding: useNewMethodInvocationEncoding)));
+          postTransformationArguments)));
 }
 
 bool isValueClass(Class node) {
@@ -483,47 +453,33 @@
 // access kind on InstanceInvocation.
 Expression _createInvocation(
     Expression receiver, Name name, Arguments arguments,
-    {Procedure? interfaceTarget,
-    required bool useNewMethodInvocationEncoding}) {
-  if (useNewMethodInvocationEncoding) {
-    if (interfaceTarget != null) {
-      return InstanceInvocation(
-          InstanceAccessKind.Instance, receiver, name, arguments,
-          interfaceTarget: interfaceTarget,
-          functionType: interfaceTarget.getterType as FunctionType);
-    } else {
-      return DynamicInvocation(
-          DynamicAccessKind.Dynamic, receiver, name, arguments);
-    }
+    {Procedure? interfaceTarget}) {
+  if (interfaceTarget != null) {
+    return InstanceInvocation(
+        InstanceAccessKind.Instance, receiver, name, arguments,
+        interfaceTarget: interfaceTarget,
+        functionType: interfaceTarget.getterType as FunctionType);
   } else {
-    return MethodInvocation(receiver, name, arguments, interfaceTarget);
+    return DynamicInvocation(
+        DynamicAccessKind.Dynamic, receiver, name, arguments);
   }
 }
 
 Expression _createEquals(Expression left, Expression right,
-    {required Procedure interfaceTarget,
-    required bool useNewMethodInvocationEncoding}) {
-  if (useNewMethodInvocationEncoding) {
-    return EqualsCall(left, right,
-        interfaceTarget: interfaceTarget,
-        functionType: interfaceTarget.getterType as FunctionType);
-  } else {
-    return MethodInvocation(left, Name('=='), Arguments([right]));
-  }
+    {required Procedure interfaceTarget}) {
+  return EqualsCall(left, right,
+      interfaceTarget: interfaceTarget,
+      functionType: interfaceTarget.getterType as FunctionType);
 }
 
 // TODO(johnniwinther): Ensure correct result type on InstanceGet.
 Expression _createGet(Expression receiver, Name name,
-    {Member? interfaceTarget, required bool useNewMethodInvocationEncoding}) {
-  if (useNewMethodInvocationEncoding) {
-    if (interfaceTarget != null) {
-      return InstanceGet(InstanceAccessKind.Instance, receiver, name,
-          interfaceTarget: interfaceTarget,
-          resultType: interfaceTarget.getterType);
-    } else {
-      return DynamicGet(DynamicAccessKind.Dynamic, receiver, name);
-    }
+    {Member? interfaceTarget}) {
+  if (interfaceTarget != null) {
+    return InstanceGet(InstanceAccessKind.Instance, receiver, name,
+        interfaceTarget: interfaceTarget,
+        resultType: interfaceTarget.getterType);
   } else {
-    return PropertyGet(receiver, name, interfaceTarget);
+    return DynamicGet(DynamicAccessKind.Dynamic, receiver, name);
   }
 }
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 4439705..e598523 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -136,9 +136,11 @@
 }
 
 class FreshTypeParameters {
-  ///
+  /// The newly created type parameters.
   final List<TypeParameter> freshTypeParameters;
+  /// List of [TypeParameterType]s for [TypeParameter].
   final List<DartType> freshTypeArguments;
+  /// Substitution from the original type parameters to [freshTypeArguments].
   final Substitution substitution;
 
   FreshTypeParameters(
@@ -175,6 +177,8 @@
 
   static const Substitution empty = _NullSubstitution.instance;
 
+  bool get isEmpty => identical(this, empty);
+
   /// Substitutes each parameter to the type it maps to in [map].
   static Substitution fromMap(Map<TypeParameter, DartType> map) {
     if (map.isEmpty) return _NullSubstitution.instance;
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index af4d5e3..3d6cf83 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -208,7 +208,7 @@
     handleFunctionNode(node.function);
   }
 
-  visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+  visitRedirectingFactory(RedirectingFactory node) {
     currentReturnType = null;
     currentYieldType = null;
   }
@@ -521,8 +521,12 @@
 
   @override
   DartType visitConstructorTearOff(ConstructorTearOff node) {
-    return node.constructorReference.asConstructor.function
-        .computeFunctionType(Nullability.nonNullable);
+    return node.function.computeFunctionType(Nullability.nonNullable);
+  }
+
+  @override
+  DartType visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+    return node.function.computeFunctionType(Nullability.nonNullable);
   }
 
   @override
@@ -633,61 +637,6 @@
   }
 
   @override
-  DartType visitMethodInvocation(MethodInvocation node) {
-    Member? target = node.interfaceTarget;
-    if (target == null) {
-      DartType receiver = visitExpression(node.receiver);
-      if (node.name.text == '==') {
-        visitExpression(node.arguments.positional.single);
-        return environment.coreTypes.boolLegacyRawType;
-      }
-      if (node.name.text == 'call' && receiver is FunctionType) {
-        return handleFunctionCall(node, receiver, node.arguments);
-      }
-      checkUnresolvedInvocation(receiver, node);
-      return handleDynamicCall(receiver, node.arguments);
-    } else if (target is Procedure &&
-        environment.isSpecialCasedBinaryOperator(target)) {
-      assert(node.arguments.positional.length == 1);
-      DartType receiver = visitExpression(node.receiver);
-      DartType argument = visitExpression(node.arguments.positional[0]);
-      return environment.getTypeOfSpecialCasedBinaryOperator(
-          receiver, argument);
-    } else {
-      return handleCall(node.arguments, target.getterType,
-          receiver: getReceiverType(node, node.receiver, target));
-    }
-  }
-
-  @override
-  DartType visitPropertyGet(PropertyGet node) {
-    Member? target = node.interfaceTarget;
-    if (target == null) {
-      final DartType receiver = visitExpression(node.receiver);
-      checkUnresolvedInvocation(receiver, node);
-      return const DynamicType();
-    } else {
-      Substitution receiver = getReceiverType(node, node.receiver, target);
-      return receiver.substituteType(target.getterType);
-    }
-  }
-
-  @override
-  DartType visitPropertySet(PropertySet node) {
-    Member? target = node.interfaceTarget;
-    DartType value = visitExpression(node.value);
-    if (target != null) {
-      Substitution receiver = getReceiverType(node, node.receiver, target);
-      checkAssignable(node.value, value,
-          receiver.substituteType(target.setterType, contravariant: true));
-    } else {
-      final DartType receiver = visitExpression(node.receiver);
-      checkUnresolvedInvocation(receiver, node);
-    }
-    return value;
-  }
-
-  @override
   DartType visitNot(Not node) {
     visitExpression(node.operand);
     return environment.coreTypes.boolLegacyRawType;
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index aec9d76..f589e8a 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -72,6 +72,8 @@
 
   bool inUnevaluatedConstant = false;
 
+  bool inConstant = false;
+
   Library? currentLibrary;
 
   Member? currentMember;
@@ -635,6 +637,13 @@
     }
   }
 
+  @override
+  void visitTypedefTearOff(TypedefTearOff node) {
+    declareTypeParameters(node.typeParameters);
+    super.visitTypedefTearOff(node);
+    undeclareTypeParameters(node.typeParameters);
+  }
+
   void checkTargetedInvocation(Member target, InvocationExpression node) {
     visitChildren(node);
     // ignore: unnecessary_null_comparison
@@ -821,10 +830,13 @@
   visitTypeParameterType(TypeParameterType node) {
     TypeParameter parameter = node.parameter;
     if (!typeParametersInScope.contains(parameter)) {
+      TreeNode? owner = parameter.parent is FunctionNode
+          ? parameter.parent!.parent
+          : parameter.parent;
       problem(
           currentParent,
           "Type parameter '$parameter' referenced out of"
-          " scope, parent is: '${parameter.parent}'.");
+          " scope, owner is: '${owner}'.");
     }
     if (parameter.parent is Class && !classTypeParametersAreInScope) {
       problem(
@@ -876,6 +888,31 @@
           " ${node.typedefNode.typeParameters.length} parameters.");
     }
   }
+
+  @override
+  void visitConstantExpression(ConstantExpression node) {
+    bool oldInConstant = inConstant;
+    inConstant = true;
+    visitChildren(node);
+    inConstant = oldInConstant;
+  }
+
+  @override
+  void visitTypeParameter(TypeParameter node) {
+    if (inConstant) {
+      // Don't expect the type parameters to have the current parent as parent.
+      node.visitChildren(this);
+    } else {
+      visitChildren(node);
+    }
+  }
+
+  @override
+  void visitTypedefTearOffConstant(TypedefTearOffConstant node) {
+    declareTypeParameters(node.parameters);
+    super.visitTypedefTearOffConstant(node);
+    undeclareTypeParameters(node.parameters);
+  }
 }
 
 void verifyGetStaticType(TypeEnvironment env, Component component) {
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index 1f71e2c..5e5c959 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -23,8 +23,6 @@
   R visitInstanceGet(InstanceGet node) => defaultExpression(node);
   R visitInstanceSet(InstanceSet node) => defaultExpression(node);
   R visitInstanceTearOff(InstanceTearOff node) => defaultExpression(node);
-  R visitPropertyGet(PropertyGet node) => defaultExpression(node);
-  R visitPropertySet(PropertySet node) => defaultExpression(node);
   R visitSuperPropertyGet(SuperPropertyGet node) => defaultExpression(node);
   R visitSuperPropertySet(SuperPropertySet node) => defaultExpression(node);
   R visitStaticGet(StaticGet node) => defaultExpression(node);
@@ -39,7 +37,6 @@
       defaultExpression(node);
   R visitEqualsNull(EqualsNull node) => defaultExpression(node);
   R visitEqualsCall(EqualsCall node) => defaultExpression(node);
-  R visitMethodInvocation(MethodInvocation node) => defaultExpression(node);
   R visitSuperMethodInvocation(SuperMethodInvocation node) =>
       defaultExpression(node);
   R visitStaticInvocation(StaticInvocation node) => defaultExpression(node);
@@ -82,6 +79,8 @@
   R visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
       defaultExpression(node);
   R visitConstructorTearOff(ConstructorTearOff node) => defaultExpression(node);
+  R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) =>
+      defaultExpression(node);
   R visitTypedefTearOff(TypedefTearOff node) => defaultExpression(node);
 }
 
@@ -124,7 +123,7 @@
   R visitConstructor(Constructor node) => defaultMember(node);
   R visitProcedure(Procedure node) => defaultMember(node);
   R visitField(Field node) => defaultMember(node);
-  R visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+  R visitRedirectingFactory(RedirectingFactory node) {
     return defaultMember(node);
   }
 }
@@ -137,8 +136,7 @@
   R visitConstructor(Constructor node, A arg) => defaultMember(node, arg);
   R visitProcedure(Procedure node, A arg) => defaultMember(node, arg);
   R visitField(Field node, A arg) => defaultMember(node, arg);
-  R visitRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor node, A arg) {
+  R visitRedirectingFactory(RedirectingFactory node, A arg) {
     return defaultMember(node, arg);
   }
 }
@@ -199,8 +197,6 @@
   R visitInstanceGet(InstanceGet node) => defaultExpression(node);
   R visitInstanceSet(InstanceSet node) => defaultExpression(node);
   R visitInstanceTearOff(InstanceTearOff node) => defaultExpression(node);
-  R visitPropertyGet(PropertyGet node) => defaultExpression(node);
-  R visitPropertySet(PropertySet node) => defaultExpression(node);
   R visitSuperPropertyGet(SuperPropertyGet node) => defaultExpression(node);
   R visitSuperPropertySet(SuperPropertySet node) => defaultExpression(node);
   R visitStaticGet(StaticGet node) => defaultExpression(node);
@@ -215,7 +211,6 @@
       defaultExpression(node);
   R visitEqualsNull(EqualsNull node) => defaultExpression(node);
   R visitEqualsCall(EqualsCall node) => defaultExpression(node);
-  R visitMethodInvocation(MethodInvocation node) => defaultExpression(node);
   R visitSuperMethodInvocation(SuperMethodInvocation node) =>
       defaultExpression(node);
   R visitStaticInvocation(StaticInvocation node) => defaultExpression(node);
@@ -258,6 +253,8 @@
   R visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
       defaultExpression(node);
   R visitConstructorTearOff(ConstructorTearOff node) => defaultExpression(node);
+  R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) =>
+      defaultExpression(node);
   R visitTypedefTearOff(TypedefTearOff node) => defaultExpression(node);
 
   // Statements
@@ -292,7 +289,7 @@
   R visitConstructor(Constructor node) => defaultMember(node);
   R visitProcedure(Procedure node) => defaultMember(node);
   R visitField(Field node) => defaultMember(node);
-  R visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+  R visitRedirectingFactory(RedirectingFactory node) {
     return defaultMember(node);
   }
 
@@ -353,8 +350,6 @@
   R visitInstanceSet(InstanceSet node, A arg) => defaultExpression(node, arg);
   R visitInstanceTearOff(InstanceTearOff node, A arg) =>
       defaultExpression(node, arg);
-  R visitPropertyGet(PropertyGet node, A arg) => defaultExpression(node, arg);
-  R visitPropertySet(PropertySet node, A arg) => defaultExpression(node, arg);
   R visitSuperPropertyGet(SuperPropertyGet node, A arg) =>
       defaultExpression(node, arg);
   R visitSuperPropertySet(SuperPropertySet node, A arg) =>
@@ -375,8 +370,6 @@
       defaultExpression(node, arg);
   R visitEqualsNull(EqualsNull node, A arg) => defaultExpression(node, arg);
   R visitEqualsCall(EqualsCall node, A arg) => defaultExpression(node, arg);
-  R visitMethodInvocation(MethodInvocation node, A arg) =>
-      defaultExpression(node, arg);
   R visitSuperMethodInvocation(SuperMethodInvocation node, A arg) =>
       defaultExpression(node, arg);
   R visitStaticInvocation(StaticInvocation node, A arg) =>
@@ -436,6 +429,8 @@
       defaultExpression(node, arg);
   R visitConstructorTearOff(ConstructorTearOff node, A arg) =>
       defaultExpression(node, arg);
+  R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node, A arg) =>
+      defaultExpression(node, arg);
   R visitTypedefTearOff(TypedefTearOff node, A arg) =>
       defaultExpression(node, arg);
 
@@ -480,8 +475,7 @@
   R visitConstructor(Constructor node, A arg) => defaultMember(node, arg);
   R visitProcedure(Procedure node, A arg) => defaultMember(node, arg);
   R visitField(Field node, A arg) => defaultMember(node, arg);
-  R visitRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor node, A arg) {
+  R visitRedirectingFactory(RedirectingFactory node, A arg) {
     return defaultMember(node, arg);
   }
 
@@ -589,10 +583,49 @@
       defaultConstant(node);
   R visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
       defaultConstant(node);
+  R visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      defaultConstant(node);
   R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
   R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
 }
 
+abstract class ConstantVisitor1<R, A> {
+  const ConstantVisitor1();
+
+  R defaultConstant(Constant node, A arg);
+
+  R visitNullConstant(NullConstant node, A arg) => defaultConstant(node, arg);
+  R visitBoolConstant(BoolConstant node, A arg) => defaultConstant(node, arg);
+  R visitIntConstant(IntConstant node, A arg) => defaultConstant(node, arg);
+  R visitDoubleConstant(DoubleConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitStringConstant(StringConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitSymbolConstant(SymbolConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitMapConstant(MapConstant node, A arg) => defaultConstant(node, arg);
+  R visitListConstant(ListConstant node, A arg) => defaultConstant(node, arg);
+  R visitSetConstant(SetConstant node, A arg) => defaultConstant(node, arg);
+  R visitInstanceConstant(InstanceConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitInstantiationConstant(InstantiationConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitStaticTearOffConstant(StaticTearOffConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitTypedefTearOffConstant(TypedefTearOffConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitConstructorTearOffConstant(ConstructorTearOffConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitTypeLiteralConstant(TypeLiteralConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitUnevaluatedConstant(UnevaluatedConstant node, A arg) =>
+      defaultConstant(node, arg);
+}
+
 abstract class _ConstantCallback<R> {
   R defaultConstant(Constant node);
 
@@ -610,6 +643,8 @@
   R visitTypedefTearOffConstant(TypedefTearOffConstant node);
   R visitStaticTearOffConstant(StaticTearOffConstant node);
   R visitConstructorTearOffConstant(ConstructorTearOffConstant node);
+  R visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node);
   R visitTypeLiteralConstant(TypeLiteralConstant node);
   R visitUnevaluatedConstant(UnevaluatedConstant node);
 }
@@ -636,6 +671,11 @@
       _callback.visitConstructorTearOffConstant(node);
 
   @override
+  R visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      _callback.visitRedirectingFactoryTearOffConstant(node);
+
+  @override
   R visitInstantiationConstant(InstantiationConstant node) =>
       _callback.visitInstantiationConstant(node);
 
@@ -730,6 +770,9 @@
       defaultConstant(node);
   R visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
       defaultConstant(node);
+  R visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      defaultConstant(node);
   R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
   R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
 }
@@ -774,6 +817,9 @@
       defaultConstant(node);
   void visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
       defaultConstant(node);
+  void visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      defaultConstant(node);
   void visitTypeLiteralConstant(TypeLiteralConstant node) =>
       defaultConstant(node);
   void visitUnevaluatedConstant(UnevaluatedConstant node) =>
@@ -788,12 +834,26 @@
   R visitFieldReference(Field node) => defaultMemberReference(node);
   R visitConstructorReference(Constructor node) => defaultMemberReference(node);
   R visitProcedureReference(Procedure node) => defaultMemberReference(node);
-  R visitRedirectingFactoryConstructorReference(
-      RedirectingFactoryConstructor node) {
+  R visitRedirectingFactoryReference(RedirectingFactory node) {
     return defaultMemberReference(node);
   }
 }
 
+abstract class MemberReferenceVisitor1<R, A> {
+  const MemberReferenceVisitor1();
+
+  R defaultMemberReference(Member node, A arg);
+
+  R visitFieldReference(Field node, A arg) => defaultMemberReference(node, arg);
+  R visitConstructorReference(Constructor node, A arg) =>
+      defaultMemberReference(node, arg);
+  R visitProcedureReference(Procedure node, A arg) =>
+      defaultMemberReference(node, arg);
+  R visitRedirectingFactoryReference(RedirectingFactory node, A arg) {
+    return defaultMemberReference(node, arg);
+  }
+}
+
 abstract class Visitor<R> extends TreeVisitor<R>
     implements
         DartTypeVisitor<R>,
@@ -839,6 +899,9 @@
       defaultConstant(node);
   R visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
       defaultConstant(node);
+  R visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      defaultConstant(node);
   R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
   R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
 
@@ -878,6 +941,11 @@
       defaultConstantReference(node);
   R visitConstructorTearOffConstantReference(ConstructorTearOffConstant node) =>
       defaultConstantReference(node);
+  R visitRedirectingFactoryTearOffConstantReference(
+          RedirectingFactoryTearOffConstant node) =>
+      defaultConstantReference(node);
+  R visitTypedefTearOffConstantReference(TypedefTearOffConstant node) =>
+      defaultConstantReference(node);
   R visitTypeLiteralConstantReference(TypeLiteralConstant node) =>
       defaultConstantReference(node);
   R visitUnevaluatedConstantReference(UnevaluatedConstant node) =>
@@ -889,8 +957,7 @@
   R visitFieldReference(Field node) => defaultMemberReference(node);
   R visitConstructorReference(Constructor node) => defaultMemberReference(node);
   R visitProcedureReference(Procedure node) => defaultMemberReference(node);
-  R visitRedirectingFactoryConstructorReference(
-      RedirectingFactoryConstructor node) {
+  R visitRedirectingFactoryReference(RedirectingFactory node) {
     return defaultMemberReference(node);
   }
 
@@ -899,6 +966,118 @@
   R visitNamedType(NamedType node) => defaultNode(node);
 }
 
+abstract class Visitor1<R, A> extends TreeVisitor1<R, A>
+    implements
+        DartTypeVisitor1<R, A>,
+        ConstantVisitor1<R, A>,
+        MemberReferenceVisitor1<R, A> {
+  const Visitor1();
+
+  /// The catch-all case, except for references.
+  R defaultNode(Node node, A arg);
+  R defaultTreeNode(TreeNode node, A arg) => defaultNode(node, arg);
+
+  // DartTypes
+  R defaultDartType(DartType node, A arg) => defaultNode(node, arg);
+  R visitInvalidType(InvalidType node, A arg) => defaultDartType(node, arg);
+  R visitDynamicType(DynamicType node, A arg) => defaultDartType(node, arg);
+  R visitVoidType(VoidType node, A arg) => defaultDartType(node, arg);
+  R visitInterfaceType(InterfaceType node, A arg) => defaultDartType(node, arg);
+  R visitFutureOrType(FutureOrType node, A arg) => defaultDartType(node, arg);
+  R visitFunctionType(FunctionType node, A arg) => defaultDartType(node, arg);
+  R visitTypeParameterType(TypeParameterType node, A arg) =>
+      defaultDartType(node, arg);
+  R visitTypedefType(TypedefType node, A arg) => defaultDartType(node, arg);
+  R visitNeverType(NeverType node, A arg) => defaultDartType(node, arg);
+  R visitNullType(NullType node, A arg) => defaultDartType(node, arg);
+  R visitExtensionType(ExtensionType node, A arg) => defaultDartType(node, arg);
+
+  // Constants
+  R defaultConstant(Constant node, A arg) => defaultNode(node, arg);
+  R visitNullConstant(NullConstant node, A arg) => defaultConstant(node, arg);
+  R visitBoolConstant(BoolConstant node, A arg) => defaultConstant(node, arg);
+  R visitIntConstant(IntConstant node, A arg) => defaultConstant(node, arg);
+  R visitDoubleConstant(DoubleConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitStringConstant(StringConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitSymbolConstant(SymbolConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitMapConstant(MapConstant node, A arg) => defaultConstant(node, arg);
+  R visitListConstant(ListConstant node, A arg) => defaultConstant(node, arg);
+  R visitSetConstant(SetConstant node, A arg) => defaultConstant(node, arg);
+  R visitInstanceConstant(InstanceConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitInstantiationConstant(InstantiationConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitTypeLiteralConstant(TypeLiteralConstant node, A arg) =>
+      defaultConstant(node, arg);
+  R visitUnevaluatedConstant(UnevaluatedConstant node, A arg) =>
+      defaultConstant(node, arg);
+
+  // Class references
+  R visitClassReference(Class node, A arg);
+
+  R visitTypedefReference(Typedef node, A arg);
+
+  R visitExtensionReference(Extension node, A arg);
+
+  // Constant references
+  R defaultConstantReference(Constant node, A arg);
+
+  R visitNullConstantReference(NullConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitBoolConstantReference(BoolConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitIntConstantReference(IntConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitDoubleConstantReference(DoubleConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitStringConstantReference(StringConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitSymbolConstantReference(SymbolConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitMapConstantReference(MapConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitListConstantReference(ListConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitSetConstantReference(SetConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitInstanceConstantReference(InstanceConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitInstantiationConstantReference(InstantiationConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitConstructorTearOffConstantReference(
+          ConstructorTearOffConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitRedirectingFactoryTearOffConstantReference(
+          RedirectingFactoryTearOffConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitStaticTearOffConstantReference(StaticTearOffConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitTypedefTearOffConstantReference(TypedefTearOffConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitTypeLiteralConstantReference(TypeLiteralConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+  R visitUnevaluatedConstantReference(UnevaluatedConstant node, A arg) =>
+      defaultConstantReference(node, arg);
+
+  // Member references
+  R defaultMemberReference(Member node, A arg);
+
+  R visitFieldReference(Field node, A arg) => defaultMemberReference(node, arg);
+  R visitConstructorReference(Constructor node, A arg) =>
+      defaultMemberReference(node, arg);
+  R visitProcedureReference(Procedure node, A arg) =>
+      defaultMemberReference(node, arg);
+  R visitRedirectingFactoryReference(RedirectingFactory node, A arg) =>
+      defaultMemberReference(node, arg);
+
+  R visitName(Name node, A arg) => defaultNode(node, arg);
+  R visitSupertype(Supertype node, A arg) => defaultNode(node, arg);
+  R visitNamedType(NamedType node, A arg) => defaultNode(node, arg);
+}
+
 /// Visitor mixin that throws as its base case.
 mixin VisitorThrowingMixin<R> implements Visitor<R> {
   @override
@@ -1346,14 +1525,14 @@
     transformList(nodes, parent, dummyField);
   }
 
-  /// Transforms or removes [RedirectingFactoryConstructor] nodes in [nodes] as
+  /// Transforms or removes [RedirectingFactory] nodes in [nodes] as
   /// children of [parent].
   ///
   /// This is convenience method for calling [transformList] with removal
-  /// sentinel for [RedirectingFactoryConstructor] nodes.
-  void transformRedirectingFactoryConstructorList(
-      List<RedirectingFactoryConstructor> nodes, TreeNode parent) {
-    transformList(nodes, parent, dummyRedirectingFactoryConstructor);
+  /// sentinel for [RedirectingFactory] nodes.
+  void transformRedirectingFactoryList(
+      List<RedirectingFactory> nodes, TreeNode parent) {
+    transformList(nodes, parent, dummyRedirectingFactory);
   }
 
   /// Transforms or removes [Typedef] nodes in [nodes] as children of [parent].
@@ -1498,8 +1677,6 @@
   R visitInstanceSet(InstanceSet node, T arg) => defaultExpression(node, arg);
   R visitInstanceTearOff(InstanceTearOff node, T arg) =>
       defaultExpression(node, arg);
-  R visitPropertyGet(PropertyGet node, T arg) => defaultExpression(node, arg);
-  R visitPropertySet(PropertySet node, T arg) => defaultExpression(node, arg);
   R visitSuperPropertyGet(SuperPropertyGet node, T arg) =>
       defaultExpression(node, arg);
   R visitSuperPropertySet(SuperPropertySet node, T arg) =>
@@ -1520,8 +1697,6 @@
       defaultExpression(node, arg);
   R visitEqualsNull(EqualsNull node, T arg) => defaultExpression(node, arg);
   R visitEqualsCall(EqualsCall node, T arg) => defaultExpression(node, arg);
-  R visitMethodInvocation(MethodInvocation node, T arg) =>
-      defaultExpression(node, arg);
   R visitSuperMethodInvocation(SuperMethodInvocation node, T arg) =>
       defaultExpression(node, arg);
   R visitStaticInvocation(StaticInvocation node, T arg) =>
@@ -1581,6 +1756,8 @@
       defaultExpression(node, arg);
   R visitConstructorTearOff(ConstructorTearOff node, T arg) =>
       defaultExpression(node, arg);
+  R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node, T arg) =>
+      defaultExpression(node, arg);
   R visitTypedefTearOff(TypedefTearOff node, T arg) =>
       defaultExpression(node, arg);
 }
diff --git a/pkg/kernel/test/ast_membench.dart b/pkg/kernel/test/ast_membench.dart
index baf8245..bd448d0 100644
--- a/pkg/kernel/test/ast_membench.dart
+++ b/pkg/kernel/test/ast_membench.dart
@@ -3,8 +3,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 'package:kernel/kernel.dart';
 import 'dart:io';
 
diff --git a/pkg/kernel/test/binary/can_read_platform_test.dart b/pkg/kernel/test/binary/can_read_platform_test.dart
index 2c8d827..2b447bc 100644
--- a/pkg/kernel/test/binary/can_read_platform_test.dart
+++ b/pkg/kernel/test/binary/can_read_platform_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:io';
 
 import 'package:kernel/binary/ast_from_binary.dart';
diff --git a/pkg/kernel/test/binary/component_mode_test.dart b/pkg/kernel/test/binary/component_mode_test.dart
index 2358e2f..c036b67 100644
--- a/pkg/kernel/test/binary/component_mode_test.dart
+++ b/pkg/kernel/test/binary/component_mode_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 'package:kernel/binary/ast_from_binary.dart';
 
 import 'utils.dart';
diff --git a/pkg/kernel/test/binary/invalid_index_size.dart b/pkg/kernel/test/binary/invalid_index_size.dart
index 2722ee4..893c14b 100644
--- a/pkg/kernel/test/binary/invalid_index_size.dart
+++ b/pkg/kernel/test/binary/invalid_index_size.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 'package:kernel/binary/ast_from_binary.dart' show ParseError;
 
 import 'utils.dart';
diff --git a/pkg/kernel/test/binary/lazy_reading_test.dart b/pkg/kernel/test/binary/lazy_reading_test.dart
index 9d8d45c..f8bec83 100644
--- a/pkg/kernel/test/binary/lazy_reading_test.dart
+++ b/pkg/kernel/test/binary/lazy_reading_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 'package:kernel/binary/ast_from_binary.dart';
 import 'package:kernel/src/tool/find_referenced_libraries.dart';
 import 'utils.dart';
@@ -47,9 +45,9 @@
     final Library loadedLib = loadedComponent.libraries.single;
     final Class loadedClassA = loadedLib.classes.first;
     final ExpressionStatement loadedConstructorA =
-        loadedClassA.constructors.single.function.body;
+        loadedClassA.constructors.single.function.body as ExpressionStatement;
     final ConstructorInvocation loadedConstructorInvocation =
-        loadedConstructorA.expression;
+        loadedConstructorA.expression as ConstructorInvocation;
     final Class pointedToClass =
         loadedConstructorInvocation.target.enclosingClass;
     final Library pointedToLib =
@@ -81,9 +79,9 @@
     final Library loadedLib = loadedComponent2.libraries.single;
     final Class loadedClassA = loadedLib.classes.first;
     final ExpressionStatement loadedConstructorA =
-        loadedClassA.constructors.single.function.body;
+        loadedClassA.constructors.single.function.body as ExpressionStatement;
     final ConstructorInvocation loadedConstructorInvocation =
-        loadedConstructorA.expression;
+        loadedConstructorA.expression as ConstructorInvocation;
     final Class pointedToClass =
         loadedConstructorInvocation.target.enclosingClass;
     final Library pointedToLib =
diff --git a/pkg/kernel/test/binary/library_flags_test.dart b/pkg/kernel/test/binary/library_flags_test.dart
index c930c3c..d8776d6 100644
--- a/pkg/kernel/test/binary/library_flags_test.dart
+++ b/pkg/kernel/test/binary/library_flags_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 'utils.dart';
 
 /// Test that library flags are serialized and read correctly.
diff --git a/pkg/kernel/test/binary/utils.dart b/pkg/kernel/test/binary/utils.dart
index 4253db8..1005909 100644
--- a/pkg/kernel/test/binary/utils.dart
+++ b/pkg/kernel/test/binary/utils.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:io' show BytesBuilder;
 
 import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
diff --git a/pkg/kernel/test/binary_bench.dart b/pkg/kernel/test/binary_bench.dart
index 75834e6..3c63ecd 100644
--- a/pkg/kernel/test/binary_bench.dart
+++ b/pkg/kernel/test/binary_bench.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
-
 // This files contains methods for benchmarking Kernel binary serialization
 // and deserialization routines.
 
@@ -35,8 +33,8 @@
   },
 };
 
-Benchmark benchmark;
-File sourceDill;
+Benchmark? benchmark;
+late File sourceDill;
 bool forGolem = false;
 bool forRaw = false;
 
@@ -47,7 +45,7 @@
   }
 
   final bytes = sourceDill.readAsBytesSync();
-  benchmark(bytes);
+  benchmark!(bytes);
 }
 
 const warmupIterations = 100;
@@ -64,7 +62,8 @@
   }
   final warmupUs = sw.elapsedMicroseconds / warmupIterations;
 
-  final runsUs = new List<int>.filled(benchmarkIterations, null);
+  final runsUs =
+      new List<int>.filled(benchmarkIterations, /* dummy value = */ 0);
   for (var i = 0; i < benchmarkIterations; i++) {
     sw.reset();
     _fromBinary(bytes, eager: eager);
@@ -88,7 +87,8 @@
   }
   final warmupUs = sw.elapsedMicroseconds / warmupIterations;
 
-  final runsUs = new List<int>.filled(benchmarkIterations, null);
+  final runsUs =
+      new List<int>.filled(benchmarkIterations, /* dummy value = */ 0);
   for (var i = 0; i < benchmarkIterations; i++) {
     sw.reset();
     _toBinary(p);
@@ -106,7 +106,7 @@
 
   BenchmarkResult(this.name, this.coldRunUs, this.warmupUs, this.runsUs);
 
-  static T add<T extends num>(T x, T y) => x + y;
+  static T add<T extends num>(T x, T y) => x + y as T;
 
   void report() {
     runsUs.sort();
diff --git a/pkg/kernel/test/class_hierarchy_basic.dart b/pkg/kernel/test/class_hierarchy_basic.dart
index 1a9b34e..78ca0c5 100644
--- a/pkg/kernel/test/class_hierarchy_basic.dart
+++ b/pkg/kernel/test/class_hierarchy_basic.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
-
 library kernel.class_hierarchy_basic;
 
 import 'package:kernel/class_hierarchy.dart';
@@ -97,19 +95,19 @@
     superMixtures[node] = new Set<Class>()..add(node);
     supertypes[node] = new Set<Class>()..add(node);
     if (node.supertype != null) {
-      buildSuperTypeSets(node.supertype.classNode);
-      superclasses[node].addAll(superclasses[node.supertype.classNode]);
-      superMixtures[node].addAll(superMixtures[node.supertype.classNode]);
-      supertypes[node].addAll(supertypes[node.supertype.classNode]);
+      buildSuperTypeSets(node.supertype!.classNode);
+      superclasses[node]!.addAll(superclasses[node.supertype!.classNode]!);
+      superMixtures[node]!.addAll(superMixtures[node.supertype!.classNode]!);
+      supertypes[node]!.addAll(supertypes[node.supertype!.classNode]!);
     }
     if (node.mixedInType != null) {
-      buildSuperTypeSets(node.mixedInType.classNode);
-      superMixtures[node].addAll(superMixtures[node.mixedInType.classNode]);
-      supertypes[node].addAll(supertypes[node.mixedInType.classNode]);
+      buildSuperTypeSets(node.mixedInType!.classNode);
+      superMixtures[node]!.addAll(superMixtures[node.mixedInType!.classNode]!);
+      supertypes[node]!.addAll(supertypes[node.mixedInType!.classNode]!);
     }
     for (var supertype in node.implementedTypes) {
       buildSuperTypeSets(supertype.classNode);
-      supertypes[node].addAll(supertypes[supertype.classNode]);
+      supertypes[node]!.addAll(supertypes[supertype.classNode]!);
     }
     classes.add(node);
     classIndex[node] = classes.length - 1;
@@ -125,8 +123,8 @@
       buildSuperTypeInstantiations(superclass);
       var substitution = Substitution.fromPairs(
           superclass.typeParameters, supertype.typeArguments);
-      supertypeInstantiations[superclass].forEach((key, type) {
-        supertypeInstantiations[node][key] =
+      supertypeInstantiations[superclass]!.forEach((key, type) {
+        supertypeInstantiations[node]![key] =
             substitution.substituteSupertype(type);
       });
     }
@@ -137,25 +135,26 @@
     gettersAndCalls[node] = <Name, Member>{};
     setters[node] = <Name, Member>{};
     if (node.supertype != null) {
-      buildDispatchTable(node.supertype.classNode);
-      gettersAndCalls[node].addAll(gettersAndCalls[node.supertype.classNode]);
-      setters[node].addAll(setters[node.supertype.classNode]);
+      buildDispatchTable(node.supertype!.classNode);
+      gettersAndCalls[node]!
+          .addAll(gettersAndCalls[node.supertype!.classNode]!);
+      setters[node]!.addAll(setters[node.supertype!.classNode]!);
     }
     // Overwrite map entries with declared members.
     Class mixin = node.mixedInType?.classNode ?? node;
     for (Procedure procedure in mixin.procedures) {
       if (procedure.isStatic || procedure.isAbstract) continue;
       if (procedure.kind == ProcedureKind.Setter) {
-        setters[node][procedure.name] = procedure;
+        setters[node]![procedure.name] = procedure;
       } else {
-        gettersAndCalls[node][procedure.name] = procedure;
+        gettersAndCalls[node]![procedure.name] = procedure;
       }
     }
     for (Field field in mixin.fields) {
       if (field.isStatic) continue;
-      gettersAndCalls[node][field.name] = field;
+      gettersAndCalls[node]![field.name] = field;
       if (!field.isFinal) {
-        setters[node][field.name] = field;
+        setters[node]![field.name] = field;
       }
     }
   }
@@ -163,7 +162,7 @@
   void mergeMaps(
       Map<Name, List<Member>> source, Map<Name, List<Member>> destination) {
     for (var name in source.keys) {
-      destination.putIfAbsent(name, () => <Member>[]).addAll(source[name]);
+      destination.putIfAbsent(name, () => <Member>[]).addAll(source[name]!);
     }
   }
 
@@ -171,12 +170,12 @@
     if (interfaceGettersAndCalls.containsKey(node)) return;
     interfaceGettersAndCalls[node] = <Name, List<Member>>{};
     interfaceSetters[node] = <Name, List<Member>>{};
-    void inheritFrom(Supertype type) {
+    void inheritFrom(Supertype? type) {
       if (type == null) return;
       buildInterfaceTable(type.classNode);
-      mergeMaps(interfaceGettersAndCalls[type.classNode],
-          interfaceGettersAndCalls[node]);
-      mergeMaps(interfaceSetters[type.classNode], interfaceSetters[node]);
+      mergeMaps(interfaceGettersAndCalls[type.classNode]!,
+          interfaceGettersAndCalls[node]!);
+      mergeMaps(interfaceSetters[type.classNode]!, interfaceSetters[node]!);
     }
 
     inheritFrom(node.supertype);
@@ -186,70 +185,70 @@
     for (Procedure procedure in node.mixin.procedures) {
       if (procedure.isStatic) continue;
       if (procedure.kind == ProcedureKind.Setter) {
-        interfaceSetters[node][procedure.name] = <Member>[procedure];
+        interfaceSetters[node]![procedure.name] = <Member>[procedure];
       } else {
-        interfaceGettersAndCalls[node][procedure.name] = <Member>[procedure];
+        interfaceGettersAndCalls[node]![procedure.name] = <Member>[procedure];
       }
     }
     for (Field field in node.mixin.fields) {
       if (field.isStatic) continue;
-      interfaceGettersAndCalls[node][field.name] = <Member>[field];
+      interfaceGettersAndCalls[node]![field.name] = <Member>[field];
       if (!field.isFinal) {
-        interfaceSetters[node][field.name] = <Member>[field];
+        interfaceSetters[node]![field.name] = <Member>[field];
       }
     }
   }
 
   bool isSubclassOf(Class subtype, Class supertype) {
-    return superclasses[subtype].contains(supertype);
+    return superclasses[subtype]!.contains(supertype);
   }
 
   bool isSubmixtureOf(Class subtype, Class supertype) {
-    return superMixtures[subtype].contains(supertype);
+    return superMixtures[subtype]!.contains(supertype);
   }
 
   bool isSubtypeOf(Class subtype, Class supertype) {
-    return supertypes[subtype].contains(supertype);
+    return supertypes[subtype]!.contains(supertype);
   }
 
-  Supertype getClassAsInstanceOf(Class type, Class supertype) {
-    return supertypeInstantiations[type][supertype];
+  Supertype? getClassAsInstanceOf(Class type, Class supertype) {
+    return supertypeInstantiations[type]![supertype];
   }
 
-  Member getDispatchTarget(Class class_, Name name, {bool setter: false}) {
-    return setter ? setters[class_][name] : gettersAndCalls[class_][name];
+  Member? getDispatchTarget(Class class_, Name name, {bool setter: false}) {
+    return setter ? setters[class_]![name] : gettersAndCalls[class_]![name];
   }
 
   List<Member> getDispatchTargets(Class class_, {bool setters: false}) {
     return setters
-        ? this.setters[class_].values
-        : gettersAndCalls[class_].values;
+        ? this.setters[class_]!.values.toList()
+        : gettersAndCalls[class_]!.values.toList();
   }
 
-  Member tryFirst(List<Member> members) {
-    return (members == null || members.isEmpty) ? null : members[0];
+  Member? tryFirst(Iterable<Member>? members) {
+    return (members == null || members.isEmpty) ? null : members.first;
   }
 
-  Member getInterfaceMember(Class class_, Name name, {bool setter: false}) {
+  Member? getInterfaceMember(Class class_, Name name, {bool setter: false}) {
     return tryFirst(getInterfaceMembersByName(class_, name, setter: setter));
   }
 
   Iterable<Member> getInterfaceMembersByName(Class class_, Name name,
       {bool setter: false}) {
     var iterable = setter
-        ? interfaceSetters[class_][name]
-        : interfaceGettersAndCalls[class_][name];
+        ? interfaceSetters[class_]![name]
+        : interfaceGettersAndCalls[class_]![name];
     return iterable == null ? const <Member>[] : iterable;
   }
 
   List<Member> getInterfaceMembers(Class class_, {bool setters: false}) {
     return setters
-        ? interfaceSetters[class_].values.expand((x) => x)
-        : interfaceGettersAndCalls[class_].values.expand((x) => x);
+        ? interfaceSetters[class_]!.values.expand((x) => x).toList()
+        : interfaceGettersAndCalls[class_]!.values.expand((x) => x).toList();
   }
 
   int getClassIndex(Class node) {
-    return classIndex[node];
+    return classIndex[node]!;
   }
 
   List<int> getExpenseHistogram() => <int>[];
diff --git a/pkg/kernel/test/class_hierarchy_bench.dart b/pkg/kernel/test/class_hierarchy_bench.dart
index 97d3dcd..f6bf037 100644
--- a/pkg/kernel/test/class_hierarchy_bench.dart
+++ b/pkg/kernel/test/class_hierarchy_bench.dart
@@ -3,8 +3,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 'package:kernel/kernel.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
@@ -61,7 +59,8 @@
   int hierarchyCount = int.parse(options['cycle']);
   var hierarchies = <ClosedWorldClassHierarchy>[];
   for (int i = 0; i < hierarchyCount; i++) {
-    hierarchies.add(buildHierarchy());
+    // TODO(johnniwinther): This doesn't work for the [BasicClassHierarchy].
+    hierarchies.add(buildHierarchy() as ClosedWorldClassHierarchy);
   }
 
   List<Class> classes = hierarchies.first.classes.toList();
@@ -246,13 +245,13 @@
     classIds[class_] = classIds.length;
   }
 
-  List<int> depth = new List.filled(classes.length, null);
+  List<int> depth = new List.filled(classes.length, /* dummy value = */ 0);
   for (int i = 0; i < depth.length; ++i) {
     int parentDepth = 0;
     var classNode = classes[i];
     for (var supertype in classNode.supers) {
       var superclass = supertype.classNode;
-      int index = classIds[superclass];
+      int index = classIds[superclass]!;
       if (!(index < i)) {
         throw '${classNode.name}($i) extends ${superclass.name}($index)';
       }
@@ -264,7 +263,7 @@
   List<int> depthHistogram = getHistogramOf(depth);
   double averageDepth = average(depth);
   double medianDepth = median(depth);
-  int totalDepth = sum(depth);
+  int totalDepth = sum(depth) as int;
 
   int numberOfClasses = classes.length;
   String expenseHistogram =
diff --git a/pkg/kernel/test/class_hierarchy_membench.dart b/pkg/kernel/test/class_hierarchy_membench.dart
index 2c65048..0e6aefa 100644
--- a/pkg/kernel/test/class_hierarchy_membench.dart
+++ b/pkg/kernel/test/class_hierarchy_membench.dart
@@ -3,8 +3,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 'package:kernel/kernel.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
@@ -53,7 +51,8 @@
 
   List<ClosedWorldClassHierarchy> keepAlive = <ClosedWorldClassHierarchy>[];
   for (int i = 0; i < copyCount; ++i) {
-    keepAlive.add(buildHierarchy());
+    // TODO(johnniwinther): This doesn't work for the [BasicClassHierarchy].
+    keepAlive.add(buildHierarchy() as ClosedWorldClassHierarchy);
   }
 
   print('$copyCount copies built');
diff --git a/pkg/kernel/test/class_hierarchy_self_check.dart b/pkg/kernel/test/class_hierarchy_self_check.dart
index 182a2b7..4cea403 100644
--- a/pkg/kernel/test/class_hierarchy_self_check.dart
+++ b/pkg/kernel/test/class_hierarchy_self_check.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 'package:kernel/kernel.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
@@ -23,7 +21,7 @@
   BasicClassHierarchy basic = new BasicClassHierarchy(component);
   CoreTypes coreTypes = new CoreTypes(component);
   ClosedWorldClassHierarchy classHierarchy =
-      new ClassHierarchy(component, coreTypes);
+      new ClassHierarchy(component, coreTypes) as ClosedWorldClassHierarchy;
   int total = classHierarchy.numberOfClasses;
   int progress = 0;
   for (var class1 in classHierarchy.classes) {
@@ -60,18 +58,18 @@
   progress = 0;
   for (var classNode in classHierarchy.classes) {
     Iterable<Name> candidateNames = <Iterable<Name>>[
-      basic.gettersAndCalls[classNode].keys,
-      basic.setters[classNode].keys,
+      basic.gettersAndCalls[classNode]!.keys,
+      basic.setters[classNode]!.keys,
       pickRandom(nameList, 100)
     ].expand((x) => x);
     for (Name name in candidateNames) {
-      Member expectedGetter =
+      Member? expectedGetter =
           basic.getDispatchTarget(classNode, name, setter: false);
-      Member expectedSetter =
+      Member? expectedSetter =
           basic.getDispatchTarget(classNode, name, setter: true);
-      Member actualGetter =
+      Member? actualGetter =
           classHierarchy.getDispatchTarget(classNode, name, setter: false);
-      Member actualSetter =
+      Member? actualSetter =
           classHierarchy.getDispatchTarget(classNode, name, setter: true);
       if (actualGetter != expectedGetter) {
         fail('lookupGetter($classNode, $name) returned '
@@ -90,18 +88,18 @@
   progress = 0;
   for (var classNode in classHierarchy.classes) {
     Iterable<Name> candidateNames = [
-      basic.interfaceGettersAndCalls[classNode].keys,
-      basic.interfaceSetters[classNode].keys,
+      basic.interfaceGettersAndCalls[classNode]!.keys,
+      basic.interfaceSetters[classNode]!.keys,
       pickRandom(nameList, 100)
     ].expand((x) => x);
     for (Name name in candidateNames) {
-      Member expectedGetter =
+      Member? expectedGetter =
           basic.getInterfaceMember(classNode, name, setter: false);
-      Member expectedSetter =
+      Member? expectedSetter =
           basic.getInterfaceMember(classNode, name, setter: true);
-      Member actualGetter =
+      Member? actualGetter =
           classHierarchy.getInterfaceMember(classNode, name, setter: false);
-      Member actualSetter =
+      Member? actualSetter =
           classHierarchy.getInterfaceMember(classNode, name, setter: true);
       if (actualGetter != expectedGetter) {
         fail('getInterfaceMember($classNode, $name) returned '
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index 65b263d..f5a2bc5 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_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 "package:expect/minitest.dart";
 
 import "package:kernel/ast.dart";
@@ -82,11 +80,11 @@
 
 class ClosedWorldClassHierarchyTest {
   final Component component = createMockSdkComponent();
-  CoreTypes coreTypes;
+  late CoreTypes coreTypes;
 
-  Library library;
+  late Library library;
 
-  ClassHierarchy _hierarchy;
+  ClassHierarchy? _hierarchy;
 
   ClosedWorldClassHierarchyTest() {
     coreTypes = new CoreTypes(component);
@@ -335,8 +333,9 @@
   /// The [TypeParameterType]s corresponding to [typeParameterNames] are
   /// passed to optional [extends_] and [implements_] callbacks.
   Class addGenericClass(String name, List<String> typeParameterNames,
-      {Supertype extends_(List<DartType> typeParameterTypes),
-      List<Supertype> implements_(List<DartType> typeParameterTypes)}) {
+      {Supertype Function(List<DartType> typeParameterTypes)? extends_,
+      List<Supertype> Function(List<DartType> typeParameterTypes)?
+          implements_}) {
     var typeParameters = typeParameterNames
         .map((name) => new TypeParameter(
             name, coreTypes.objectLegacyRawType, coreTypes.objectLegacyRawType))
diff --git a/pkg/kernel/test/class_hierarchy_test_disabled.dart b/pkg/kernel/test/class_hierarchy_test_disabled.dart
index 5cba5d7..40155b0 100644
--- a/pkg/kernel/test/class_hierarchy_test_disabled.dart
+++ b/pkg/kernel/test/class_hierarchy_test_disabled.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 'package:kernel/kernel.dart';
 import 'package:test/test.dart';
 import 'class_hierarchy_self_check.dart';
diff --git a/pkg/kernel/test/constant_equals_test.dart b/pkg/kernel/test/constant_equals_test.dart
index 689ae71..80611c6 100644
--- a/pkg/kernel/test/constant_equals_test.dart
+++ b/pkg/kernel/test/constant_equals_test.dart
@@ -8,6 +8,9 @@
   if (a != b) {
     throw 'Expected $a and $b to be equal.';
   }
+  if (a.hashCode != b.hashCode) {
+    throw 'Expected $a and $b hash codes to be equal.';
+  }
 }
 
 testNotEquals(Constant a, Constant b) {
@@ -33,10 +36,29 @@
       fileUri: uri,
       isStatic: true);
 
+  Class cls = new Class(name: 'Class', fileUri: uri);
+  Procedure factory = new Procedure(
+      new Name('foo'), ProcedureKind.Factory, new FunctionNode(null),
+      fileUri: uri, isStatic: true);
+  cls.addProcedure(factory);
+  Constructor constructor = new Constructor(new FunctionNode(null),
+      name: new Name('foo'), fileUri: uri);
+  cls.addConstructor(constructor);
+  Procedure redirectingFactory = new Procedure(
+      new Name('foo'), ProcedureKind.Factory, new FunctionNode(null),
+      fileUri: uri, isStatic: true)
+    ..isRedirectingFactory = true;
+  cls.addProcedure(redirectingFactory);
+
   TearOffConstant tearOffConstant1a = new StaticTearOffConstant(procedure1);
   TearOffConstant tearOffConstant1b = new StaticTearOffConstant(procedure1);
   TearOffConstant tearOffConstant2 = new StaticTearOffConstant(procedure2);
   TearOffConstant tearOffConstant3 = new StaticTearOffConstant(procedure3);
+  TearOffConstant tearOffConstant4 =
+      new ConstructorTearOffConstant(constructor);
+  TearOffConstant tearOffConstant5 = new ConstructorTearOffConstant(factory);
+  TearOffConstant tearOffConstant6 =
+      new RedirectingFactoryTearOffConstant(redirectingFactory);
 
   // foo() {}
   // const a = foo;
@@ -161,5 +183,13 @@
             [typeParameter2a, typeParameter2b],
             tearOffConstant3,
             [new TypeParameterType(typeParameter2b, Nullability.nullable)]));
+
+    testEquals(tearOffConstant4, tearOffConstant4);
+    testEquals(tearOffConstant5, tearOffConstant5);
+    testEquals(tearOffConstant6, tearOffConstant6);
+
+    testNotEquals(tearOffConstant4, tearOffConstant5);
+    testNotEquals(tearOffConstant4, tearOffConstant6);
+    testNotEquals(tearOffConstant5, tearOffConstant6);
   }
 }
diff --git a/pkg/kernel/test/convert_field_to_setter_getter.dart b/pkg/kernel/test/convert_field_to_setter_getter.dart
index d7e7fd7..89f1fd9 100644
--- a/pkg/kernel/test/convert_field_to_setter_getter.dart
+++ b/pkg/kernel/test/convert_field_to_setter_getter.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 'package:kernel/binary/ast_from_binary.dart';
 import 'package:kernel/binary/ast_to_binary.dart';
 import 'binary/utils.dart';
@@ -42,14 +40,16 @@
   // Canonical names are now set: Verify that the field is marked as such,
   // canonical-name-wise.
   String getterCanonicalName = '${field.getterReference.canonicalName}';
-  if (field.getterReference.canonicalName.parent.name != "@getters") {
-    throw "Expected @getters parent, but had "
-        "${field.getterReference.canonicalName.parent.name}";
+  if (field.getterReference.canonicalName!.parent!.name !=
+      CanonicalName.gettersName) {
+    throw "Expected ${CanonicalName.gettersName} parent, but had "
+        "${field.getterReference.canonicalName!.parent!.name}";
   }
-  String setterCanonicalName = '${field.setterReference.canonicalName}';
-  if (field.setterReference.canonicalName.parent.name != "@setters") {
-    throw "Expected @setters parent, but had "
-        "${field.setterReference.canonicalName.parent.name}";
+  String setterCanonicalName = '${field.setterReference!.canonicalName}';
+  if (field.setterReference!.canonicalName!.parent!.name !=
+      CanonicalName.settersName) {
+    throw "Expected ${CanonicalName.settersName} parent, but had "
+        "${field.setterReference!.canonicalName!.parent!.name}";
   }
 
   // Replace the field with a setter/getter pair.
@@ -65,7 +65,7 @@
   // a setter/getter), the reference wouldn't (because of the way `bindTo` is
   // implemented) actually have it's canonical name set, and serialization
   // wouldn't work.)
-  field.getterReference?.canonicalName?.unbind();
+  field.getterReference.canonicalName?.unbind();
   lib1.addProcedure(getter);
 
   FunctionNode setterFunction = new FunctionNode(new Block([]),
@@ -82,18 +82,18 @@
   List<int> writtenBytesGetterSetter = serialize(lib1, lib2);
   // Canonical names are now set: Verify that the getter/setter is marked as
   // such, canonical-name-wise.
-  if (getter.reference.canonicalName.parent.name != "@getters") {
+  if (getter.reference.canonicalName!.parent!.name != "@getters") {
     throw "Expected @getters parent, but had "
-        "${getter.reference.canonicalName.parent.name}";
+        "${getter.reference.canonicalName!.parent!.name}";
   }
   if ('${getter.reference.canonicalName}' != getterCanonicalName) {
     throw "Unexpected getter canonical name. "
         "Expected $getterCanonicalName, "
         "actual ${getter.reference.canonicalName}.";
   }
-  if (setter.reference.canonicalName.parent.name != "@setters") {
+  if (setter.reference.canonicalName!.parent!.name != "@setters") {
     throw "Expected @setters parent, but had "
-        "${setter.reference.canonicalName.parent.name}";
+        "${setter.reference.canonicalName!.parent!.name}";
   }
   if ('${setter.reference.canonicalName}' != setterCanonicalName) {
     throw "Unexpected setter canonical name. "
@@ -110,7 +110,7 @@
       fileUri: lib1Uri);
   // Important: Unbind any old canonical name
   // (nulling out the canonical name is not enough, see above).
-  fieldReplacement.getterReference?.canonicalName?.unbind();
+  fieldReplacement.getterReference.canonicalName?.unbind();
   fieldReplacement.setterReference?.canonicalName?.unbind();
   lib1.addField(fieldReplacement);
 
@@ -119,15 +119,15 @@
   List<int> writtenBytesFieldNew = serialize(lib1, lib2);
   // Canonical names are now set: Verify that the field is marked as such,
   // canonical-name-wise.
-  if (fieldReplacement.getterReference.canonicalName.parent.name !=
+  if (fieldReplacement.getterReference.canonicalName!.parent!.name !=
       "@getters") {
     throw "Expected @getters parent, but had "
-        "${fieldReplacement.getterReference.canonicalName.parent.name}";
+        "${fieldReplacement.getterReference.canonicalName!.parent!.name}";
   }
-  if (fieldReplacement.setterReference.canonicalName.parent.name !=
+  if (fieldReplacement.setterReference!.canonicalName!.parent!.name !=
       "@setters") {
     throw "Expected @setters parent, but had "
-        "${fieldReplacement.setterReference.canonicalName.parent.name}";
+        "${fieldReplacement.setterReference!.canonicalName!.parent!.name}";
   }
 
   // Load the written stuff and ensure it is as expected.
@@ -188,15 +188,16 @@
 }
 
 Member getSetTarget(Procedure p) {
-  Block block = p.function.body;
-  ExpressionStatement getterStatement = block.statements[0];
-  StaticSet staticSet = getterStatement.expression;
+  Block block = p.function.body as Block;
+  ExpressionStatement getterStatement =
+      block.statements[0] as ExpressionStatement;
+  StaticSet staticSet = getterStatement.expression as StaticSet;
   return staticSet.target;
 }
 
 Member getGetTarget(Procedure p) {
-  Block block = p.function.body;
-  ReturnStatement setterStatement = block.statements[1];
-  StaticGet staticGet = setterStatement.expression;
+  Block block = p.function.body as Block;
+  ReturnStatement setterStatement = block.statements[1] as ReturnStatement;
+  StaticGet staticGet = setterStatement.expression as StaticGet;
   return staticGet.target;
 }
diff --git a/pkg/kernel/test/dart_type_equivalence_test.dart b/pkg/kernel/test/dart_type_equivalence_test.dart
index acf4b96..41a7a01 100644
--- a/pkg/kernel/test/dart_type_equivalence_test.dart
+++ b/pkg/kernel/test/dart_type_equivalence_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 "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/equivalence_test.dart b/pkg/kernel/test/equivalence_test.dart
new file mode 100644
index 0000000..de5ec47
--- /dev/null
+++ b/pkg/kernel/test/equivalence_test.dart
@@ -0,0 +1,204 @@
+// 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:expect/expect.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/src/equivalence.dart';
+
+final Component component1 = createComponent();
+final Component component2 = createComponent();
+
+List<Test> tests = [
+  Test(IntLiteral(0), IntLiteral(0)),
+  Test(IntLiteral(42), IntLiteral(42)),
+  Test(IntLiteral(0), IntLiteral(42), inequivalence: '''
+Values 0 and 42 are not equivalent
+.root
+ IntLiteral.value
+'''),
+  Test(StringLiteral('0'), StringLiteral('0')),
+  Test(StringLiteral('42'), StringLiteral('42')),
+  Test(StringLiteral('0'), StringLiteral('42'), inequivalence: '''
+Values 0 and 42 are not equivalent
+.root
+ StringLiteral.value
+'''),
+  Test(IntLiteral(0), IntLiteral(42), strategy: const IgnoreIntLiteralValue()),
+  Test(StringLiteral('0'), StringLiteral('42'),
+      strategy: const IgnoreIntLiteralValue(), inequivalence: '''
+Values 0 and 42 are not equivalent
+.root
+ StringLiteral.value
+'''),
+  Test(IntLiteral(0), StringLiteral('0'), inequivalence: '''
+Inequivalent nodes
+1: IntLiteral(0)
+2: StringLiteral("0")
+.root
+'''),
+  Test(Not(Not(Not(BoolLiteral(true)))), Not(Not(Not(BoolLiteral(true))))),
+  Test(Not(Not(BoolLiteral(true))), Not(Not(Not(BoolLiteral(true)))),
+      inequivalence: '''
+Inequivalent nodes
+1: BoolLiteral(true)
+2: Not(!true)
+.root
+ Not.operand
+  Not.operand
+'''),
+  Test(Not(Not(Not(BoolLiteral(true)))), Not(Not(BoolLiteral(true))),
+      inequivalence: '''
+Inequivalent nodes
+1: Not(!true)
+2: BoolLiteral(true)
+.root
+ Not.operand
+  Not.operand
+'''),
+  Test(Not(Not(Not(BoolLiteral(true)))), Not(Not(Not(BoolLiteral(false)))),
+      inequivalence: '''
+Values true and false are not equivalent
+.root
+ Not.operand
+  Not.operand
+   Not.operand
+    BoolLiteral.value
+'''),
+  Test(component1, component2),
+  Test(component1.libraries[0], component2.libraries[0]),
+  Test(component1.libraries[0], component2.libraries[0]),
+  Test(component1.libraries[0], component2.libraries[1], inequivalence: '''
+Inequivalent nodes
+1: library file://uri1/
+2: library file://uri2/
+.root
+'''),
+  Test(component1.libraries[1], component2.libraries[2], inequivalence: '''
+Inequivalent nodes
+1: library file://uri2/
+2: library file://uri3/
+.root
+'''),
+  Test(component1.libraries[1], component2.libraries[3], inequivalence: '''
+Values file://uri2/ and file://uri3/ are not equivalent
+.root
+ Library(library file://uri2/).fileUri
+'''),
+  Test(component1.libraries[0].procedures[0],
+      component2.libraries[0].procedures[1],
+      inequivalence: '''
+Inequivalent nodes
+1: foo
+2: bar
+.root
+'''),
+  // TODO(johnniwinther): Improve message for inequivalent references with the
+  // same simple name.
+  Test(component1.libraries[0].procedures[0],
+      component2.libraries[2].procedures[0],
+      inequivalence: '''
+Inequivalent nodes
+1: foo
+2: foo
+.root
+'''),
+  Test(StaticTearOff.byReference(Reference()),
+      StaticTearOff.byReference(Reference())),
+  Test(
+      StaticTearOff.byReference(
+          component1.libraries[0].procedures[0].reference),
+      StaticTearOff.byReference(
+          component2.libraries[0].procedures[0].reference)),
+  // TODO(johnniwinther): Improve message for inequivalent references with the
+  // same simple name.
+  Test(
+      StaticTearOff.byReference(
+          component1.libraries[0].procedures[0].reference),
+      StaticTearOff.byReference(
+          component2.libraries[2].procedures[0].reference),
+      inequivalence: '''
+Inequivalent references:
+1: Reference to foo
+2: Reference to foo
+.root
+ StaticTearOff.targetReference
+'''),
+];
+
+main() {
+  for (Test test in tests) {
+    EquivalenceResult result =
+        checkEquivalence(test.a, test.b, strategy: test.strategy);
+    if (test.isEquivalent) {
+      Expect.equals(result.isEquivalent, test.isEquivalent,
+          'Unexpected result for\n${test.a}\n${test.b}:\n$result');
+    } else if (result.isEquivalent) {
+      Expect.equals(
+          result.isEquivalent,
+          test.isEquivalent,
+          'Unexpected equivalence for\n${test.a}\n${test.b}:\n'
+          'Expected ${test.inequivalence}');
+    } else {
+      Expect.stringEquals(
+          result.toString(),
+          test.inequivalence!,
+          'Unexpected inequivalence result for\n${test.a}\n${test.b}:\n'
+          'Expected:\n---\n${test.inequivalence}\n---\n'
+          'Actual:\n---\n${result}\n---');
+    }
+  }
+}
+
+class Test {
+  final Node a;
+  final Node b;
+  final String? inequivalence;
+  final EquivalenceStrategy strategy;
+
+  Test(this.a, this.b,
+      {this.inequivalence, this.strategy = const EquivalenceStrategy()});
+
+  bool get isEquivalent => inequivalence == null;
+}
+
+class IgnoreIntLiteralValue extends EquivalenceStrategy {
+  const IgnoreIntLiteralValue();
+
+  @override
+  bool checkIntLiteral_value(
+          EquivalenceVisitor visitor, IntLiteral a, IntLiteral b) =>
+      true;
+}
+
+Component createComponent() {
+  Component component = new Component();
+  Uri uri1 = Uri.parse('file://uri1');
+  Uri uri2 = Uri.parse('file://uri2');
+  Uri uri3 = Uri.parse('file://uri3');
+  Library library1 = new Library(uri1, fileUri: uri1);
+  component.libraries.add(library1);
+  Procedure procedure1foo = new Procedure(
+      new Name('foo'), ProcedureKind.Method, new FunctionNode(null),
+      fileUri: uri1);
+  library1.addProcedure(procedure1foo);
+  Procedure procedure1bar = new Procedure(
+      new Name('bar'), ProcedureKind.Method, new FunctionNode(null),
+      fileUri: uri1);
+  library1.addProcedure(procedure1bar);
+
+  Library library2 = new Library(uri2, fileUri: uri2);
+  component.libraries.add(library2);
+
+  Library library3 = new Library(uri3, fileUri: uri2);
+  component.libraries.add(library3);
+  Procedure procedure3foo = new Procedure(
+      new Name('foo'), ProcedureKind.Method, new FunctionNode(null),
+      fileUri: uri1);
+  library3.addProcedure(procedure3foo);
+
+  Library library4 = new Library(uri2, fileUri: uri3);
+  component.libraries.add(library4);
+
+  return component;
+}
diff --git a/pkg/kernel/test/equivalent_dill_test.dart b/pkg/kernel/test/equivalent_dill_test.dart
new file mode 100644
index 0000000..baac8b3
--- /dev/null
+++ b/pkg/kernel/test/equivalent_dill_test.dart
@@ -0,0 +1,112 @@
+// 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.
+
+// @dart = 2.9
+
+import 'dart:io';
+
+import 'package:kernel/binary/ast_from_binary.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/src/equivalence.dart';
+
+main(List<String> args) {
+  String resolvedExecutable = Platform.environment['resolvedExecutable'];
+  File exe =
+      new File(resolvedExecutable ?? Platform.resolvedExecutable).absolute;
+  int steps = 0;
+  Directory parent = exe.parent.parent;
+  while (true) {
+    Set<String> foundDirs = {};
+    for (FileSystemEntity entry in parent.listSync(recursive: false)) {
+      if (entry is Directory) {
+        List<String> pathSegments = entry.uri.pathSegments;
+        String name = pathSegments[pathSegments.length - 2];
+        foundDirs.add(name);
+      }
+    }
+    if (foundDirs.contains("pkg") &&
+        foundDirs.contains("tools") &&
+        foundDirs.contains("tests")) {
+      break;
+    }
+    steps++;
+    if (parent.uri == parent.parent.uri) {
+      throw "Reached end without finding the root.";
+    }
+    parent = parent.parent;
+  }
+  // We had to go $steps steps to reach the "root" --- now we should go 2 steps
+  // shorter to be in the "compiled dir".
+  parent = exe.parent;
+  for (int i = steps - 2; i >= 0; i--) {
+    parent = parent.parent;
+  }
+
+  List<File> dills = [];
+  for (FileSystemEntity entry in parent.listSync(recursive: false)) {
+    if (entry is File) {
+      if (entry.path.toLowerCase().endsWith(".dill")) {
+        dills.add(entry);
+      }
+    }
+  }
+  Directory sdk = new Directory.fromUri(parent.uri.resolve("dart-sdk/"));
+  for (FileSystemEntity entry in sdk.listSync(recursive: true)) {
+    if (entry is File) {
+      if (entry.path.toLowerCase().endsWith(".dill")) {
+        dills.add(entry);
+      }
+    }
+  }
+
+  print("Found ${dills.length} dills!");
+
+  List<File> errors = [];
+  for (File dill in dills) {
+    if (args.isNotEmpty &&
+        !args.any((arg) => dill.absolute.path.endsWith(arg))) {
+      print('Skipping $dill');
+      continue;
+    }
+    if (!canRead(dill)) {
+      errors.add(dill);
+    }
+  }
+  if (errors.isEmpty) {
+    print("Read all OK.");
+  } else {
+    print("Errors when reading:");
+    for (File error in errors) {
+      print(error);
+    }
+    exitCode = 1;
+  }
+}
+
+bool canRead(File dill) {
+  print("Reading $dill");
+  List<int> bytes = dill.readAsBytesSync();
+
+  try {
+    Component component1 = new Component();
+    new BinaryBuilder(bytes).readComponent(component1);
+
+    Component component2 = new Component();
+    new BinaryBuilder(bytes).readComponent(component2);
+
+    EquivalenceResult result = checkEquivalence(component1, component2);
+    if (!result.isEquivalent) {
+      print(result);
+    }
+    return result.isEquivalent;
+  } catch (e, st) {
+    print("Error for $dill:");
+    print(e);
+    print(st);
+    print("");
+    print("--------------------");
+    print("");
+    return false;
+  }
+}
diff --git a/pkg/kernel/test/flatten_test.dart b/pkg/kernel/test/flatten_test.dart
index 2dd50b8..2c5c656 100644
--- a/pkg/kernel/test/flatten_test.dart
+++ b/pkg/kernel/test/flatten_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 "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart';
@@ -62,7 +60,7 @@
 class Test {
   final String input;
   final String output;
-  final String typeParameters;
+  final String? typeParameters;
 
   const Test(this.input, this.output, [this.typeParameters]);
 }
diff --git a/pkg/kernel/test/future_value_type_test.dart b/pkg/kernel/test/future_value_type_test.dart
index f256cfe..9d0e32e 100644
--- a/pkg/kernel/test/future_value_type_test.dart
+++ b/pkg/kernel/test/future_value_type_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 "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/graph_test.dart b/pkg/kernel/test/graph_test.dart
index 28668f6..1dc79f9 100644
--- a/pkg/kernel/test/graph_test.dart
+++ b/pkg/kernel/test/graph_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.md file.
 
-// @dart = 2.9
-
 library kernel.test.graph_test;
 
 import 'package:expect/expect.dart' show Expect;
@@ -17,7 +15,7 @@
 
   Iterable<String> get vertices => graph.keys;
 
-  Iterable<String> neighborsOf(String vertex) => graph[vertex];
+  Iterable<String> neighborsOf(String vertex) => graph[vertex]!;
 }
 
 void test(String expected, Map<String, List<String>> graph) {
diff --git a/pkg/kernel/test/heap_test.dart b/pkg/kernel/test/heap_test.dart
index 95071ef..32b294e 100644
--- a/pkg/kernel/test/heap_test.dart
+++ b/pkg/kernel/test/heap_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 'package:kernel/src/heap.dart';
 import 'package:test/test.dart';
 
diff --git a/pkg/kernel/test/import_table_test.dart b/pkg/kernel/test/import_table_test.dart
index 62c10f0..c64f614 100644
--- a/pkg/kernel/test/import_table_test.dart
+++ b/pkg/kernel/test/import_table_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 'package:kernel/import_table.dart';
 
 main() {
diff --git a/pkg/compiler/test/model/indentation_test.dart b/pkg/kernel/test/indentation_test.dart
similarity index 88%
rename from pkg/compiler/test/model/indentation_test.dart
rename to pkg/kernel/test/indentation_test.dart
index 98a4f41..94bf983 100644
--- a/pkg/compiler/test/model/indentation_test.dart
+++ b/pkg/kernel/test/indentation_test.dart
@@ -2,10 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.7
-
-import "package:expect/expect.dart";
-import 'package:compiler/src/util/util.dart' show Indentation;
+import 'package:expect/expect.dart';
+import 'package:kernel/text/indentation.dart' show Indentation;
 
 main() {
   Indentation ind = new Indentation();
diff --git a/pkg/kernel/test/legacy_erasure_test.dart b/pkg/kernel/test/legacy_erasure_test.dart
index 4e14b3b..24b1a33 100644
--- a/pkg/kernel/test/legacy_erasure_test.dart
+++ b/pkg/kernel/test/legacy_erasure_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 "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/load_concat_dill_keeps_source_test.dart b/pkg/kernel/test/load_concat_dill_keeps_source_test.dart
index 0c2dc97..e8debc6 100644
--- a/pkg/kernel/test/load_concat_dill_keeps_source_test.dart
+++ b/pkg/kernel/test/load_concat_dill_keeps_source_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
-
 // Test that 79cc54e51924cd5a6bdc2bd1771f2d0ee7af8899 works as intended.
 
 import 'dart:convert';
@@ -67,16 +65,16 @@
   builder.readComponent(tmp);
   if (tmp.uriToSource[uri1] == null) throw "No data for $uri1";
   if (tmp.uriToSource[uri2] == null) throw "No data for $uri2";
-  if (expect1 && tmp.uriToSource[uri1].source.isEmpty) {
+  if (expect1 && tmp.uriToSource[uri1]!.source.isEmpty) {
     throw "No data for $uri1";
   }
-  if (!expect1 && tmp.uriToSource[uri1].source.isNotEmpty) {
+  if (!expect1 && tmp.uriToSource[uri1]!.source.isNotEmpty) {
     throw "Unexpected data for $uri1";
   }
-  if (expect2 && tmp.uriToSource[uri2].source.isEmpty) {
+  if (expect2 && tmp.uriToSource[uri2]!.source.isEmpty) {
     throw "No data data for $uri2";
   }
-  if (!expect2 && tmp.uriToSource[uri2].source.isNotEmpty) {
+  if (!expect2 && tmp.uriToSource[uri2]!.source.isNotEmpty) {
     throw "Unexpected data for $uri2";
   }
 }
diff --git a/pkg/kernel/test/metadata_test.dart b/pkg/kernel/test/metadata_test.dart
index ed46532..16418c6 100644
--- a/pkg/kernel/test/metadata_test.dart
+++ b/pkg/kernel/test/metadata_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:convert';
 import 'dart:io';
 
@@ -21,10 +19,10 @@
 /// * type representing the first type parameter of its enclosing function
 class Metadata {
   final String string;
-  final Reference _memberRef;
+  final Reference? _memberRef;
   final DartType type;
 
-  Member get member => _memberRef?.asMember;
+  Member? get member => _memberRef?.asMember;
 
   Metadata.forNode(TreeNode n)
       : this(
@@ -36,7 +34,7 @@
   Metadata(this.string, this._memberRef, this.type);
 }
 
-Member getMemberForMetadata(TreeNode node) {
+Member? getMemberForMetadata(TreeNode node) {
   final parent = node.parent;
   if (parent == null) return null;
   if (parent is Member) return parent;
@@ -67,7 +65,7 @@
     sink.writeByteList(utf8.encode(metadata.string));
     sink.writeStringReference(metadata.string);
     sink.writeNullAllowedCanonicalNameReference(
-        metadata.member?.reference?.canonicalName);
+        metadata.member?.reference.canonicalName);
     sink.writeDartType(metadata.type);
   }
 
@@ -116,7 +114,7 @@
 /// [shouldAnnotate] predicate.
 void annotate(Component p, NodePredicate shouldAnnotate) {
   globalDebuggingNames = new NameSystem();
-  final repository = p.metadata[TestMetadataRepository.kTag];
+  final repository = p.metadata[TestMetadataRepository.kTag]!;
   p.accept(new Visitor(shouldAnnotate, (node) {
     repository.mapping[node] = new Metadata.forNode(node);
   }));
@@ -126,7 +124,7 @@
 /// component matching [shouldAnnotate] predicate has correct metadata.
 void validate(Component p, NodePredicate shouldAnnotate) {
   globalDebuggingNames = new NameSystem();
-  final repository = p.metadata[TestMetadataRepository.kTag];
+  final repository = p.metadata[TestMetadataRepository.kTag]!;
   p.accept(new Visitor(shouldAnnotate, (node) {
     final m = repository.mapping[node];
     final expected = new Metadata.forNode(node);
@@ -168,7 +166,7 @@
     final component = fromBinary(platformBinary);
     annotate(component, shouldAnnotate);
     validate(component, shouldAnnotate);
-    expect(component.metadata[TestMetadataRepository.kTag].mapping.length,
+    expect(component.metadata[TestMetadataRepository.kTag]!.mapping.length,
         greaterThan(0));
 
     final annotatedComponentBinary = binaryTransformer(toBinary(component));
@@ -176,7 +174,7 @@
     validate(annotatedComponentFromBinary, shouldAnnotate);
     expect(
         annotatedComponentFromBinary
-            .metadata[TestMetadataRepository.kTag].mapping.length,
+            .metadata[TestMetadataRepository.kTag]!.mapping.length,
         greaterThan(0));
   }
 
diff --git a/pkg/kernel/test/nnbd_top_merge_test.dart b/pkg/kernel/test/nnbd_top_merge_test.dart
index 7fac29a..c6255f1 100644
--- a/pkg/kernel/test/nnbd_top_merge_test.dart
+++ b/pkg/kernel/test/nnbd_top_merge_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 "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart';
@@ -129,8 +127,8 @@
     List<String> parts = input.split(' vs ');
     DartType aType = env.parseType(parts[0]);
     DartType bType = env.parseType(parts[1]);
-    DartType expectedOutputType1;
-    DartType expectedOutputType2;
+    DartType? expectedOutputType1;
+    DartType? expectedOutputType2;
     if (output is List) {
       expectedOutputType1 = env.parseType(output[0]);
       expectedOutputType2 = env.parseType(output[1]);
@@ -138,8 +136,8 @@
       expectedOutputType1 = expectedOutputType2 = env.parseType(output);
     }
 
-    void test(DartType a, DartType b, DartType expectedOutputType) {
-      DartType actualOutputType = nnbdTopMerge(env.coreTypes, a, b);
+    void test(DartType a, DartType b, DartType? expectedOutputType) {
+      DartType? actualOutputType = nnbdTopMerge(env.coreTypes, a, b);
       print('nnbdTopMerge($a,$b) = '
           '$actualOutputType (expected=$expectedOutputType)');
       Expect.equals(
diff --git a/pkg/kernel/test/non_null_test.dart b/pkg/kernel/test/non_null_test.dart
index 5a3dca1..3fc2b89 100644
--- a/pkg/kernel/test/non_null_test.dart
+++ b/pkg/kernel/test/non_null_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/norm_test.dart b/pkg/kernel/test/norm_test.dart
index 0f2cd38..0e1c9b1 100644
--- a/pkg/kernel/test/norm_test.dart
+++ b/pkg/kernel/test/norm_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 "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/regression_40662_test.dart b/pkg/kernel/test/regression_40662_test.dart
deleted file mode 100644
index 77eaf47..0000000
--- a/pkg/kernel/test/regression_40662_test.dart
+++ /dev/null
@@ -1,18 +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 file.
-
-// @dart = 2.9
-
-// Regression test for https://github.com/dart-lang/sdk/issues/40662.
-
-import "package:expect/expect.dart" show Expect;
-
-bar(int a, List<int> b) {
-  Expect.equals(-1, a);
-  Expect.equals(-1, (b[0] - 2));
-}
-
-foo(int x) async => bar(x - 1, x != null ? [x + 1, x + 2, await null] : null);
-
-void main() async => await foo(0);
diff --git a/pkg/kernel/test/relink_test.dart b/pkg/kernel/test/relink_test.dart
index 3f4c9be..47da2a9 100644
--- a/pkg/kernel/test/relink_test.dart
+++ b/pkg/kernel/test/relink_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 'package:kernel/binary/ast_from_binary.dart';
 import 'package:kernel/binary/ast_to_binary.dart';
 import 'package:kernel/src/tool/find_referenced_libraries.dart';
@@ -141,9 +139,11 @@
       Uri.parse('org-dartlang:///main.dart')) {
     throw "Expected main first, got ${component1Prime.libraries[0].importUri}";
   }
-  Block block = component1Prime.libraries[0].procedures[0].function.body;
-  ReturnStatement returnStatement = block.statements[0];
-  StaticInvocation staticInvocation = returnStatement.expression;
+  Block block =
+      component1Prime.libraries[0].procedures[0].function.body as Block;
+  ReturnStatement returnStatement = block.statements[0] as ReturnStatement;
+  StaticInvocation staticInvocation =
+      returnStatement.expression as StaticInvocation;
   Procedure target = staticInvocation.target;
   return target;
 }
diff --git a/pkg/kernel/test/round_trip.dart b/pkg/kernel/test/round_trip.dart
index 3766db0..188a2a1 100644
--- a/pkg/kernel/test/round_trip.dart
+++ b/pkg/kernel/test/round_trip.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
-
 library kernel.round_trip;
 
 import 'dart:io';
@@ -30,7 +28,7 @@
   }
 }
 
-void testRoundTrip(List<int> bytes, List<int> sdkBytes) async {
+Future<void> testRoundTrip(List<int> bytes, List<int>? sdkBytes) async {
   var component = new Component();
   if (sdkBytes != null) {
     var sdk = new Component(nameRoot: component.root);
diff --git a/pkg/kernel/test/round_trip_self_check.dart b/pkg/kernel/test/round_trip_self_check.dart
index da2e0e1..058cef8 100644
--- a/pkg/kernel/test/round_trip_self_check.dart
+++ b/pkg/kernel/test/round_trip_self_check.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
-
 library kernel.round_trip_test;
 
 import 'self_check_util.dart';
diff --git a/pkg/kernel/test/self_check_util.dart b/pkg/kernel/test/self_check_util.dart
index e742142..1ebdd39 100644
--- a/pkg/kernel/test/self_check_util.dart
+++ b/pkg/kernel/test/self_check_util.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 'package:kernel/src/tool/batch_util.dart';
diff --git a/pkg/kernel/test/serialize_bench.dart b/pkg/kernel/test/serialize_bench.dart
index 0a413f9..72853ae 100644
--- a/pkg/kernel/test/serialize_bench.dart
+++ b/pkg/kernel/test/serialize_bench.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 'package:kernel/kernel.dart';
 import 'dart:io';
 
diff --git a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
index ddc5c9f..4261086 100644
--- a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
+++ b/pkg/kernel/test/text_serializer_from_kernel_nodes_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
-
 library kernel.text_serializer_from_kernel_nodes_test;
 
 import 'package:kernel/ast.dart';
@@ -25,14 +23,17 @@
   final TextSerializer<T> serializer;
 
   TestCase(
-      {this.name,
-      this.node,
-      this.expectation,
-      this.serializer,
-      SerializationState Function() makeSerializationState,
-      DeserializationState Function() makeDeserializationState})
+      {required this.name,
+      required this.node,
+      required this.expectation,
+      required this.serializer,
+      SerializationState Function()? makeSerializationState,
+      DeserializationState Function()? makeDeserializationState})
+      // ignore: unnecessary_null_comparison
       : assert(node != null),
+        // ignore: unnecessary_null_comparison
         assert(expectation != null),
+        // ignore: unnecessary_null_comparison
         assert(serializer != null),
         this.makeSerializationState = makeSerializationState ??
             (() => new SerializationState(new SerializationEnvironment(null))),
@@ -75,12 +76,12 @@
     new TestCase<Statement>(
         name: 'let dynamic x = 42 in let Null x^0 = null in x;',
         node: () {
-          VariableDeclaration outterLetVar = new VariableDeclaration('x',
+          VariableDeclaration outerLetVar = new VariableDeclaration('x',
               type: const DynamicType(), initializer: new IntLiteral(42));
           VariableDeclaration innerLetVar = new VariableDeclaration('x',
               type: const NullType(), initializer: new NullLiteral());
-          return new ExpressionStatement(new Let(outterLetVar,
-              new Let(innerLetVar, new VariableGet(outterLetVar))));
+          return new ExpressionStatement(new Let(
+              outerLetVar, new Let(innerLetVar, new VariableGet(outerLetVar))));
         }(),
         expectation: ''
             '(expr (let "x^0" () (dynamic) (int 42) ()'
@@ -90,12 +91,12 @@
     new TestCase<Statement>(
         name: 'let dynamic x = 42 in let Null x^0 = null in x^0;',
         node: () {
-          VariableDeclaration outterLetVar = new VariableDeclaration('x',
+          VariableDeclaration outerLetVar = new VariableDeclaration('x',
               type: const DynamicType(), initializer: new IntLiteral(42));
           VariableDeclaration innerLetVar = new VariableDeclaration('x',
               type: const NullType(), initializer: new NullLiteral());
-          return new ExpressionStatement(new Let(outterLetVar,
-              new Let(innerLetVar, new VariableGet(innerLetVar))));
+          return new ExpressionStatement(new Let(
+              outerLetVar, new Let(innerLetVar, new VariableGet(innerLetVar))));
         }(),
         expectation: ''
             '(expr (let "x^0" () (dynamic) (int 42) ()'
@@ -133,9 +134,10 @@
           node: new ExpressionStatement(new StaticGet(field)),
           expectation: ''
               '(expr (get-static "package:foo/bar.dart::@getters::field"))',
-          makeSerializationState: () => new SerializationState(null),
-          makeDeserializationState: () =>
-              new DeserializationState(null, component.root),
+          makeSerializationState: () =>
+              new SerializationState(new SerializationEnvironment(null)),
+          makeDeserializationState: () => new DeserializationState(
+              new DeserializationEnvironment(null), component.root),
           serializer: statementSerializer);
     }(),
     () {
@@ -150,9 +152,10 @@
           node: new ExpressionStatement(new StaticGet(field)),
           expectation: ''
               '(expr (get-static "package:foo/bar.dart::@getters::field"))',
-          makeSerializationState: () => new SerializationState(null),
-          makeDeserializationState: () =>
-              new DeserializationState(null, component.root),
+          makeSerializationState: () =>
+              new SerializationState(new SerializationEnvironment(null)),
+          makeDeserializationState: () => new DeserializationState(
+              new DeserializationEnvironment(null), component.root),
           serializer: statementSerializer);
     }(),
     () {
@@ -169,9 +172,10 @@
           expectation: ''
               '(expr'
               ' (set-static "package:foo/bar.dart::@setters::field" (int 1)))',
-          makeSerializationState: () => new SerializationState(null),
-          makeDeserializationState: () =>
-              new DeserializationState(null, component.root),
+          makeSerializationState: () =>
+              new SerializationState(new SerializationEnvironment(null)),
+          makeDeserializationState: () => new DeserializationState(
+              new DeserializationEnvironment(null), component.root),
           serializer: statementSerializer);
     }(),
     () {
@@ -197,9 +201,10 @@
           expectation: ''
               '(expr (invoke-static "package:foo/bar.dart::@methods::foo"'
               ' () ((int 42)) ()))',
-          makeSerializationState: () => new SerializationState(null),
-          makeDeserializationState: () =>
-              new DeserializationState(null, component.root),
+          makeSerializationState: () =>
+              new SerializationState(new SerializationEnvironment(null)),
+          makeDeserializationState: () => new DeserializationState(
+              new DeserializationEnvironment(null), component.root),
           serializer: statementSerializer);
     }(),
     () {
@@ -222,9 +227,10 @@
               '(expr (invoke-const-static'
               ' "package:foo/bar.dart::A::@factories::foo"'
               ' () () ()))',
-          makeSerializationState: () => new SerializationState(null),
-          makeDeserializationState: () =>
-              new DeserializationState(null, component.root),
+          makeSerializationState: () =>
+              new SerializationState(new SerializationEnvironment(null)),
+          makeDeserializationState: () => new DeserializationState(
+              new DeserializationEnvironment(null), component.root),
           serializer: statementSerializer);
     }(),
     () {
@@ -240,10 +246,14 @@
           new VariableDeclaration('x', type: const DynamicType());
       return new TestCase<Statement>(
           name: '/* suppose A {dynamic field;} A x; */ x.{A::field};',
-          node: new ExpressionStatement(new PropertyGet.byReference(
-              new VariableGet(x), field.name, field.getterReference)),
+          node: new ExpressionStatement(new InstanceGet.byReference(
+              InstanceAccessKind.Instance, new VariableGet(x), field.name,
+              interfaceTargetReference: field.getterReference,
+              resultType: field.getterType)),
           expectation: ''
-              '(expr (get-prop (get-var "x^0" _) (public "field")))',
+              '(expr (get-instance (instance) (get-var "x^0" _) '
+              '(public "field") "package:foo/bar.dart::A::@getters::field" '
+              '(dynamic)))',
           makeSerializationState: () =>
               new SerializationState(new SerializationEnvironment(null)
                 ..addBinder(x, nameClue: 'x')
@@ -268,10 +278,14 @@
           new VariableDeclaration('x', type: const DynamicType());
       return new TestCase<Statement>(
           name: '/* suppose A {dynamic field;} A x; */ x.{A::field};',
-          node: new ExpressionStatement(new PropertyGet.byReference(
-              new VariableGet(x), field.name, field.getterReference)),
+          node: new ExpressionStatement(new InstanceGet.byReference(
+              InstanceAccessKind.Instance, new VariableGet(x), field.name,
+              interfaceTargetReference: field.getterReference,
+              resultType: field.getterType)),
           expectation: ''
-              '(expr (get-prop (get-var "x^0" _) (public "field")))',
+              '(expr (get-instance (instance) (get-var "x^0" _) '
+              '(public "field") "package:foo/bar.dart::A::@getters::field" '
+              '(dynamic)))',
           makeSerializationState: () =>
               new SerializationState(new SerializationEnvironment(null)
                 ..addBinder(x, nameClue: 'x')
@@ -296,13 +310,16 @@
           new VariableDeclaration('x', type: const DynamicType());
       return new TestCase<Statement>(
           name: '/* suppose A {dynamic field;} A x; */ x.{A::field} = 42;',
-          node: new ExpressionStatement(PropertySet.byReference(
+          node: new ExpressionStatement(InstanceSet.byReference(
+              InstanceAccessKind.Instance,
               new VariableGet(x),
               field.name,
               new IntLiteral(42),
-              field.setterReference)),
+              interfaceTargetReference: field.setterReference!)),
           expectation: ''
-              '(expr (set-prop (get-var "x^0" _) (public "field") (int 42)))',
+              '(expr (set-instance (instance) (get-var "x^0" _) '
+              '(public "field") (int 42) '
+              '"package:foo/bar.dart::A::@setters::field"))',
           makeSerializationState: () =>
               new SerializationState(new SerializationEnvironment(null)
                 ..addBinder(x, nameClue: 'x')
@@ -329,14 +346,18 @@
           new VariableDeclaration('x', type: const DynamicType());
       return new TestCase<Statement>(
           name: '/* suppose A {foo() {...}} A x; */ x.{A::foo}();',
-          node: new ExpressionStatement(new MethodInvocation.byReference(
+          node: new ExpressionStatement(new InstanceInvocation.byReference(
+              InstanceAccessKind.Instance,
               new VariableGet(x),
               method.name,
               new Arguments([]),
-              method.reference)),
+              interfaceTargetReference: method.reference,
+              functionType: method.getterType as FunctionType)),
           expectation: ''
-              '(expr (invoke-method (get-var "x^0" _) (public "foo")'
-              ' () () ()))',
+              '(expr (invoke-instance (instance) (get-var "x^0" _) '
+              '(public "foo") () () () '
+              '"package:foo/bar.dart::A::@methods::foo" '
+              '(-> () () () () () () (dynamic))))',
           makeSerializationState: () =>
               new SerializationState(new SerializationEnvironment(null)
                 ..addBinder(x, nameClue: 'x')
@@ -365,9 +386,10 @@
               '(expr (invoke-constructor'
               ' "package:foo/bar.dart::A::@constructors::foo"'
               ' () () ()))',
-          makeSerializationState: () => new SerializationState(null),
-          makeDeserializationState: () =>
-              new DeserializationState(null, component.root),
+          makeSerializationState: () =>
+              new SerializationState(new SerializationEnvironment(null)),
+          makeDeserializationState: () => new DeserializationState(
+              new DeserializationEnvironment(null), component.root),
           serializer: statementSerializer);
     }(),
     () {
@@ -387,13 +409,14 @@
               '(expr (invoke-const-constructor'
               ' "package:foo/bar.dart::A::@constructors::foo"'
               ' () () ()))',
-          makeSerializationState: () => new SerializationState(null),
-          makeDeserializationState: () =>
-              new DeserializationState(null, component.root),
+          makeSerializationState: () =>
+              new SerializationState(new SerializationEnvironment(null)),
+          makeDeserializationState: () => new DeserializationState(
+              new DeserializationEnvironment(null), component.root),
           serializer: statementSerializer);
     }(),
     () {
-      TypeParameter outterParam =
+      TypeParameter outerParam =
           new TypeParameter('T', const DynamicType(), const DynamicType());
       TypeParameter innerParam =
           new TypeParameter('T', const DynamicType(), const DynamicType());
@@ -407,9 +430,9 @@
                     Nullability.legacy,
                     typeParameters: [innerParam])
               ],
-              new TypeParameterType(outterParam, Nullability.legacy),
+              new TypeParameterType(outerParam, Nullability.legacy),
               Nullability.legacy,
-              typeParameters: [outterParam]))),
+              typeParameters: [outerParam]))),
           expectation: ''
               '(expr (type (-> ("T^0") ((dynamic)) ((dynamic)) '
               '((-> ("T^1") ((dynamic)) ((dynamic)) () () () '
@@ -417,7 +440,7 @@
           makeSerializationState: () =>
               new SerializationState(new SerializationEnvironment(null)),
           makeDeserializationState: () => new DeserializationState(
-              new DeserializationEnvironment(null), null),
+              new DeserializationEnvironment(null), new CanonicalName.root()),
           serializer: statementSerializer);
     }(),
     () {
@@ -444,7 +467,7 @@
           makeSerializationState: () =>
               new SerializationState(new SerializationEnvironment(null)),
           makeDeserializationState: () => new DeserializationState(
-              new DeserializationEnvironment(null), null),
+              new DeserializationEnvironment(null), new CanonicalName.root()),
           serializer: statementSerializer);
     }(),
     () {
@@ -471,7 +494,7 @@
           makeSerializationState: () =>
               new SerializationState(new SerializationEnvironment(null)),
           makeDeserializationState: () => new DeserializationState(
-              new DeserializationEnvironment(null), null),
+              new DeserializationEnvironment(null), component.root),
           serializer: memberSerializer);
     }(),
     () {
@@ -588,7 +611,7 @@
           "  but expected:\n    ${testCase.expectation}");
     }
 
-    TreeNode deserialized =
+    Node deserialized =
         testCase.readNode(roundTripInput, testCase.makeDeserializationState());
     String roundTripOutput =
         testCase.writeNode(deserialized, testCase.makeSerializationState());
diff --git a/pkg/kernel/test/text_serializer_test.dart b/pkg/kernel/test/text_serializer_test.dart
index 0a3f209..4fd8305 100644
--- a/pkg/kernel/test/text_serializer_test.dart
+++ b/pkg/kernel/test/text_serializer_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
-
 library kernel.text_serializer_test;
 
 import 'package:kernel/ast.dart';
@@ -27,7 +25,9 @@
   TextIterator stream = new TextIterator(input, 0);
   stream.moveNext();
   Expression result = expressionSerializer.readFrom(
-      stream, new DeserializationState(null, new CanonicalName.root()));
+      stream,
+      new DeserializationState(
+          new DeserializationEnvironment(null), new CanonicalName.root()));
   if (stream.moveNext()) {
     throw StateError("extra cruft in basic literal");
   }
@@ -36,8 +36,8 @@
 
 String writeExpression(Expression expression) {
   StringBuffer buffer = new StringBuffer();
-  expressionSerializer.writeTo(
-      buffer, expression, new SerializationState(null));
+  expressionSerializer.writeTo(buffer, expression,
+      new SerializationState(new SerializationEnvironment(null)));
   return buffer.toString();
 }
 
@@ -45,11 +45,7 @@
   final List<String> failures = [];
 
   void run() {
-    test('(get-prop (int 0) (public "hashCode"))');
     test('(get-super (public "hashCode"))');
-    test('(invoke-method (int 0) (public "foo") () ((int 1) (int 2)) ())');
-    test('(invoke-method (int 0) (public "foo") ((dynamic) (void)) '
-        '((int 1) (int 2)) ("others" (list (dynamic) ((int 3) (int 4)))))');
     test('(let "x^0" () (dynamic) (int 0) () (null))');
     test('(let "x^0" () (dynamic) _ () (null))');
     test('(let "x^0" ((const)) (dynamic) (int 0) () (null))');
diff --git a/pkg/kernel/test/type_hashcode_quality.dart b/pkg/kernel/test/type_hashcode_quality.dart
index f33541e..8bf1f34 100644
--- a/pkg/kernel/test/type_hashcode_quality.dart
+++ b/pkg/kernel/test/type_hashcode_quality.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 'package:kernel/kernel.dart';
 import 'dart:io';
 
@@ -40,7 +38,7 @@
     if (hash == 0) {
       print('Type has a hash code of zero: $node');
     }
-    DartType existing = table[hash];
+    DartType? existing = table[hash];
     if (existing == null) {
       table[hash] = node;
     } else if (existing != node) {
diff --git a/pkg/kernel/test/type_hashcode_test.dart b/pkg/kernel/test/type_hashcode_test.dart
index 9a16a72..8d13fe6 100644
--- a/pkg/kernel/test/type_hashcode_test.dart
+++ b/pkg/kernel/test/type_hashcode_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 'package:kernel/kernel.dart';
 import 'type_parser.dart';
 import 'package:test/test.dart';
@@ -55,11 +53,13 @@
   String type1;
   String type2;
   Iterable<String> quantifiedVariables;
-  Map<String, String> expectedSubstitution; // Null if unification should fail.
+  Map<String, String?>?
+      expectedSubstitution; // Null if unification should fail.
 
-  TestCase.success(this.type1, this.type2, this.expectedSubstitution) {
-    quantifiedVariables = expectedSubstitution.keys;
-  }
+  TestCase.success(
+      this.type1, this.type2, Map<String, String?> expectedSubstitution)
+      : this.expectedSubstitution = expectedSubstitution,
+        this.quantifiedVariables = expectedSubstitution.keys;
 
   TestCase.fail(this.type1, this.type2, this.quantifiedVariables);
 
@@ -68,7 +68,7 @@
   String toString() => '∃ ${quantifiedVariables.join(',')}. $type1 = $type2';
 }
 
-TestCase successCase(String type1, String type2, Map<String, String> expected,
+TestCase successCase(String type1, String type2, Map<String, String?> expected,
     {bool debug: false}) {
   return new TestCase.success(type1, type2, expected);
 }
diff --git a/pkg/kernel/test/type_parser.dart b/pkg/kernel/test/type_parser.dart
index 67a4c05..52401b9 100644
--- a/pkg/kernel/test/type_parser.dart
+++ b/pkg/kernel/test/type_parser.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
-
 // A very simple parser for a subset of DartTypes for use in testing type
 // algebra.
 library kernel.test.type_parser;
@@ -41,14 +39,14 @@
 class DartTypeParser {
   final String string;
   int index = 0;
-  String tokenText;
+  String? tokenText;
   final TypeEnvironment environment;
   final Map<String, TypeParameter> localTypeParameters =
       <String, TypeParameter>{};
 
   DartTypeParser(this.string, this.environment);
 
-  TreeNode lookupType(String name) {
+  TreeNode? lookupType(String name) {
     return localTypeParameters[name] ?? environment(name);
   }
 
@@ -139,8 +137,8 @@
     }
   }
 
-  Nullability parseOptionalNullability(
-      [Nullability defaultNullability = Nullability.nonNullable]) {
+  Nullability? parseOptionalNullability(
+      [Nullability? defaultNullability = Nullability.nonNullable]) {
     int token = peekToken();
     switch (token) {
       case Token.QuestionMark:
@@ -159,23 +157,23 @@
     switch (token) {
       case Token.Name:
         scanToken();
-        String name = this.tokenText;
+        String name = this.tokenText!;
         if (name == 'void') return const VoidType();
         if (name == 'dynamic') return const DynamicType();
         var target = lookupType(name);
         if (target == null) {
           return fail('Unresolved type $name');
         } else if (target is Class) {
-          List<DartType> typeArguments = parseOptionalTypeArgumentList();
-          Nullability nullability = parseOptionalNullability();
+          List<DartType>? typeArguments = parseOptionalTypeArgumentList();
+          Nullability nullability = parseOptionalNullability()!;
           return new InterfaceType(target, nullability, typeArguments);
         } else if (target is Typedef) {
-          List<DartType> typeArguments = parseOptionalTypeArgumentList();
-          Nullability nullability = parseOptionalNullability();
+          List<DartType>? typeArguments = parseOptionalTypeArgumentList();
+          Nullability nullability = parseOptionalNullability()!;
           return new TypedefType(target, nullability, typeArguments);
         } else if (target is TypeParameter) {
-          Nullability nullability = parseOptionalNullability(null);
-          DartType promotedBound;
+          Nullability? nullability = parseOptionalNullability(null);
+          DartType? promotedBound;
           switch (peekToken()) {
             case Token.LeftAngle:
               return fail('Attempt to apply type arguments to a type variable');
@@ -199,7 +197,7 @@
         List<NamedType> namedParameters = <NamedType>[];
         parseParameterList(parameters, namedParameters);
         consumeString('=>');
-        Nullability nullability = parseOptionalNullability();
+        Nullability nullability = parseOptionalNullability()!;
         var returnType = parseType();
         return new FunctionType(parameters, returnType, nullability,
             namedParameters: namedParameters);
@@ -210,7 +208,7 @@
         List<NamedType> namedParameters = <NamedType>[];
         parseParameterList(parameters, namedParameters);
         consumeString('=>');
-        Nullability nullability = parseOptionalNullability();
+        Nullability nullability = parseOptionalNullability()!;
         var returnType = parseType();
         popTypeParameters(typeParameters);
         return new FunctionType(parameters, returnType, nullability,
@@ -246,7 +244,7 @@
     if (type is InterfaceType && type.typeArguments.isEmpty) {
       return type.classNode.name;
     } else if (type is TypeParameterType) {
-      return type.parameter.name;
+      return type.parameter.name!;
     } else {
       return fail('Unexpected colon after $type');
     }
@@ -267,12 +265,12 @@
     return types;
   }
 
-  List<DartType> parseOptionalList(int open, int close) {
+  List<DartType>? parseOptionalList(int open, int close) {
     if (peekToken() != open) return null;
     return parseTypeList(open, close);
   }
 
-  List<DartType> parseOptionalTypeArgumentList() {
+  List<DartType>? parseOptionalTypeArgumentList() {
     return parseOptionalList(Token.LeftAngle, Token.RightAngle);
   }
 
@@ -302,14 +300,14 @@
     if (localTypeParameters.containsKey(typeParameter.name)) {
       return fail('Shadowing a type parameter is not allowed');
     }
-    localTypeParameters[typeParameter.name] = typeParameter;
+    localTypeParameters[typeParameter.name!] = typeParameter;
     var next = peekToken();
     if (next == Token.Colon) {
       scanToken();
       typeParameter.bound = parseType();
     } else {
-      typeParameter.bound =
-          new InterfaceType(lookupType('Object'), Nullability.nullable);
+      typeParameter.bound = new InterfaceType(
+          lookupType('Object') as Class, Nullability.nullable);
     }
     return typeParameter;
   }
@@ -322,7 +320,7 @@
 class LazyTypeEnvironment {
   final Map<String, Class> classes = <String, Class>{};
   final Map<String, TypeParameter> typeParameters = <String, TypeParameter>{};
-  Library dummyLibrary;
+  late final Library dummyLibrary;
   final Component component = new Component();
 
   LazyTypeEnvironment() {
@@ -360,14 +358,14 @@
     for (var typeParameter
         in new DartTypeParser('<$typeParametersList>', lookup)
             .parseAndPushTypeParameterList()) {
-      typeParameters[typeParameter.name] = typeParameter;
+      typeParameters[typeParameter.name!] = typeParameter;
     }
   }
 
   DartType parse(String type) => parseDartType(type, lookup);
 
   Supertype parseSuper(String type) {
-    InterfaceType interfaceType = parse(type);
+    InterfaceType interfaceType = parse(type) as InterfaceType;
     return new Supertype(interfaceType.classNode, interfaceType.typeArguments);
   }
 
@@ -376,9 +374,9 @@
     return parse(type);
   }
 
-  TypeParameter getTypeParameter(String name) {
+  TypeParameter? getTypeParameter(String name) {
     if (name.length != 1) throw 'Type parameter names must have length 1';
-    return lookup(name);
+    return lookup(name) as TypeParameter?;
   }
 }
 
diff --git a/pkg/kernel/test/type_parser_test.dart b/pkg/kernel/test/type_parser_test.dart
index e015daa..5a2e651 100644
--- a/pkg/kernel/test/type_parser_test.dart
+++ b/pkg/kernel/test/type_parser_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 'package:expect/expect.dart' show Expect;
 
 import 'package:kernel/testing/type_parser.dart';
diff --git a/pkg/kernel/test/type_substitute_bounds_test.dart b/pkg/kernel/test/type_substitute_bounds_test.dart
index c92d17a..ca16ac0 100644
--- a/pkg/kernel/test/type_substitute_bounds_test.dart
+++ b/pkg/kernel/test/type_substitute_bounds_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
-
 library kernel.type_substitute_bounds_test;
 
 import 'package:kernel/kernel.dart';
@@ -45,7 +43,7 @@
 
   String toString() {
     var substitution = bounds.keys.map((key) {
-      var bound = bounds[key];
+      var bound = bounds[key]!;
       return '${bound.lower} <: $key <: ${bound.upper}';
     }).join(',');
     return '$type [$substitution] <: $expected';
@@ -72,7 +70,7 @@
       var upperBounds = <TypeParameter, DartType>{};
       var lowerBounds = <TypeParameter, DartType>{};
       testCase.bounds.forEach((String name, TypeBound bounds) {
-        var parameter = environment.getTypeParameter(name);
+        var parameter = environment.getTypeParameter(name)!;
         upperBounds[parameter] = environment.parse(bounds.upper);
         lowerBounds[parameter] = environment.parse(bounds.lower);
       });
diff --git a/pkg/kernel/test/type_substitution_identity_test.dart b/pkg/kernel/test/type_substitution_identity_test.dart
index 99d7fe7..d8fabbd 100644
--- a/pkg/kernel/test/type_substitution_identity_test.dart
+++ b/pkg/kernel/test/type_substitution_identity_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 'package:kernel/kernel.dart';
 import 'package:kernel/type_algebra.dart';
 import 'type_parser.dart';
diff --git a/pkg/kernel/test/typedef_unalias_test.dart b/pkg/kernel/test/typedef_unalias_test.dart
index aded3c3..196ac3f 100644
--- a/pkg/kernel/test/typedef_unalias_test.dart
+++ b/pkg/kernel/test/typedef_unalias_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
-
 library kernel.typedef_unalias_test;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/union_find_test.dart b/pkg/kernel/test/union_find_test.dart
new file mode 100644
index 0000000..2e5249d
--- /dev/null
+++ b/pkg/kernel/test/union_find_test.dart
@@ -0,0 +1,108 @@
+// 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:kernel/src/union_find.dart';
+
+testSame<T>(UnionFind<T> unionFind, T a, T b, bool expected) {
+  expect(expected, unionFind.nodesInSameSet(unionFind[a], unionFind[b]));
+}
+
+testSets<T>(UnionFind<T> unionFind, Set<Set<T>> sets) {
+  for (Set<T> set in sets) {
+    UnionFindNode<T> root = unionFind.findNode(unionFind[set.first]);
+    for (T value in unionFind.values) {
+      testSame(unionFind, value, root.value, set.contains(value));
+    }
+  }
+}
+
+testFind<T>(UnionFind<T> unionFind, T value, T expected) {
+  expect(expected, unionFind.findNode(unionFind[value]).value);
+}
+
+testUnion<T>(UnionFind<T> unionFind, T a, T b, T expected) {
+  expect(expected, unionFind.unionOfNodes(unionFind[a], unionFind[b]).value);
+}
+
+main() {
+  UnionFind<int> unionFind = new UnionFind();
+  // {0}
+  testFind(unionFind, 0, 0);
+  testSame(unionFind, 0, 0, true);
+  testSets(unionFind, {
+    {0}
+  });
+
+  // {0}, {1}
+  testFind(unionFind, 1, 1);
+  testSame(unionFind, 0, 1, false);
+  testSame(unionFind, 1, 0, false);
+  testSame(unionFind, 1, 1, true);
+  testSets(unionFind, {
+    {0},
+    {1}
+  });
+
+  // {0}, {1}, {2}
+  testFind(unionFind, 2, 2);
+  testSame(unionFind, 0, 2, false);
+  testSame(unionFind, 1, 2, false);
+  testSame(unionFind, 2, 2, true);
+  testSets(unionFind, {
+    {0},
+    {1},
+    {2}
+  });
+
+  // {0}, {1}, {2}
+  testUnion(unionFind, 0, 0, 0);
+  testSame(unionFind, 0, 0, true);
+  testSame(unionFind, 0, 1, false);
+  testSame(unionFind, 0, 2, false);
+  testSets(unionFind, {
+    {0},
+    {1},
+    {2}
+  });
+
+  // {0, 1}, {2}
+  testUnion(unionFind, 0, 1, 0);
+  testSame(unionFind, 0, 0, true);
+  testSame(unionFind, 0, 1, true);
+  testSame(unionFind, 1, 0, true);
+  testSame(unionFind, 0, 2, false);
+  testFind(unionFind, 0, 0);
+  testFind(unionFind, 1, 0);
+  testSets(unionFind, {
+    {0, 1},
+    {2}
+  });
+
+  // {0, 1}, {2, 3}
+  testUnion(unionFind, 2, 3, 2);
+  testSame(unionFind, 0, 0, true);
+  testSame(unionFind, 0, 1, true);
+  testSame(unionFind, 0, 2, false);
+  testSame(unionFind, 0, 3, false);
+  testSame(unionFind, 0, 0, true);
+  testSame(unionFind, 0, 1, true);
+  testSame(unionFind, 0, 2, false);
+  testSame(unionFind, 0, 3, false);
+  testFind(unionFind, 2, 2);
+  testFind(unionFind, 3, 2);
+  testSets(unionFind, {
+    {0, 1},
+    {2, 3}
+  });
+
+  // {0, 1, 2, 3}
+  testUnion(unionFind, 1, 2, 0);
+  testSets(unionFind, {
+    {0, 1, 2, 3}
+  });
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/kernel/test/verify_bench.dart b/pkg/kernel/test/verify_bench.dart
index 6326b89..c5fc42e 100644
--- a/pkg/kernel/test/verify_bench.dart
+++ b/pkg/kernel/test/verify_bench.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:io';
 
 import 'package:kernel/kernel.dart';
diff --git a/pkg/kernel/test/verify_self_check.dart b/pkg/kernel/test/verify_self_check.dart
index bb2cd02..bc9b184 100644
--- a/pkg/kernel/test/verify_self_check.dart
+++ b/pkg/kernel/test/verify_self_check.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 'package:kernel/kernel.dart';
 import 'package:kernel/verifier.dart';
 
diff --git a/pkg/kernel/test/verify_test.dart b/pkg/kernel/test/verify_test.dart
index 9803f71..97919d4 100644
--- a/pkg/kernel/test/verify_test.dart
+++ b/pkg/kernel/test/verify_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 'package:kernel/ast.dart';
 import 'package:kernel/text/ast_to_text.dart';
 import 'package:kernel/verifier.dart';
@@ -30,7 +28,7 @@
       test.addNode(VariableGet(node));
       return node;
     },
-    (Node node) => "Variable '$node' used out of scope.",
+    (Node? node) => "Variable '$node' used out of scope.",
   );
   negative1Test(
     'VariableSet out of scope',
@@ -39,7 +37,7 @@
       test.addNode(VariableSet(variable, new NullLiteral()));
       return variable;
     },
-    (Node node) => "Variable '$node' used out of scope.",
+    (Node? node) => "Variable '$node' used out of scope.",
   );
   negative1Test(
     'Variable block scope',
@@ -51,7 +49,7 @@
       ]));
       return variable;
     },
-    (Node node) => "Variable '$node' used out of scope.",
+    (Node? node) => "Variable '$node' used out of scope.",
   );
   negative1Test(
     'Variable let scope',
@@ -63,7 +61,7 @@
           new VariableGet(variable)));
       return variable;
     },
-    (Node node) => "Variable '$node' used out of scope.",
+    (Node? node) => "Variable '$node' used out of scope.",
   );
   negative1Test(
     'Variable redeclared',
@@ -72,7 +70,7 @@
       test.addNode(Block([variable, variable]));
       return variable;
     },
-    (Node node) => "Variable '$node' declared more than once.",
+    (Node? node) => "Variable '$node' declared more than once.",
   );
   negative1Test(
     'Member redeclared',
@@ -86,7 +84,7 @@
           fileUri: dummyUri));
       return field;
     },
-    (Node node) => "Member '$node' has been declared more than once.",
+    (Node? node) => "Member '$node' has been declared more than once.",
   );
   negative1Test(
     'Class redeclared',
@@ -96,7 +94,7 @@
           otherClass); // Test harness also adds otherClass to component.
       return test.otherClass;
     },
-    (Node node) => "Class '$node' declared more than once.",
+    (Node? node) => "Class '$node' declared more than once.",
   );
   negative1Test(
     'Class type parameter redeclared',
@@ -109,7 +107,7 @@
           fileUri: dummyUri));
       return parameter;
     },
-    (Node node) => "Type parameter '$node' redeclared.",
+    (Node? node) => "Type parameter '$node' redeclared.",
   );
   negative1Test(
     'Member type parameter redeclared',
@@ -124,7 +122,7 @@
 
       return parameter;
     },
-    (Node node) => "Type parameter '$node' redeclared.",
+    (Node? node) => "Type parameter '$node' redeclared.",
   );
   negative2Test(
     'Type parameter out of scope',
@@ -134,9 +132,9 @@
           typeArgument: new TypeParameterType(parameter, Nullability.legacy)));
       return [parameter, null];
     },
-    (Node node, Node parent) =>
+    (Node? node, Node? parent) =>
         "Type parameter '$node' referenced out of scope,"
-        " parent is: '$parent'.",
+        " owner is: '$parent'.",
   );
   negative2Test(
     'Class type parameter from another class',
@@ -146,9 +144,9 @@
           TypeLiteral(new TypeParameterType(node, Nullability.legacy)));
       return [node, test.otherClass];
     },
-    (Node node, Node parent) =>
+    (Node? node, Node? parent) =>
         "Type parameter '$node' referenced out of scope,"
-        " parent is: '$parent'.",
+        " owner is: '$parent'.",
   );
   negative2Test(
     'Class type parameter in static method',
@@ -164,7 +162,7 @@
 
       return [node, test.enclosingClass];
     },
-    (Node node, Node parent) =>
+    (Node? node, Node? parent) =>
         "Type parameter '$node' referenced from static context,"
         " parent is: '$parent'.",
   );
@@ -179,7 +177,7 @@
           fileUri: dummyUri));
       return [node, test.enclosingClass];
     },
-    (Node node, Node parent) =>
+    (Node? node, Node? parent) =>
         "Type parameter '$node' referenced from static context,"
         " parent is: '$parent'.",
   );
@@ -206,9 +204,9 @@
 
       return [parameter, parent];
     },
-    (Node node, Node parent) =>
+    (Node? node, Node? parent) =>
         "Type parameter '$node' referenced out of scope,"
-        " parent is: '$parent'.",
+        " owner is: '${(parent as TreeNode).parent}'.",
   );
   negative1Test(
     'Interface type arity too low',
@@ -218,7 +216,7 @@
       test.addNode(TypeLiteral(node));
       return node;
     },
-    (Node node) => "Type $node provides 0 type arguments,"
+    (Node? node) => "Type $node provides 0 type arguments,"
         " but the class declares 1 parameters.",
   );
   negative1Test(
@@ -229,7 +227,7 @@
       test.addNode(TypeLiteral(node));
       return node;
     },
-    (Node node) => "Type $node provides 2 type arguments,"
+    (Node? node) => "Type $node provides 2 type arguments,"
         " but the class declares 1 parameters.",
   );
   negative1Test(
@@ -240,16 +238,18 @@
           new TypeLiteral(new InterfaceType(orphan, Nullability.legacy)));
       return orphan;
     },
-    (Node node) => "Dangling reference to '$node', parent is: 'null'.",
+    (Node? node) => "Dangling reference to '$node', parent is: 'null'.",
   );
   negative1Test(
     'Dangling field get',
     (TestHarness test) {
       Field orphan = new Field.mutable(new Name('foo'), fileUri: dummyUri);
-      test.addNode(new PropertyGet(new NullLiteral(), orphan.name, orphan));
+      test.addNode(new InstanceGet(
+          InstanceAccessKind.Instance, new NullLiteral(), orphan.name,
+          interfaceTarget: orphan, resultType: orphan.getterType));
       return orphan;
     },
-    (Node node) => "Dangling reference to '$node', parent is: 'null'.",
+    (Node? node) => "Dangling reference to '$node', parent is: 'null'.",
   );
   simpleNegativeTest(
     'Missing block parent pointer',
@@ -299,7 +299,7 @@
           StaticInvocation(method, new Arguments([new NullLiteral()])));
       return method;
     },
-    (Node node) => "StaticInvocation with incompatible arguments for"
+    (Node? node) => "StaticInvocation with incompatible arguments for"
         " '$node'.",
   );
   negative1Test(
@@ -316,7 +316,7 @@
       test.addNode(StaticInvocation(method, new Arguments.empty()));
       return method;
     },
-    (Node node) => "StaticInvocation with incompatible arguments for '$node'.",
+    (Node? node) => "StaticInvocation with incompatible arguments for '$node'.",
   );
   negative1Test(
     'StaticInvocation with unmatched named parameter',
@@ -331,7 +331,7 @@
               named: [new NamedExpression('p', new NullLiteral())])));
       return method;
     },
-    (Node node) => "StaticInvocation with incompatible arguments for"
+    (Node? node) => "StaticInvocation with incompatible arguments for"
         " '$node'.",
   );
   negative1Test(
@@ -348,7 +348,7 @@
       test.addNode(StaticInvocation(method, new Arguments.empty()));
       return method;
     },
-    (Node node) => "StaticInvocation with wrong number of type arguments for"
+    (Node? node) => "StaticInvocation with wrong number of type arguments for"
         " '$node'.",
   );
   negative1Test(
@@ -360,7 +360,7 @@
       test.addNode(ConstructorInvocation(constructor, new Arguments.empty()));
       return constructor;
     },
-    (Node node) =>
+    (Node? node) =>
         "ConstructorInvocation with wrong number of type arguments for"
         " '$node'.",
   );
@@ -433,7 +433,7 @@
       test.addNode(typedef_);
       return typedef_;
     },
-    (Node node) => "The typedef '$node' refers to itself",
+    (Node? node) => "The typedef '$node' refers to itself",
   );
   negative1Test(
     'Invalid typedef Foo = `(Foo) => void`',
@@ -446,7 +446,7 @@
       test.addNode(typedef_);
       return typedef_;
     },
-    (Node node) => "The typedef '$node' refers to itself",
+    (Node? node) => "The typedef '$node' refers to itself",
   );
   negative1Test(
     'Invalid typedef Foo = `() => Foo`',
@@ -457,7 +457,7 @@
       test.addNode(typedef_);
       return typedef_;
     },
-    (Node node) => "The typedef '$node' refers to itself",
+    (Node? node) => "The typedef '$node' refers to itself",
   );
   negative1Test(
     'Invalid typedef Foo = C<Foo>',
@@ -468,7 +468,7 @@
       test.addNode(typedef_);
       return typedef_;
     },
-    (Node node) => "The typedef '$node' refers to itself",
+    (Node? node) => "The typedef '$node' refers to itself",
   );
   negative1Test(
     'Invalid typedefs Foo = Bar, Bar = Foo',
@@ -481,7 +481,7 @@
       test.enclosingLibrary.addTypedef(bar);
       return foo;
     },
-    (Node foo) => "The typedef '$foo' refers to itself",
+    (Node? foo) => "The typedef '$foo' refers to itself",
   );
   negative1Test(
     'Invalid typedefs Foo = Bar, Bar = C<Foo>',
@@ -495,7 +495,7 @@
       test.enclosingLibrary.addTypedef(bar);
       return foo;
     },
-    (Node foo) => "The typedef '$foo' refers to itself",
+    (Node? foo) => "The typedef '$foo' refers to itself",
   );
   negative1Test(
     'Invalid typedefs Foo = C<Bar>, Bar = C<Foo>',
@@ -510,7 +510,7 @@
       test.enclosingLibrary.addTypedef(bar);
       return foo;
     },
-    (Node foo) => "The typedef '$foo' refers to itself",
+    (Node? foo) => "The typedef '$foo' refers to itself",
   );
   positiveTest(
     'Valid long typedefs C20 = C19 = ... = C1 = C0 = dynamic',
@@ -541,7 +541,7 @@
       first.type = new TypedefType(typedef_, Nullability.legacy);
       return firstTypedef;
     },
-    (Node node) => "The typedef '$node' refers to itself",
+    (Node? node) => "The typedef '$node' refers to itself",
   );
   positiveTest(
     'Valid typedef Foo<T extends C> = C<T>',
@@ -611,7 +611,7 @@
       test.enclosingLibrary.addTypedef(bar);
       return foo;
     },
-    (Node foo) => "The typedef '$foo' refers to itself",
+    (Node? foo) => "The typedef '$foo' refers to itself",
   );
   negative1Test(
     'Invalid typedef Foo<T extends Foo<dynamic> = C<T>',
@@ -628,7 +628,7 @@
       test.addNode(foo);
       return foo;
     },
-    (Node foo) => "The typedef '$foo' refers to itself",
+    (Node? foo) => "The typedef '$foo' refers to itself",
   );
   negative1Test(
     'Typedef arity error',
@@ -643,7 +643,7 @@
       test.enclosingLibrary.addField(field);
       return typedefType;
     },
-    (Node typedefType) =>
+    (Node? typedefType) =>
         "The typedef type $typedefType provides 0 type arguments,"
         " but the typedef declares 1 parameters.",
   );
@@ -659,7 +659,7 @@
       test.enclosingLibrary.addField(field);
       return foo;
     },
-    (Node foo) => "Dangling reference to '$foo', parent is: 'null'",
+    (Node? foo) => "Dangling reference to '$foo', parent is: 'null'",
   );
   negative1Test(
     'Non-static top-level field',
@@ -668,7 +668,7 @@
       test.enclosingLibrary.addField(field);
       return null;
     },
-    (Node node) => "The top-level field 'field' should be static",
+    (Node? node) => "The top-level field 'field' should be static",
   );
 }
 
@@ -683,21 +683,21 @@
 }
 
 class TestHarness {
-  Component component;
-  Class objectClass;
-  Library stubLibrary;
+  late Component component;
+  late Class objectClass;
+  late Library stubLibrary;
 
-  TypeParameter classTypeParameter;
+  late TypeParameter classTypeParameter;
 
-  Library enclosingLibrary;
-  Class enclosingClass;
-  Procedure enclosingMember;
+  late Library enclosingLibrary;
+  late Class enclosingClass;
+  late Procedure enclosingMember;
 
-  Class otherClass;
+  late Class otherClass;
 
-  InterfaceType objectLegacyRawType;
-  InterfaceType enclosingLegacyRawType;
-  InterfaceType otherLegacyRawType;
+  late InterfaceType objectLegacyRawType;
+  late InterfaceType enclosingLegacyRawType;
+  late InterfaceType otherLegacyRawType;
 
   void addNode(TreeNode node) {
     if (node is Expression) {
@@ -729,8 +729,8 @@
       enclosingClass.addField(node);
     } else if (node is Constructor) {
       enclosingClass.addConstructor(node);
-    } else if (node is RedirectingFactoryConstructor) {
-      enclosingClass.addRedirectingFactoryConstructor(node);
+    } else if (node is RedirectingFactory) {
+      enclosingClass.addRedirectingFactory(node);
     } else {
       throw "Unexpected class member: ${node.runtimeType}";
     }
@@ -756,7 +756,7 @@
 
   VariableDeclaration makeVariable() => new VariableDeclaration(null);
 
-  TypeParameter makeTypeParameter([String name]) {
+  TypeParameter makeTypeParameter([String? name]) {
     return new TypeParameter(name, objectLegacyRawType, const DynamicType());
   }
 
@@ -802,10 +802,10 @@
   }
 }
 
-negative1Test(String name, Node Function(TestHarness test) nodeProvider,
-    dynamic Function(Node node) matcher) {
+negative1Test(String name, Node? Function(TestHarness test) nodeProvider,
+    dynamic Function(Node? node) matcher) {
   TestHarness testHarness = new TestHarness();
-  Node node = nodeProvider(testHarness);
+  Node? node = nodeProvider(testHarness);
   test(
     name,
     () {
@@ -818,10 +818,10 @@
   );
 }
 
-negative2Test(String name, List<Node> Function(TestHarness test) nodeProvider,
-    dynamic Function(Node node, Node other) matcher) {
+negative2Test(String name, List<Node?> Function(TestHarness test) nodeProvider,
+    dynamic Function(Node? node, Node? other) matcher) {
   TestHarness testHarness = new TestHarness();
-  List<Node> nodes = nodeProvider(testHarness);
+  List<Node?> nodes = nodeProvider(testHarness);
   if (nodes.length != 2) throw "Needs exactly 2 nodes: Node and other!";
   test(
     name,
diff --git a/pkg/kernel/tool/smoke_test_quick.dart b/pkg/kernel/tool/smoke_test_quick.dart
index 6ca6e19..b5a0b9a 100644
--- a/pkg/kernel/tool/smoke_test_quick.dart
+++ b/pkg/kernel/tool/smoke_test_quick.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:io';
 
 final String repoDir = _computeRepoDir();
diff --git a/pkg/nnbd_migration/lib/migration_cli.dart b/pkg/nnbd_migration/lib/migration_cli.dart
index a9893c0..9a0a6ec 100644
--- a/pkg/nnbd_migration/lib/migration_cli.dart
+++ b/pkg/nnbd_migration/lib/migration_cli.dart
@@ -1000,7 +1000,7 @@
   bool get isPreviewServerRunning => _task?.isPreviewServerRunning ?? false;
 
   LineInfo getLineInfo(String path) =>
-      (context.currentSession.getFile2(path) as FileResult).lineInfo;
+      (context.currentSession.getFile(path) as FileResult).lineInfo;
 
   void prepareToRerun() {
     var driver = context.driver;
@@ -1015,11 +1015,11 @@
     var pathsProcessed = <String?>{};
     for (var path in pathsToProcess) {
       if (pathsProcessed.contains(path)) continue;
-      var result = await driver.getResolvedLibrary2(path);
+      var result = await driver.getResolvedLibrary(path);
       // Parts will either be found in a library, below, or if the library
       // isn't [isIncluded], will be picked up in the final loop.
       if (result is ResolvedLibraryResult) {
-        for (var unit in result.units!) {
+        for (var unit in result.units) {
           if (!pathsProcessed.contains(unit.path)) {
             await process(unit);
             pathsProcessed.add(unit.path);
@@ -1029,7 +1029,7 @@
     }
 
     for (var path in pathsToProcess.difference(pathsProcessed)) {
-      var result = await driver.getResolvedUnit2(path);
+      var result = await driver.getResolvedUnit(path);
       if (result is ResolvedUnitResult) {
         await process(result);
       }
@@ -1049,7 +1049,7 @@
     // Process each source file.
     bool allSourcesAlreadyMigrated = true;
     await processResources((ResolvedUnitResult result) async {
-      if (!result.unit!.featureSet.isEnabled(Feature.non_nullable)) {
+      if (!result.unit.featureSet.isEnabled(Feature.non_nullable)) {
         allSourcesAlreadyMigrated = false;
       }
       _progressBar.tick();
@@ -1093,7 +1093,7 @@
     });
     await processResources((ResolvedUnitResult result) async {
       _progressBar.tick();
-      if (_migrationCli.shouldBeMigrated(result.path!)) {
+      if (_migrationCli.shouldBeMigrated(result.path)) {
         await _task!.finalizeUnit(result);
       }
     });
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index e79df1f..aaa17c7 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -175,6 +175,12 @@
           'Removed a null-aware assignment, because the target cannot be null',
       kind: NullabilityFixKind.removeDeadCode);
 
+  /// A built_value `@nullable` annotation has been discarded.
+  static const removeNullableAnnotation = NullabilityFixDescription._(
+    appliedMessage: 'Discarded a use of the built_value annotation @nullable',
+    kind: NullabilityFixKind.removeNullableAnnotation,
+  );
+
   /// A message used to indicate a fix has been applied.
   final String appliedMessage;
 
@@ -293,6 +299,7 @@
   removeAs,
   removeDeadCode,
   removeLanguageVersionComment,
+  removeNullableAnnotation,
   replaceVar,
   typeNotMadeNullable,
   typeNotMadeNullableDueToHint,
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 42249d9..d155843 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -141,6 +141,12 @@
   /// return statements.
   DecoratedType? _currentFunctionType;
 
+  /// If the innermost enclosing executable is a constructor with field formal
+  /// parameters, a map from each field's getter to the corresponding field
+  /// formal parameter element.  Otherwise, an empty map.
+  Map<PropertyAccessorElement, FieldFormalParameterElement>
+      _currentFieldFormals = const {};
+
   FunctionExpression? _currentFunctionExpression;
 
   /// The [ClassElement] or [ExtensionElement] of the current class or extension
@@ -192,7 +198,7 @@
   ///
   /// Note that this is not guaranteed to be complete. It is used to make hard
   /// edges on a best-effort basis.
-  var _postDominatedLocals = _ScopedLocalSet();
+  var _postDominatedLocals = ScopedSet<Element>();
 
   /// Map whose keys are expressions of the form `a?.b` on the LHS of
   /// assignments, and whose values are the nullability nodes corresponding to
@@ -242,6 +248,10 @@
         _whereOrNullTransformer =
             WhereOrNullTransformer(typeProvider, _typeSystem);
 
+  /// The synthetic element we use as a stand-in for `this` when analyzing
+  /// extension methods.
+  Element get _extensionThis => DynamicElementImpl.instance;
+
   /// Gets the decorated type of [element] from [_variables], performing any
   /// necessary substitutions.
   ///
@@ -319,7 +329,7 @@
             source: targetType,
             destination: onType,
             hard: targetExpression == null ||
-                _postDominatedLocals.isReferenceInScope(targetExpression));
+                _isReferenceInScope(targetExpression));
         // (3) substitute those decorated types into the declared type of the
         // extension method or extension property, so that the caller will match
         // up parameter types and the return type appropriately.
@@ -507,8 +517,7 @@
         bool isPure = otherOperand is SimpleIdentifier;
         var conditionInfo = _ConditionInfo(node,
             isPure: isPure,
-            postDominatingIntent:
-                _postDominatedLocals.isReferenceInScope(otherOperand),
+            postDominatingIntent: _isReferenceInScope(otherOperand),
             trueGuard: otherNode,
             falseDemonstratesNonNullIntent: otherNode);
         _conditionInfo = notEqual ? conditionInfo.not(node) : conditionInfo;
@@ -886,18 +895,20 @@
     _dispatch(node.parameters);
     var parameterElement = node.declaredElement as FieldFormalParameterElement;
     var parameterType = _variables!.decoratedElementType(parameterElement);
-    var field = parameterElement.field!;
-    _fieldsNotInitializedByConstructor!.remove(field);
-    var fieldType = _variables!.decoratedElementType(field);
-    var origin = FieldFormalParameterOrigin(source, node);
-    if (node.type == null) {
-      _linkDecoratedTypes(parameterType, fieldType, origin, isUnion: false);
-      _checkAssignment(origin, FixReasonTarget.root,
-          source: fieldType, destination: parameterType, hard: false);
-    } else {
-      _dispatch(node.type);
-      _checkAssignment(origin, FixReasonTarget.root,
-          source: parameterType, destination: fieldType, hard: true);
+    var field = parameterElement.field;
+    if (field != null) {
+      _fieldsNotInitializedByConstructor!.remove(field);
+      var fieldType = _variables!.decoratedElementType(field);
+      var origin = FieldFormalParameterOrigin(source, node);
+      if (node.type == null) {
+        _linkDecoratedTypes(parameterType, fieldType, origin, isUnion: false);
+        _checkAssignment(origin, FixReasonTarget.root,
+            source: fieldType, destination: parameterType, hard: false);
+      } else {
+        _dispatch(node.type);
+        _checkAssignment(origin, FixReasonTarget.root,
+            source: parameterType, destination: fieldType, hard: true);
+      }
     }
 
     return null;
@@ -928,7 +939,7 @@
           _elementsWrittenToInLocalFunction;
       try {
         _elementsWrittenToInLocalFunction = {};
-        _postDominatedLocals = _ScopedLocalSet();
+        _postDominatedLocals = ScopedSet<Element>();
         _flowAnalysis!.functionExpression_begin(node);
         _dispatch(node.functionExpression);
         _flowAnalysis!.functionExpression_end();
@@ -983,9 +994,11 @@
     _addParametersToFlowAnalysis(node.parameters);
     var previousFunction = _currentFunctionExpression;
     var previousFunctionType = _currentFunctionType;
+    var previousFieldFormals = _currentFieldFormals;
     _currentFunctionExpression = node;
     _currentFunctionType =
         _variables!.decoratedElementType(node.declaredElement!);
+    _currentFieldFormals = const {};
     var previousPostDominatedLocals = _postDominatedLocals;
     var previousElementsWrittenToInLocalFunction =
         _elementsWrittenToInLocalFunction;
@@ -993,7 +1006,7 @@
       if (node.parent is! FunctionDeclaration) {
         _elementsWrittenToInLocalFunction = {};
       }
-      _postDominatedLocals = _ScopedLocalSet();
+      _postDominatedLocals = ScopedSet<Element>();
       _postDominatedLocals.doScoped(
           elements: node.declaredElement!.parameters,
           action: () => _dispatch(node.body));
@@ -1010,6 +1023,7 @@
             previousElementsWrittenToInLocalFunction;
       }
       _currentFunctionType = previousFunctionType;
+      _currentFieldFormals = previousFieldFormals;
       _currentFunctionExpression = previousFunction;
       _postDominatedLocals = previousPostDominatedLocals;
     }
@@ -1238,8 +1252,7 @@
         decoratedType.node, IsCheckMainTypeOrigin(source, type));
     _conditionInfo = _ConditionInfo(node,
         isPure: expression is SimpleIdentifier,
-        postDominatingIntent:
-            _postDominatedLocals.isReferenceInScope(expression),
+        postDominatingIntent: _isReferenceInScope(expression),
         trueDemonstratesNonNullIntent: expressionNode);
     if (node.notOperator != null) {
       _conditionInfo = _conditionInfo!.not(node);
@@ -1377,7 +1390,7 @@
       }
       _variables!.recordDecoratedExpressionType(node, expressionType);
     }
-    _handleArgumentErrorCheckNotNull(node);
+    _handleCustomCheckNotNull(node);
     _handleQuiverCheckNotNull(node);
     return expressionType;
   }
@@ -1645,7 +1658,7 @@
   DecoratedType? visitSimpleIdentifier(SimpleIdentifier node) {
     DecoratedType? targetType;
     DecoratedType? result;
-    var staticElement = getWriteOrReadElement(node);
+    var staticElement = _favorFieldFormalElements(getWriteOrReadElement(node));
     if (staticElement is PromotableElement) {
       if (!node.inDeclarationContext()) {
         var promotedType = _flowAnalysis!.variableRead(node, staticElement);
@@ -2004,7 +2017,7 @@
     //
     // We cannot make a hard edge from y to never in this case.
     if (node.variables.length == 1) {
-      _postDominatedLocals.add(node.variables.single.declaredElement);
+      _postDominatedLocals.add(node.variables.single.declaredElement!);
     }
 
     return null;
@@ -2061,11 +2074,26 @@
     // there's nothing to do.
     if (_currentExtendedType == null) return;
     var origin = ImplicitThisOrigin(source, node);
-    var hard =
-        _postDominatedLocals.isInScope(_postDominatedLocals.extensionThis);
+    var hard = _postDominatedLocals.isInScope(_extensionThis);
     _graph.makeNonNullable(thisType!.node, origin, hard: hard, guards: _guards);
   }
 
+  /// Computes the map to be stored in [_currentFieldFormals] while visiting the
+  /// constructor having the given [constructorElement].
+  Map<PropertyAccessorElement, FieldFormalParameterElement>
+      _computeFieldFormalMap(ConstructorElement constructorElement) {
+    var result = <PropertyAccessorElement, FieldFormalParameterElement>{};
+    for (var parameter in constructorElement.parameters) {
+      if (parameter is FieldFormalParameterElement) {
+        var getter = parameter.field?.getter;
+        if (getter != null) {
+          result[getter] = parameter;
+        }
+      }
+    }
+    return result;
+  }
+
   @override
   void _connect(NullabilityNode? source, NullabilityNode? destination,
       EdgeOrigin origin, FixReasonTarget? edgeTarget,
@@ -2287,6 +2315,24 @@
     }
   }
 
+  /// If the innermost enclosing executable is a constructor with field formal
+  /// parameters, and [staticElement] refers to the getter associated with one
+  /// of those fields, returns the corresponding field formal parameter element.
+  /// Otherwise returns [staticElement] unchanged.
+  ///
+  /// This allows us to treat null checks on the field as though they were null
+  /// checks on the field formal parameter, which is not strictly correct, but
+  /// tends to produce migrations that are more in line with user intent.
+  Element? _favorFieldFormalElements(Element? staticElement) {
+    if (staticElement is PropertyAccessorElement) {
+      var fieldFormal = _currentFieldFormals[staticElement];
+      if (fieldFormal != null) {
+        return fieldFormal;
+      }
+    }
+    return staticElement;
+  }
+
   DecoratedType _fixNumericTypes(
       DecoratedType decoratedType, DartType? undecoratedType) {
     if (decoratedType.type!.isDartCoreNum && undecoratedType!.isDartCoreInt) {
@@ -2315,30 +2361,6 @@
         .decoratedTypeParameterBound((type.type as TypeParameterType).element);
   }
 
-  void _handleArgumentErrorCheckNotNull(MethodInvocation node) {
-    var callee = node.methodName.staticElement;
-    var calleeIsStatic = callee is ExecutableElement && callee.isStatic;
-    var target = node.realTarget;
-    bool targetIsArgumentError =
-        (target is SimpleIdentifier && target.name == 'ArgumentError') ||
-            (target is PrefixedIdentifier &&
-                target.identifier.name == 'ArgumentError');
-
-    if (calleeIsStatic &&
-        targetIsArgumentError &&
-        callee!.name == 'checkNotNull' &&
-        node.argumentList.arguments.isNotEmpty) {
-      var argument = node.argumentList.arguments.first;
-      if (argument is SimpleIdentifier &&
-          _postDominatedLocals.isReferenceInScope(argument)) {
-        var argumentType =
-            _variables!.decoratedElementType(argument.staticElement!);
-        _graph.makeNonNullable(argumentType.node,
-            ArgumentErrorCheckNotNullOrigin(source, argument));
-      }
-    }
-  }
-
   /// Creates the necessary constraint(s) for an assignment of the given
   /// [expression] to a destination whose type is [destinationType].
   ///
@@ -2475,8 +2497,7 @@
       }
     }
     if (assignmentExpression != null) {
-      var element = _postDominatedLocals
-          .referencedElement(assignmentExpression.leftHandSide);
+      var element = _referencedElement(assignmentExpression.leftHandSide);
       if (element != null) {
         _postDominatedLocals.removeFromAllScopes(element);
         _elementsWrittenToInLocalFunction?.add(element);
@@ -2512,6 +2533,32 @@
         redirectedClass.typeParameters);
   }
 
+  void _handleCustomCheckNotNull(MethodInvocation node) {
+    var callee = node.methodName.staticElement;
+    if (node.argumentList.arguments.isNotEmpty &&
+        callee is ExecutableElement &&
+        callee.isStatic) {
+      var enclosingElement = callee.enclosingElement;
+      if (enclosingElement is ClassElement) {
+        if (callee.name == 'checkNotNull' &&
+                enclosingElement.name == 'ArgumentError' &&
+                callee.library.isDartCore ||
+            callee.name == 'checkNotNull' &&
+                enclosingElement.name == 'BuiltValueNullFieldError' &&
+                callee.library.source.uri.toString() ==
+                    'package:built_value/built_value.dart') {
+          var argument = node.argumentList.arguments.first;
+          if (argument is SimpleIdentifier && _isReferenceInScope(argument)) {
+            var argumentType = _variables!.decoratedElementType(
+                _favorFieldFormalElements(getWriteOrReadElement(argument))!);
+            _graph.makeNonNullable(argumentType.node,
+                ArgumentErrorCheckNotNullOrigin(source, argument));
+          }
+        }
+      }
+    }
+  }
+
   void _handleExecutableDeclaration(
       Declaration node,
       ExecutableElement declaredElement,
@@ -2522,16 +2569,20 @@
       FunctionBody body,
       ConstructorName? redirectedConstructor) {
     assert(_currentFunctionType == null);
+    assert(_currentFieldFormals.isEmpty);
     _dispatchList(metadata);
     _dispatch(returnType);
     _createFlowAnalysis(node, parameters);
     _dispatch(parameters);
     _currentFunctionType = _variables!.decoratedElementType(declaredElement);
+    _currentFieldFormals = declaredElement is ConstructorElement
+        ? _computeFieldFormalMap(declaredElement)
+        : const {};
     _addParametersToFlowAnalysis(parameters);
     // Push a scope of post-dominated declarations on the stack.
     _postDominatedLocals.pushScope(elements: declaredElement.parameters);
     if (declaredElement.enclosingElement is ExtensionElement) {
-      _postDominatedLocals.add(_postDominatedLocals.extensionThis);
+      _postDominatedLocals.add(_extensionThis);
     }
     try {
       _dispatchList(initializers);
@@ -2619,6 +2670,7 @@
       _flowAnalysis = null;
       _assignedVariables = null;
       _currentFunctionType = null;
+      _currentFieldFormals = const {};
       _postDominatedLocals.popScope();
     }
   }
@@ -3090,8 +3142,7 @@
 
     if (isQuiverCheckNull && node.argumentList.arguments.isNotEmpty) {
       var argument = node.argumentList.arguments.first;
-      if (argument is SimpleIdentifier &&
-          _postDominatedLocals.isReferenceInScope(argument)) {
+      if (argument is SimpleIdentifier && _isReferenceInScope(argument)) {
         var argumentType =
             _variables!.decoratedElementType(argument.staticElement!);
         _graph.makeNonNullable(
@@ -3147,6 +3198,11 @@
   bool _isPrefix(Expression? e) =>
       e is SimpleIdentifier && e.staticElement is PrefixElement;
 
+  bool _isReferenceInScope(Expression expression) {
+    var element = _referencedElement(expression);
+    return element != null && _postDominatedLocals.isInScope(element);
+  }
+
   bool _isUntypedParameter(NormalFormalParameter parameter) {
     if (parameter is SimpleFormalParameter) {
       return parameter.type == null;
@@ -3261,6 +3317,19 @@
     return node;
   }
 
+  /// Returns the element referenced directly by [expression], if any; otherwise
+  /// returns `null`.
+  Element? _referencedElement(Expression expression) {
+    expression = expression.unParenthesized;
+    if (expression is SimpleIdentifier) {
+      return _favorFieldFormalElements(expression.staticElement);
+    } else if (expression is ThisExpression || expression is SuperExpression) {
+      return _extensionThis;
+    } else {
+      return null;
+    }
+  }
+
   /// Determines whether uses of [expression] should cause hard edges to be
   /// created in the nullability graph.
   ///
@@ -3288,8 +3357,7 @@
     // expression is unconditionally executed, and (b) the expression is a
     // reference to a local variable or parameter and it post-dominates the
     // declaration of that local variable or parameter.
-    return !isConditionallyExecuted &&
-        _postDominatedLocals.isReferenceInScope(expression);
+    return !isConditionallyExecuted && _isReferenceInScope(expression);
   }
 
   DecoratedType? _thisOrSuper(Expression node) {
@@ -3772,30 +3840,3 @@
       trueDemonstratesNonNullIntent: falseDemonstratesNonNullIntent,
       falseDemonstratesNonNullIntent: trueDemonstratesNonNullIntent);
 }
-
-/// A [ScopedSet] specific to the [Element]s of locals/parameters.
-///
-/// Contains helpers for dealing with expressions as if they were elements.
-class _ScopedLocalSet extends ScopedSet<Element?> {
-  /// The synthetic element we use as a stand-in for `this` when analyzing
-  /// extension methods.
-  Element get extensionThis => DynamicElementImpl.instance;
-
-  bool isReferenceInScope(Expression expression) {
-    var element = referencedElement(expression);
-    return element != null && isInScope(element);
-  }
-
-  /// Returns the element referenced directly by [expression], if any; otherwise
-  /// returns `null`.
-  Element? referencedElement(Expression expression) {
-    expression = expression.unParenthesized;
-    if (expression is SimpleIdentifier) {
-      return expression.staticElement;
-    } else if (expression is ThisExpression || expression is SuperExpression) {
-      return extensionThis;
-    } else {
-      return null;
-    }
-  }
-}
diff --git a/pkg/nnbd_migration/lib/src/edit_plan.dart b/pkg/nnbd_migration/lib/src/edit_plan.dart
index 33728b9..b0e55fc 100644
--- a/pkg/nnbd_migration/lib/src/edit_plan.dart
+++ b/pkg/nnbd_migration/lib/src/edit_plan.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:convert';
+import 'dart:math';
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/precedence.dart';
@@ -837,6 +838,8 @@
       return node.members;
     } else if (node is CompilationUnit) {
       return [...node.directives, ...node.declarations];
+    } else if (node is MethodDeclaration) {
+      return node.metadata;
     } else {
       return null;
     }
@@ -1424,8 +1427,8 @@
       if (firstPlanIndex == 0 && lastPlanIndex == sequenceNodes!.length - 1) {
         // We're removing everything.  Try to remove additional whitespace so
         // that we're left with just `()`, `{}`, or `[]`.
-        var candidateFirstRemovalOffset =
-            planner._backAcrossWhitespace(firstRemovalOffset, node!.offset);
+        var candidateFirstRemovalOffset = planner._backAcrossWhitespace(
+            firstRemovalOffset, min(firstRemovalOffset, node!.offset));
         if (planner
             ._isJustAfter(candidateFirstRemovalOffset, const ['(', '[', '{'])) {
           var candidateLastRemovalEnd =
@@ -1541,7 +1544,8 @@
     if (parent is Block ||
         parent is ClassDeclaration ||
         parent is CompilationUnit ||
-        parent is FormalParameter) {
+        parent is FormalParameter ||
+        parent is MethodDeclaration) {
       // These parent types don't use separators.
       return null;
     } else {
diff --git a/pkg/nnbd_migration/lib/src/fix_aggregator.dart b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
index 7e74f7e..ddf1bb4 100644
--- a/pkg/nnbd_migration/lib/src/fix_aggregator.dart
+++ b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
@@ -911,6 +911,34 @@
 }
 
 /// Implementation of [NodeChange] specialized for operating on
+/// [MethodDeclaration] nodes.
+class NodeChangeForMethodDeclaration extends NodeChange<MethodDeclaration> {
+  /// If non-null, indicates a `@nullable` annotation which should be removed
+  /// from this node.
+  Annotation? annotationToRemove;
+
+  /// If [annotationToRemove] is non-null, the information that should be
+  /// contained in the edit.
+  AtomicEditInfo? removeAnnotationInfo;
+
+  NodeChangeForMethodDeclaration() : super._();
+
+  @override
+  Iterable<String> get _toStringParts =>
+      [if (annotationToRemove != null) 'annotationToRemove'];
+
+  @override
+  EditPlan _apply(MethodDeclaration node, FixAggregator aggregator) {
+    return aggregator.planner.passThrough(node, innerPlans: [
+      if (annotationToRemove != null)
+        aggregator.planner
+            .removeNode(annotationToRemove!, info: removeAnnotationInfo),
+      ...aggregator.innerPlansForNode(node),
+    ]);
+  }
+}
+
+/// Implementation of [NodeChange] specialized for operating on
 /// [MethodInvocation] nodes.
 class NodeChangeForMethodInvocation
     extends NodeChangeForExpression<MethodInvocation>
@@ -1423,6 +1451,10 @@
   NodeChange visitIfStatement(IfStatement node) => NodeChangeForIfStatement();
 
   @override
+  NodeChange visitMethodDeclaration(MethodDeclaration node) =>
+      NodeChangeForMethodDeclaration();
+
+  @override
   NodeChange visitMethodInvocation(MethodInvocation node) =>
       NodeChangeForMethodInvocation();
 
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 77fc0d3..bcfdef6 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -141,7 +141,7 @@
       TypeProvider typeProvider,
       TypeSystemImpl typeSystem,
       Variables? variables,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       NullabilityMigrationListener? listener,
       CompilationUnit? unit,
       bool? warnOnWeakCode,
@@ -170,7 +170,7 @@
       this._typeSystem,
       this._variables,
       this.source,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       this.listener,
       this.unit,
       this.migrationResolutionHooks,
@@ -557,7 +557,7 @@
 
   @override
   void setCompoundAssignmentExpressionTypes(CompoundAssignmentExpression node) {
-    assert(_assignmentLikeExpressionHandlers[node as Expression] == null);
+    assert(_assignmentLikeExpressionHandlers[node] == null);
     if (node is AssignmentExpression) {
       var handler = _AssignmentExpressionHandler(node);
       _assignmentLikeExpressionHandlers[node] = handler;
@@ -1147,15 +1147,18 @@
       // Potentially add an explicit type to a field formal parameter.
       var decl = node.declaredElement as FieldFormalParameterElement;
       var decoratedType = _fixBuilder._variables!.decoratedElementType(decl);
-      var decoratedFieldType =
-          _fixBuilder._variables!.decoratedElementType(decl.field!);
-      var typeToAdd = _fixBuilder._variables!.toFinalType(decoratedType);
-      var fieldFinalType =
-          _fixBuilder._variables!.toFinalType(decoratedFieldType);
-      if (typeToAdd is InterfaceType &&
-          !_fixBuilder._typeSystem.isSubtypeOf(fieldFinalType, typeToAdd)) {
-        (_fixBuilder._getChange(node) as NodeChangeForFieldFormalParameter)
-            .addExplicitType = typeToAdd;
+      var field = decl.field;
+      if (field != null) {
+        var decoratedFieldType =
+            _fixBuilder._variables!.decoratedElementType(field);
+        var typeToAdd = _fixBuilder._variables!.toFinalType(decoratedType);
+        var fieldFinalType =
+            _fixBuilder._variables!.toFinalType(decoratedFieldType);
+        if (typeToAdd is InterfaceType &&
+            !_fixBuilder._typeSystem.isSubtypeOf(fieldFinalType, typeToAdd)) {
+          (_fixBuilder._getChange(node) as NodeChangeForFieldFormalParameter)
+              .addExplicitType = typeToAdd;
+        }
       }
     } else if (node.parameters != null) {
       // Handle function-typed field formal parameters.
@@ -1198,6 +1201,31 @@
   }
 
   @override
+  void visitMethodDeclaration(MethodDeclaration node) {
+    if (node.isGetter && node.isAbstract) {
+      for (var annotation in node.metadata) {
+        if (annotation.arguments == null) {
+          var element = annotation.element;
+          if (element is PropertyAccessorElement &&
+              element.name == 'nullable') {
+            if (element.enclosingElement is CompilationUnitElement) {
+              if (element.library.source.uri.toString() ==
+                  'package:built_value/built_value.dart') {
+                var info = AtomicEditInfo(
+                    NullabilityFixDescription.removeNullableAnnotation, {});
+                (_fixBuilder._getChange(node) as NodeChangeForMethodDeclaration)
+                  ..annotationToRemove = annotation
+                  ..removeAnnotationInfo = info;
+              }
+            }
+          }
+        }
+      }
+    }
+    super.visitMethodDeclaration(node);
+  }
+
+  @override
   void visitTypeName(TypeName node) {
     var decoratedType = _fixBuilder._variables!
         .decoratedTypeAnnotation(_fixBuilder.source, node);
diff --git a/pkg/nnbd_migration/lib/src/front_end/info_builder.dart b/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
index c6f6fb4..c6f4bb7 100644
--- a/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
@@ -96,11 +96,11 @@
     for (var filePath in sources) {
       progressBar.tick();
       var session = driverProvider!.getAnalysisSession(filePath);
-      var result = await session.getResolvedLibrary2(filePath!);
+      var result = await session.getResolvedLibrary(filePath!);
       if (result is ResolvedLibraryResult) {
-        for (var unitResult in result.units!) {
+        for (var unitResult in result.units) {
           var sourceInfo =
-              sourceInfoMap[unitResult.unit!.declaredElement!.source];
+              sourceInfoMap[unitResult.unit.declaredElement!.source];
           // Note: there might have been no information for this unit in
           // sourceInfoMap.  That can happen if there's an already-migrated
           // library being referenced by the code being migrated, but not all
@@ -111,7 +111,7 @@
           // referenced (we'll just skip the entire library because we'll only
           // ever see its parts).
           sourceInfo ??= SourceInformation();
-          var edit = listener!.sourceChange.getFileEdit(unitResult.path!);
+          var edit = listener!.sourceChange.getFileEdit(unitResult.path);
           var unit = _explainUnit(sourceInfo, unitResult, edit);
           if (_pathsToProcess!.contains(unitResult.path)) {
             units.add(unit);
@@ -185,7 +185,7 @@
         break;
       case NullabilityFixKind.addRequired:
         var metaImport =
-            _findImportDirective(result.unit!, 'package:meta/meta.dart');
+            _findImportDirective(result.unit, 'package:meta/meta.dart');
         if (metaImport == null) {
           edits.add(
               EditDetail('Add /*required*/ hint', offset, 0, '/*required*/ '));
@@ -265,6 +265,10 @@
       case NullabilityFixKind.addThen:
         // We don't offer any edits around addition of `.then` to a future.
         break;
+      case NullabilityFixKind.removeNullableAnnotation:
+        // We don't offer any edits around removal of built_value `@nullable`
+        // annotations.
+        break;
     }
     return edits;
   }
@@ -273,7 +277,7 @@
   List<NavigationSource> _computeNavigationSources(ResolvedUnitResult result) {
     var collector = NavigationCollectorImpl();
     computeDartNavigation(
-        result.session.resourceProvider, collector, result.unit!, null, null);
+        result.session.resourceProvider, collector, result.unit, null, null);
     collector.createRegions();
     var files = collector.files;
     var regions = collector.regions;
@@ -377,8 +381,8 @@
     var content = result.content;
     unitInfo.diskContent = content;
     var alreadyMigrated =
-        result.unit!.featureSet.isEnabled(Feature.non_nullable);
-    unitInfo.wasExplicitlyOptedOut = result.unit!.languageVersionToken != null;
+        result.unit.featureSet.isEnabled(Feature.non_nullable);
+    unitInfo.wasExplicitlyOptedOut = result.unit.languageVersionToken != null;
     if (alreadyMigrated) {
       unitInfo.migrationStatus = UnitMigrationStatus.alreadyMigrated;
       unitInfo.migrationStatusCanBeChanged = false;
@@ -401,7 +405,7 @@
     // before we re-populate the region list.
     regions.clear();
 
-    var lineInfo = result.unit!.lineInfo;
+    var lineInfo = result.unit.lineInfo;
     var insertions = <int?, List<AtomicEdit>>{};
     var infosSeen = Set<AtomicEditInfo>.identity();
 
@@ -422,7 +426,7 @@
         var end = offset + length;
         // Insert the replacement text without deleting the replaced text.
         if (replacement.isNotEmpty) {
-          content = content!.replaceRange(end, end, replacement);
+          content = content.replaceRange(end, end, replacement);
           (insertions[sourceOffset] ??= []).add(AtomicEdit.insert(replacement));
         }
         var info = edit.info;
diff --git a/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart b/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart
index 7a72ee6..90adae8 100644
--- a/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart
@@ -113,6 +113,8 @@
         return 'typeNotMadeNullable';
       case NullabilityFixKind.typeNotMadeNullableDueToHint:
         return 'typeNotMadeNullableDueToHint';
+      case NullabilityFixKind.removeNullableAnnotation:
+        return 'removeNullableAnnotation';
     }
   }
 }
diff --git a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
index bed1a35..fea31af 100644
--- a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
@@ -277,8 +277,8 @@
         var edit = SourceEdit(offset, configText.length, newText);
         listener.addSourceFileEdit(
             'enable Null Safety language feature',
-            Location(
-                packageConfigFile.path, offset, newText.length, line, 0, 0, 0),
+            Location(packageConfigFile.path, offset, newText.length, line, 0,
+                endLine: 0, endColumn: 0),
             SourceFileEdit(packageConfigFile.path, 0, edits: [edit]));
       }
     } on FormatException catch (e) {
@@ -599,7 +599,8 @@
     var edit = SourceEdit(offset, 0, content);
     listener.addSourceFileEdit(
         'enable Null Safety language feature',
-        Location(path, offset, content.length, line, 0, 0, 0),
+        Location(path, offset, content.length, line, 0,
+            endLine: 0, endColumn: 0),
         SourceFileEdit(path, 0, edits: [edit]));
   }
 
@@ -609,7 +610,8 @@
     var edit = SourceEdit(offset, span.length, content);
     listener.addSourceFileEdit(
         'enable Null Safety language feature',
-        Location(path, offset, content.length, line, 0, 0, 0),
+        Location(path, offset, content.length, line, 0,
+            endLine: 0, endColumn: 0),
         SourceFileEdit(path, 0, edits: [edit]));
   }
 
diff --git a/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart b/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart
index c5f8ef3..6b6257cc 100644
--- a/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart
@@ -43,6 +43,7 @@
     NullabilityFixKind.removeAs,
     NullabilityFixKind.addLate,
     NullabilityFixKind.addLateDueToTestSetup,
+    NullabilityFixKind.removeNullableAnnotation,
     NullabilityFixKind.addLateDueToHint,
     NullabilityFixKind.addLateFinalDueToHint,
     NullabilityFixKind.checkExpressionDueToHint,
@@ -337,6 +338,8 @@
         return '$count type$s not made nullable';
       case NullabilityFixKind.typeNotMadeNullableDueToHint:
         return '$count type$s not made nullable due to hint$s';
+      case NullabilityFixKind.removeNullableAnnotation:
+        return '$count @nullable annotation$s removed';
     }
   }
 
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 14fd871..b50bed1 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -446,9 +446,10 @@
 
   @override
   DecoratedType? visitMethodDeclaration(MethodDeclaration node) {
-    _handleExecutableDeclaration(
+    var declaredElement = node.declaredElement;
+    var decoratedType = _handleExecutableDeclaration(
         node,
-        node.declaredElement!,
+        declaredElement!,
         node.metadata,
         node.returnType,
         node.typeParameters,
@@ -456,6 +457,19 @@
         null,
         node.body,
         null);
+    if (declaredElement is PropertyAccessorElement) {
+      // Store a decorated type for the synthetic field so that in case we try
+      // to access it later we won't crash (this could happen due to errors in
+      // the source code).
+      if (declaredElement.isGetter) {
+        _variables!.recordDecoratedElementType(
+            declaredElement.variable, decoratedType.returnType);
+      } else {
+        _variables!.recordDecoratedElementType(
+            declaredElement.variable, decoratedType.positionalParameters![0],
+            soft: true);
+      }
+    }
     return null;
   }
 
@@ -675,7 +689,7 @@
   }
 
   /// Common handling of function and method declarations.
-  void _handleExecutableDeclaration(
+  DecoratedType _handleExecutableDeclaration(
       AstNode node,
       ExecutableElement declaredElement,
       NodeList<Annotation>? metadata,
@@ -726,6 +740,7 @@
     }
     _variables!
         .recordDecoratedElementType(declaredElement, decoratedFunctionType);
+    return decoratedFunctionType;
   }
 
   DecoratedType? _handleFormalParameter(
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index 07c652a..867f72a 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -123,7 +124,7 @@
 
   @override
   void finalizeInput(ResolvedUnitResult result) {
-    if (result.unit!.featureSet.isEnabled(Feature.non_nullable)) {
+    if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
       // This library has already been migrated; nothing more to do.
       return;
     }
@@ -132,7 +133,7 @@
       _propagated = true;
       _graph.propagate();
     }
-    var unit = result.unit!;
+    var unit = result.unit;
     var compilationUnit = unit.declaredElement!;
     var library = compilationUnit.library;
     var source = compilationUnit.source;
@@ -146,7 +147,7 @@
         result.typeProvider,
         library.typeSystem as TypeSystemImpl,
         _variables,
-        library,
+        library as LibraryElementImpl,
         _permissive! ? listener : null,
         unit,
         warnOnWeakCode,
@@ -188,7 +189,7 @@
         !_queriedUnmigratedDependencies,
         'Should only query unmigratedDependencies after all calls to '
         'prepareInput');
-    if (result.unit!.featureSet.isEnabled(Feature.non_nullable)) {
+    if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
       // This library has already been migrated; nothing more to do.
       return;
     }
@@ -202,7 +203,7 @@
           instrumentation: _instrumentation);
       _decoratedClassHierarchy = DecoratedClassHierarchy(_variables, _graph);
     }
-    var unit = result.unit!;
+    var unit = result.unit;
     try {
       DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
       unit.accept(NodeBuilder(
@@ -219,12 +220,12 @@
   }
 
   void processInput(ResolvedUnitResult result) {
-    if (result.unit!.featureSet.isEnabled(Feature.non_nullable)) {
+    if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
       // This library has already been migrated; nothing more to do.
       return;
     }
     ExperimentStatusException.sanityCheck(result);
-    var unit = result.unit!;
+    var unit = result.unit;
     try {
       DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
       unit.accept(EdgeBuilder(
@@ -270,8 +271,8 @@
       edit.length,
       startLocation.lineNumber,
       startLocation.columnNumber,
-      endLocation.lineNumber,
-      endLocation.columnNumber,
+      endLine: endLocation.lineNumber,
+      endColumn: endLocation.columnNumber,
     );
     return location;
   }
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index 44d0475..7222753 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -214,7 +214,8 @@
   }
 
   /// Associates decorated type information with the given [element].
-  void recordDecoratedElementType(Element? element, DecoratedType? type) {
+  void recordDecoratedElementType(Element? element, DecoratedType? type,
+      {bool soft = false}) {
     assert(() {
       assert(element is! TypeParameterElement,
           'Use recordDecoratedTypeParameterBound instead');
@@ -227,6 +228,9 @@
       }
       return true;
     }());
+    if (soft && _decoratedElementTypes.containsKey(element)) {
+      return;
+    }
     _decoratedElementTypes[element] = type;
   }
 
diff --git a/pkg/nnbd_migration/test/abstract_context.dart b/pkg/nnbd_migration/test/abstract_context.dart
index 1b2b8a3..4e7b83e 100644
--- a/pkg/nnbd_migration/test/abstract_context.dart
+++ b/pkg/nnbd_migration/test/abstract_context.dart
@@ -45,6 +45,17 @@
 
   String get testsPath => '$homePath/tests';
 
+  void addBuiltValuePackage() {
+    addPackageFile('built_value', 'built_value.dart', '''
+abstract class Built<V extends Built<V, B>, B extends Builder<V, B>> {}
+abstract class Builder<V extends Built<V, B>, B extends Builder<V, B>> {}
+const String nullable = 'nullable';
+class BuiltValueNullFieldError extends Error {
+  static T checkNotNull<T>(T? value, String type, String field) => value!;
+}
+''');
+  }
+
   void addMetaPackage() {
     addPackageFile('meta', 'meta.dart', r'''
 library meta;
@@ -120,7 +131,7 @@
   }
 
   LineInfo getLineInfo(String path) =>
-      (session.getFile2(path) as FileResult).lineInfo;
+      (session.getFile(path) as FileResult).lineInfo;
 
   void setUp() {
     setupResourceProvider();
diff --git a/pkg/nnbd_migration/test/abstract_single_unit.dart b/pkg/nnbd_migration/test/abstract_single_unit.dart
index dc9049a..7934ab3 100644
--- a/pkg/nnbd_migration/test/abstract_single_unit.dart
+++ b/pkg/nnbd_migration/test/abstract_single_unit.dart
@@ -38,7 +38,7 @@
   Future<void> resolveTestUnit(String code) async {
     addTestSource(code, testUri);
     testAnalysisResult =
-        await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
+        await session.getResolvedUnit(testFile) as ResolvedUnitResult;
     testUnit = testAnalysisResult.unit;
     if (verifyNoTestUnitErrors) {
       expect(testAnalysisResult.errors.where((AnalysisError error) {
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 6d1fe57..cc1bc01 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -48,7 +48,7 @@
   /// Optional parameter [removeViaComments] indicates whether dead code should
   /// be removed in its entirety (the default) or removed by commenting it out.
   Future<void> _checkMultipleFileChanges(
-      Map<String, String> input, Map<String, String> expectedOutput,
+      Map<String, String> input, Map<String, dynamic> expectedOutput,
       {Map<String, String> migratedInput = const {},
       bool removeViaComments = false,
       bool warnOnWeakCode = false,
@@ -65,9 +65,9 @@
         removeViaComments: removeViaComments,
         warnOnWeakCode: warnOnWeakCode);
     for (var path in input.keys) {
-      var resolvedLibrary = await session.getResolvedLibrary2(path);
+      var resolvedLibrary = await session.getResolvedLibrary(path);
       if (resolvedLibrary is ResolvedLibraryResult) {
-        for (var unit in resolvedLibrary.units!) {
+        for (var unit in resolvedLibrary.units) {
           var errors =
               unit.errors.where((e) => e.severity == Severity.error).toList();
           if (!allowErrors && errors.isNotEmpty) {
@@ -80,18 +80,18 @@
     expect(migration.unmigratedDependencies, isEmpty);
     _betweenStages();
     for (var path in input.keys) {
-      var resolvedLibrary = await session.getResolvedLibrary2(path);
+      var resolvedLibrary = await session.getResolvedLibrary(path);
       if (resolvedLibrary is ResolvedLibraryResult) {
-        for (var unit in resolvedLibrary.units!) {
+        for (var unit in resolvedLibrary.units) {
           migration.processInput(unit);
         }
       }
     }
     _betweenStages();
     for (var path in input.keys) {
-      var resolvedLibrary = await session.getResolvedLibrary2(path);
+      var resolvedLibrary = await session.getResolvedLibrary(path);
       if (resolvedLibrary is ResolvedLibraryResult) {
-        for (var unit in resolvedLibrary.units!) {
+        for (var unit in resolvedLibrary.units) {
           migration.finalizeInput(unit);
         }
       }
@@ -116,7 +116,7 @@
   ///
   /// Optional parameter [removeViaComments] indicates whether dead code should
   /// be removed in its entirety (the default) or removed by commenting it out.
-  Future<void> _checkSingleFileChanges(String content, String expected,
+  Future<void> _checkSingleFileChanges(String content, dynamic expected,
       {Map<String, String> migratedInput = const {},
       bool removeViaComments = false,
       bool warnOnWeakCode = false,
@@ -495,6 +495,111 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_built_value_non_nullable_getter() async {
+    addBuiltValuePackage();
+    var root = '$projectPath/lib';
+    var path1 = convertPath('$root/lib.dart');
+    var file1 = r'''
+import 'package:built_value/built_value.dart';
+
+part 'lib.g.dart';
+
+abstract class Foo implements Built<Foo, FooBuilder> {
+  int get value;
+  Foo._();
+  factory Foo([void Function(FooBuilder) updates]) = _$Foo;
+}
+''';
+    var expected1 = r'''
+import 'package:built_value/built_value.dart';
+
+part 'lib.g.dart';
+
+abstract class Foo implements Built<Foo, FooBuilder> {
+  int get value;
+  Foo._();
+  factory Foo([void Function(FooBuilder) updates]) = _$Foo;
+}
+''';
+    // Note: in a real-world scenario the generated file would be in a different
+    // directory but we don't need to simulate that detail for this test.  Also,
+    // the generated file would have a lot more code in it, but we don't need to
+    // simulate all the details of what is generated.
+    var path2 = convertPath('$root/lib.g.dart');
+    var file2 = r'''
+part of 'lib.dart';
+
+class _$Foo extends Foo {
+  @override
+  final int value;
+
+  factory _$Foo([void Function(FooBuilder) updates]) => throw '';
+
+  _$Foo._({this.value}) : super._() {
+    BuiltValueNullFieldError.checkNotNull(value, 'Foo', 'value');
+  }
+}
+
+class FooBuilder implements Builder<Foo, FooBuilder> {
+  int get value => throw '';
+}
+''';
+    await _checkMultipleFileChanges(
+        {path1: file1, path2: file2}, {path1: expected1, path2: anything});
+  }
+
+  Future<void> test_built_value_nullable_getter() async {
+    addBuiltValuePackage();
+    var root = '$projectPath/lib';
+    var path1 = convertPath('$root/lib.dart');
+    var file1 = r'''
+import 'package:built_value/built_value.dart';
+
+part 'lib.g.dart';
+
+abstract class Foo implements Built<Foo, FooBuilder> {
+  @nullable
+  int get value;
+  Foo._();
+  factory Foo([void Function(FooBuilder) updates]) = _$Foo;
+}
+''';
+    var expected1 = r'''
+import 'package:built_value/built_value.dart';
+
+part 'lib.g.dart';
+
+abstract class Foo implements Built<Foo, FooBuilder> {
+  int? get value;
+  Foo._();
+  factory Foo([void Function(FooBuilder) updates]) = _$Foo;
+}
+''';
+    // Note: in a real-world scenario the generated file would be in a different
+    // directory but we don't need to simulate that detail for this test.  Also,
+    // the generated file would have a lot more code in it, but we don't need to
+    // simulate all the details of what is generated.
+    var path2 = convertPath('$root/lib.g.dart');
+    var file2 = r'''
+part of 'lib.dart';
+
+class _$Foo extends Foo {
+  @override
+  final int value;
+
+  factory _$Foo([void Function(FooBuilder) updates]) => throw '';
+
+  _$Foo._({this.value}) : super._();
+}
+
+class FooBuilder implements Builder<Foo, FooBuilder> {
+  int get value => throw '';
+}
+''';
+    await _checkMultipleFileChanges(
+        {path1: file1, path2: file2}, {path1: expected1, path2: anything});
+  }
+
   Future<void> test_call_already_migrated_extension() async {
     var content = '''
 import 'already_migrated.dart';
@@ -1111,6 +1216,41 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_constructor_field_formal_resolves_to_getter() async {
+    var content = '''
+class C {
+  int get i => 0;
+  C(this.i);
+}
+''';
+    // It doesn't matter what the migration produces; we just want to make sure
+    // there isn't a crash.
+    await _checkSingleFileChanges(content, anything, allowErrors: true);
+  }
+
+  Future<void> test_constructor_field_formal_resolves_to_setter() async {
+    var content = '''
+class C {
+  set i(int value) {}
+  C(this.i);
+}
+''';
+    // It doesn't matter what the migration produces; we just want to make sure
+    // there isn't a crash.
+    await _checkSingleFileChanges(content, anything, allowErrors: true);
+  }
+
+  Future<void> test_constructor_field_formal_unresolved() async {
+    var content = '''
+class C {
+  C(this.i);
+}
+''';
+    // It doesn't matter what the migration produces; we just want to make sure
+    // there isn't a crash.
+    await _checkSingleFileChanges(content, anything, allowErrors: true);
+  }
+
   Future<void> test_constructor_optional_param_factory() async {
     var content = '''
 class C {
@@ -6106,6 +6246,84 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_non_null_intent_field_formal_assert() async {
+    var content = '''
+class C {
+  int i;
+  C(this.i) {
+    assert(i != null);
+  }
+}
+f(int j, bool b) {
+  if (b) {
+    C(j);
+  }
+}
+g() {
+  f(null, false);
+}
+''';
+    var expected = '''
+class C {
+  int i;
+  C(this.i) {
+    assert(i != null);
+  }
+}
+f(int? j, bool b) {
+  if (b) {
+    C(j!);
+  }
+}
+g() {
+  f(null, false);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  Future<void> test_non_null_intent_field_formal_use() async {
+    var content = '''
+class C {
+  int i;
+  C(this.i) {
+    f(i);
+  }
+}
+f(int j) {
+  assert(j != null);
+}
+g(int k, bool b) {
+  if (b) {
+    C(k);
+  }
+}
+h() {
+  g(null, false);
+}
+''';
+    var expected = '''
+class C {
+  int i;
+  C(this.i) {
+    f(i);
+  }
+}
+f(int j) {
+  assert(j != null);
+}
+g(int? k, bool b) {
+  if (b) {
+    C(k!);
+  }
+}
+h() {
+  g(null, false);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void>
       test_non_null_intent_propagated_through_substitution_nodes() async {
     var content = '''
diff --git a/pkg/nnbd_migration/test/edit_plan_test.dart b/pkg/nnbd_migration/test/edit_plan_test.dart
index 3cc00e7..135ec47 100644
--- a/pkg/nnbd_migration/test/edit_plan_test.dart
+++ b/pkg/nnbd_migration/test/edit_plan_test.dart
@@ -888,6 +888,39 @@
     expect(changes.keys, [entry.offset]);
   }
 
+  Future<void>
+      test_remove_metadata_from_defaultFormalParameter_all_full_line() async {
+    await analyze('''
+f({
+  @deprecated
+  int? x}) {}''');
+    var deprecated = findNode.annotation('@deprecated');
+    checkPlan(
+        planner!.passThrough(deprecated.parent,
+            innerPlans: [planner!.removeNode(deprecated)]),
+        '''
+f({
+  int? x}) {}''');
+  }
+
+  Future<void> test_remove_metadata_from_method_declaration() async {
+    await analyze('''
+class C {
+  @deprecated
+  f() {}
+}
+''');
+    var deprecated = findNode.annotation('@deprecated');
+    checkPlan(
+        planner!.passThrough(deprecated.parent,
+            innerPlans: [planner!.removeNode(deprecated)]),
+        '''
+class C {
+  f() {}
+}
+''');
+  }
+
   Future<void> test_remove_parameter() async {
     await analyze('f(int x, int y, int z) => null;');
     var parameter = findNode.simple('y').parent!;
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index a9026b2..74fa1a8 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/generated/element_type_provider.dart';
@@ -3886,7 +3887,7 @@
         typeProvider,
         typeSystem,
         variables,
-        definingLibrary,
+        definingLibrary as LibraryElementImpl,
         null,
         scope.thisOrAncestorOfType<CompilationUnit>(),
         warnOnWeakCode,
diff --git a/pkg/nnbd_migration/test/front_end/info_builder_test.dart b/pkg/nnbd_migration/test/front_end/info_builder_test.dart
index e4da1b7..23a7900 100644
--- a/pkg/nnbd_migration/test/front_end/info_builder_test.dart
+++ b/pkg/nnbd_migration/test/front_end/info_builder_test.dart
@@ -24,7 +24,7 @@
 @reflectiveTest
 class BuildEnclosingMemberDescriptionTest extends AbstractAnalysisTest {
   Future<ResolvedUnitResult> resolveTestFile() async {
-    return await session.getResolvedUnit2(testFile!) as ResolvedUnitResult;
+    return await session.getResolvedUnit(testFile!) as ResolvedUnitResult;
   }
 
   Future<void> test_classConstructor_named() async {
@@ -35,7 +35,7 @@
 ''');
     var result = await resolveTestFile();
     ClassDeclaration class_ =
-        result.unit!.declarations.single as ClassDeclaration;
+        result.unit.declarations.single as ClassDeclaration;
     var constructor = class_.members.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(constructor),
         equals("the constructor 'C.aaa'"));
@@ -49,7 +49,7 @@
 ''');
     var result = await resolveTestFile();
     ClassDeclaration class_ =
-        result.unit!.declarations.single as ClassDeclaration;
+        result.unit.declarations.single as ClassDeclaration;
     var constructor = class_.members.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(constructor),
         equals("the default constructor of 'C'"));
@@ -63,7 +63,7 @@
 ''');
     var result = await resolveTestFile();
     ClassDeclaration class_ =
-        result.unit!.declarations.single as ClassDeclaration;
+        result.unit.declarations.single as ClassDeclaration;
     FieldDeclaration fieldDeclaration =
         class_.members.single as FieldDeclaration;
     var field = fieldDeclaration.fields.variables[0];
@@ -79,7 +79,7 @@
 ''');
     var result = await resolveTestFile();
     ClassDeclaration class_ =
-        result.unit!.declarations.single as ClassDeclaration;
+        result.unit.declarations.single as ClassDeclaration;
     FieldDeclaration fieldDeclaration =
         class_.members.single as FieldDeclaration;
     var type = fieldDeclaration.fields.type;
@@ -95,7 +95,7 @@
 ''');
     var result = await resolveTestFile();
     ClassDeclaration class_ =
-        result.unit!.declarations.single as ClassDeclaration;
+        result.unit.declarations.single as ClassDeclaration;
     var getter = class_.members.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(getter),
         equals("the getter 'C.aaa'"));
@@ -109,7 +109,7 @@
 ''');
     var result = await resolveTestFile();
     ClassDeclaration class_ =
-        result.unit!.declarations.single as ClassDeclaration;
+        result.unit.declarations.single as ClassDeclaration;
     var method = class_.members.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(method),
         equals("the method 'C.aaa'"));
@@ -123,7 +123,7 @@
 ''');
     var result = await resolveTestFile();
     ClassDeclaration class_ =
-        result.unit!.declarations.single as ClassDeclaration;
+        result.unit.declarations.single as ClassDeclaration;
     var operator = class_.members.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(operator),
         equals("the operator 'C.=='"));
@@ -137,7 +137,7 @@
 ''');
     var result = await resolveTestFile();
     ClassDeclaration class_ =
-        result.unit!.declarations.single as ClassDeclaration;
+        result.unit.declarations.single as ClassDeclaration;
     var setter = class_.members.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(setter),
         equals("the setter 'C.aaa='"));
@@ -151,7 +151,7 @@
 ''');
     var result = await resolveTestFile();
     ExtensionDeclaration extension_ =
-        result.unit!.declarations.single as ExtensionDeclaration;
+        result.unit.declarations.single as ExtensionDeclaration;
     var method = extension_.members.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(method),
         equals("the method 'E.aaa'"));
@@ -165,7 +165,7 @@
 ''');
     var result = await resolveTestFile();
     ExtensionDeclaration extension_ =
-        result.unit!.declarations.single as ExtensionDeclaration;
+        result.unit.declarations.single as ExtensionDeclaration;
     var method = extension_.members.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(method),
         equals("the method 'aaa' in unnamed extension on List<dynamic>"));
@@ -179,7 +179,7 @@
 ''');
     var result = await resolveTestFile();
     MixinDeclaration mixin_ =
-        result.unit!.declarations.single as MixinDeclaration;
+        result.unit.declarations.single as MixinDeclaration;
     var method = mixin_.members.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(method),
         equals("the method 'C.aaa'"));
@@ -190,7 +190,7 @@
 void aaa(value) {}
 ''');
     var result = await resolveTestFile();
-    var function = result.unit!.declarations.single;
+    var function = result.unit.declarations.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(function),
         equals("the function 'aaa'"));
   }
@@ -200,7 +200,7 @@
 int get aaa => 7;
 ''');
     var result = await resolveTestFile();
-    var getter = result.unit!.declarations.single;
+    var getter = result.unit.declarations.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(getter),
         equals("the getter 'aaa'"));
   }
@@ -210,7 +210,7 @@
 void set aaa(value) {}
 ''');
     var result = await resolveTestFile();
-    var setter = result.unit!.declarations.single;
+    var setter = result.unit.declarations.single;
     expect(InfoBuilder.buildEnclosingMemberDescription(setter),
         equals("the setter 'aaa='"));
   }
@@ -221,7 +221,7 @@
 ''');
     var result = await resolveTestFile();
     TopLevelVariableDeclaration topLevelVariableDeclaration =
-        result.unit!.declarations.single as TopLevelVariableDeclaration;
+        result.unit.declarations.single as TopLevelVariableDeclaration;
     var variable = topLevelVariableDeclaration.variables.variables[0];
     expect(InfoBuilder.buildEnclosingMemberDescription(variable),
         equals("the variable 'i'"));
@@ -233,7 +233,7 @@
 ''');
     var result = await resolveTestFile();
     TopLevelVariableDeclaration topLevelVariableDeclaration =
-        result.unit!.declarations.single as TopLevelVariableDeclaration;
+        result.unit.declarations.single as TopLevelVariableDeclaration;
     var type = topLevelVariableDeclaration.variables.type;
     expect(InfoBuilder.buildEnclosingMemberDescription(type),
         equals("the variable 'i'"));
diff --git a/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart b/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
index 96c987d..451a1d7 100644
--- a/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
+++ b/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
@@ -236,7 +236,7 @@
     Future<void> _forEachPath(
         void Function(ResolvedUnitResult) callback) async {
       for (var testPath in testPaths) {
-        var result = await driver!.currentSession.getResolvedUnit2(testPath!)
+        var result = await driver!.currentSession.getResolvedUnit(testPath!)
             as ResolvedUnitResult;
         callback(result);
       }
diff --git a/pkg/nnbd_migration/test/instrumentation_test.dart b/pkg/nnbd_migration/test/instrumentation_test.dart
index be4ba0d..821b21c 100644
--- a/pkg/nnbd_migration/test/instrumentation_test.dart
+++ b/pkg/nnbd_migration/test/instrumentation_test.dart
@@ -149,9 +149,9 @@
         removeViaComments: removeViaComments,
         warnOnWeakCode: warnOnWeakCode);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
-    source = result.unit!.declaredElement!.source;
-    findNode = FindNode(content, result.unit!);
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+    source = result.unit.declaredElement!.source;
+    findNode = FindNode(content, result.unit);
     migration.prepareInput(result);
     expect(migration.unmigratedDependencies, isEmpty);
     migration.processInput(result);
diff --git a/pkg/nnbd_migration/test/preview/preview_site_test.dart b/pkg/nnbd_migration/test/preview/preview_site_test.dart
index aeee9da..872d4d0 100644
--- a/pkg/nnbd_migration/test/preview/preview_site_test.dart
+++ b/pkg/nnbd_migration/test/preview/preview_site_test.dart
@@ -65,7 +65,7 @@
     // Add a source change for analysis_options, which has no UnitInfo.
     dartfixListener!.addSourceFileEdit(
         'enable experiment',
-        Location(analysisOptionsPath, 9, 0, 1, 9, 1, 9),
+        Location(analysisOptionsPath, 9, 0, 1, 9, endLine: 1, endColumn: 9),
         SourceFileEdit(analysisOptionsPath, 0, edits: [
           SourceEdit(9, 0, '\n  enable-experiment:\n  - non-nullable')
         ]));
@@ -100,7 +100,7 @@
     file.writeAsStringSync(currentContent);
     dartfixListener!.addSourceFileEdit(
         'test change',
-        Location(path, 10, 0, 1, 10, 1, 10),
+        Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
         SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
     expect(() => site.performApply([]), throwsA(isA<StateError>()));
     expect(file.readAsStringSync(), currentContent);
@@ -115,7 +115,7 @@
     site.unitInfoMap[path] = UnitInfo(path)..diskContent = content;
     dartfixListener!.addSourceFileEdit(
         'test change',
-        Location(path, 10, 0, 1, 10, 1, 10),
+        Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
         SourceFileEdit(path, 0, edits: [
           SourceEdit(10, 0, 'List args'),
           SourceEdit(13, 0, '\n  print(args);\n')
@@ -136,7 +136,7 @@
     site.unitInfoMap[path] = UnitInfo(path)..diskContent = content;
     dartfixListener!.addSourceFileEdit(
         'test change',
-        Location(path, 10, 0, 1, 10, 1, 10),
+        Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
         SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
     site.performApply([]);
     expect(file.readAsStringSync(), 'void main(List args) {}');
@@ -430,7 +430,7 @@
       ..wasExplicitlyOptedOut = true;
     dartfixListener!.addSourceFileEdit(
         'remove DLV comment',
-        Location(path, 0, 14, 1, 1, 3, 1),
+        Location(path, 0, 14, 1, 1, endLine: 3, endColumn: 1),
         SourceFileEdit(path, 0, edits: [SourceEdit(0, 14, '')]));
     var navigationTree =
         NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
@@ -471,7 +471,7 @@
       ..wasExplicitlyOptedOut = false;
     dartfixListener!.addSourceFileEdit(
         'test change',
-        Location(path, 10, 0, 1, 10, 1, 10),
+        Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
         SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
     var navigationTree =
         NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
@@ -525,11 +525,11 @@
       ..wasExplicitlyOptedOut = false;
     dartfixListener!.addSourceFileEdit(
         'test change',
-        Location(pathA, 10, 0, 1, 10, 1, 10),
+        Location(pathA, 10, 0, 1, 10, endLine: 1, endColumn: 10),
         SourceFileEdit(pathA, 0, edits: [SourceEdit(10, 0, 'List args')]));
     dartfixListener!.addSourceFileEdit(
         'test change',
-        Location(pathB, 10, 0, 1, 10, 1, 10),
+        Location(pathB, 10, 0, 1, 10, endLine: 1, endColumn: 10),
         SourceFileEdit(pathB, 0, edits: [SourceEdit(10, 0, 'List args')]));
     var navigationTree =
         NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
@@ -563,7 +563,7 @@
       ..wasExplicitlyOptedOut = true;
     dartfixListener!.addSourceFileEdit(
         'remove DLV comment',
-        Location(path, 0, 14, 1, 1, 3, 1),
+        Location(path, 0, 14, 1, 1, endLine: 3, endColumn: 1),
         SourceFileEdit(path, 0, edits: [SourceEdit(0, 14, '')]));
     var navigationTree =
         NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
diff --git a/pkg/nnbd_migration/tool/trial_migration.dart b/pkg/nnbd_migration/tool/trial_migration.dart
index 4422c58..982cbf7 100644
--- a/pkg/nnbd_migration/tool/trial_migration.dart
+++ b/pkg/nnbd_migration/tool/trial_migration.dart
@@ -67,12 +67,12 @@
       files.addAll(localFiles);
       var session = context.currentSession;
       LineInfo getLineInfo(String path) =>
-          (session.getFile2(path) as FileResult).lineInfo;
+          (session.getFile(path) as FileResult).lineInfo;
       var migration =
           NullabilityMigration(listener, getLineInfo, permissive: true);
       for (var file in localFiles) {
         var resolvedUnit =
-            await session.getResolvedUnit2(file) as ResolvedUnitResult;
+            await session.getResolvedUnit(file) as ResolvedUnitResult;
         if (!resolvedUnit.errors.any((e) => e.severity == Severity.error)) {
           migration.prepareInput(resolvedUnit);
         } else {
@@ -81,14 +81,14 @@
       }
       for (var file in localFiles) {
         var resolvedUnit =
-            await session.getResolvedUnit2(file) as ResolvedUnitResult;
+            await session.getResolvedUnit(file) as ResolvedUnitResult;
         if (!resolvedUnit.errors.any((e) => e.severity == Severity.error)) {
           migration.processInput(resolvedUnit);
         }
       }
       for (var file in localFiles) {
         var resolvedUnit =
-            await session.getResolvedUnit2(file) as ResolvedUnitResult;
+            await session.getResolvedUnit(file) as ResolvedUnitResult;
         if (!resolvedUnit.errors.any((e) => e.severity == Severity.error)) {
           migration.finalizeInput(resolvedUnit);
         }
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 79e9538..8386f5a 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -66,6 +66,7 @@
 kernel/testcases/*: Skip # These are not tests but input for tests.
 vm/test/transformations/type_flow/transformer_test: Slow, Pass
 vm/testcases/*: SkipByDesign # These are not tests but input for tests.
+vm_service/test/cpu_samples_stream_test: Slow, Pass # Requires CPU sample buffer to fill.
 wasm/*: SkipByDesign # These can't be run without running wasm:setup first.
 
 [ $compiler == dart2analyzer ]
diff --git a/pkg/scrape/example/annotation_arguments.dart b/pkg/scrape/example/annotation_arguments.dart
new file mode 100644
index 0000000..cf5da95
--- /dev/null
+++ b/pkg/scrape/example/annotation_arguments.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.
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:scrape/scrape.dart';
+
+void main(List<String> arguments) {
+  Scrape()
+    ..addHistogram('Has argument list?')
+    ..addHistogram('Arguments', order: SortOrder.numeric)
+    ..addHistogram('Argument type')
+    ..addHistogram('Argument identifier')
+    ..addHistogram('Annotation')
+    ..addVisitor(() => AnnotationVisitor())
+    ..runCommandLine(arguments);
+}
+
+class AnnotationVisitor extends ScrapeVisitor {
+  @override
+  void visitAnnotation(Annotation node) {
+    record('Annotation', node.name.name);
+
+    var arguments = node.arguments;
+    if (arguments != null) {
+      record('Has argument list?', 'yes');
+      record('Arguments', arguments.arguments.length);
+      arguments.arguments.forEach(_recordArgument);
+    } else {
+      record('Has argument list?', 'no');
+    }
+
+    super.visitAnnotation(node);
+  }
+
+  void _recordArgument(AstNode? node) {
+    if (node is NamedExpression) {
+      _recordArgument(node.expression);
+    } else if (node is IfElement) {
+      _recordArgument(node.thenElement);
+      _recordArgument(node.elseElement);
+    } else if (node is ForElement) {
+      _recordArgument(node.body);
+    } else if (node is SpreadElement) {
+      _recordArgument(node.expression);
+    } else if (node is MapLiteralEntry) {
+      _recordArgument(node.key);
+      _recordArgument(node.value);
+    } else if (node is SimpleIdentifier || node is PrefixedIdentifier) {
+      record('Argument identifier', node.toString());
+      record('Argument type', 'identifier');
+    } else if (node is PrefixExpression) {
+      record('Argument type', 'unary operator');
+    } else if (node is BinaryExpression) {
+      record('Argument type', 'binary operator');
+    } else if (node is BooleanLiteral) {
+      record('Argument type', 'bool');
+    } else if (node is DoubleLiteral) {
+      record('Argument type', 'double');
+    } else if (node is IntegerLiteral) {
+      record('Argument type', 'int');
+    } else if (node is ListLiteral) {
+      record('Argument type', 'list');
+      node.elements.forEach(_recordArgument);
+    } else if (node is MethodInvocation) {
+      record('Argument type', 'method call');
+    } else if (node is NullLiteral) {
+      record('Argument type', 'null');
+    } else if (node is SetOrMapLiteral) {
+      record('Argument type', 'set or map');
+      node.elements.forEach(_recordArgument);
+    } else if (node is StringLiteral) {
+      record('Argument type', 'string');
+    } else if (node is SymbolLiteral) {
+      record('Argument type', 'symbol');
+    } else if (node == null) {
+      // Do nothing. Only happens for null else elements.
+    } else {
+      record('Argument type', node.runtimeType.toString());
+    }
+  }
+}
diff --git a/pkg/scrape/lib/src/histogram.dart b/pkg/scrape/lib/src/histogram.dart
index 74e35df..e27f137 100644
--- a/pkg/scrape/lib/src/histogram.dart
+++ b/pkg/scrape/lib/src/histogram.dart
@@ -86,14 +86,25 @@
       }
     }
 
-    if (skipped > 0) print('And $skipped more less than 0.1%...');
+    if (skipped > 0) print('And $skipped more...');
 
     // If we're counting numeric keys, show other statistics too.
     if (_order == SortOrder.numeric && keys.isNotEmpty) {
       var sum = keys.fold<int>(
           0, (result, key) => result + (key as int) * _counts[key]!);
       var average = sum / total;
-      var median = _counts[keys[keys.length ~/ 2]];
+
+      // Find the median key where half the total count is below it.
+      var count = 0;
+      var median = -1;
+      for (var key in keys) {
+        count += _counts[key]!;
+        if (count >= total ~/ 2) {
+          median = key as int;
+          break;
+        }
+      }
+
       print('Sum $sum, average ${average.toStringAsFixed(3)}, median $median');
     }
   }
diff --git a/pkg/test_runner/tool/orphan_files.dart b/pkg/test_runner/tool/orphan_files.dart
index 8d7e8f6..968458b 100644
--- a/pkg/test_runner/tool/orphan_files.dart
+++ b/pkg/test_runner/tool/orphan_files.dart
@@ -74,7 +74,7 @@
 
 void _parseReferences(Set<String> importedPaths, String filePath) {
   var absolute = Path(filePath).absolute.toNativePath();
-  var parseResult = _analysisContext.currentSession.getParsedUnit2(absolute);
+  var parseResult = _analysisContext.currentSession.getParsedUnit(absolute);
   var unit = (parseResult as ParsedUnitResult).unit;
 
   void add(String importPath) {
diff --git a/pkg/testing/lib/src/analyze.dart b/pkg/testing/lib/src/analyze.dart
index 099d020..05009ec 100644
--- a/pkg/testing/lib/src/analyze.dart
+++ b/pkg/testing/lib/src/analyze.dart
@@ -18,21 +18,21 @@
 import 'suite.dart' show Suite;
 
 class Analyze extends Suite {
-  final Uri analysisOptions;
+  final Uri? analysisOptions;
 
   final List<Uri> uris;
 
   final List<RegExp> exclude;
 
-  final List<String> gitGrepPathspecs;
+  final List<String>? gitGrepPathspecs;
 
-  final List<String> gitGrepPatterns;
+  final List<String>? gitGrepPatterns;
 
   Analyze(this.analysisOptions, this.uris, this.exclude, this.gitGrepPathspecs,
       this.gitGrepPatterns)
       : super("analyze", "analyze", null);
 
-  Future<Null> run(Uri packages, List<Uri> extraUris) {
+  Future<Null> run(Uri packages, List<Uri>? extraUris) {
     List<Uri> allUris = new List<Uri>.from(uris);
     if (extraUris != null) {
       allUris.addAll(extraUris);
@@ -43,8 +43,8 @@
 
   static Future<Analyze> fromJsonMap(
       Uri base, Map json, List<Suite> suites) async {
-    String optionsPath = json["options"];
-    Uri optionsUri = optionsPath == null ? null : base.resolve(optionsPath);
+    String? optionsPath = json["options"];
+    Uri? optionsUri = optionsPath == null ? null : base.resolve(optionsPath);
 
     List<Uri> uris = json["uris"].map<Uri>((relative) {
       String r = relative;
@@ -54,9 +54,9 @@
     List<RegExp> exclude =
         json["exclude"].map<RegExp>((p) => new RegExp(p)).toList();
 
-    Map gitGrep = json["git grep"];
-    List<String> gitGrepPathspecs;
-    List<String> gitGrepPatterns;
+    Map? gitGrep = json["git grep"];
+    List<String>? gitGrepPathspecs;
+    List<String>? gitGrepPatterns;
     if (gitGrep != null) {
       gitGrepPathspecs = gitGrep["pathspecs"] == null
           ? const <String>["."]
@@ -73,13 +73,13 @@
 }
 
 class AnalyzerDiagnostic {
-  final String kind;
+  final String? kind;
 
-  final String detailedKind;
+  final String? detailedKind;
 
-  final String code;
+  final String? code;
 
-  final Uri uri;
+  final Uri? uri;
 
   final int line;
 
@@ -106,7 +106,7 @@
     addPart() {
       parts.add(line
           .substring(start, index == -1 ? null : index)
-          .replaceAllMapped(unescapePattern, (Match m) => m[1]));
+          .replaceAllMapped(unescapePattern, (Match m) => m[1]!));
     }
 
     while (index != -1) {
@@ -136,8 +136,8 @@
   String toString() {
     return kind == null
         ? "Malformed output from dartanalyzer:\n$message"
-        : "${uri.toFilePath()}:$line:$startColumn: "
-            "${kind == 'INFO' ? 'warning: hint' : kind.toLowerCase()}:\n"
+        : "${uri!.toFilePath()}:$line:$startColumn: "
+            "${kind == 'INFO' ? 'warning: hint' : kind!.toLowerCase()}:\n"
             "[$code] $message";
   }
 }
@@ -154,12 +154,12 @@
 
 /// Run dartanalyzer on all tests in [uris].
 Future<Null> analyzeUris(
-    Uri analysisOptions,
+    Uri? analysisOptions,
     Uri packages,
     List<Uri> uris,
     List<RegExp> exclude,
-    List<String> gitGrepPathspecs,
-    List<String> gitGrepPatterns) async {
+    List<String>? gitGrepPathspecs,
+    List<String>? gitGrepPatterns) async {
   if (uris.isEmpty) return;
   String topLevel;
   try {
@@ -205,7 +205,7 @@
     arguments.addAll(
         gitGrepPatterns.expand((String pattern) => <String>["-e", pattern]));
     arguments.add("--");
-    arguments.addAll(gitGrepPathspecs);
+    arguments.addAll(gitGrepPathspecs!);
     filesToAnalyze.addAll(splitLines(await git("grep", arguments))
         .map((String line) => line.trimRight()));
   }
@@ -245,7 +245,7 @@
   processAnalyzerOutput(Stream<AnalyzerDiagnostic> diagnostics) async {
     await for (AnalyzerDiagnostic diagnostic in diagnostics) {
       if (diagnostic.uri != null) {
-        String path = toFilePath(diagnostic.uri);
+        String path = toFilePath(diagnostic.uri!);
         if (!filesToAnalyze.contains(path)) continue;
       }
       String message = "$diagnostic";
@@ -283,7 +283,7 @@
 }
 
 Future<String> git(String command, Iterable<String> arguments,
-    {String workingDirectory}) async {
+    {String? workingDirectory}) async {
   ProcessResult result = await Process.run(
       Platform.isWindows ? "git.bat" : "git",
       <String>[command]..addAll(arguments),
diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart
index c56fc21..8ab797b 100644
--- a/pkg/testing/lib/src/chain.dart
+++ b/pkg/testing/lib/src/chain.dart
@@ -115,7 +115,7 @@
         .map((s) => s.substring(0, s.length - 3))
         .toList();
     TestExpectations expectations = await ReadTestExpectations(
-        <String>[suite.statusFile.toFilePath()], {}, expectationSet);
+        <String>[suite.statusFile!.toFilePath()], {}, expectationSet);
     Stream<TestDescription> stream = list(suite);
     if (suite.processMultitests) {
       stream = stream.transform(new MultitestTransformer());
@@ -149,12 +149,12 @@
       final Set<Expectation> expectedOutcomes = processExpectedOutcomes(
           expectations.expectations(description.shortName), description);
       final StringBuffer sb = new StringBuffer();
-      final Step lastStep = steps.isNotEmpty ? steps.last : null;
+      final Step? lastStep = steps.isNotEmpty ? steps.last : null;
       final Iterator<Step> iterator = steps.iterator;
 
-      Result result;
+      Result? result;
       // Records the outcome of the last step that was run.
-      Step lastStepRun;
+      Step? lastStepRun;
 
       /// Performs one step of [iterator].
       ///
@@ -194,30 +194,30 @@
           future = new Future.value(null);
         }
         future = future.then((_currentResult) async {
-          Result currentResult = _currentResult;
+          Result? currentResult = _currentResult;
           if (currentResult != null) {
             logger.logStepComplete(completed, unexpectedResults.length,
-                descriptions.length, suite, description, lastStepRun);
+                descriptions.length, suite, description, lastStepRun!);
             result = currentResult;
             if (currentResult.outcome == Expectation.Pass) {
               // The input to the next step is the output of this step.
-              return doStep(result.output);
+              return doStep(result!.output);
             }
           }
-          await cleanUp(description, result);
+          await cleanUp(description, result!);
           result =
-              processTestResult(description, result, lastStep == lastStepRun);
-          if (!expectedOutcomes.contains(result.outcome) &&
-              !expectedOutcomes.contains(result.outcome.canonical)) {
-            result.addLog("$sb");
-            unexpectedResults[description] = result;
+              processTestResult(description, result!, lastStep == lastStepRun);
+          if (!expectedOutcomes.contains(result!.outcome) &&
+              !expectedOutcomes.contains(result!.outcome.canonical)) {
+            result!.addLog("$sb");
+            unexpectedResults[description] = result!;
             unexpectedOutcomes[description] = expectedOutcomes;
             logger.logUnexpectedResult(
-                suite, description, result, expectedOutcomes);
+                suite, description, result!, expectedOutcomes);
             exitCode = 1;
           } else {
             logger.logExpectedResult(
-                suite, description, result, expectedOutcomes);
+                suite, description, result!, expectedOutcomes);
             logger.logMessage(sb);
           }
           logger.logTestComplete(++completed, unexpectedResults.length,
@@ -241,7 +241,7 @@
     if (unexpectedResults.isNotEmpty) {
       unexpectedResults.forEach((TestDescription description, Result result) {
         logger.logUnexpectedResult(
-            suite, description, result, unexpectedOutcomes[description]);
+            suite, description, result, unexpectedOutcomes[description]!);
       });
       print("${unexpectedResults.length} failed:");
       unexpectedResults.forEach((TestDescription description, Result result) {
@@ -278,7 +278,7 @@
       TestDescription description, Result result, bool last) {
     if (description is FileBasedTestDescription &&
         description.multitestExpectations != null) {
-      if (isError(description.multitestExpectations)) {
+      if (isError(description.multitestExpectations!)) {
         result =
             toNegativeTestResult(result, description.multitestExpectations);
       }
@@ -286,14 +286,14 @@
       if (result.outcome == Expectation.Pass) {
         result.addLog("Negative test didn't report an error.\n");
       } else if (result.outcome == Expectation.Fail) {
-        result.addLog("Negative test reported an error as expeceted.\n");
+        result.addLog("Negative test reported an error as expected.\n");
       }
       result = toNegativeTestResult(result);
     }
     return result;
   }
 
-  Result toNegativeTestResult(Result result, [Set<String> expectations]) {
+  Result toNegativeTestResult(Result result, [Set<String>? expectations]) {
     Expectation outcome = result.outcome;
     if (outcome == Expectation.Pass) {
       if (expectations == null) {
@@ -312,9 +312,9 @@
     return result.copyWithOutcome(outcome);
   }
 
-  Future<void> cleanUp(TestDescription description, Result result) => null;
+  Future<void> cleanUp(TestDescription description, Result result) async {}
 
-  Future<void> postRun() => null;
+  Future<void> postRun() async {}
 }
 
 abstract class Step<I, O, C extends ChainContext> {
@@ -355,25 +355,25 @@
 
   Result<O> crash(error, StackTrace trace) => new Result<O>.crash(error, trace);
 
-  Result<O> fail(O output, [error, StackTrace trace]) {
+  Result<O> fail(O output, [error, StackTrace? trace]) {
     return new Result<O>.fail(output, error, trace);
   }
 }
 
 class Result<O> {
-  final O output;
+  final O? output;
 
   final Expectation outcome;
 
   final error;
 
-  final StackTrace trace;
+  final StackTrace? trace;
 
   final List<String> logs = <String>[];
 
   /// If set, running the test with '-D$autoFixCommand' will automatically
   /// update the test to match new expectations.
-  final String autoFixCommand;
+  final String? autoFixCommand;
 
   /// If set, the test can be fixed by running
   ///
@@ -391,7 +391,7 @@
   Result.crash(error, StackTrace trace)
       : this(null, Expectation.Crash, error, trace: trace);
 
-  Result.fail(O output, [error, StackTrace trace])
+  Result.fail(O output, [error, StackTrace? trace])
       : this(output, Expectation.Fail, error, trace: trace);
 
   bool get isPass => outcome == Expectation.Pass;
@@ -420,7 +420,8 @@
 Future<Null> runChain(CreateContext f, Map<String, String> environment,
     Set<String> selectors, String jsonText) {
   return withErrorHandling(() async {
-    Chain suite = new Suite.fromJsonMap(Uri.base, json.decode(jsonText));
+    Chain suite =
+        new Suite.fromJsonMap(Uri.base, json.decode(jsonText)) as Chain;
     print("Running ${suite.name}");
     ChainContext context = await f(suite, environment);
     return context.run(suite, selectors);
diff --git a/pkg/testing/lib/src/discover.dart b/pkg/testing/lib/src/discover.dart
index 3fd09e9..6b761ab 100644
--- a/pkg/testing/lib/src/discover.dart
+++ b/pkg/testing/lib/src/discover.dart
@@ -20,10 +20,10 @@
     <String>["-c", "--packages=${packageConfig.toFilePath()}"];
 
 Stream<FileBasedTestDescription> listTests(List<Uri> testRoots,
-    {Pattern pattern}) {
+    {Pattern? pattern}) {
   StreamController<FileBasedTestDescription> controller =
       new StreamController<FileBasedTestDescription>();
-  Map<Uri, StreamSubscription> subscriptions = <Uri, StreamSubscription>{};
+  Map<Uri, StreamSubscription?> subscriptions = <Uri, StreamSubscription>{};
   for (Uri testRootUri in testRoots) {
     subscriptions[testRootUri] = null;
     Directory testRoot = new Directory.fromUri(testRootUri);
@@ -32,8 +32,9 @@
         Stream<FileSystemEntity> stream =
             testRoot.list(recursive: true, followLinks: false);
         var subscription = stream.listen((FileSystemEntity entity) {
-          FileBasedTestDescription description = FileBasedTestDescription
-              .from(testRootUri, entity, pattern: pattern);
+          FileBasedTestDescription? description = FileBasedTestDescription.from(
+              testRootUri, entity,
+              pattern: pattern);
           if (description != null) {
             controller.add(description);
           }
@@ -59,7 +60,7 @@
 }
 
 Uri computePackageConfig() {
-  String path = Platform.packageConfig;
+  String? path = Platform.packageConfig;
   if (path != null) return Uri.base.resolve(path);
   return Uri.base.resolve(".packages");
 }
@@ -72,7 +73,7 @@
     : null;
 
 Uri computeDartSdk() {
-  String dartSdkPath = Platform.environment["DART_SDK"] ?? _dartSdk;
+  String? dartSdkPath = Platform.environment["DART_SDK"] ?? _dartSdk;
   if (dartSdkPath != null) {
     return Uri.base.resolveUri(new Uri.file(dartSdkPath));
   } else {
@@ -83,7 +84,7 @@
 }
 
 Future<Process> startDart(Uri program,
-    [List<String> arguments, List<String> vmArguments]) {
+    [List<String>? arguments, List<String>? vmArguments]) {
   List<String> allArguments = <String>[];
   allArguments.addAll(vmArguments ?? dartArguments);
   allArguments.add(program.toFilePath());
diff --git a/pkg/testing/lib/src/error_handling.dart b/pkg/testing/lib/src/error_handling.dart
index 452e4b7..872f2f0 100644
--- a/pkg/testing/lib/src/error_handling.dart
+++ b/pkg/testing/lib/src/error_handling.dart
@@ -12,13 +12,14 @@
 
 import 'log.dart';
 
-Future<T> withErrorHandling<T>(Future<T> f(), {Logger logger}) async {
+Future<T?> withErrorHandling<T>(Future<T> f(), {Logger? logger}) async {
   final ReceivePort port = new ReceivePort();
   try {
     return await f();
   } catch (e, trace) {
     exitCode = 1;
     stderr.writeln(e);
+    // ignore: unnecessary_null_comparison
     if (trace != null) {
       stderr.writeln(trace);
     }
diff --git a/pkg/testing/lib/src/expectation.dart b/pkg/testing/lib/src/expectation.dart
index 58efce8..153adee 100644
--- a/pkg/testing/lib/src/expectation.dart
+++ b/pkg/testing/lib/src/expectation.dart
@@ -42,7 +42,7 @@
 
   String toString() => name;
 
-  static Expectation fromGroup(ExpectationGroup group) {
+  static Expectation? fromGroup(ExpectationGroup group) {
     switch (group) {
       case ExpectationGroup.Crash:
         return Expectation.Crash;
@@ -57,7 +57,6 @@
       case ExpectationGroup.Timeout:
         return Expectation.Timeout;
     }
-    throw "Unhandled group: '$group'.";
   }
 }
 
@@ -89,8 +88,8 @@
     Map<String, Expectation> internalMap =
         new Map<String, Expectation>.from(Default.internalMap);
     for (Map map in data) {
-      String name;
-      String group;
+      String? name;
+      String? group;
       map.forEach((_key, _value) {
         String key = _key;
         String value = _value;
@@ -113,12 +112,12 @@
       if (group == null) {
         throw "No group provided in '$map'";
       }
-      Expectation expectation = new Expectation(name, groupFromString(group));
-      name = name.toLowerCase();
+      Expectation expectation = new Expectation(name!, groupFromString(group!));
+      name = name!.toLowerCase();
       if (internalMap.containsKey(name)) {
         throw "Duplicated expectation name: '$name'.";
       }
-      internalMap[name] = expectation;
+      internalMap[name!] = expectation;
     }
     return new ExpectationSet(internalMap);
   }
diff --git a/pkg/testing/lib/src/log.dart b/pkg/testing/lib/src/log.dart
index 7e6fafd..d46ab0a 100644
--- a/pkg/testing/lib/src/log.dart
+++ b/pkg/testing/lib/src/log.dart
@@ -78,19 +78,19 @@
 class StdoutLogger implements Logger {
   const StdoutLogger();
 
-  void logTestStart(int completed, int failed, int total, Suite suite,
-      TestDescription description) {}
+  void logTestStart(int completed, int failed, int total, Suite? suite,
+      TestDescription? description) {}
 
-  void logTestComplete(int completed, int failed, int total, Suite suite,
-      TestDescription description) {
+  void logTestComplete(int completed, int failed, int total, Suite? suite,
+      TestDescription? description) {
     String message = formatProgress(completed, failed, total);
     if (suite != null) {
-      message += ": ${formatTestDescription(suite, description)}";
+      message += ": ${formatTestDescription(suite, description!)}";
     }
     logProgress(message);
   }
 
-  void logStepStart(int completed, int failed, int total, Suite suite,
+  void logStepStart(int completed, int failed, int total, Suite? suite,
       TestDescription description, Step step) {
     String message = formatProgress(completed, failed, total);
     if (suite != null) {
@@ -102,7 +102,7 @@
     logProgress(message);
   }
 
-  void logStepComplete(int completed, int failed, int total, Suite suite,
+  void logStepComplete(int completed, int failed, int total, Suite? suite,
       TestDescription description, Step step) {
     if (!step.isAsync) return;
     String message = formatProgress(completed, failed, total);
@@ -152,7 +152,7 @@
   void logUnexpectedResult(Suite suite, TestDescription description,
       Result result, Set<Expectation> expectedOutcomes) {
     print("${eraseLine}UNEXPECTED: ${suite.name}/${description.shortName}");
-    Uri statusFile = suite.statusFile;
+    Uri? statusFile = suite.statusFile;
     if (statusFile != null) {
       String path = statusFile.toFilePath();
       if (result.outcome == Expectation.Pass) {
@@ -186,6 +186,7 @@
 
   void logUncaughtError(error, StackTrace stackTrace) {
     logMessage(error);
+    // ignore: unnecessary_null_comparison
     if (stackTrace != null) {
       logMessage(stackTrace);
     }
diff --git a/pkg/testing/lib/src/multitest.dart b/pkg/testing/lib/src/multitest.dart
index d87ac1b..62bb63e 100644
--- a/pkg/testing/lib/src/multitest.dart
+++ b/pkg/testing/lib/src/multitest.dart
@@ -51,8 +51,8 @@
 
     nextTest:
     await for (TestDescription test in stream) {
-      FileBasedTestDescription multitest;
-      String contents;
+      FileBasedTestDescription? multitest;
+      String? contents;
       if (test is FileBasedTestDescription) {
         contents = await test.file.readAsString();
         if (contents.contains(multitestMarker)) {
@@ -73,11 +73,11 @@
         "none": new Set<String>(),
       };
       int lineNumber = 0;
-      for (String line in splitLines(contents)) {
+      for (String line in splitLines(contents!)) {
         lineNumber++;
         int index = line.indexOf(multitestMarker);
-        String subtestName;
-        List<String> subtestOutcomesList;
+        String? subtestName;
+        List<String>? subtestOutcomesList;
         if (index != -1) {
           String annotationText =
               line.substring(index + _multitestMarkerLength).trim();
@@ -102,7 +102,7 @@
           lines.add(line);
           Set<String> subtestOutcomes =
               outcomes.putIfAbsent(subtestName, () => new Set<String>());
-          if (subtestOutcomesList.length != 1 ||
+          if (subtestOutcomesList!.length != 1 ||
               subtestOutcomesList.single != "continued") {
             for (String outcome in subtestOutcomesList) {
               if (validOutcomes.contains(outcome)) {
@@ -125,8 +125,9 @@
       Directory generated =
           new Directory.fromUri(root.resolve(multitest.shortName));
       generated = await generated.create(recursive: true);
-      for (String name in testsAsLines.keys) {
-        List<String> lines = testsAsLines[name];
+      for (MapEntry<String, List<String>> entry in testsAsLines.entries) {
+        String name = entry.key;
+        List<String> lines = entry.value;
         Uri uri = generated.uri.resolve("${name}_generated.dart");
         FileBasedTestDescription subtest =
             new FileBasedTestDescription(root, new File.fromUri(uri));
diff --git a/pkg/testing/lib/src/run.dart b/pkg/testing/lib/src/run.dart
index 7ce9bd0..4567236 100644
--- a/pkg/testing/lib/src/run.dart
+++ b/pkg/testing/lib/src/run.dart
@@ -34,10 +34,10 @@
 
 import 'run_tests.dart' show CommandLine;
 
-Future<TestRoot> computeTestRoot(String configurationPath, Uri base) {
+Future<TestRoot> computeTestRoot(String? configurationPath, Uri? base) {
   Uri configuration = configurationPath == null
       ? Uri.base.resolve("testing.json")
-      : base.resolve(configurationPath);
+      : base!.resolve(configurationPath);
   return TestRoot.fromUri(configuration);
 }
 
@@ -50,8 +50,8 @@
 /// `testing.json` isn't located in the current working directory and is a path
 /// relative to [me] which defaults to `Platform.script`.
 Future<Null> runMe(List<String> arguments, CreateContext f,
-    {String configurationPath,
-    Uri me,
+    {String? configurationPath,
+    Uri? me,
     int shards = 1,
     int shard = 0,
     Logger logger: const StdoutLogger()}) {
@@ -98,7 +98,7 @@
 /// `testing.json` isn't located in the current working directory and is a path
 /// relative to `Uri.base`.
 Future<Null> run(List<String> arguments, List<String> suiteNames,
-    [String configurationPath]) {
+    [String? configurationPath]) {
   return withErrorHandling(() async {
     TestRoot root = await computeTestRoot(configurationPath, Uri.base);
     List<Suite> suites = root.suites
@@ -106,7 +106,7 @@
         .toList();
     SuiteRunner runner = new SuiteRunner(suites, <String, String>{},
         const <String>[], new Set<String>(), new Set<String>());
-    String program = await runner.generateDartProgram();
+    String? program = await runner.generateDartProgram();
     await runner.analyze(root.packages);
     if (program != null) {
       await runProgram(program, root.packages);
@@ -125,7 +125,7 @@
       errorsAreFatal: false,
       checked: true,
       packageConfig: packages);
-  List error;
+  List? error;
   var subscription = isolate.errors.listen((data) {
     error = data;
     exitPort.close();
@@ -137,7 +137,7 @@
   subscription.cancel();
   return error == null
       ? null
-      : new Future<Null>.error(error[0], new StackTrace.fromString(error[1]));
+      : new Future<Null>.error(error![0], new StackTrace.fromString(error![1]));
 }
 
 class SuiteRunner {
@@ -162,7 +162,7 @@
         (selectedSuites.isEmpty || selectedSuites.contains(suite.name));
   }
 
-  Future<String> generateDartProgram() async {
+  Future<String?> generateDartProgram() async {
     testUris.clear();
     StringBuffer imports = new StringBuffer();
     StringBuffer dart = new StringBuffer();
@@ -238,10 +238,10 @@
   }
 
   Stream<FileBasedTestDescription> listDescriptions() async* {
-    for (Dart suite in suites.where((Suite suite) => suite is Dart)) {
+    for (Dart suite in suites.whereType<Dart>()) {
       await for (FileBasedTestDescription description
           in listTests(<Uri>[suite.uri], pattern: "")) {
-        testUris.add(await Isolate.resolvePackageUri(description.uri));
+        testUris.add((await Isolate.resolvePackageUri(description.uri))!);
         if (shouldRunSuite(suite)) {
           String path = description.file.uri.path;
           if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
@@ -254,19 +254,19 @@
   }
 
   Stream<Chain> listChainSuites() async* {
-    for (Chain suite in suites.where((Suite suite) => suite is Chain)) {
-      testUris.add(await Isolate.resolvePackageUri(suite.source));
+    for (Chain suite in suites.whereType<Chain>()) {
+      testUris.add((await Isolate.resolvePackageUri(suite.source))!);
       if (shouldRunSuite(suite)) {
         yield suite;
       }
     }
   }
 
-  Iterable<Suite> listTestDartSuites() {
-    return suites.where((Suite suite) => suite is TestDart);
+  Iterable<TestDart> listTestDartSuites() {
+    return suites.whereType<TestDart>();
   }
 
-  Iterable<Suite> listAnalyzerSuites() {
-    return suites.where((Suite suite) => suite is Analyze);
+  Iterable<Analyze> listAnalyzerSuites() {
+    return suites.whereType<Analyze>();
   }
 }
diff --git a/pkg/testing/lib/src/run_tests.dart b/pkg/testing/lib/src/run_tests.dart
index b4ccd3b..03d5d3d 100644
--- a/pkg/testing/lib/src/run_tests.dart
+++ b/pkg/testing/lib/src/run_tests.dart
@@ -64,7 +64,7 @@
 
   Iterable<String> get selectors => arguments;
 
-  Future<Uri> get configuration async {
+  Future<Uri?> get configuration async {
     const String configPrefix = "--config=";
     List<String> configurationPaths = options
         .where((String option) => option.startsWith(configPrefix))
@@ -111,7 +111,7 @@
     }
     const StdoutLogger()
         .logMessage("Reading configuration file '$configurationPath'.");
-    Uri configuration =
+    Uri? configuration =
         await Isolate.resolvePackageUri(Uri.base.resolve(configurationPath));
     if (configuration == null ||
         !await new File.fromUri(configuration).exists()) {
@@ -147,7 +147,7 @@
         enableVerboseOutput();
       }
       Map<String, String> environment = cl.environment;
-      Uri configuration = await cl.configuration;
+      Uri? configuration = await cl.configuration;
       if (configuration == null) return;
       if (!isVerbose) {
         print("Use --verbose to display more details.");
@@ -155,7 +155,7 @@
       TestRoot root = await TestRoot.fromUri(configuration);
       SuiteRunner runner = new SuiteRunner(
           root.suites, environment, cl.selectors, cl.selectedSuites, cl.skip);
-      String program = await runner.generateDartProgram();
+      String? program = await runner.generateDartProgram();
       bool hasAnalyzerSuites = await runner.analyze(root.packages);
       Stopwatch sw = new Stopwatch()..start();
       if (program == null) {
@@ -178,7 +178,7 @@
         try {
           await runGuarded(() {
             print("Running test $name");
-            return tests[name]();
+            return tests[name]!();
           }, printLineOnStdout: sb.writeln);
           const StdoutLogger().logMessage(sb);
         } catch (e) {
diff --git a/pkg/testing/lib/src/stdio_process.dart b/pkg/testing/lib/src/stdio_process.dart
index 16bbfdf..587a07f 100644
--- a/pkg/testing/lib/src/stdio_process.dart
+++ b/pkg/testing/lib/src/stdio_process.dart
@@ -41,13 +41,13 @@
   }
 
   static Future<StdioProcess> run(String executable, List<String> arguments,
-      {String input,
-      Duration timeout: const Duration(seconds: 60),
+      {String? input,
+      Duration? timeout: const Duration(seconds: 60),
       bool suppressOutput: true,
       bool runInShell: false}) async {
     Process process =
         await Process.start(executable, arguments, runInShell: runInShell);
-    Timer timer;
+    Timer? timer;
     StringBuffer sb = new StringBuffer();
     if (timeout != null) {
       timer = new Timer(timeout, () {
@@ -75,8 +75,8 @@
       stdoutStream = stdoutStream.transform(transformToStdio(io.stdout));
       stderrStream = stderrStream.transform(transformToStdio(io.stderr));
     }
-    Future<List<String>> stdoutFuture = stdoutStream.toList();
-    Future<List<String>> stderrFuture = stderrStream.toList();
+    Future<List<String>> stdoutFuture = stdoutStream.toList() as Future<List<String>>;
+    Future<List<String>> stderrFuture = stderrStream.toList() as Future<List<String>>;
     int exitCode = await process.exitCode;
     timer?.cancel();
     sb.writeAll(await stdoutFuture);
diff --git a/pkg/testing/lib/src/suite.dart b/pkg/testing/lib/src/suite.dart
index 54aa7c8..b159797 100644
--- a/pkg/testing/lib/src/suite.dart
+++ b/pkg/testing/lib/src/suite.dart
@@ -14,7 +14,7 @@
 
   final String kind;
 
-  final Uri statusFile;
+  final Uri? statusFile;
 
   Suite(this.name, this.kind, this.statusFile);
 
diff --git a/pkg/testing/lib/src/test_dart/path.dart b/pkg/testing/lib/src/test_dart/path.dart
index 3c5fbea..f0b5b51 100644
--- a/pkg/testing/lib/src/test_dart/path.dart
+++ b/pkg/testing/lib/src/test_dart/path.dart
@@ -192,7 +192,7 @@
   Path makeCanonical() {
     bool isAbs = isAbsolute;
     List segs = segments();
-    String drive;
+    String? drive;
     if (isAbs && !segs.isEmpty && segs[0].length == 2 && segs[0][1] == ':') {
       drive = segs[0];
       segs.removeRange(0, 1);
@@ -267,7 +267,7 @@
   }
 
   List<String> segments() {
-    List result = _path.split('/');
+    List<String> result = _path.split('/');
     if (isAbsolute) result.removeRange(0, 1);
     if (hasTrailingSeparator) result.removeLast();
     return result;
diff --git a/pkg/testing/lib/src/test_dart/status_expression.dart b/pkg/testing/lib/src/test_dart/status_expression.dart
index 200d241..395483a 100644
--- a/pkg/testing/lib/src/test_dart/status_expression.dart
+++ b/pkg/testing/lib/src/test_dart/status_expression.dart
@@ -64,7 +64,9 @@
     if (!testRegexp.hasMatch(expression)) {
       throw new FormatException("Syntax error in '$expression'");
     }
-    for (Match match in regexp.allMatches(expression)) tokens.add(match[0]);
+    for (Match match in regexp.allMatches(expression)) {
+      tokens.add(match[0]!);
+    }
     return tokens;
   }
 }
@@ -179,8 +181,8 @@
 // An iterator that allows peeking at the current token.
 class Scanner {
   List<String> tokens;
-  Iterator tokenIterator;
-  String current;
+  late Iterator tokenIterator;
+  String? current;
 
   Scanner(this.tokens) {
     tokenIterator = tokens.iterator;
@@ -241,11 +243,11 @@
       scanner.advance();
       return value;
     }
-    if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
+    if (!new RegExp(r"^\w+$").hasMatch(scanner.current!)) {
       throw new FormatException(
           "Expected identifier in expression, got ${scanner.current}");
     }
-    SetExpression value = new SetConstant(scanner.current);
+    SetExpression value = new SetConstant(scanner.current!);
     scanner.advance();
     return value;
   }
@@ -290,21 +292,21 @@
           "Expected \$ in expression, got ${scanner.current}");
     }
     scanner.advance();
-    if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
+    if (!new RegExp(r"^\w+$").hasMatch(scanner.current!)) {
       throw new FormatException(
           "Expected identifier in expression, got ${scanner.current}");
     }
-    TermVariable left = new TermVariable(scanner.current);
+    TermVariable left = new TermVariable(scanner.current!);
     scanner.advance();
     if (scanner.current == Token.EQUALS ||
         scanner.current == Token.NOT_EQUALS) {
       bool negate = scanner.current == Token.NOT_EQUALS;
       scanner.advance();
-      if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
+      if (!new RegExp(r"^\w+$").hasMatch(scanner.current!)) {
         throw new FormatException(
             "Expected value in expression, got ${scanner.current}");
       }
-      TermConstant right = new TermConstant(scanner.current);
+      TermConstant right = new TermConstant(scanner.current!);
       scanner.advance();
       return new Comparison(left, right, negate);
     } else {
diff --git a/pkg/testing/lib/src/test_dart/status_file_parser.dart b/pkg/testing/lib/src/test_dart/status_file_parser.dart
index 1ce711f..a3d2f58 100644
--- a/pkg/testing/lib/src/test_dart/status_file_parser.dart
+++ b/pkg/testing/lib/src/test_dart/status_file_parser.dart
@@ -29,7 +29,7 @@
 class Section {
   final StatusFile statusFile;
 
-  final BooleanExpression condition;
+  final BooleanExpression? condition;
   final List<TestRule> testRules;
   final int lineNumber;
 
@@ -40,7 +40,7 @@
       : testRules = <TestRule>[];
 
   bool isEnabled(Map<String, String> environment) =>
-      condition == null || condition.evaluate(environment);
+      condition == null || condition!.evaluate(environment);
 
   String toString() {
     return "Section: $condition";
@@ -93,17 +93,17 @@
 
   lines.listen((String line) {
     lineNumber++;
-    Match match = SplitComment.firstMatch(line);
-    line = (match == null) ? "" : match[1];
+    Match? match = SplitComment.firstMatch(line);
+    line = (match == null) ? "" : match[1]!;
     line = line.trim();
     if (line.isEmpty) return;
 
     // Extract the comment to get the issue number if needed.
-    String comment = (match == null || match[2] == null) ? "" : match[2];
+    String comment = (match == null || match[2] == null) ? "" : match[2]!;
 
     match = HeaderPattern.firstMatch(line);
     if (match != null) {
-      String condition_string = match[1].trim();
+      String condition_string = match[1]!.trim();
       List<String> tokens = new Tokenizer(condition_string).tokenize();
       ExpressionParser parser = new ExpressionParser(new Scanner(tokens));
       currentSection =
@@ -114,21 +114,21 @@
 
     match = RulePattern.firstMatch(line);
     if (match != null) {
-      String name = match[1].trim();
+      String name = match[1]!.trim();
       // TODO(whesse): Handle test names ending in a wildcard (*).
-      String expression_string = match[2].trim();
+      String expression_string = match[2]!.trim();
       List<String> tokens = new Tokenizer(expression_string).tokenize();
       SetExpression expression =
           new ExpressionParser(new Scanner(tokens)).parseSetExpression();
 
       // Look for issue number in comment.
-      String issueString = null;
+      String? issueString = null;
       match = IssueNumberPattern.firstMatch(comment);
       if (match != null) {
         issueString = match[1];
         if (issueString == null) issueString = match[2];
       }
-      int issue = issueString != null ? int.parse(issueString) : null;
+      int? issue = issueString != null ? int.parse(issueString) : null;
       currentSection.testRules
           .add(new TestRule(name, expression, issue, lineNumber));
       return;
@@ -141,7 +141,7 @@
 class TestRule {
   String name;
   SetExpression expression;
-  int issue;
+  int? issue;
   int lineNumber;
 
   TestRule(this.name, this.expression, this.issue, this.lineNumber);
@@ -161,8 +161,8 @@
 
   Map<String, Set<Expectation>> _map;
   bool _preprocessed = false;
-  Map<String, RegExp> _regExpCache;
-  Map<String, List<RegExp>> _keyToRegExps;
+  Map<String, RegExp>? _regExpCache;
+  Map<String, List<RegExp>>? _keyToRegExps;
 
   /**
    * Create a TestExpectations object. See the [expectations] method
@@ -203,7 +203,7 @@
     _preprocessForMatching();
 
     _map.forEach((key, expectation) {
-      List regExps = _keyToRegExps[key];
+      List<RegExp> regExps = _keyToRegExps![key]!;
       if (regExps.length > splitFilename.length) return;
       for (var i = 0; i < regExps.length; i++) {
         if (!regExps[i].hasMatch(splitFilename[i])) return;
@@ -231,20 +231,19 @@
     _regExpCache = {};
 
     _map.forEach((key, expectations) {
-      if (_keyToRegExps[key] != null) return;
+      if (_keyToRegExps![key] != null) return;
       var splitKey = key.split('/');
-      var regExps = new List<RegExp>.filled(splitKey.length, null);
-      for (var i = 0; i < splitKey.length; i++) {
+      var regExps = new List<RegExp>.generate(splitKey.length, (int i) {
         var component = splitKey[i];
-        var regExp = _regExpCache[component];
+        var regExp = _regExpCache![component];
         if (regExp == null) {
           var pattern = "^${splitKey[i]}\$".replaceAll('*', '.*');
           regExp = new RegExp(pattern);
-          _regExpCache[component] = regExp;
+          _regExpCache![component] = regExp;
         }
-        regExps[i] = regExp;
-      }
-      _keyToRegExps[key] = regExps;
+        return regExp;
+      }, growable: false);
+      _keyToRegExps![key] = regExps;
     });
 
     _regExpCache = null;
diff --git a/pkg/testing/lib/src/test_description.dart b/pkg/testing/lib/src/test_description.dart
index 7480ee0..1fe0ac1 100644
--- a/pkg/testing/lib/src/test_description.dart
+++ b/pkg/testing/lib/src/test_description.dart
@@ -17,11 +17,11 @@
 class FileBasedTestDescription extends TestDescription {
   final Uri root;
   final File file;
-  final Uri output;
+  final Uri? output;
 
   /// If non-null, this is a generated multitest, and the set contains the
   /// expected outcomes.
-  Set<String> multitestExpectations;
+  Set<String>? multitestExpectations;
 
   FileBasedTestDescription(this.root, this.file, {this.output});
 
@@ -52,8 +52,8 @@
     sink.writeln('.main,');
   }
 
-  static FileBasedTestDescription from(Uri root, FileSystemEntity entity,
-      {Pattern pattern}) {
+  static FileBasedTestDescription? from(Uri root, FileSystemEntity entity,
+      {Pattern? pattern}) {
     if (entity is! File) return null;
     pattern ??= "_test.dart";
     String path = entity.uri.path;
diff --git a/pkg/testing/lib/src/test_root.dart b/pkg/testing/lib/src/test_root.dart
index 9e3b65e..554abee 100644
--- a/pkg/testing/lib/src/test_root.dart
+++ b/pkg/testing/lib/src/test_root.dart
@@ -49,7 +49,7 @@
 
   TestRoot(this.packages, this.suites);
 
-  Analyze get analyze => suites.last;
+  Analyze get analyze => suites.last as Analyze;
 
   List<Uri> get urisToAnalyze => analyze.uris;
 
diff --git a/pkg/testing/lib/src/zone_helper.dart b/pkg/testing/lib/src/zone_helper.dart
index d8d7d39..a378d7a 100644
--- a/pkg/testing/lib/src/zone_helper.dart
+++ b/pkg/testing/lib/src/zone_helper.dart
@@ -14,8 +14,8 @@
 import 'log.dart' show StdoutLogger;
 
 Future runGuarded(Future f(),
-    {void printLineOnStdout(line),
-    void handleLateError(error, StackTrace stackTrace)}) {
+    {void Function(String)? printLineOnStdout,
+    void Function(dynamic, StackTrace)? handleLateError}) {
   var printWrapper;
   if (printLineOnStdout != null) {
     printWrapper = (_1, _2, _3, String line) {
@@ -39,6 +39,7 @@
         // Ignored.
       }
       stderr
+          // ignore: unnecessary_null_comparison
           .write("$errorString\n" + (stackTrace == null ? "" : "$stackTrace"));
       stderr.flush();
       exit(255);
@@ -81,7 +82,7 @@
 /// Ping [isolate] to ensure control messages have been delivered.  Control
 /// messages are things like [Isolate.addErrorListener] and
 /// [Isolate.addOnExitListener].
-Future acknowledgeControlMessages(Isolate isolate, {Capability resume}) {
+Future acknowledgeControlMessages(Isolate isolate, {Capability? resume}) {
   ReceivePort ping = new ReceivePort();
   Isolate.current.ping(ping.sendPort);
   if (resume == null) {
diff --git a/pkg/testing/pubspec.yaml b/pkg/testing/pubspec.yaml
index f012946..d85f43f 100644
--- a/pkg/testing/pubspec.yaml
+++ b/pkg/testing/pubspec.yaml
@@ -4,4 +4,4 @@
 # This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 environment:
-  sdk: '>=2.0.0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 4c46e9e..e3a221e 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -18,7 +18,6 @@
 ///         dart pkg/vm/bin/kernel_service.dart --train <source-file>
 ///
 ///
-library runtime.tools.kernel_service;
 
 import 'dart:async' show Future, ZoneSpecification, runZoned;
 import 'dart:collection' show UnmodifiableMapBase;
@@ -88,11 +87,11 @@
 
 CompilerOptions setupCompilerOptions(
     FileSystem fileSystem,
-    Uri platformKernelPath,
+    Uri? platformKernelPath,
     bool enableAsserts,
     int nullSafety,
-    List<String> experimentalFlags,
-    Uri packagesUri,
+    List<String>? experimentalFlags,
+    Uri? packagesUri,
     List<String> errorsPlain,
     List<String> errorsColorized,
     String invocationModes,
@@ -159,11 +158,11 @@
 abstract class Compiler {
   final int isolateGroupId;
   final FileSystem fileSystem;
-  final Uri platformKernelPath;
+  final Uri? platformKernelPath;
   final bool enableAsserts;
   final int nullSafety;
-  final List<String> experimentalFlags;
-  final String packageConfig;
+  final List<String>? experimentalFlags;
+  final String? packageConfig;
   final String invocationModes;
   final String verbosityLevel;
 
@@ -175,7 +174,7 @@
   final List<String> errorsPlain = <String>[];
   final List<String> errorsColorized = <String>[];
 
-  CompilerOptions options;
+  late final CompilerOptions options;
 
   Compiler(this.isolateGroupId, this.fileSystem, this.platformKernelPath,
       {this.enableAsserts: false,
@@ -186,11 +185,10 @@
       this.packageConfig: null,
       this.invocationModes: '',
       this.verbosityLevel: Verbosity.defaultValue}) {
-    Uri packagesUri = null;
+    Uri? packagesUri = null;
+    final packageConfig = this.packageConfig ?? Platform.packageConfig;
     if (packageConfig != null) {
       packagesUri = Uri.parse(packageConfig);
-    } else if (Platform.packageConfig != null) {
-      packagesUri = Uri.parse(Platform.packageConfig);
     }
 
     if (verbose) {
@@ -216,7 +214,7 @@
   Future<CompilerResult> compile(Uri script) {
     return runWithPrintToStderr(() async {
       final CompilerResult compilerResult = await compileInternal(script);
-      final Component component = compilerResult.component;
+      final Component? component = compilerResult.component;
 
       if (errorsPlain.isEmpty) {
         // Record dependencies only if compilation was error free.
@@ -231,20 +229,16 @@
 }
 
 class CompilerResult {
-  final Component component;
+  final Component? component;
 
   /// Set of libraries loaded from .dill, with or without the SDK depending on
   /// the compilation settings.
   final Set<Library> loadedLibraries;
-  final ClassHierarchy classHierarchy;
-  final CoreTypes coreTypes;
+  final ClassHierarchy? classHierarchy;
+  final CoreTypes? coreTypes;
 
-  CompilerResult(
-      this.component, this.loadedLibraries, this.classHierarchy, this.coreTypes)
-      : assert(component != null),
-        assert(loadedLibraries != null),
-        assert(classHierarchy != null),
-        assert(coreTypes != null);
+  CompilerResult(this.component, this.loadedLibraries, this.classHierarchy,
+      this.coreTypes);
 }
 
 // Environment map which looks up environment defines in the VM environment
@@ -255,17 +249,17 @@
 // the full (isolate specific) environment as a finite, static map.
 class EnvironmentMap extends UnmodifiableMapBase<String, String> {
   @override
-  bool containsKey(Object key) {
-    return new bool.hasEnvironment(key);
+  bool containsKey(Object? key) {
+    return key is String && new bool.hasEnvironment(key);
   }
 
   @override
-  String operator [](Object key) {
+  String? operator [](Object? key) {
     // The fromEnvironment constructor is specified to throw when called using
     // new. However, the VM implementation actually looks up the given name in
     // the environment.
     if (containsKey(key)) {
-      return new String.fromEnvironment(key);
+      return new String.fromEnvironment(key as String);
     }
     return null;
   }
@@ -292,14 +286,14 @@
 }
 
 class IncrementalCompilerWrapper extends Compiler {
-  IncrementalCompiler generator;
+  IncrementalCompiler? generator;
 
   IncrementalCompilerWrapper(
-      int isolateGroupId, FileSystem fileSystem, Uri platformKernelPath,
+      int isolateGroupId, FileSystem fileSystem, Uri? platformKernelPath,
       {bool enableAsserts: false,
       int nullSafety: kNullSafetyOptionUnspecified,
-      List<String> experimentalFlags: null,
-      String packageConfig: null,
+      List<String>? experimentalFlags,
+      String? packageConfig,
       String invocationModes: '',
       String verbosityLevel: Verbosity.defaultValue})
       : super(isolateGroupId, fileSystem, platformKernelPath,
@@ -316,10 +310,10 @@
       Component component,
       int isolateGroupId,
       FileSystem fileSystem,
-      Uri platformKernelPath,
+      Uri? platformKernelPath,
       {bool enableAsserts: false,
-      List<String> experimentalFlags: null,
-      String packageConfig: null,
+      List<String>? experimentalFlags,
+      String? packageConfig,
       String invocationModes: ''}) {
     IncrementalCompilerWrapper result = IncrementalCompilerWrapper(
         isolateGroupId, fileSystem, platformKernelPath,
@@ -330,15 +324,13 @@
     result.generator = new IncrementalCompiler.forExpressionCompilationOnly(
         component,
         result.options,
-        component.mainMethod?.enclosingLibrary?.fileUri);
+        component.mainMethod!.enclosingLibrary.fileUri);
     return result;
   }
 
   @override
   Future<CompilerResult> compileInternal(Uri script) async {
-    if (generator == null) {
-      generator = new IncrementalCompiler(options, script);
-    }
+    final generator = this.generator ??= IncrementalCompiler(options, script);
     errorsPlain.clear();
     errorsColorized.clear();
     final component = await generator.compile(entryPoint: script);
@@ -346,8 +338,8 @@
         generator.getClassHierarchy(), generator.getCoreTypes());
   }
 
-  void accept() => generator.accept();
-  void invalidate(Uri uri) => generator.invalidate(uri);
+  void accept() => generator!.accept();
+  void invalidate(Uri uri) => generator!.invalidate(uri);
 
   Future<IncrementalCompilerWrapper> clone(int isolateGroupId) async {
     IncrementalCompilerWrapper clone = IncrementalCompilerWrapper(
@@ -357,6 +349,7 @@
         experimentalFlags: experimentalFlags,
         packageConfig: packageConfig,
         invocationModes: invocationModes);
+    final generator = this.generator!;
     // TODO(VM TEAM): This does not seem safe. What if cloning while having
     // pending deltas for instance?
     generator.resetDeltaState();
@@ -367,9 +360,10 @@
     MemoryFileSystem memoryFileSystem = (fileSystem as HybridFileSystem).memory;
 
     String filename = 'full-component-$isolateGroupId.dill';
-    Sink sink = FileSink(memoryFileSystem.entityForUri(Uri.file(filename)));
+    Sink<List<int>> sink =
+        FileSink(memoryFileSystem.entityForUri(Uri.file(filename)));
     new BinaryPrinter(sink).writeComponentFile(fullComponent);
-    await sink.close();
+    sink.close();
 
     clone.generator = new IncrementalCompiler(options, generator.entryPoint,
         initializeFromDillUri: Uri.file(filename));
@@ -385,8 +379,8 @@
       {this.requireMain: false,
       bool enableAsserts: false,
       int nullSafety: kNullSafetyOptionUnspecified,
-      List<String> experimentalFlags: null,
-      String packageConfig: null,
+      List<String>? experimentalFlags,
+      String? packageConfig,
       String invocationModes: '',
       String verbosityLevel: Verbosity.defaultValue})
       : super(isolateGroupId, fileSystem, platformKernelPath,
@@ -399,12 +393,15 @@
 
   @override
   Future<CompilerResult> compileInternal(Uri script) async {
-    fe.CompilerResult compilerResult = requireMain
+    final fe.CompilerResult? compilerResult = requireMain
         ? await kernelForProgram(script, options)
         : await kernelForModule([script], options);
+    if (compilerResult == null) {
+      return CompilerResult(null, const {}, null, null);
+    }
 
     Set<Library> loadedLibraries = createLoadedLibrariesSet(
-        compilerResult?.loadedComponents, compilerResult?.sdkComponent,
+        compilerResult.loadedComponents, compilerResult.sdkComponent,
         includePlatform: !options.omitPlatform);
 
     return new CompilerResult(compilerResult.component, loadedLibraries,
@@ -416,21 +413,21 @@
 final Map<int, List<Uri>> isolateDependencies = {};
 final Map<int, _ExpressionCompilationFromDillSettings> isolateLoadNotifies = {};
 
-IncrementalCompilerWrapper lookupIncrementalCompiler(int isolateGroupId) {
+IncrementalCompilerWrapper? lookupIncrementalCompiler(int isolateGroupId) {
   return isolateCompilers[isolateGroupId];
 }
 
 Future<Compiler> lookupOrBuildNewIncrementalCompiler(int isolateGroupId,
-    List sourceFiles, Uri platformKernelPath, List<int> platformKernel,
+    List sourceFiles, Uri platformKernelPath, List<int>? platformKernel,
     {bool enableAsserts: false,
     int nullSafety: kNullSafetyOptionUnspecified,
-    List<String> experimentalFlags: null,
-    String packageConfig: null,
-    String multirootFilepaths,
-    String multirootScheme,
+    List<String>? experimentalFlags,
+    String? packageConfig,
+    String? multirootFilepaths,
+    String? multirootScheme,
     String invocationModes: '',
     String verbosityLevel: Verbosity.defaultValue}) async {
-  IncrementalCompilerWrapper compiler =
+  IncrementalCompilerWrapper? compiler =
       lookupIncrementalCompiler(isolateGroupId);
   if (compiler != null) {
     updateSources(compiler, sourceFiles);
@@ -439,9 +436,7 @@
     // This is how identify scenario where child isolate hot reload requests
     // requires setting up actual compiler first: non-empty sourceFiles list has
     // no actual content specified for the source file.
-    if (sourceFiles != null &&
-        sourceFiles.length > 0 &&
-        sourceFiles[1] == null) {
+    if (sourceFiles.isNotEmpty && sourceFiles[1] == null) {
       // Just use first compiler that should represent main isolate as a source for cloning.
       var source = isolateCompilers.entries.first;
       compiler = await source.value.clone(isolateGroupId);
@@ -473,7 +468,7 @@
     final FileSystem fs = compiler.fileSystem;
     for (int i = 0; i < sourceFiles.length ~/ 2; i++) {
       Uri uri = Uri.parse(sourceFiles[i * 2]);
-      List<int> source = sourceFiles[i * 2 + 1];
+      List<int>? source = sourceFiles[i * 2 + 1];
       // The source is only provided by unit tests and is normally empty.
       // Don't add an entry for the uri so the compiler will fallback to the
       // real file system for the updated source.
@@ -505,23 +500,24 @@
   final List<String> definitions = request[5].cast<String>();
   final List<String> typeDefinitions = request[6].cast<String>();
   final String libraryUri = request[7];
-  final String klass = request[8]; // might be null
+  final String? klass = request[8];
   final bool isStatic = request[9];
-  final List dillData = request[10];
+  final List<List<int>> dillData = request[10].cast<List<int>>();
   final int blobLoadCount = request[11];
   final bool enableAsserts = request[12];
-  final List<String> experimentalFlags =
+  final List<String>? experimentalFlags =
       request[13] != null ? request[13].cast<String>() : null;
 
-  IncrementalCompilerWrapper compiler = isolateCompilers[isolateGroupId];
+  IncrementalCompilerWrapper? compiler = isolateCompilers[isolateGroupId];
 
-  _ExpressionCompilationFromDillSettings isolateLoadDillData =
+  _ExpressionCompilationFromDillSettings? isolateLoadDillData =
       isolateLoadNotifies[isolateGroupId];
   if (isolateLoadDillData != null) {
     // Check if we can reuse the compiler.
     if (isolateLoadDillData.blobLoadCount != blobLoadCount ||
         isolateLoadDillData.prevDillCount != dillData.length) {
-      compiler = isolateCompilers[isolateGroupId] = null;
+      isolateCompilers.remove(isolateGroupId);
+      compiler = null;
     }
   }
 
@@ -558,7 +554,7 @@
         }
       }
       if (!foundDartCore) {
-        List<int> platformKernel = null;
+        List<int> platformKernel;
         if (dart_platform_kernel is List<int>) {
           platformKernel = dart_platform_kernel;
         } else {
@@ -596,7 +592,7 @@
             packageConfig: dotPackagesFile);
         isolateCompilers[isolateGroupId] = compiler;
         await compiler.compile(
-            component.mainMethod?.enclosingLibrary?.importUri ??
+            component.mainMethod?.enclosingLibrary.importUri ??
                 component.libraries.last.importUri);
       } catch (e) {
         port.send(new CompilationResult.errors([
@@ -621,7 +617,7 @@
 
   CompilationResult result;
   try {
-    Procedure procedure = await compiler.generator.compileExpression(
+    Procedure? procedure = await compiler.generator!.compileExpression(
         expression, definitions, typeDefinitions, libraryUri, klass, isStatic);
 
     if (procedure == null) {
@@ -649,7 +645,7 @@
 }
 
 void _recordDependencies(
-    int isolateGroupId, Component component, Uri packageConfig) {
+    int isolateGroupId, Component? component, Uri? packageConfig) {
   final dependencies = isolateDependencies[isolateGroupId] ??= <Uri>[];
 
   if (component != null) {
@@ -678,8 +674,8 @@
   return uri.toFilePath().replaceAll("\\", "\\\\").replaceAll(" ", "\\ ");
 }
 
-List<int> _serializeDependencies(List<Uri> uris) {
-  return utf8.encode(uris.map(_escapeDependency).join(" "));
+Uint8List _serializeDependencies(List<Uri> uris) {
+  return utf8.encode(uris.map(_escapeDependency).join(" ")) as Uint8List;
 }
 
 Future _processListDependenciesRequest(
@@ -750,23 +746,23 @@
     return;
   }
 
-  final String inputFileUri = request[2];
-  final Uri script =
+  final String? inputFileUri = request[2];
+  final Uri? script =
       inputFileUri != null ? Uri.base.resolve(inputFileUri) : null;
   final bool incremental = request[4];
   final bool snapshot = request[5];
   final int nullSafety = request[6];
   final List sourceFiles = request[8];
   final bool enableAsserts = request[9];
-  final List<String> experimentalFlags =
+  final List<String>? experimentalFlags =
       request[10] != null ? request[10].cast<String>() : null;
-  final String packageConfig = request[11];
-  final String multirootFilepaths = request[12];
-  final String multirootScheme = request[13];
-  final String workingDirectory = request[14];
+  final String? packageConfig = request[11];
+  final String? multirootFilepaths = request[12];
+  final String? multirootScheme = request[13];
+  final String? workingDirectory = request[14];
   final String verbosityLevel = request[15];
-  Uri platformKernelPath = null;
-  List<int> platformKernel = null;
+  Uri platformKernelPath;
+  List<int>? platformKernel = null;
   if (request[3] is String) {
     platformKernelPath = Uri.base.resolveUri(new Uri.file(request[3]));
   } else if (request[3] is List<int>) {
@@ -779,7 +775,7 @@
 
   final String invocationModes = snapshot ? 'compile' : '';
 
-  Compiler compiler;
+  Compiler? compiler;
 
   // Update the in-memory file system with the provided sources. Currently, only
   // unit tests compile sources that are not on the file system, so this can only
@@ -794,7 +790,7 @@
           .toResponse());
       return;
     }
-    updateSources(compiler, sourceFiles);
+    updateSources(compiler as IncrementalCompilerWrapper, sourceFiles);
     port.send(new CompilationResult.ok(null).toResponse());
     return;
   } else if (tag == kAcceptTag) {
@@ -811,16 +807,15 @@
   } else if (tag == kDetectNullabilityTag) {
     FileSystem fileSystem = _buildFileSystem(
         sourceFiles, platformKernel, multirootFilepaths, multirootScheme);
-    Uri packagesUri = null;
-    if (packageConfig != null) {
-      packagesUri = Uri.parse(packageConfig);
-    } else if (Platform.packageConfig != null) {
-      packagesUri = Uri.parse(Platform.packageConfig);
+    Uri? packagesUri = null;
+    final packageConfigWithDefault = packageConfig ?? Platform.packageConfig;
+    if (packageConfigWithDefault != null) {
+      packagesUri = Uri.parse(packageConfigWithDefault);
     }
     if (packagesUri != null && packagesUri.scheme == '') {
       // Script does not have a scheme, assume that it is a path,
       // resolve it against the working directory.
-      packagesUri = Uri.directory(workingDirectory).resolveUri(packagesUri);
+      packagesUri = Uri.directory(workingDirectory!).resolveUri(packagesUri);
     }
     final List<String> errorsPlain = <String>[];
     final List<String> errorsColorized = <String>[];
@@ -837,8 +832,7 @@
         verbosityLevel);
 
     // script should only be null for kUpdateSourcesTag.
-    assert(script != null);
-    await autoDetectNullSafetyMode(script, options);
+    await autoDetectNullSafetyMode(script!, options);
     bool value = options.nnbdMode == NnbdMode.Strong;
     port.send(new CompilationResult.nullSafety(value).toResponse());
     return;
@@ -882,7 +876,7 @@
       print("DFE: scriptUri: ${script}");
     }
 
-    CompilerResult compilerResult = await compiler.compile(script);
+    CompilerResult compilerResult = await compiler.compile(script!);
     Set<Library> loadedLibraries = compilerResult.loadedLibraries;
 
     assert(compiler.errorsPlain.length == compiler.errorsColorized.length);
@@ -894,10 +888,11 @@
     if (compiler.errorsColorized.isNotEmpty) {
       final List<String> errors =
           (enableColors) ? compiler.errorsColorized : compiler.errorsPlain;
-      if (compilerResult.component != null) {
+      final component = compilerResult.component;
+      if (component != null) {
         result = new CompilationResult.errors(
             errors,
-            serializeComponent(compilerResult.component,
+            serializeComponent(component,
                 filter: (lib) => !loadedLibraries.contains(lib)));
       } else {
         result = new CompilationResult.errors(errors, null);
@@ -908,7 +903,7 @@
       // [kernelForProgram] is marked `external`, so we can use that bit to
       // decide what to exclude.
       result = new CompilationResult.ok(serializeComponent(
-          compilerResult.component,
+          compilerResult.component!,
           filter: (lib) => !loadedLibraries.contains(lib)));
     }
   } catch (error, stack) {
@@ -920,7 +915,7 @@
   if (tag == kTrainTag) {
     // In training mode make sure to read the sdk a few more times...
     ProcessedOptions p = new ProcessedOptions(options: compiler.options);
-    var bytes = await p.loadSdkSummaryBytes();
+    final bytes = (await p.loadSdkSummaryBytes())!;
     for (int i = 0; i < 5; i++) {
       p.loadComponent(bytes, null);
     }
@@ -949,19 +944,17 @@
 ///
 /// The result can be used instead of StandardFileSystem.instance by the
 /// frontend.
-FileSystem _buildFileSystem(List sourceFiles, List<int> platformKernel,
-    String multirootFilepaths, String multirootScheme) {
+FileSystem _buildFileSystem(List sourceFiles, List<int>? platformKernel,
+    String? multirootFilepaths, String? multirootScheme) {
   FileSystem fileSystem = new HttpAwareFileSystem(StandardFileSystem.instance);
 
   if (!sourceFiles.isEmpty || platformKernel != null) {
     MemoryFileSystem memoryFileSystem =
         new MemoryFileSystem(Uri.parse('file:///'));
-    if (sourceFiles != null) {
-      for (int i = 0; i < sourceFiles.length ~/ 2; i++) {
-        memoryFileSystem
-            .entityForUri(Uri.parse(sourceFiles[i * 2]))
-            .writeAsBytesSync(sourceFiles[i * 2 + 1]);
-      }
+    for (int i = 0; i < sourceFiles.length ~/ 2; i++) {
+      memoryFileSystem
+          .entityForUri(Uri.parse(sourceFiles[i * 2]))
+          .writeAsBytesSync(sourceFiles[i * 2 + 1]);
     }
     if (platformKernel != null) {
       memoryFileSystem
@@ -982,7 +975,7 @@
   return fileSystem;
 }
 
-train(String scriptUri, String platformKernelPath) async {
+train(String scriptUri, String? platformKernelPath) async {
   // Train on program asked to train on.
   await trainInternal(scriptUri, platformKernelPath);
 
@@ -1005,7 +998,7 @@
   }
 }
 
-Future trainInternal(String scriptUri, String platformKernelPath) async {
+Future trainInternal(String scriptUri, String? platformKernelPath) async {
   var tag = kTrainTag;
   var responsePort = new RawReceivePort();
   responsePort.handler = (response) {
@@ -1048,7 +1041,7 @@
     // 2) Optional platform kernel path.
     int argIndex = 1;
     final String script = args[argIndex++];
-    final String platform = (argIndex < args.length) ? args[argIndex] : null;
+    final String? platform = (argIndex < args.length) ? args[argIndex] : null;
     train(script, platform);
   } else {
     // Entry point for the Kernel isolate.
@@ -1075,11 +1068,11 @@
 abstract class CompilationResult {
   CompilationResult._();
 
-  factory CompilationResult.ok(Uint8List bytes) = _CompilationOk;
+  factory CompilationResult.ok(Uint8List? bytes) = _CompilationOk;
 
   factory CompilationResult.nullSafety(bool val) = _CompilationNullSafety;
 
-  factory CompilationResult.errors(List<String> errors, Uint8List bytes) =
+  factory CompilationResult.errors(List<String> errors, Uint8List? bytes) =
       _CompilationError;
 
   factory CompilationResult.crash(Object exception, StackTrace stack) =
@@ -1093,11 +1086,14 @@
 }
 
 class _CompilationOk extends CompilationResult {
-  final Uint8List bytes;
+  final Uint8List? bytes;
 
   _CompilationOk(this.bytes) : super._() {
-    if (dumpKernel && bytes != null) {
-      _debugDumpKernel(bytes);
+    if (dumpKernel) {
+      final bytes = this.bytes;
+      if (bytes != null) {
+        _debugDumpKernel(bytes);
+      }
     }
   }
 
@@ -1107,7 +1103,7 @@
   @override
   get payload => bytes;
 
-  String toString() => "_CompilationOk(${bytes.length} bytes)";
+  String toString() => "_CompilationOk(${bytes?.length ?? 0} bytes)";
 }
 
 class _CompilationNullSafety extends CompilationResult {
@@ -1134,7 +1130,7 @@
 }
 
 class _CompilationError extends _CompilationFail {
-  final Uint8List bytes;
+  final Uint8List? bytes;
   final List<String> errors;
 
   _CompilationError(this.errors, this.bytes);
diff --git a/pkg/vm/bin/protobuf_aware_treeshaker.dart b/pkg/vm/bin/protobuf_aware_treeshaker.dart
index 69aa466..3af79b6 100644
--- a/pkg/vm/bin/protobuf_aware_treeshaker.dart
+++ b/pkg/vm/bin/protobuf_aware_treeshaker.dart
@@ -34,7 +34,6 @@
 import 'package:vm/kernel_front_end.dart'
     show runGlobalTransformations, ErrorDetector;
 import 'package:kernel/target/targets.dart' show TargetFlags, getTarget;
-import 'package:meta/meta.dart';
 import 'package:vm/target/install.dart' show installAdditionalTargets;
 import 'package:vm/transformations/type_flow/transformer.dart' as globalTypeFlow
     show transformComponent;
@@ -69,7 +68,7 @@
         help: 'Write to stdout about what classes and fields where remeoved')
     ..addFlag('help', help: 'Prints this help', negatable: false);
 
-  ArgResults argResults;
+  ArgResults? argResults;
   try {
     argResults = argParser.parse(args);
   } on FormatException catch (e) {
@@ -109,7 +108,7 @@
 
   installAdditionalTargets();
 
-  final target = getTarget(argResults['target'], TargetFlags());
+  final target = getTarget(argResults['target'], TargetFlags())!;
 
   // The [component] is treeshaken and has TFA annotations. Write output.
   if (argResults['aot']) {
@@ -156,7 +155,7 @@
 }
 
 Future writeComponent(Component component, String filename,
-    {@required bool removeCoreLibs, @required bool removeSource}) async {
+    {required bool removeCoreLibs, required bool removeSource}) async {
   if (removeSource) {
     component.uriToSource.clear();
   }
diff --git a/pkg/vm/lib/dominators.dart b/pkg/vm/lib/dominators.dart
index 19c5d84..81309d3 100644
--- a/pkg/vm/lib/dominators.dart
+++ b/pkg/vm/lib/dominators.dart
@@ -2,18 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library vm.dominators;
-
 class Vertex<T extends Vertex<T>> {
   // Input: vertices directly reachable from this vertex.
   final List<T> successors = <T>[];
 
   // Output: the nearest vertex that all paths from the root must go through to
   // reach this vertex.
-  T dominator;
+  T? dominator;
 
   bool isDominatedBy(T other) {
-    var d = this;
+    Vertex<T>? d = this;
     while (d != null) {
       if (d == other) {
         return true;
@@ -26,17 +24,17 @@
   // Temporaries. See Lengauer and Tarjan.
   final List<T> _predecessors = <T>[];
   int _semi = 0;
-  T _label;
-  T _ancestor;
-  T _parent;
-  List<T> _bucket;
+  T? _label;
+  T? _ancestor;
+  T? _parent;
+  List<T>? _bucket;
 }
 
 // T. Lengauer and R. E. Tarjan. "A Fast Algorithm for Finding Dominators
 // in a Flowgraph."
 computeDominators<T extends Vertex<T>>(T root) {
   // Lengauer and Tarjan Step 1.
-  final vertex = <T>[];
+  final vertex = <T?>[];
   vertex.add(null);
 
   var n = 0;
@@ -60,33 +58,35 @@
   dfs(root);
 
   forestCompress(T v) {
-    if (v._ancestor._ancestor != null) {
-      forestCompress(v._ancestor);
-      if (v._ancestor._label._semi < v._label._semi) {
-        v._label = v._ancestor._label;
+    T ancestor = v._ancestor!;
+    if (ancestor._ancestor != null) {
+      forestCompress(ancestor);
+      ancestor = v._ancestor!;
+      if (ancestor._label!._semi < v._label!._semi) {
+        v._label = ancestor._label;
       }
-      v._ancestor = v._ancestor._ancestor;
+      v._ancestor = ancestor._ancestor;
     }
   }
 
-  forestEval(T v) {
+  T forestEval(T v) {
     if (v._ancestor == null) {
       return v;
     } else {
       forestCompress(v);
-      return v._label;
+      return v._label!;
     }
   }
 
-  forestLink(T v, T w) {
+  forestLink(T? v, T w) {
     w._ancestor = v;
   }
 
   for (var i = vertex.length - 1; i > 1; i--) {
-    Vertex<T> w = vertex[i];
+    final T w = vertex[i]!;
 
     // Lengauer and Tarjan Step 2.
-    for (Vertex<T> v in w._predecessors) {
+    for (T v in w._predecessors) {
       if (v._semi == 0) continue; // Unreachable
 
       final u = forestEval(v);
@@ -95,7 +95,7 @@
       }
     }
 
-    Vertex<T> z = vertex[w._semi];
+    Vertex<T> z = vertex[w._semi]!;
     var b = z._bucket;
     if (b == null) {
       z._bucket = b = <T>[];
@@ -104,8 +104,7 @@
     forestLink(w._parent, w);
 
     // Lengauer and Tarjan Step 3.
-    z = w._parent;
-    assert(z != null);
+    z = w._parent!;
     b = z._bucket;
     z._bucket = null;
     if (b != null) {
@@ -118,9 +117,9 @@
 
   // Lengauer and Tarjan Step 4.
   for (var i = 2; i < vertex.length; i++) {
-    final w = vertex[i];
+    final T w = vertex[i]!;
     if (w.dominator != vertex[w._semi]) {
-      w.dominator = w.dominator.dominator;
+      w.dominator = w.dominator!.dominator;
     }
   }
 }
diff --git a/pkg/vm/lib/http_filesystem.dart b/pkg/vm/lib/http_filesystem.dart
index cd8e42a..18ee3e1 100644
--- a/pkg/vm/lib/http_filesystem.dart
+++ b/pkg/vm/lib/http_filesystem.dart
@@ -1,3 +1,7 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 import 'dart:async';
 import 'dart:io' as io;
 
@@ -60,7 +64,7 @@
   }
 
   Future<T> connectAndRun<T>(Future<T> body(io.HttpClient httpClient)) async {
-    io.HttpClient httpClient;
+    io.HttpClient? httpClient;
     try {
       httpClient = new io.HttpClient();
       // Set timeout to be shorter than anticipated OS default
diff --git a/pkg/vm/lib/incremental_compiler.dart b/pkg/vm/lib/incremental_compiler.dart
index f2f483f..a8d3271 100644
--- a/pkg/vm/lib/incremental_compiler.dart
+++ b/pkg/vm/lib/incremental_compiler.dart
@@ -18,23 +18,23 @@
 /// deltas and combines them together into resultant program until it is
 /// accepted.
 class IncrementalCompiler {
-  IncrementalKernelGenerator _generator;
-  IncrementalSerializer incrementalSerializer;
+  late IncrementalKernelGenerator _generator;
+  IncrementalSerializer? incrementalSerializer;
 
   // Component that reflect the state that was most recently accepted by the
   // client. Is [null], if no compilation results were accepted by the client.
-  Component _lastKnownGood;
-  List<Component> _pendingDeltas;
+  Component? _lastKnownGood;
+  late List<Component> _pendingDeltas;
   CompilerOptions _compilerOptions;
   bool initialized = false;
   bool fullComponent = false;
-  Uri initializeFromDillUri;
+  Uri? initializeFromDillUri;
   Uri _entryPoint;
   final bool forExpressionCompilationOnly;
 
   Uri get entryPoint => _entryPoint;
   IncrementalKernelGenerator get generator => _generator;
-  Component get lastKnownGoodComponent => _lastKnownGood;
+  Component? get lastKnownGoodComponent => _lastKnownGood;
 
   IncrementalCompiler(this._compilerOptions, this._entryPoint,
       {this.initializeFromDillUri, bool incrementalSerialization: true})
@@ -59,12 +59,12 @@
   ///
   /// If [entryPoint] is specified, that points to new entry point for the
   /// compilation. Otherwise, previously set entryPoint is used.
-  Future<Component> compile({Uri entryPoint}) async {
+  Future<Component> compile({Uri? entryPoint}) async {
     final task = new TimelineTask();
     try {
       task.start("IncrementalCompiler.compile");
       _entryPoint = entryPoint ?? _entryPoint;
-      List<Uri> entryPoints;
+      List<Uri>? entryPoints;
       if (entryPoint != null) entryPoints = [entryPoint];
       Component component = await _generator.computeDelta(
           entryPoints: entryPoints, fullComponent: fullComponent);
@@ -78,8 +78,9 @@
   }
 
   _combinePendingDeltas(bool includePlatform) {
-    Procedure mainMethod;
-    NonNullableByDefaultCompiledMode compilationMode;
+    Procedure? mainMethod;
+    NonNullableByDefaultCompiledMode compilationMode =
+        NonNullableByDefaultCompiledMode.Invalid;
     Map<Uri, Library> combined = <Uri, Library>{};
     Map<Uri, Source> uriToSource = new Map<Uri, Source>();
     for (Component delta in _pendingDeltas) {
@@ -102,8 +103,8 @@
       ..setMainMethodAndMode(mainMethod?.reference, true, compilationMode);
   }
 
-  CoreTypes getCoreTypes() => _generator.getCoreTypes();
-  ClassHierarchy getClassHierarchy() => _generator.getClassHierarchy();
+  CoreTypes? getCoreTypes() => _generator.getCoreTypes();
+  ClassHierarchy? getClassHierarchy() => _generator.getClassHierarchy();
 
   /// This lets incremental compiler know that results of last [compile] call
   /// were accepted, don't need to be included into subsequent [compile] calls
@@ -116,13 +117,14 @@
     Map<Uri, Library> combined = <Uri, Library>{};
     Map<Uri, Source> uriToSource = <Uri, Source>{};
 
-    if (_lastKnownGood != null) {
+    Component? lastKnownGood = _lastKnownGood;
+    if (lastKnownGood != null) {
       // TODO(aam): Figure out how to skip no-longer-used libraries from
       // [_lastKnownGood] libraries.
-      for (Library library in _lastKnownGood.libraries) {
+      for (Library library in lastKnownGood.libraries) {
         combined[library.importUri] = library;
       }
-      uriToSource.addAll(_lastKnownGood.uriToSource);
+      uriToSource.addAll(lastKnownGood.uriToSource);
     }
 
     Component candidate = _combinePendingDeltas(true);
@@ -131,13 +133,13 @@
     }
     uriToSource.addAll(candidate.uriToSource);
 
-    _lastKnownGood = new Component(
+    _lastKnownGood = lastKnownGood = new Component(
       libraries: combined.values.toList(),
       uriToSource: uriToSource,
     )..setMainMethodAndMode(
         candidate.mainMethod?.reference, true, candidate.mode);
     for (final repo in candidate.metadata.values) {
-      _lastKnownGood.addMetadataRepository(repo);
+      lastKnownGood.addMetadataRepository(repo);
     }
     _pendingDeltas.clear();
   }
@@ -180,12 +182,12 @@
     fullComponent = true;
   }
 
-  Future<Procedure> compileExpression(
+  Future<Procedure?> compileExpression(
       String expression,
       List<String> definitions,
       List<String> typeDefinitions,
       String libraryUri,
-      String klass,
+      String? klass,
       bool isStatic) {
     Map<String, DartType> completeDefinitions = {};
     for (String name in definitions) {
@@ -200,7 +202,6 @@
     }
 
     Uri library = Uri.parse(libraryUri);
-    if (library == null) return null;
 
     return _generator.compileExpression(expression, completeDefinitions,
         typeParameters, kDebugProcedureName, library, klass, isStatic);
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 0458451..51ed004 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Defines the VM-specific translation of Dart source code to kernel binaries.
-library vm.kernel_front_end;
 
 import 'dart:async';
 import 'dart:io' show File, IOSink;
@@ -160,7 +159,7 @@
 /// Run kernel compiler tool with given [options] and [usage]
 /// and return exit code.
 Future<int> runCompiler(ArgResults options, String usage) async {
-  final String platformKernel = options['platform'];
+  final String? platformKernel = options['platform'];
 
   if (options['help']) {
     print(usage);
@@ -174,26 +173,26 @@
 
   final String input = options.rest.single;
   final String outputFileName = options['output'] ?? "$input.dill";
-  final String packages = options['packages'];
+  final String? packages = options['packages'];
   final String targetName = options['target'];
-  final String fileSystemScheme = options['filesystem-scheme'];
-  final String depfile = options['depfile'];
-  final String fromDillFile = options['from-dill'];
-  final List<String> fileSystemRoots = options['filesystem-root'];
+  final String? fileSystemScheme = options['filesystem-scheme'];
+  final String? depfile = options['depfile'];
+  final String? fromDillFile = options['from-dill'];
+  final List<String>? fileSystemRoots = options['filesystem-root'];
   final bool aot = options['aot'];
   final bool tfa = options['tfa'];
   final bool linkPlatform = options['link-platform'];
   final bool embedSources = options['embed-sources'];
   final bool enableAsserts = options['enable-asserts'];
-  final bool nullSafety = options['sound-null-safety'];
+  final bool? nullSafety = options['sound-null-safety'];
   final bool useProtobufTreeShakerV2 = options['protobuf-tree-shaker-v2'];
   final bool splitOutputByPackages = options['split-output-by-packages'];
-  final String manifestFilename = options['manifest'];
-  final String dataDir = options['component-name'] ?? options['data-dir'];
+  final String? manifestFilename = options['manifest'];
+  final String? dataDir = options['component-name'] ?? options['data-dir'];
 
   final bool minimalKernel = options['minimal-kernel'];
   final bool treeShakeWriteOnlyFields = options['tree-shake-write-only-fields'];
-  final List<String> experimentalFlags = options['enable-experiment'];
+  final List<String>? experimentalFlags = options['enable-experiment'];
   final Map<String, String> environmentDefines = {};
 
   if (!parseCommandLineDefines(options['define'], environmentDefines, usage)) {
@@ -215,7 +214,7 @@
   final fileSystem =
       createFrontEndFileSystem(fileSystemScheme, fileSystemRoots);
 
-  final Uri packagesUri = packages != null ? resolveInputUri(packages) : null;
+  final Uri? packagesUri = packages != null ? resolveInputUri(packages) : null;
 
   final platformKernelUri = Uri.base.resolveUri(new Uri.file(platformKernel));
   final List<Uri> additionalDills = <Uri>[];
@@ -230,7 +229,8 @@
 
   final verbosity = Verbosity.parseArgument(options['verbosity']);
   final errorPrinter = new ErrorPrinter(verbosity);
-  final errorDetector = new ErrorDetector(previousErrorHandler: errorPrinter);
+  final errorDetector =
+      new ErrorDetector(previousErrorHandler: errorPrinter.call);
 
   final CompilerOptions compilerOptions = new CompilerOptions()
     ..sdkSummary = platformKernelUri
@@ -278,19 +278,20 @@
 
   errorPrinter.printCompilationMessages();
 
-  if (errorDetector.hasCompilationErrors || (results.component == null)) {
+  final Component? component = results.component;
+  if (errorDetector.hasCompilationErrors || (component == null)) {
     return compileTimeErrorExitCode;
   }
 
   final IOSink sink = new File(outputFileName).openWrite();
   final BinaryPrinter printer = new BinaryPrinter(sink,
       libraryFilter: (lib) => !results.loadedLibraries.contains(lib));
-  printer.writeComponentFile(results.component);
+  printer.writeComponentFile(component);
   await sink.close();
 
   if (depfile != null) {
     await writeDepfile(
-        fileSystem, results.compiledSources, outputFileName, depfile);
+        fileSystem, results.compiledSources!, outputFileName, depfile);
   }
 
   if (splitOutputByPackages) {
@@ -312,14 +313,14 @@
 /// Results of [compileToKernel]: generated kernel [Component] and
 /// collection of compiled sources.
 class KernelCompilationResults {
-  final Component component;
+  final Component? component;
 
   /// Set of libraries loaded from .dill, with or without the SDK depending on
   /// the compilation settings.
   final Set<Library> loadedLibraries;
-  final ClassHierarchy classHierarchy;
-  final CoreTypes coreTypes;
-  final Iterable<Uri> compiledSources;
+  final ClassHierarchy? classHierarchy;
+  final CoreTypes? coreTypes;
+  final Iterable<Uri>? compiledSources;
 
   KernelCompilationResults(this.component, this.loadedLibraries,
       this.classHierarchy, this.coreTypes, this.compiledSources);
@@ -336,29 +337,30 @@
     List<String> deleteToStringPackageUris: const <String>[],
     bool aot: false,
     bool useGlobalTypeFlowAnalysis: false,
-    Map<String, String> environmentDefines,
+    required Map<String, String> environmentDefines,
     bool enableAsserts: true,
     bool useProtobufTreeShakerV2: false,
     bool minimalKernel: false,
     bool treeShakeWriteOnlyFields: false,
-    String fromDillFile: null}) async {
+    String? fromDillFile: null}) async {
   // Replace error handler to detect if there are compilation errors.
   final errorDetector =
       new ErrorDetector(previousErrorHandler: options.onDiagnostic);
-  options.onDiagnostic = errorDetector;
+  options.onDiagnostic = errorDetector.call;
 
+  final target = options.target!;
   options.environmentDefines =
-      options.target.updateEnvironmentDefines(environmentDefines);
+      target.updateEnvironmentDefines(environmentDefines);
 
-  CompilerResult compilerResult;
+  CompilerResult? compilerResult;
   if (fromDillFile != null) {
     compilerResult =
         await loadKernel(options.fileSystem, resolveInputUri(fromDillFile));
   } else {
     compilerResult = await kernelForProgram(source, options);
   }
-  Component component = compilerResult?.component;
-  Iterable<Uri> compiledSources = component?.uriToSource?.keys;
+  final Component? component = compilerResult?.component;
+  Iterable<Uri>? compiledSources = component?.uriToSource.keys;
 
   Set<Library> loadedLibraries = createLoadedLibrariesSet(
       compilerResult?.loadedComponents, compilerResult?.sdkComponent,
@@ -371,13 +373,8 @@
 
   // Run global transformations only if component is correct.
   if ((aot || minimalKernel) && component != null) {
-    await runGlobalTransformations(
-        options.target,
-        component,
-        useGlobalTypeFlowAnalysis,
-        enableAsserts,
-        useProtobufTreeShakerV2,
-        errorDetector,
+    await runGlobalTransformations(target, component, useGlobalTypeFlowAnalysis,
+        enableAsserts, useProtobufTreeShakerV2, errorDetector,
         minimalKernel: minimalKernel,
         treeShakeWriteOnlyFields: treeShakeWriteOnlyFields);
 
@@ -385,7 +382,7 @@
       // compiledSources is component.uriToSource.keys.
       // Make a copy of compiledSources to detach it from
       // component.uriToSource which is cleared below.
-      compiledSources = compiledSources.toList();
+      compiledSources = compiledSources!.toList();
 
       component.metadata.clear();
       component.uriToSource.clear();
@@ -404,7 +401,7 @@
 }
 
 Set<Library> createLoadedLibrariesSet(
-    List<Component> loadedComponents, Component sdkComponent,
+    List<Component>? loadedComponents, Component? sdkComponent,
     {bool includePlatform: false}) {
   final Set<Library> loadedLibraries = {};
   if (loadedComponents != null) {
@@ -479,8 +476,11 @@
 
 /// Runs given [action] with [CompilerContext]. This is needed to
 /// be able to report compile-time errors.
-Future<T> runWithFrontEndCompilerContext<T>(Uri source,
-    CompilerOptions compilerOptions, Component component, T action()) async {
+Future<T> runWithFrontEndCompilerContext<T>(
+    Uri source,
+    CompilerOptions compilerOptions,
+    Component component,
+    Future<T> action()) async {
   final processedOptions =
       new ProcessedOptions(options: compilerOptions, inputs: [source]);
 
@@ -496,7 +496,7 @@
 }
 
 class ErrorDetector {
-  final DiagnosticMessageHandler previousErrorHandler;
+  final DiagnosticMessageHandler? previousErrorHandler;
   bool hasCompilationErrors = false;
 
   ErrorDetector({this.previousErrorHandler});
@@ -512,8 +512,9 @@
 
 class ErrorPrinter {
   final Verbosity verbosity;
-  final DiagnosticMessageHandler previousErrorHandler;
-  final compilationMessages = <Uri, List<DiagnosticMessage>>{};
+  final DiagnosticMessageHandler? previousErrorHandler;
+  final Map<Uri?, List<DiagnosticMessage>> compilationMessages =
+      <Uri?, List<DiagnosticMessage>>{};
 
   ErrorPrinter(this.verbosity, {this.previousErrorHandler});
 
@@ -537,8 +538,8 @@
         }
         return 0;
       });
-    for (final Uri sourceUri in sortedUris) {
-      for (final DiagnosticMessage message in compilationMessages[sourceUri]) {
+    for (final Uri? sourceUri in sortedUris) {
+      for (final DiagnosticMessage message in compilationMessages[sourceUri]!) {
         if (Verbosity.shouldPrint(verbosity, message)) {
           printDiagnosticMessage(message, print);
         }
@@ -574,7 +575,7 @@
 }
 
 /// Create front-end target with given name.
-Target createFrontEndTarget(String targetName,
+Target? createFrontEndTarget(String targetName,
     {bool trackWidgetCreation = false, bool nullSafety = false}) {
   // Make sure VM-specific targets are available.
   installAdditionalTargets();
@@ -589,9 +590,8 @@
 /// If requested, create a virtual mutli-root file system and/or an http aware
 /// file system.
 FileSystem createFrontEndFileSystem(
-    String multiRootFileSystemScheme, List<String> multiRootFileSystemRoots,
-    {bool allowHttp}) {
-  allowHttp ??= false;
+    String? multiRootFileSystemScheme, List<String>? multiRootFileSystemRoots,
+    {bool allowHttp = false}) {
   FileSystem fileSystem = StandardFileSystem.instance;
   if (allowHttp) {
     fileSystem = HttpAwareFileSystem(fileSystem);
@@ -613,7 +613,7 @@
 Future<Uri> asFileUri(FileSystem fileSystem, Uri uri) async {
   FileSystemEntity fse = fileSystem.entityForUri(uri);
   if (fse is MultiRootFileSystemEntity) {
-    fse = await (fse as MultiRootFileSystemEntity).delegate;
+    fse = await fse.delegate;
   }
   return fse.uri;
 }
@@ -643,8 +643,9 @@
 Future writeOutputSplitByPackages(Uri source, CompilerOptions compilerOptions,
     KernelCompilationResults compilationResults, String outputFileName) async {
   final packages = <String>[];
-  await runWithFrontEndCompilerContext(
-      source, compilerOptions, compilationResults.component, () async {
+  final Component component = compilationResults.component!;
+  await runWithFrontEndCompilerContext(source, compilerOptions, component,
+      () async {
     // When loading a kernel file list, flutter_runner and dart_runner expect
     // 'main' to be last.
     await forEachPackage(compilationResults,
@@ -653,12 +654,10 @@
       final String filename = '$outputFileName-$package.dilp';
       final IOSink sink = new File(filename).openWrite();
 
-      Component partComponent = compilationResults.component;
-
       final BinaryPrinter printer = new BinaryPrinter(sink,
           libraryFilter: (lib) =>
               packageFor(lib, compilationResults.loadedLibraries) == package);
-      printer.writeComponentFile(partComponent);
+      printer.writeComponentFile(component);
 
       await sink.close();
     }, mainFirst: false);
@@ -671,7 +670,7 @@
   await packagesList.close();
 }
 
-String packageFor(Library lib, Set<Library> loadedLibraries) {
+String? packageFor(Library lib, Set<Library> loadedLibraries) {
   // Core libraries are not written into any package kernel binaries.
   if (loadedLibraries.contains(lib)) return null;
 
@@ -699,23 +698,25 @@
   }
 }
 
-Future<Null> forEachPackage<T>(KernelCompilationResults results,
-    T action(String package, List<Library> libraries),
-    {bool mainFirst}) async {
-  final Component component = results.component;
+Future<void> forEachPackage(KernelCompilationResults results,
+    Future<void> action(String package, List<Library> libraries),
+    {required bool mainFirst}) async {
+  final Component component = results.component!;
   final Set<Library> loadedLibraries = results.loadedLibraries;
   sortComponent(component);
 
-  final packages = new Map<String, List<Library>>();
+  final Map<String, List<Library>> packages = <String, List<Library>>{};
   packages['main'] = <Library>[]; // Always create 'main'.
   for (Library lib in component.libraries) {
-    packages
-        .putIfAbsent(packageFor(lib, loadedLibraries), () => <Library>[])
-        .add(lib);
+    final String? package = packageFor(lib, loadedLibraries);
+    // Ignore external libraries.
+    if (package == null) {
+      continue;
+    }
+    packages.putIfAbsent(package, () => <Library>[]).add(lib);
   }
-  packages.remove(null); // Ignore external libraries.
 
-  final mainLibraries = packages.remove('main');
+  final mainLibraries = packages.remove('main')!;
   if (mainFirst) {
     await action('main', mainLibraries);
   }
@@ -726,7 +727,7 @@
   component.setMainMethodAndMode(null, true, compilationMode);
   component.problemsAsJson = null;
   for (String package in packages.keys) {
-    await action(package, packages[package]);
+    await action(package, packages[package]!);
   }
   component.setMainMethodAndMode(mainMethod?.reference, true, compilationMode);
   component.problemsAsJson = problemsAsJson;
@@ -748,8 +749,8 @@
   file.write(_escapePath(output));
   file.write(':');
   for (Uri dep in compiledSources) {
-    // Skip empty or corelib dependencies.
-    if (dep == null || dep.scheme == 'org-dartlang-sdk') continue;
+    // Skip corelib dependencies.
+    if (dep.scheme == 'org-dartlang-sdk') continue;
     Uri uri = await asFileUri(fileSystem, dep);
     file.write(' ');
     file.write(_escapePath(uri.toFilePath()));
@@ -759,7 +760,7 @@
 }
 
 Future<void> createFarManifest(
-    String output, String dataDir, String packageManifestFilename) async {
+    String output, String? dataDir, String packageManifestFilename) async {
   List<String> packages = await File('$output-packages').readAsLines();
 
   // Make sure the 'main' package is the last (convention with package loader).
@@ -789,7 +790,7 @@
     'typed_data',
     'vector_math'
   ]) {
-    Digest digest;
+    Digest? digest;
     if (packages.contains(package)) {
       final filenameInBuild = '$output-$package.dilp';
       final bytes = await File(filenameInBuild).readAsBytes();
@@ -811,11 +812,20 @@
 
   CompilerResultLoadedFromKernel(this.component);
 
-  List<int> get summary => null;
+  @override
+  List<int>? get summary => null;
+
+  @override
   List<Component> get loadedComponents => const <Component>[];
+
+  @override
   List<Uri> get deps => const <Uri>[];
-  CoreTypes get coreTypes => null;
-  ClassHierarchy get classHierarchy => null;
+
+  @override
+  CoreTypes? get coreTypes => null;
+
+  @override
+  ClassHierarchy? get classHierarchy => null;
 }
 
 Future<CompilerResult> loadKernel(
diff --git a/pkg/vm/lib/metadata/call_site_attributes.dart b/pkg/vm/lib/metadata/call_site_attributes.dart
index 7ef8c93..23733d8 100644
--- a/pkg/vm/lib/metadata/call_site_attributes.dart
+++ b/pkg/vm/lib/metadata/call_site_attributes.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.metadata.call_site_attributes;
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/src/printer.dart';
 
diff --git a/pkg/vm/lib/metadata/direct_call.dart b/pkg/vm/lib/metadata/direct_call.dart
index 8e4298b..3539978 100644
--- a/pkg/vm/lib/metadata/direct_call.dart
+++ b/pkg/vm/lib/metadata/direct_call.dart
@@ -14,7 +14,7 @@
 
   DirectCallMetadata(Member target, bool checkReceiverForNull)
       : this.byReference(
-            getMemberReferenceGetter(target), checkReceiverForNull);
+            getNonNullableMemberReferenceGetter(target), checkReceiverForNull);
 
   DirectCallMetadata.byReference(
       this._targetReference, this.checkReceiverForNull);
diff --git a/pkg/vm/lib/metadata/inferred_type.dart b/pkg/vm/lib/metadata/inferred_type.dart
index 4d609fd..6f23f6e 100644
--- a/pkg/vm/lib/metadata/inferred_type.dart
+++ b/pkg/vm/lib/metadata/inferred_type.dart
@@ -9,8 +9,8 @@
 
 /// Metadata for annotating nodes with an inferred type information.
 class InferredType {
-  final Reference _concreteClassReference;
-  final Constant _constantValue;
+  final Reference? _concreteClassReference;
+  final Constant? _constantValue;
   final int _flags;
 
   static const int flagNullable = 1 << 0;
@@ -31,11 +31,11 @@
   //
   // Otherwise, a non-null type argument indicates that that particular type
   // argument (in the runtime type) is always exactly a particular `DartType`.
-  final List<DartType> exactTypeArguments;
+  final List<DartType?>? exactTypeArguments;
 
   InferredType(
-      Class concreteClass, bool nullable, bool isInt, Constant constantValue,
-      {List<DartType> exactTypeArguments,
+      Class? concreteClass, bool nullable, bool isInt, Constant? constantValue,
+      {List<DartType?>? exactTypeArguments,
       bool skipCheck: false,
       bool receiverNotInt: false})
       : this._byReference(
@@ -54,9 +54,9 @@
     assert(_constantValue == null || _concreteClassReference != null);
   }
 
-  Class get concreteClass => _concreteClassReference?.asClass;
+  Class? get concreteClass => _concreteClassReference?.asClass;
 
-  Constant get constantValue => _constantValue;
+  Constant? get constantValue => _constantValue;
 
   bool get nullable => (_flags & flagNullable) != 0;
   bool get isInt => (_flags & flagInt) != 0;
@@ -69,7 +69,7 @@
   String toString() {
     final StringBuffer buf = new StringBuffer();
     if (concreteClass != null) {
-      buf.write(concreteClass.toText(astTextStrategyForTesting));
+      buf.write(concreteClass!.toText(astTextStrategyForTesting));
     } else if (isInt) {
       buf.write('int');
     } else {
@@ -80,7 +80,7 @@
     }
     if (exactTypeArguments != null) {
       buf.write('<');
-      buf.write(exactTypeArguments
+      buf.write(exactTypeArguments!
           .map(
               (t) => t != null ? "${t.toText(astTextStrategyForTesting)}" : "?")
           .join(", "));
@@ -91,7 +91,7 @@
     }
     if (_constantValue != null) {
       buf.write(
-          ' (value: ${_constantValue.toText(astTextStrategyForTesting)})');
+          ' (value: ${_constantValue!.toText(astTextStrategyForTesting)})');
     }
     if (receiverNotInt) {
       buf.write(' (receiver not int)');
@@ -115,11 +115,11 @@
     // TODO(sjindel/tfa): Implement serialization of type arguments when can use
     // them for optimizations.
     sink.writeNullAllowedCanonicalNameReference(metadata.concreteClass != null
-        ? getCanonicalNameOfClass(metadata.concreteClass)
+        ? getCanonicalNameOfClass(metadata.concreteClass!)
         : null);
     sink.writeByte(metadata._flags);
     if (metadata.constantValue != null) {
-      sink.writeConstantReference(metadata.constantValue);
+      sink.writeConstantReference(metadata.constantValue!);
     }
   }
 
diff --git a/pkg/vm/lib/metadata/unboxing_info.dart b/pkg/vm/lib/metadata/unboxing_info.dart
index 7069c05..64646a7 100644
--- a/pkg/vm/lib/metadata/unboxing_info.dart
+++ b/pkg/vm/lib/metadata/unboxing_info.dart
@@ -14,11 +14,12 @@
   final List<int> unboxedArgsInfo;
   int returnInfo;
 
-  UnboxingInfoMetadata(int argsLen) : unboxedArgsInfo = [] {
+  UnboxingInfoMetadata(int argsLen)
+      : unboxedArgsInfo = [],
+        returnInfo = kUnboxingCandidate {
     for (int i = 0; i < argsLen; i++) {
       unboxedArgsInfo.add(kUnboxingCandidate);
     }
-    returnInfo = kUnboxingCandidate;
   }
 
   UnboxingInfoMetadata.readFromBinary(BinarySource source)
diff --git a/pkg/vm/lib/target/dart_runner.dart b/pkg/vm/lib/target/dart_runner.dart
index 928863c..995d484 100644
--- a/pkg/vm/lib/target/dart_runner.dart
+++ b/pkg/vm/lib/target/dart_runner.dart
@@ -1,7 +1,6 @@
 // Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-library vm.target.dart_runner;
 
 import 'package:kernel/target/targets.dart';
 import 'package:vm/target/vm.dart' show VmTarget;
diff --git a/pkg/vm/lib/target/flutter.dart b/pkg/vm/lib/target/flutter.dart
index 7746e98..1eadf20 100644
--- a/pkg/vm/lib/target/flutter.dart
+++ b/pkg/vm/lib/target/flutter.dart
@@ -1,7 +1,6 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-library vm.target.flutter;
 
 import 'package:kernel/ast.dart' show Component, Library;
 import 'package:kernel/core_types.dart' show CoreTypes;
@@ -13,7 +12,7 @@
 class FlutterTarget extends VmTarget {
   FlutterTarget(TargetFlags flags) : super(flags);
 
-  WidgetCreatorTracker _widgetTracker;
+  late final WidgetCreatorTracker _widgetTracker = WidgetCreatorTracker();
 
   @override
   String get name => 'flutter';
@@ -56,15 +55,12 @@
       CoreTypes coreTypes,
       List<Library> libraries,
       DiagnosticReporter diagnosticReporter,
-      {void logger(String msg),
-      ChangedStructureNotifier changedStructureNotifier}) {
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
     super.performPreConstantEvaluationTransformations(
         component, coreTypes, libraries, diagnosticReporter,
         logger: logger, changedStructureNotifier: changedStructureNotifier);
     if (flags.trackWidgetCreation) {
-      if (_widgetTracker == null) {
-        _widgetTracker = WidgetCreatorTracker();
-      }
       _widgetTracker.transform(component, libraries, changedStructureNotifier);
     }
   }
diff --git a/pkg/vm/lib/target/flutter_runner.dart b/pkg/vm/lib/target/flutter_runner.dart
index 9a2b477..addd766 100644
--- a/pkg/vm/lib/target/flutter_runner.dart
+++ b/pkg/vm/lib/target/flutter_runner.dart
@@ -1,7 +1,6 @@
 // Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-library vm.target.flutter_runner;
 
 import 'package:kernel/target/targets.dart';
 import 'package:vm/target/vm.dart' show VmTarget;
diff --git a/pkg/vm/lib/target/install.dart b/pkg/vm/lib/target/install.dart
index 4973418..b22d469 100644
--- a/pkg/vm/lib/target/install.dart
+++ b/pkg/vm/lib/target/install.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.
 
-library vm.target.install;
-
 import 'package:kernel/target/targets.dart' show targets, TargetFlags;
 import 'package:vm/target/dart_runner.dart' show DartRunnerTarget;
 import 'package:vm/target/flutter.dart' show FlutterTarget;
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index 3230605..01def63 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -1,7 +1,6 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-library vm.target.vm;
 
 import 'package:kernel/ast.dart';
 import 'package:kernel/clone.dart';
@@ -33,14 +32,14 @@
 class VmTarget extends Target {
   final TargetFlags flags;
 
-  Class _growableList;
-  Class _immutableList;
-  Class _internalLinkedHashMap;
-  Class _immutableMap;
-  Class _oneByteString;
-  Class _twoByteString;
-  Class _smi;
-  Class _double; // _Double, not double.
+  Class? _growableList;
+  Class? _immutableList;
+  Class? _internalLinkedHashMap;
+  Class? _immutableMap;
+  Class? _oneByteString;
+  Class? _twoByteString;
+  Class? _smi;
+  Class? _double; // _Double, not double.
 
   VmTarget(this.flags);
 
@@ -65,9 +64,6 @@
       !flags.forceNoExplicitGetterCallsForTesting;
 
   @override
-  bool get supportsNewMethodInvocationEncoding => true;
-
-  @override
   int get enabledConstructorTearOffLowerings =>
       flags.forceConstructorTearOffLoweringForTesting;
 
@@ -111,11 +107,11 @@
     // support patching fields.
     // See http://dartbug.com/32836 for the background.
     final Field host =
-        coreTypes.index.getMember('dart:typed_data', 'Endian', 'host');
+        coreTypes.index.getField('dart:typed_data', 'Endian', 'host');
     final Field little =
-        coreTypes.index.getMember('dart:typed_data', 'Endian', 'little');
+        coreTypes.index.getField('dart:typed_data', 'Endian', 'little');
     host.isConst = true;
-    host.initializer = new CloneVisitorNotMembers().clone(little.initializer)
+    host.initializer = new CloneVisitorNotMembers().clone(little.initializer!)
       ..parent = host;
   }
 
@@ -125,8 +121,8 @@
       CoreTypes coreTypes,
       List<Library> libraries,
       DiagnosticReporter diagnosticReporter,
-      {void logger(String msg),
-      ChangedStructureNotifier changedStructureNotifier}) {
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
     super.performPreConstantEvaluationTransformations(
         component, coreTypes, libraries, diagnosticReporter,
         logger: logger, changedStructureNotifier: changedStructureNotifier);
@@ -151,11 +147,11 @@
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       List<Library> libraries,
-      Map<String, String> environmentDefines,
+      Map<String, String>? environmentDefines,
       DiagnosticReporter diagnosticReporter,
-      ReferenceFromIndex referenceFromIndex,
-      {void logger(String msg),
-      ChangedStructureNotifier changedStructureNotifier}) {
+      ReferenceFromIndex? referenceFromIndex,
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
     transformMixins.transformLibraries(
         this, coreTypes, hierarchy, libraries, referenceFromIndex);
     logger?.call("Transformed mixin applications");
@@ -165,7 +161,7 @@
     } else {
       // Transform @FfiNative(..) functions into ffi native call functions.
       transformFfiNative.transformLibraries(
-          component, libraries, referenceFromIndex);
+          component, libraries, diagnosticReporter, referenceFromIndex);
       logger?.call("Transformed ffi natives");
       // TODO(jensj/dacoharkes): We can probably limit the transformations to
       // libraries that transitivley depend on dart:ffi.
@@ -183,7 +179,7 @@
     }
 
     // TODO(kmillikin): Make this run on a per-method basis.
-    bool productMode = environmentDefines["dart.vm.product"] == "true";
+    bool productMode = environmentDefines!["dart.vm.product"] == "true";
     transformAsync.transformLibraries(
         new TypeEnvironment(coreTypes, hierarchy), libraries,
         productMode: productMode);
@@ -203,9 +199,9 @@
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       Procedure procedure,
-      Map<String, String> environmentDefines,
-      {void logger(String msg)}) {
-    bool productMode = environmentDefines["dart.vm.product"] == "true";
+      Map<String, String>? environmentDefines,
+      {void Function(String msg)? logger}) {
+    bool productMode = environmentDefines!["dart.vm.product"] == "true";
     transformAsync.transformProcedure(
         new TypeEnvironment(coreTypes, hierarchy), procedure,
         productMode: productMode);
@@ -450,7 +446,7 @@
   }
 
   @override
-  Class concreteIntLiteralClass(CoreTypes coreTypes, int value) {
+  Class? concreteIntLiteralClass(CoreTypes coreTypes, int value) {
     const int bitsPerInt32 = 32;
     const int smiBits32 = bitsPerInt32 - 2;
     const int smiMin32 = -(1 << smiBits32);
@@ -489,7 +485,6 @@
   Map<String, String> updateEnvironmentDefines(Map<String, String> map) {
     // TODO(alexmarkov): Call this from the front-end in order to have
     //  the same defines when compiling platform.
-    assert(map != null);
     map['dart.isVM'] = 'true';
     // TODO(dartbug.com/36460): Derive dart.library.* definitions from platform.
     for (String library in extraRequiredLibraries) {
diff --git a/pkg/vm/lib/transformations/call_site_annotator.dart b/pkg/vm/lib/transformations/call_site_annotator.dart
index 76803a9..691ba84 100644
--- a/pkg/vm/lib/transformations/call_site_annotator.dart
+++ b/pkg/vm/lib/transformations/call_site_annotator.dart
@@ -2,14 +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.
 
-// @dart=2.12
-
 // This transformation annotates call sites with the receiver type.
 // This is done to avoid reimplementing [Expression.getStaticType] in
 // C++.
 // We don't annotate all call-sites, but only those where VM could benefit from
 // knowing static type of the receiver.
-library vm.transformations.call_site_annotator;
 
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -60,18 +57,6 @@
   }
 
   @override
-  visitPropertyGet(PropertyGet node) =>
-      throw 'Unexpected node ${node.runtimeType}: $node at ${node.location}';
-
-  @override
-  visitPropertySet(PropertySet node) =>
-      throw 'Unexpected node ${node.runtimeType}: $node at ${node.location}';
-
-  @override
-  visitMethodInvocation(MethodInvocation node) =>
-      throw 'Unexpected node ${node.runtimeType}: $node at ${node.location}';
-
-  @override
   visitInstanceSet(InstanceSet node) {
     super.visitInstanceSet(node);
 
diff --git a/pkg/vm/lib/transformations/deferred_loading.dart b/pkg/vm/lib/transformations/deferred_loading.dart
index 03bb9c2..b7dd321 100644
--- a/pkg/vm/lib/transformations/deferred_loading.dart
+++ b/pkg/vm/lib/transformations/deferred_loading.dart
@@ -9,15 +9,15 @@
 import '../metadata/loading_units.dart';
 
 class _LoadingUnitBuilder {
-  int id;
+  late int id;
   final _LibraryVertex root;
   final List<Library> members = <Library>[];
   final List<_LoadingUnitBuilder> children = <_LoadingUnitBuilder>[];
 
   _LoadingUnitBuilder(this.root);
 
-  _LoadingUnitBuilder get parent => root.dominator?.loadingUnit;
-  int get parentId => parent == null ? 0 : parent.id;
+  _LoadingUnitBuilder? get parent => root.dominator?.loadingUnit;
+  int get parentId => parent == null ? 0 : parent!.id;
 
   LoadingUnit asLoadingUnit() {
     return new LoadingUnit(
@@ -31,7 +31,7 @@
 class _LibraryVertex extends Vertex<_LibraryVertex> {
   final Library library;
   bool isLoadingRoot = true;
-  _LoadingUnitBuilder loadingUnit;
+  _LoadingUnitBuilder? loadingUnit;
   _LibraryVertex(this.library);
 
   String toString() => "_LibraryVertex(${library.importUri})";
@@ -45,11 +45,11 @@
   }
   for (final vertex in map.values) {
     for (final dep in vertex.library.dependencies) {
-      final target = map[dep.targetLibrary];
+      final target = map[dep.targetLibrary]!;
       vertex.successors.add(target);
     }
   }
-  final root = map[component.mainMethod.parent as Library];
+  final root = map[component.mainMethod!.enclosingLibrary]!;
 
   // Fake imports from root library to every core library so they end up in
   // the same loading unit attributed to the user's root library.
@@ -71,7 +71,7 @@
       if (dep.isDeferred) {
         continue;
       }
-      var importee = map[dep.targetLibrary];
+      var importee = map[dep.targetLibrary]!;
       if (importer.isDominatedBy(importee)) {
         continue;
       }
@@ -80,7 +80,7 @@
   }
   assert(root.isLoadingRoot);
 
-  var loadingUnits = <_LoadingUnitBuilder>[];
+  final List<_LoadingUnitBuilder> loadingUnits = <_LoadingUnitBuilder>[];
   for (var vertex in map.values) {
     if (vertex.isLoadingRoot) {
       var unit = new _LoadingUnitBuilder(vertex);
@@ -99,11 +99,11 @@
     if (dom == null) {
       continue; // Unreachable library.
     }
-    while (dom.loadingUnit == null) {
+    while (dom!.loadingUnit == null) {
       dom = dom.dominator;
     }
     vertex.loadingUnit = dom.loadingUnit;
-    vertex.loadingUnit.members.add(vertex.library);
+    vertex.loadingUnit!.members.add(vertex.library);
   }
 
   // 4. Sort loading units so parents are before children. Normally this order
@@ -117,7 +117,7 @@
   }
   var index = 0;
   loadingUnits.clear();
-  loadingUnits.add(root.loadingUnit);
+  loadingUnits.add(root.loadingUnit!);
   while (index < loadingUnits.length) {
     var unit = loadingUnits[index];
     unit.id = ++index;
diff --git a/pkg/vm/lib/transformations/devirtualization.dart b/pkg/vm/lib/transformations/devirtualization.dart
index 38de80f..7d82594 100644
--- a/pkg/vm/lib/transformations/devirtualization.dart
+++ b/pkg/vm/lib/transformations/devirtualization.dart
@@ -16,7 +16,8 @@
 Component transformComponent(CoreTypes coreTypes, Component component) {
   void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
   ClosedWorldClassHierarchy hierarchy = new ClassHierarchy(component, coreTypes,
-      onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
+          onAmbiguousSupertypes: ignoreAmbiguousSupertypes)
+      as ClosedWorldClassHierarchy;
   final hierarchySubtypes = hierarchy.computeSubtypesInformation();
   new CHADevirtualization(coreTypes, component, hierarchy, hierarchySubtypes)
       .visitComponent(component);
@@ -32,14 +33,14 @@
   static const _trace = const bool.fromEnvironment('trace.devirtualization');
 
   final DirectCallMetadataRepository _metadata;
-  Set<Name> _objectMemberNames;
+  final Set<Name> _objectMemberNames;
 
   Devirtualization(
       CoreTypes coreTypes, Component component, ClassHierarchy hierarchy)
-      : _metadata = new DirectCallMetadataRepository() {
-    _objectMemberNames = new Set<Name>.from(hierarchy
-        .getInterfaceMembers(coreTypes.objectClass)
-        .map((Member m) => m.name));
+      : _metadata = new DirectCallMetadataRepository(),
+        _objectMemberNames = new Set<Name>.from(hierarchy
+            .getInterfaceMembers(coreTypes.objectClass)
+            .map((Member m) => m.name)) {
     component.addMetadataRepository(_metadata);
   }
 
@@ -49,7 +50,7 @@
       (member is Field) || ((member is Procedure) && member.isGetter);
 
   bool isLegalTargetForMethodInvocation(Member target, Arguments arguments) {
-    final FunctionNode func = target.function;
+    final FunctionNode func = target.function!;
 
     final positionalArgs = arguments.positional.length;
     if ((positionalArgs < func.requiredParameterCount) ||
@@ -82,10 +83,10 @@
       directCall.checkReceiverForNull &&
       _objectMemberNames.contains(directCall.target.name);
 
-  DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget,
+  DirectCallMetadata? getDirectCall(TreeNode node, Member? interfaceTarget,
       {bool setter = false});
 
-  makeDirectCall(TreeNode node, Member target, DirectCallMetadata directCall) {
+  makeDirectCall(TreeNode node, Member? target, DirectCallMetadata directCall) {
     if (_trace) {
       print("[devirt] Resolving ${target} to ${directCall.target}"
           " at ${node.location}");
@@ -102,12 +103,12 @@
   }
 
   void _handleMethodInvocation(
-      TreeNode node, Member target, Arguments arguments) {
+      TreeNode node, Member? target, Arguments arguments) {
     if (target != null && !isMethod(target)) {
       return;
     }
 
-    final DirectCallMetadata directCall = getDirectCall(node, target);
+    final DirectCallMetadata? directCall = getDirectCall(node, target);
 
     // TODO(alexmarkov): Convert _isLegalTargetForMethodInvocation()
     // check into an assertion once front-end implements all override checks.
@@ -136,18 +137,18 @@
     super.visitEqualsCall(node);
 
     final target = node.interfaceTarget;
-    final DirectCallMetadata directCall = getDirectCall(node, target);
+    final DirectCallMetadata? directCall = getDirectCall(node, target);
     if (directCall != null && !directCall.checkReceiverForNull) {
       makeDirectCall(node, target, directCall);
     }
   }
 
-  void _handlePropertyGet(TreeNode node, Member target) {
+  void _handlePropertyGet(TreeNode node, Member? target) {
     if (target != null && !isFieldOrGetter(target)) {
       return;
     }
 
-    final DirectCallMetadata directCall = getDirectCall(node, target);
+    final DirectCallMetadata? directCall = getDirectCall(node, target);
 
     if ((directCall != null) &&
         isFieldOrGetter(directCall.target) &&
@@ -168,8 +169,8 @@
     _handlePropertyGet(node, null);
   }
 
-  void _handlePropertySet(TreeNode node, Member target) {
-    final DirectCallMetadata directCall =
+  void _handlePropertySet(TreeNode node, Member? target) {
+    final DirectCallMetadata? directCall =
         getDirectCall(node, target, setter: true);
     if (directCall != null) {
       makeDirectCall(node, target, directCall);
@@ -198,12 +199,12 @@
       : super(coreTypes, component, hierarchy);
 
   @override
-  DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget,
+  DirectCallMetadata? getDirectCall(TreeNode node, Member? interfaceTarget,
       {bool setter = false}) {
     if (interfaceTarget == null) {
       return null;
     }
-    Member singleTarget = _hierarchySubtype
+    Member? singleTarget = _hierarchySubtype
         .getSingleTargetForInterfaceInvocation(interfaceTarget, setter: setter);
     if (singleTarget == null) {
       return null;
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index bc29a1a..88edf51 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.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.12
-
 // This file contains logic which is shared between the ffi_definition and
 // ffi_use_site transformers.
 
@@ -292,7 +290,9 @@
   /// Classes corresponding to [NativeType], indexed by [NativeType].
   final List<Class> nativeTypesClasses;
 
-  Library? currentLibrary;
+  Library? _currentLibrary;
+  Library get currentLibrary => _currentLibrary!;
+
   IndexedLibrary? currentLibraryIndex;
 
   FfiTransformer(this.index, this.coreTypes, this.hierarchy,
@@ -459,11 +459,11 @@
 
   @override
   TreeNode visitLibrary(Library node) {
-    assert(currentLibrary == null);
-    currentLibrary = node;
+    assert(_currentLibrary == null);
+    _currentLibrary = node;
     currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
     final result = super.visitLibrary(node);
-    currentLibrary = null;
+    _currentLibrary = null;
     return result;
   }
 
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index e84e660..2238251 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.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.
 
-library vm.transformations.ffi_definitions;
-
 import 'dart:math' as math;
 
 import 'package:front_end/src/api_unstable/vm.dart'
@@ -69,8 +67,8 @@
     ClassHierarchy hierarchy,
     List<Library> libraries,
     DiagnosticReporter diagnosticReporter,
-    ReferenceFromIndex referenceFromIndex,
-    ChangedStructureNotifier changedStructureNotifier) {
+    ReferenceFromIndex? referenceFromIndex,
+    ChangedStructureNotifier? changedStructureNotifier) {
   final LibraryIndex index = LibraryIndex(component,
       const ["dart:core", "dart:ffi", "dart:_internal", "dart:typed_data"]);
   if (!index.containsLibrary("dart:ffi")) {
@@ -94,7 +92,7 @@
   CompoundDependencyGraph(this.map);
 
   Iterable<T> get vertices => map.keys;
-  Iterable<T> neighborsOf(T vertex) => map[vertex];
+  Iterable<T> neighborsOf(T vertex) => map[vertex]!;
 }
 
 /// Checks and elaborates the dart:ffi compounds and their fields.
@@ -107,16 +105,14 @@
   Set<Class> transformCompoundsInvalid = {};
   Map<Class, NativeTypeCfe> compoundCache = {};
 
-  ChangedStructureNotifier changedStructureNotifier;
-
-  IndexedLibrary currentLibraryIndex;
+  ChangedStructureNotifier? changedStructureNotifier;
 
   _FfiDefinitionTransformer(
       this.index,
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       DiagnosticReporter diagnosticReporter,
-      ReferenceFromIndex referenceFromIndex,
+      ReferenceFromIndex? referenceFromIndex,
       this.changedStructureNotifier)
       : super(index, coreTypes, hierarchy, diagnosticReporter,
             referenceFromIndex) {}
@@ -183,7 +179,7 @@
         report = true;
       }
       if (component.length == 1) {
-        if (dependencyGraph.map[component.single].contains(component.single)) {
+        if (dependencyGraph.map[component.single]!.contains(component.single)) {
           // Direct cycle.
           report = true;
         }
@@ -191,7 +187,7 @@
       if (report) {
         component.forEach((Class e) {
           diagnosticReporter.report(
-              templateFfiFieldCyclic.withArguments(e.superclass.name, e.name,
+              templateFfiFieldCyclic.withArguments(e.superclass!.name, e.name,
                   component.map((e) => e.name).toList()),
               e.fileOffset,
               e.name.length,
@@ -231,12 +227,6 @@
   }
 
   @override
-  visitLibrary(Library node) {
-    currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
-    return super.visitLibrary(node);
-  }
-
-  @override
   visitExtension(Extension node) {
     // The extension and it's members are only metadata.
     return node;
@@ -260,9 +250,12 @@
 
     final packing = _checkCompoundClass(node);
 
-    final indexedClass = currentLibraryIndex?.lookupIndexedClass(node.name);
+    final IndexedClass? indexedClass =
+        currentLibraryIndex?.lookupIndexedClass(node.name);
     _checkConstructors(node, indexedClass);
-    indexedCompoundClasses[node] = indexedClass;
+    if (indexedClass != null) {
+      indexedCompoundClasses[node] = indexedClass;
+    }
 
     final fieldsValid = _checkFieldAnnotations(node, packing);
     if (fieldsValid) {
@@ -276,14 +269,14 @@
   }
 
   /// Returns packing if any.
-  int _checkCompoundClass(Class node) {
+  int? _checkCompoundClass(Class node) {
     if (node.typeParameters.length > 0) {
       diagnosticReporter.report(
           templateFfiStructGeneric.withArguments(
-              node.superclass.name, node.name),
+              node.superclass!.name, node.name),
           node.fileOffset,
           1,
-          node.location.file);
+          node.location!.file);
     }
 
     if (node.superclass != structClass && node.superclass != unionClass) {
@@ -299,7 +292,7 @@
             templateFfiPackedAnnotation.withArguments(node.name),
             node.fileOffset,
             node.name.length,
-            node.location.file);
+            node.location!.file);
       }
       if (packingAnnotations.isNotEmpty) {
         final packing = packingAnnotations.first;
@@ -309,7 +302,7 @@
             packing == 8 ||
             packing == 16)) {
           diagnosticReporter.report(messageFfiPackedAnnotationAlignment,
-              node.fileOffset, node.name.length, node.location.file);
+              node.fileOffset, node.name.length, node.location!.file);
         }
         return packing;
       }
@@ -352,14 +345,14 @@
     if (member is Field) {
       return member.type;
     }
-    final Procedure p = member;
+    final p = member as Procedure;
     if (p.isGetter) {
       return p.function.returnType;
     }
     return p.function.positionalParameters.single.type;
   }
 
-  bool _checkFieldAnnotations(Class node, int packing) {
+  bool _checkFieldAnnotations(Class node, int? packing) {
     bool success = true;
     final membersWithAnnotations =
         _compoundFieldMembers(node, includeSetters: false);
@@ -443,9 +436,9 @@
         success = false;
       } else {
         final DartType nativeType = InterfaceType(
-            nativeTypesClasses[_getFieldType(nativeTypeAnnos.first).index],
+            nativeTypesClasses[_getFieldType(nativeTypeAnnos.first)!.index],
             Nullability.legacy);
-        final DartType shouldBeDartType = convertNativeTypeToDartType(
+        final DartType? shouldBeDartType = convertNativeTypeToDartType(
             nativeType,
             allowCompounds: true,
             allowHandle: false);
@@ -453,11 +446,11 @@
             !env.isSubtypeOf(type, shouldBeDartType,
                 SubtypeCheckMode.ignoringNullabilities)) {
           diagnosticReporter.report(
-              templateFfiTypeMismatch.withArguments(type, shouldBeDartType,
+              templateFfiTypeMismatch.withArguments(type, shouldBeDartType!,
                   nativeType, node.enclosingLibrary.isNonNullableByDefault),
               f.fileOffset,
               1,
-              f.location.file);
+              f.location!.file);
           // This class is invalid, but continue reporting other errors on it.
           success = false;
         }
@@ -466,7 +459,7 @@
     return success;
   }
 
-  void _checkPacking(Class outerClass, int outerClassPacking, Class fieldClass,
+  void _checkPacking(Class outerClass, int? outerClassPacking, Class fieldClass,
       Member errorNode) {
     if (outerClassPacking == null) {
       // Outer struct has no packing, nesting anything is fine.
@@ -495,7 +488,7 @@
     }
   }
 
-  void _checkConstructors(Class node, IndexedClass indexedClass) {
+  void _checkConstructors(Class node, IndexedClass? indexedClass) {
     final toRemove = <Initializer>[];
 
     // Constructors cannot have initializers because initializers refer to
@@ -508,13 +501,13 @@
               templateFfiFieldInitializer.withArguments(i.field.name.text),
               i.fileOffset,
               1,
-              i.location.file);
+              i.location!.file);
         }
       }
     }
     // Remove initializers referring to fields to prevent cascading errors.
     for (final Initializer i in toRemove) {
-      final Constructor c = i.parent;
+      final c = i.parent as Constructor;
       c.initializers.remove(i);
     }
 
@@ -563,7 +556,7 @@
       final dartType = _compoundMemberType(m);
 
       // Nullable.
-      NativeTypeCfe type;
+      NativeTypeCfe? type;
       if (isArrayType(dartType)) {
         final sizeAnnotations = _getArraySizeAnnotations(m).toList();
         if (sizeAnnotations.length == 1) {
@@ -582,7 +575,7 @@
         final nativeTypeAnnos = _getNativeTypeAnnotations(m).toList();
         if (nativeTypeAnnos.length == 1) {
           final clazz = nativeTypeAnnos.first;
-          final nativeType = _getFieldType(clazz);
+          final nativeType = _getFieldType(clazz)!;
           type = PrimitiveNativeTypeCfe(nativeType, clazz);
         }
       }
@@ -633,17 +626,18 @@
   ///
   /// Returns the total size of the compound (for all ABIs).
   void _replaceFields(
-      Class node, IndexedClass indexedClass, CompoundData compoundData) {
+      Class node, IndexedClass? indexedClass, CompoundData compoundData) {
     final compoundType = compoundData.compoundType as CompoundNativeTypeCfe;
     final compoundLayout = compoundType.layout;
 
     _annoteCompoundWithFields(node, compoundType.members, compoundData.packing);
     if (compoundType.members.isEmpty) {
       diagnosticReporter.report(
-          templateFfiEmptyStruct.withArguments(node.superclass.name, node.name),
+          templateFfiEmptyStruct.withArguments(
+              node.superclass!.name, node.name),
           node.fileOffset,
           node.name.length,
-          node.location.file);
+          node.location!.file);
     }
 
     final unalignedAccess = compoundData.packing != null;
@@ -651,9 +645,9 @@
     int i = 0;
     for (final compoundField in compoundData.compoundFields) {
       NativeTypeCfe type = compoundField.type;
-      Field field = compoundField.field;
-      Procedure getter = compoundField.getter;
-      Procedure setter = compoundField.setter;
+      Field? field = compoundField.field;
+      Procedure? getter = compoundField.getter;
+      Procedure? setter = compoundField.setter;
 
       final fieldOffsets = compoundLayout
           .map((Abi abi, CompoundLayout v) => MapEntry(abi, v.offsets[i]));
@@ -691,7 +685,7 @@
   static const vmFfiStructFields = "vm:ffi:struct-fields";
 
   // return value is nullable.
-  InstanceConstant _compoundAnnotatedFields(Class node) {
+  InstanceConstant? _compoundAnnotatedFields(Class node) {
     for (final annotation in node.annotations) {
       if (annotation is ConstantExpression) {
         final constant = annotation.constant;
@@ -699,7 +693,8 @@
             constant.classNode == pragmaClass &&
             constant.fieldValues[pragmaName.getterReference] ==
                 StringConstant(vmFfiStructFields)) {
-          return constant.fieldValues[pragmaOptions.getterReference];
+          return constant.fieldValues[pragmaOptions.getterReference]
+              as InstanceConstant?;
         }
       }
     }
@@ -724,20 +719,22 @@
 
   /// Must only be called if all the depencies are already in the cache.
   CompoundNativeTypeCfe _compoundAnnotatedNativeTypeCfe(Class compoundClass) {
-    final layoutConstant = _compoundAnnotatedFields(compoundClass);
+    final layoutConstant = _compoundAnnotatedFields(compoundClass)!;
     final fieldTypes = layoutConstant
         .fieldValues[ffiStructLayoutTypesField.getterReference] as ListConstant;
     final members = <NativeTypeCfe>[];
     for (final fieldType in fieldTypes.entries) {
       if (fieldType is TypeLiteralConstant) {
         final dartType = fieldType.type;
-        members.add(NativeTypeCfe(this, dartType));
+        members
+            .add(NativeTypeCfe(this, dartType, compoundCache: compoundCache));
       } else if (fieldType is InstanceConstant) {
         final singleElementConstant = fieldType
                 .fieldValues[ffiInlineArrayElementTypeField.getterReference]
             as TypeLiteralConstant;
-        final singleElementType =
-            NativeTypeCfe(this, singleElementConstant.type);
+        final singleElementType = NativeTypeCfe(
+            this, singleElementConstant.type,
+            compoundCache: compoundCache);
         final arrayLengthConstant =
             fieldType.fieldValues[ffiInlineArrayLengthField.getterReference]
                 as IntConstant;
@@ -759,7 +756,7 @@
 
   // packing is `int?`.
   void _annoteCompoundWithFields(
-      Class node, List<NativeTypeCfe> types, int packing) {
+      Class node, List<NativeTypeCfe> types, int? packing) {
     List<Constant> constants =
         types.map((t) => t.generateConstant(this)).toList();
 
@@ -778,7 +775,7 @@
   }
 
   void _generateMethodsForField(Class node, Field field, NativeTypeCfe type,
-      Map<Abi, int> offsets, bool unalignedAccess, IndexedClass indexedClass) {
+      Map<Abi, int> offsets, bool unalignedAccess, IndexedClass? indexedClass) {
     // TODO(johnniwinther): Avoid passing [indexedClass]. When compiling
     // incrementally, [field] should already carry the references from
     // [indexedClass].
@@ -798,7 +795,7 @@
     node.addProcedure(getter);
 
     if (!field.isFinal) {
-      Reference setterReference =
+      Reference? setterReference =
           indexedClass?.lookupSetterReference(field.name) ??
               field.setterReference;
       assert(setterReference == field.setterReference,
@@ -828,8 +825,8 @@
   ///
   /// If sizes are not supplied still emits a field so that the use site
   /// transformer can still rewrite to it.
-  void _addSizeOfField(Class compound, IndexedClass indexedClass,
-      [Map<Abi, int> sizes = null]) {
+  void _addSizeOfField(Class compound, IndexedClass? indexedClass,
+      [Map<Abi, int>? sizes = null]) {
     if (sizes == null) {
       sizes = Map.fromEntries(Abi.values.map((abi) => MapEntry(abi, 0)));
     }
@@ -846,8 +843,8 @@
         isStatic: true)
       ..fileOffset = compound.fileOffset
       ..isNonNullableByDefault = true
-      ..addAnnotation(ConstantExpression(InstanceConstant(pragmaClass.reference,
-          /*type_arguments=*/ [], {
+      ..addAnnotation(ConstantExpression(
+          InstanceConstant(pragmaClass.reference, /*type_arguments=*/ [], {
         pragmaName.getterReference: StringConstant("vm:prefer-inline"),
         pragmaOptions.getterReference: NullConstant(),
       })));
@@ -855,7 +852,7 @@
     compound.addProcedure(getter);
   }
 
-  NativeType _getFieldType(Class c) {
+  NativeType? _getFieldType(Class c) {
     final fieldType = getType(c);
 
     if (fieldType == NativeType.kVoid) {
@@ -924,10 +921,7 @@
 
 class CompoundData {
   final List<CompoundField> compoundFields;
-
-  // Nullable.
-  final int packing;
-
+  final int? packing;
   final NativeTypeCfe compoundType;
 
   CompoundData(this.compoundFields, this.packing, this.compoundType);
@@ -935,15 +929,9 @@
 
 class CompoundField {
   final NativeTypeCfe type;
-
-  // Nullable.
-  final Field field;
-
-  // Nullable.
-  final Procedure getter;
-
-  // Nullable.
-  final Procedure setter;
+  final Field? field;
+  final Procedure? getter;
+  final Procedure? setter;
 
   CompoundField(this.type, this.field, this.getter, this.setter);
 }
@@ -970,11 +958,11 @@
 /// intimately to AST nodes such as [Class].
 abstract class NativeTypeCfe {
   factory NativeTypeCfe(FfiTransformer transformer, DartType dartType,
-      {List<int> arrayDimensions,
+      {List<int>? arrayDimensions,
       Map<Class, NativeTypeCfe> compoundCache = const {}}) {
     if (transformer.isPrimitiveType(dartType)) {
       final clazz = (dartType as InterfaceType).classNode;
-      final nativeType = transformer.getType(clazz);
+      final nativeType = transformer.getType(clazz)!;
       return PrimitiveNativeTypeCfe(nativeType, clazz);
     }
     if (transformer.isPointerType(dartType)) {
@@ -983,7 +971,7 @@
     if (transformer.isCompoundSubtype(dartType)) {
       final clazz = (dartType as InterfaceType).classNode;
       if (compoundCache.containsKey(clazz)) {
-        return compoundCache[clazz];
+        return compoundCache[clazz]!;
       } else {
         throw "Class '$clazz' not found in compoundCache.";
       }
@@ -1090,8 +1078,8 @@
   }
 
   @override
-  Map<Abi, int> get alignment => Map.fromEntries(Abi.values.map(
-      (abi) => MapEntry(abi, nonSizeAlignment[abi][nativeType] ?? size[abi])));
+  Map<Abi, int> get alignment => Map.fromEntries(Abi.values.map((abi) =>
+      MapEntry(abi, nonSizeAlignment[abi]![nativeType] ?? size[abi]!)));
 
   @override
   Constant generateConstant(FfiTransformer transformer) =>
@@ -1103,8 +1091,8 @@
   bool isUnaligned(Map<Abi, int> offsets) {
     final alignments = alignment;
     for (final abi in offsets.keys) {
-      final offset = offsets[abi];
-      final alignment = alignments[abi];
+      final offset = offsets[abi]!;
+      final alignment = alignments[abi]!;
       if (offset % alignment != 0) {
         return true;
       }
@@ -1127,7 +1115,7 @@
       ReturnStatement(StaticInvocation(
           (unalignedAccess && isFloat
               ? transformer.loadUnalignedMethods
-              : transformer.loadMethods)[nativeType],
+              : transformer.loadMethods)[nativeType]!,
           Arguments([
             transformer.getCompoundTypedDataBaseField(
                 ThisExpression(), fileOffset),
@@ -1151,7 +1139,7 @@
       ReturnStatement(StaticInvocation(
           (unalignedAccess && isFloat
               ? transformer.storeUnalignedMethods
-              : transformer.storeMethods)[nativeType],
+              : transformer.storeMethods)[nativeType]!,
           Arguments([
             transformer.getCompoundTypedDataBaseField(
                 ThisExpression(), fileOffset),
@@ -1172,7 +1160,7 @@
   Constant generateConstant(FfiTransformer transformer) => TypeLiteralConstant(
           InterfaceType(transformer.pointerClass, Nullability.nonNullable, [
         InterfaceType(
-            transformer.pointerClass.superclass, Nullability.nonNullable)
+            transformer.pointerClass.superclass!, Nullability.nonNullable)
       ]));
 
   /// Sample output for `Pointer<Int8> get x =>`:
@@ -1191,7 +1179,7 @@
           transformer.fromAddressInternal,
           Arguments([
             StaticInvocation(
-                transformer.loadMethods[NativeType.kIntptr],
+                transformer.loadMethods[NativeType.kIntptr]!,
                 Arguments([
                   transformer.getCompoundTypedDataBaseField(
                       ThisExpression(), fileOffset),
@@ -1217,7 +1205,7 @@
           VariableDeclaration argument,
           FfiTransformer transformer) =>
       ReturnStatement(StaticInvocation(
-          transformer.storeMethods[NativeType.kIntptr],
+          transformer.storeMethods[NativeType.kIntptr]!,
           Arguments([
             transformer.getCompoundTypedDataBaseField(
                 ThisExpression(), fileOffset),
@@ -1308,10 +1296,10 @@
 
 class StructNativeTypeCfe extends CompoundNativeTypeCfe {
   // Nullable int.
-  final int packing;
+  final int? packing;
 
   factory StructNativeTypeCfe(Class clazz, List<NativeTypeCfe> members,
-      {int packing}) {
+      {int? packing}) {
     final layout = Map.fromEntries(Abi.values
         .map((abi) => MapEntry(abi, _calculateLayout(members, packing, abi))));
     return StructNativeTypeCfe._(clazz, members, packing, layout);
@@ -1324,13 +1312,13 @@
   // Keep consistent with runtime/vm/compiler/ffi/native_type.cc
   // NativeStructType::FromNativeTypes.
   static CompoundLayout _calculateLayout(
-      List<NativeTypeCfe> types, int packing, Abi abi) {
+      List<NativeTypeCfe> types, int? packing, Abi abi) {
     int offset = 0;
     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].size[abi]!;
+      int alignment = types[i].alignment[abi]!;
       if (packing != null && packing < alignment) {
         alignment = packing;
       }
@@ -1363,8 +1351,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].size[abi]!;
+      int alignment = types[i].alignment[abi]!;
       unionSize = math.max(unionSize, size);
       unionAlignment = math.max(unionAlignment, alignment);
     }
diff --git a/pkg/vm/lib/transformations/ffi_native.dart b/pkg/vm/lib/transformations/ffi_native.dart
index f3fdb03..e666652 100644
--- a/pkg/vm/lib/transformations/ffi_native.dart
+++ b/pkg/vm/lib/transformations/ffi_native.dart
@@ -2,23 +2,28 @@
 // for 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.12
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/library_index.dart' show LibraryIndex;
 import 'package:kernel/reference_from_index.dart'
     show IndexedLibrary, ReferenceFromIndex;
+import 'package:kernel/target/targets.dart' show DiagnosticReporter;
+import 'package:front_end/src/api_unstable/vm.dart'
+    show messageFfiNativeAnnotationMustAnnotateStatic;
 
 /// Transform @FfiNative annotated functions into FFI native function pointer
 /// functions.
-void transformLibraries(Component component, List<Library> libraries,
-    ReferenceFromIndex referenceFromIndex) {
+void transformLibraries(
+    Component component,
+    List<Library> libraries,
+    DiagnosticReporter diagnosticReporter,
+    ReferenceFromIndex? referenceFromIndex) {
   final index = LibraryIndex(component, ['dart:ffi']);
   // Skip if dart:ffi isn't loaded (e.g. during incremental compile).
   if (index.tryGetClass('dart:ffi', 'FfiNative') == null) {
     return;
   }
-  final transformer = FfiNativeTransformer(index, referenceFromIndex);
+  final transformer =
+      FfiNativeTransformer(index, diagnosticReporter, referenceFromIndex);
   libraries.forEach(transformer.visitLibrary);
 }
 
@@ -26,19 +31,24 @@
   Library? currentLibrary;
   IndexedLibrary? currentLibraryIndex;
 
+  final DiagnosticReporter diagnosticReporter;
   final ReferenceFromIndex? referenceFromIndex;
   final Class ffiNativeClass;
   final Class nativeFunctionClass;
   final Field ffiNativeNameField;
+  final Field ffiNativeIsLeafField;
   final Field resolverField;
   final Procedure asFunctionProcedure;
   final Procedure fromAddressInternal;
 
-  FfiNativeTransformer(LibraryIndex index, this.referenceFromIndex)
+  FfiNativeTransformer(
+      LibraryIndex index, this.diagnosticReporter, this.referenceFromIndex)
       : ffiNativeClass = index.getClass('dart:ffi', 'FfiNative'),
         nativeFunctionClass = index.getClass('dart:ffi', 'NativeFunction'),
         ffiNativeNameField =
             index.getField('dart:ffi', 'FfiNative', 'nativeName'),
+        ffiNativeIsLeafField =
+            index.getField('dart:ffi', 'FfiNative', 'isLeaf'),
         resolverField = index.getTopLevelField('dart:ffi', '_ffi_resolver'),
         asFunctionProcedure = index.getProcedure(
             'dart:ffi', 'NativeFunctionPointer', 'asFunction'),
@@ -50,10 +60,9 @@
     assert(currentLibrary == null);
     currentLibrary = node;
     currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
-    // We only transform top-level, external procedures:
-    transformList(node.procedures, node);
+    final result = super.visitLibrary(node);
     currentLibrary = null;
-    return node;
+    return result;
   }
 
   InstanceConstant? _tryGetFfiNativeAnnotation(Member node) {
@@ -71,21 +80,23 @@
   }
 
   // Transform:
-  //   @FfiNative<Double Function(Double)>('Math_sqrt')
-  //   external double _sqrt(double x);
+  //   @FfiNative<Double Function(Double)>('Math_sqrt', isLeaf:true)
+  //   external double _square_root(double x);
   //
   // Into:
-  //   final _@FfiNative_Math_sqrt =
+  //   final _@FfiNative__square_root =
   //       Pointer<NativeFunction<Double Function(Double)>>
   //           .fromAddress(_ffi_resolver('dart:math', 'Math_sqrt'))
-  //           .asFunction<double Function(double)>();
-  //   double _sqrt(double x) => _@FfiNative_Math_sqrt(x);
+  //           .asFunction<double Function(double)>(isLeaf:true);
+  //   double _square_root(double x) => _@FfiNative__square_root(x);
   Statement transformFfiNative(
       Procedure node, InstanceConstant annotationConst) {
     assert(currentLibrary != null);
     final params = node.function.positionalParameters;
     final functionName = annotationConst
         .fieldValues[ffiNativeNameField.getterReference] as StringConstant;
+    final isLeaf = annotationConst
+        .fieldValues[ffiNativeIsLeafField.getterReference] as BoolConstant;
 
     // double Function(double)
     final DartType dartType =
@@ -115,26 +126,30 @@
         Arguments([resolverInvocation], types: [nativeInterfaceType]));
 
     // NativeFunctionPointer.asFunction
-    //     <Double Function(Double), double Function(double)>(...)
-    final asFunctionInvocation = StaticInvocation(asFunctionProcedure,
-        Arguments([fromAddressInvocation], types: [nativeType, dartType]));
+    //     <Double Function(Double), double Function(double)>(..., isLeaf:true)
+    final asFunctionInvocation = StaticInvocation(
+        asFunctionProcedure,
+        Arguments([fromAddressInvocation],
+            types: [nativeType, dartType],
+            named: [NamedExpression("isLeaf", BoolLiteral(isLeaf.value))]));
 
-    // final _@FfiNative_Math_sqrt = ...
-    final fieldName = Name('_@FfiNative_${functionName.value}', currentLibrary);
+    // final _@FfiNative__square_root = ...
+    final fieldName = Name('_@FfiNative_${node.name.text}', currentLibrary);
     final funcPtrField = Field.immutable(fieldName,
         type: dartType,
         initializer: asFunctionInvocation,
         isStatic: true,
         isFinal: true,
         fileUri: currentLibrary!.fileUri,
-        getterReference: currentLibraryIndex?.lookupGetterReference(fieldName));
+        getterReference: currentLibraryIndex?.lookupGetterReference(fieldName))
+      ..fileOffset = node.fileOffset;
     currentLibrary!.addField(funcPtrField);
 
-    // _@FfiNative_Math_sqrt(x)
+    // _@FfiNative__square_root(x)
     final callFuncPtrInvocation = FunctionInvocation(
         FunctionAccessKind.FunctionType,
         StaticGet(funcPtrField),
-        Arguments(params.map((p) => VariableGet(p)).toList()),
+        Arguments(params.map<Expression>((p) => VariableGet(p)).toList()),
         functionType: dartType as FunctionType);
 
     return ReturnStatement(callFuncPtrInvocation);
@@ -144,7 +159,7 @@
   visitProcedure(Procedure node) {
     // Only transform functions that are external and have FfiNative annotation:
     //   @FfiNative<Double Function(Double)>('Math_sqrt')
-    //   external double _sqrt(double x);
+    //   external double _square_root(double x);
     if (!node.isExternal) {
       return node;
     }
@@ -153,6 +168,11 @@
       return node;
     }
 
+    if (!node.isStatic) {
+      diagnosticReporter.report(messageFfiNativeAnnotationMustAnnotateStatic,
+          node.fileOffset, 1, node.location!.file);
+    }
+
     node.isExternal = false;
     node.function.body = transformFfiNative(node, ffiNativeAnnotation)
       ..parent = node.function;
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 4600fde..49281ed 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.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.
 
-library vm.transformations.ffi_use_sites;
-
 import 'package:front_end/src/api_unstable/vm.dart'
     show
         messageFfiExceptionalReturnNull,
@@ -44,7 +42,7 @@
     ClassHierarchy hierarchy,
     List<Library> libraries,
     DiagnosticReporter diagnosticReporter,
-    ReferenceFromIndex referenceFromIndex) {
+    ReferenceFromIndex? referenceFromIndex) {
   final index = new LibraryIndex(
       component, ["dart:ffi", "dart:_internal", "dart:typed_data"]);
   if (!index.containsLibrary("dart:ffi")) {
@@ -64,7 +62,7 @@
 
 /// Checks and replaces calls to dart:ffi compound fields and methods.
 class _FfiUseSiteTransformer extends FfiTransformer {
-  StaticTypeContext _staticTypeContext;
+  StaticTypeContext? _staticTypeContext;
 
   bool get isFfiLibrary => currentLibrary == ffiLibrary;
 
@@ -77,7 +75,7 @@
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       DiagnosticReporter diagnosticReporter,
-      ReferenceFromIndex referenceFromIndex)
+      ReferenceFromIndex? referenceFromIndex)
       : super(index, coreTypes, hierarchy, diagnosticReporter,
             referenceFromIndex) {}
 
@@ -174,7 +172,7 @@
         _ensureNativeTypeValid(nativeType, node, allowCompounds: true);
 
         if (nativeType is InterfaceType) {
-          Expression inlineSizeOf = _inlineSizeOf(nativeType);
+          Expression? inlineSizeOf = _inlineSizeOf(nativeType);
           if (inlineSizeOf != null) {
             return inlineSizeOf;
           }
@@ -204,7 +202,7 @@
         return replacement;
       } else if (target == asFunctionMethod) {
         final dartType = node.arguments.types[1];
-        final DartType nativeType = InterfaceType(
+        final InterfaceType nativeType = InterfaceType(
             nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
 
         _ensureNativeTypeValid(nativeType, node);
@@ -212,10 +210,9 @@
         _ensureIsLeafIsConst(node);
         _ensureLeafCallDoesNotUseHandles(nativeType, node);
 
-        final DartType nativeSignature =
-            (nativeType as InterfaceType).typeArguments[0];
+        final DartType nativeSignature = nativeType.typeArguments[0];
 
-        bool isLeaf = _getIsLeafBoolean(node);
+        bool? isLeaf = _getIsLeafBoolean(node);
         if (isLeaf == null) {
           isLeaf = false;
         }
@@ -241,7 +238,7 @@
         final DartType nativeType = InterfaceType(
             nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
         final Expression func = node.arguments.positional[0];
-        final DartType dartType = func.getStaticType(_staticTypeContext);
+        final DartType dartType = func.getStaticType(_staticTypeContext!);
 
         _ensureIsStaticFunction(func);
 
@@ -255,7 +252,7 @@
             ((node.arguments.types[0] as FunctionType).returnType
                     as InterfaceType)
                 .classNode;
-        final NativeType expectedReturn = getType(expectedReturnClass);
+        final NativeType? expectedReturn = getType(expectedReturnClass);
 
         if (expectedReturn == NativeType.kVoid ||
             expectedReturn == NativeType.kPointer ||
@@ -307,7 +304,7 @@
           }
 
           final DartType returnType =
-              exceptionalReturn.getStaticType(_staticTypeContext);
+              exceptionalReturn.getStaticType(_staticTypeContext!);
 
           if (!env.isSubtypeOf(returnType, funcType.returnType,
               SubtypeCheckMode.ignoringNullabilities)) {
@@ -337,7 +334,7 @@
 
         // Inline the body to get rid of a generic invocation of sizeOf.
         // TODO(http://dartbug.com/39964): Add `allignmentOf<T>()` call.
-        Expression sizeInBytes = _inlineSizeOf(nativeType);
+        Expression? sizeInBytes = _inlineSizeOf(nativeType as InterfaceType);
         if (sizeInBytes != null) {
           if (node.arguments.positional.length == 2) {
             sizeInBytes = multiply(node.arguments.positional[1], sizeInBytes);
@@ -399,9 +396,9 @@
           .distinct()
           .fold(nestedExpression, _invokeCompoundConstructor);
 
-  Expression _inlineSizeOf(InterfaceType nativeType) {
+  Expression? _inlineSizeOf(InterfaceType nativeType) {
     final Class nativeClass = nativeType.classNode;
-    final NativeType nt = getType(nativeClass);
+    final NativeType? nt = getType(nativeClass);
     if (nt == null) {
       // User-defined compounds.
       final Procedure sizeOfGetter = nativeClass.procedures
@@ -455,7 +452,7 @@
                 .substituteType(lookupFunctionType.withoutTypeParameters)
             as FunctionType);
 
-    bool isLeaf = _getIsLeafBoolean(node);
+    bool? isLeaf = _getIsLeafBoolean(node);
     if (isLeaf == null) {
       isLeaf = false;
     }
@@ -516,7 +513,7 @@
           pointer,
           offsetByMethod.name,
           Arguments([
-            multiply(node.arguments.positional[1], _inlineSizeOf(dartType))
+            multiply(node.arguments.positional[1], _inlineSizeOf(dartType)!)
           ]),
           interfaceTarget: offsetByMethod,
           functionType:
@@ -534,8 +531,8 @@
 
     final typedDataBasePrime = typedDataBaseOffset(
         getArrayTypedDataBaseField(NullCheck(node.arguments.positional[0])),
-        multiply(node.arguments.positional[1], _inlineSizeOf(dartType)),
-        _inlineSizeOf(dartType),
+        multiply(node.arguments.positional[1], _inlineSizeOf(dartType)!),
+        _inlineSizeOf(dartType)!,
         dartType,
         node.fileOffset);
 
@@ -598,7 +595,7 @@
         type: coreTypes.intNonNullableRawType)
       ..fileOffset = node.fileOffset;
     final singleElementSizeVar = VariableDeclaration("#singleElementSize",
-        initializer: _inlineSizeOf(elementType),
+        initializer: _inlineSizeOf(elementType as InterfaceType),
         type: coreTypes.intNonNullableRawType)
       ..fileOffset = node.fileOffset;
     final elementSizeVar = VariableDeclaration("#elementSize",
@@ -682,12 +679,12 @@
     try {
       if (target == elementAtMethod) {
         final DartType pointerType =
-            node.receiver.getStaticType(_staticTypeContext);
-        final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
+            node.receiver.getStaticType(_staticTypeContext!);
+        final DartType nativeType = _pointerTypeGetTypeArg(pointerType)!;
 
         _ensureNativeTypeValid(nativeType, node, allowCompounds: true);
 
-        Expression inlineSizeOf = _inlineSizeOf(nativeType);
+        Expression? inlineSizeOf = _inlineSizeOf(nativeType as InterfaceType);
         if (inlineSizeOf != null) {
           // Generates `receiver.offsetBy(inlineSizeOfExpression)`.
           return InstanceInvocation(
@@ -712,7 +709,7 @@
     return node;
   }
 
-  DartType _pointerTypeGetTypeArg(DartType pointerType) {
+  DartType? _pointerTypeGetTypeArg(DartType pointerType) {
     return pointerType is InterfaceType ? pointerType.typeArguments[0] : null;
   }
 
@@ -722,7 +719,7 @@
     final DartType correspondingDartType = convertNativeTypeToDartType(
         nativeType,
         allowCompounds: true,
-        allowHandle: allowHandle);
+        allowHandle: allowHandle)!;
     if (dartType == correspondingDartType) return;
     if (env.isSubtypeOf(correspondingDartType, dartType,
         SubtypeCheckMode.ignoringNullabilities)) {
@@ -785,7 +782,7 @@
   /// Returns the class that should not be implemented or extended.
   ///
   /// If the superclass is not sealed, returns `null`.
-  Class _extendsOrImplementsSealedClass(Class klass) {
+  Class? _extendsOrImplementsSealedClass(Class klass) {
     // Classes in dart:ffi themselves can extend FFI classes.
     if (klass == arrayClass ||
         klass == arraySizeClass ||
@@ -822,7 +819,7 @@
   }
 
   void _ensureNotExtendsOrImplementsSealedClass(Class klass) {
-    final Class extended = _extendsOrImplementsSealedClass(klass);
+    final Class? extended = _extendsOrImplementsSealedClass(klass);
     if (extended != null) {
       diagnosticReporter.report(
           templateFfiExtendsOrImplementsSealedClass
@@ -838,7 +835,7 @@
   // - `true` if leaf
   // - `false` if not leaf
   // - `null` if the expression is not valid (e.g. non-const bool, null)
-  bool _getIsLeafBoolean(StaticInvocation node) {
+  bool? _getIsLeafBoolean(StaticInvocation node) {
     for (final named in node.arguments.named) {
       if (named.name == 'isLeaf') {
         final expr = named.value;
@@ -891,8 +888,8 @@
         }
       }
       // Check if any of the argument types are Handle.
-      for (InterfaceType param in functionType.positionalParameters) {
-        if (param.classNode == handleClass) {
+      for (DartType param in functionType.positionalParameters) {
+        if ((param as InterfaceType).classNode == handleClass) {
           diagnosticReporter.report(messageFfiLeafCallMustNotTakeHandle,
               node.fileOffset, 1, node.location?.file);
         }
diff --git a/pkg/vm/lib/transformations/late_var_init_transformer.dart b/pkg/vm/lib/transformations/late_var_init_transformer.dart
index 7d245f1..48fd416 100644
--- a/pkg/vm/lib/transformations/late_var_init_transformer.dart
+++ b/pkg/vm/lib/transformations/late_var_init_transformer.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.12
-
 import 'package:kernel/ast.dart';
 
 /// Wraps the initializers of late local variables in closures.
diff --git a/pkg/vm/lib/transformations/list_literals_lowering.dart b/pkg/vm/lib/transformations/list_literals_lowering.dart
index e6b5e13..1acb42f 100644
--- a/pkg/vm/lib/transformations/list_literals_lowering.dart
+++ b/pkg/vm/lib/transformations/list_literals_lowering.dart
@@ -22,23 +22,24 @@
   final Procedure _defaultFactory;
 
   // Specialized _GrowableList._literalN(e1, ..., eN) factories.
-  final List<Procedure> _specializedFactories =
-      List<Procedure>.filled(numSpecializedFactories, null);
+  final List<Procedure?> _specializedFactories =
+      List<Procedure?>.filled(numSpecializedFactories, null);
 
   ListLiteralsLowering(this.coreTypes)
       : _defaultFactory =
-            coreTypes.index.getMember('dart:core', '_GrowableList', '');
+            coreTypes.index.getProcedure('dart:core', '_GrowableList', '');
 
   Procedure getSpecializedFactory(int length) =>
       (_specializedFactories[length - 1] ??= coreTypes.index
-          .getMember('dart:core', '_GrowableList', '_literal$length'));
+          .getProcedure('dart:core', '_GrowableList', '_literal$length'));
 
   Expression transformListLiteral(ListLiteral node) {
     if (node.isConst) {
       throw 'Unexpected constant ListLiteral node'
           ' (such nodes should be converted to ConstantExpression): $node';
     }
-    if (node.parent is Field && isRedirectingFactoryField(node.parent)) {
+    final parent = node.parent;
+    if (parent is Field && isRedirectingFactoryField(parent)) {
       // Do not transform list literals which are used to represent
       // redirecting factories.
       return node;
diff --git a/pkg/vm/lib/transformations/lowering.dart b/pkg/vm/lib/transformations/lowering.dart
index 4b320ad..d776f33 100644
--- a/pkg/vm/lib/transformations/lowering.dart
+++ b/pkg/vm/lib/transformations/lowering.dart
@@ -37,8 +37,8 @@
   final FactorySpecializer factorySpecializer;
   final ListLiteralsLowering listLiteralsLowering;
 
-  Member _currentMember;
-  StaticTypeContext _cachedStaticTypeContext;
+  Member? _currentMember;
+  StaticTypeContext? _cachedStaticTypeContext;
 
   _Lowering(CoreTypes coreTypes, ClassHierarchy hierarchy, this.nullSafety)
       : env = TypeEnvironment(coreTypes, hierarchy),
@@ -47,7 +47,7 @@
         listLiteralsLowering = ListLiteralsLowering(coreTypes);
 
   StaticTypeContext get _staticTypeContext =>
-      _cachedStaticTypeContext ??= StaticTypeContext(_currentMember, env);
+      _cachedStaticTypeContext ??= StaticTypeContext(_currentMember!, env);
 
   @override
   defaultMember(Member node) {
diff --git a/pkg/vm/lib/transformations/mixin_deduplication.dart b/pkg/vm/lib/transformations/mixin_deduplication.dart
index ba65266..61f008b 100644
--- a/pkg/vm/lib/transformations/mixin_deduplication.dart
+++ b/pkg/vm/lib/transformations/mixin_deduplication.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.transformations.mixin_deduplication;
-
 import 'package:kernel/ast.dart';
 
 /// De-duplication of identical mixin applications.
diff --git a/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart b/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
index 5e9600e..75b566f 100644
--- a/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
+++ b/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
@@ -46,7 +46,6 @@
       case Action.invoke:
         return '${target}';
     }
-    return '?';
   }
 }
 
diff --git a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
index 98592ef..b4eeab7 100644
--- a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
+++ b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
@@ -28,7 +28,7 @@
   void _addIfEntryPoint(
       List<Expression> annotations, String name, TreeNode node) {
     for (var ann in annotations) {
-      ParsedPragma pragma = parser.parsePragma(ann);
+      ParsedPragma? pragma = parser.parsePragma(ann);
       if (pragma is ParsedEntryPointPragma) {
         metadata.protectedNames.add(name);
         if (node is Field) {
diff --git a/pkg/vm/lib/transformations/pragma.dart b/pkg/vm/lib/transformations/pragma.dart
index cde363a..dfac713 100644
--- a/pkg/vm/lib/transformations/pragma.dart
+++ b/pkg/vm/lib/transformations/pragma.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.
 
-library vm.transformations.pragma;
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart' show CoreTypes;
 
@@ -54,7 +52,7 @@
 abstract class PragmaAnnotationParser {
   /// May return 'null' if the annotation does not represent a recognized
   /// @pragma.
-  ParsedPragma parsePragma(Expression annotation);
+  ParsedPragma? parsePragma(Expression annotation);
 }
 
 class ConstantPragmaAnnotationParser extends PragmaAnnotationParser {
@@ -62,8 +60,8 @@
 
   ConstantPragmaAnnotationParser(this.coreTypes);
 
-  ParsedPragma parsePragma(Expression annotation) {
-    InstanceConstant pragmaConstant;
+  ParsedPragma? parsePragma(Expression annotation) {
+    InstanceConstant? pragmaConstant;
     if (annotation is ConstantExpression) {
       Constant constant = annotation.constant;
       if (constant is InstanceConstant) {
@@ -79,7 +77,7 @@
     if (pragmaConstant == null) return null;
 
     String pragmaName;
-    Constant name =
+    Constant? name =
         pragmaConstant.fieldValues[coreTypes.pragmaName.getterReference];
     if (name is StringConstant) {
       pragmaName = name.value;
@@ -88,12 +86,11 @@
     }
 
     Constant options =
-        pragmaConstant.fieldValues[coreTypes.pragmaOptions.getterReference];
-    assert(options != null);
+        pragmaConstant.fieldValues[coreTypes.pragmaOptions.getterReference]!;
 
     switch (pragmaName) {
       case kEntryPointPragmaName:
-        PragmaEntryPointType type;
+        PragmaEntryPointType? type;
         if (options is NullConstant) {
           type = PragmaEntryPointType.Default;
         } else if (options is BoolConstant && options.value == true) {
@@ -113,7 +110,6 @@
         }
         return type != null ? new ParsedEntryPointPragma(type) : null;
       case kExactResultTypePragmaName:
-        if (options == null) return null;
         if (options is TypeLiteralConstant) {
           return new ParsedResultTypeByTypePragma(options.type, false);
         } else if (options is StringConstant) {
@@ -132,7 +128,7 @@
       case kNonNullableResultType:
         return new ParsedNonNullableResultType();
       case kRecognizedPragmaName:
-        PragmaRecognizedType type;
+        PragmaRecognizedType? type;
         if (options is StringConstant) {
           if (options.value == "asm-intrinsic") {
             type = PragmaRecognizedType.AsmIntrinsic;
diff --git a/pkg/vm/lib/transformations/specializer/factory_specializer.dart b/pkg/vm/lib/transformations/specializer/factory_specializer.dart
index 7475638..b86c3e6 100644
--- a/pkg/vm/lib/transformations/specializer/factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/factory_specializer.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.transformations.specializer.factory_specializer;
-
 import 'package:kernel/kernel.dart';
 import 'package:kernel/core_types.dart';
 import 'package:vm/transformations/specializer/list_factory_specializer.dart';
diff --git a/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart b/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
index 248c192..1a3f10f 100644
--- a/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.transformations.specializer.list_factory_specializer;
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:vm/transformations/specializer/factory_specializer.dart';
diff --git a/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart b/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart
index 8a01984..55f9d52 100644
--- a/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.transformations.specializer.map_factory_specializer;
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart';
 import 'dart:core';
diff --git a/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart b/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart
index a508435..2479e3d 100644
--- a/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.transformations.specializer.set_factory_specializer;
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart' show CoreTypes;
 
diff --git a/pkg/vm/lib/transformations/to_string_transformer.dart b/pkg/vm/lib/transformations/to_string_transformer.dart
index 10e7575..0cd1b5f 100644
--- a/pkg/vm/lib/transformations/to_string_transformer.dart
+++ b/pkg/vm/lib/transformations/to_string_transformer.dart
@@ -13,7 +13,7 @@
 /// `super.toString()`.
 class ToStringVisitor extends RecursiveVisitor {
   /// The [packageUris] must not be null.
-  ToStringVisitor(this._packageUris) : assert(_packageUris != null);
+  ToStringVisitor(this._packageUris);
 
   /// A set of package URIs to apply this transformer to, e.g. 'dart:ui' and
   /// 'package:flutter/foundation.dart'.
@@ -42,7 +42,7 @@
       if (className == 'pragma' && libraryUri == 'dart:core') {
         for (var fieldRef in constant.fieldValues.keys) {
           if (fieldRef.asField.name.text == 'name') {
-            Constant name = constant.fieldValues[fieldRef];
+            Constant? name = constant.fieldValues[fieldRef];
             return name is StringConstant &&
                 name.value == 'flutter:keep-to-string';
           }
@@ -57,13 +57,12 @@
   void visitProcedure(Procedure node) {
     if (node.name.text == 'toString' &&
         node.enclosingClass != null &&
-        node.enclosingLibrary != null &&
         !node.isStatic &&
         !node.isAbstract &&
-        !node.enclosingClass.isEnum &&
+        !node.enclosingClass!.isEnum &&
         _isInTargetPackage(node) &&
         !_hasKeepAnnotation(node)) {
-      node.function.body.replaceWith(
+      node.function.body!.replaceWith(
         ReturnStatement(
           SuperMethodInvocation(
             node.name,
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 502fe14..75eff47 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Global type flow analysis.
-library kernel.transformations.analysis;
 
 import 'dart:collection';
 import 'dart:core' hide Type;
@@ -49,24 +48,28 @@
 
 /// Maintains set of dependent invocations.
 class _DependencyTracker {
-  Set<_Invocation> _dependentInvocations;
+  Set<_Invocation>? _dependentInvocations;
 
   void addDependentInvocation(_Invocation invocation) {
     if (!identical(invocation, this)) {
-      _dependentInvocations ??= new Set<_Invocation>();
-      _dependentInvocations.add(invocation);
+      var dependentInvocations = _dependentInvocations;
+      if (dependentInvocations == null) {
+        _dependentInvocations = dependentInvocations = Set<_Invocation>();
+      }
+      dependentInvocations.add(invocation);
     }
   }
 
   void invalidateDependentInvocations(_WorkList workList) {
-    if (_dependentInvocations != null) {
+    final dependentInvocations = _dependentInvocations;
+    if (dependentInvocations != null) {
       if (kPrintTrace) {
         tracePrint('   - CHANGED: $this');
-        for (var di in _dependentInvocations) {
+        for (var di in dependentInvocations) {
           tracePrint('     - invalidating $di');
         }
       }
-      _dependentInvocations.forEach(workList.invalidateInvocation);
+      dependentInvocations.forEach(workList.invalidateInvocation);
     }
   }
 }
@@ -81,12 +84,12 @@
   final Selector selector;
   final Args<Type> args;
 
-  Type result;
+  Type? result;
 
   /// Result of the invocation calculated before invocation was invalidated.
   /// Used to check if the re-analysis of the invocation yields the same
   /// result or not (to avoid invalidation of callers if result hasn't changed).
-  Type invalidatedResult;
+  Type? invalidatedResult;
 
   /// Number of times result of this invocation was invalidated.
   int invalidationCounter = 0;
@@ -106,7 +109,7 @@
   /// Returns result of this invocation if its available without
   /// further analysis, or `null` if it's not available.
   /// Used for recursive calls while this invocation is being processed.
-  Type get resultForRecursiveInvocation => result;
+  Type? get resultForRecursiveInvocation => result;
 
   /// Use [type] as a current computed result of this invocation.
   /// If this invocation was invalidated, and the invalidated result is
@@ -114,7 +117,6 @@
   /// Result type may be saturated if this invocation was invalidated
   /// too many times.
   void setResult(TypeFlowAnalysis typeFlowAnalysis, Type type) {
-    assert(type != null);
     result = type;
 
     if (invalidatedResult != null) {
@@ -130,8 +132,8 @@
         // the analysis, result is saturated after invocation is invalidated
         // at least [_Invocation.invalidationLimit] times.
         if (invalidationCounter > _Invocation.invalidationLimit) {
-          result =
-              result.union(invalidatedResult, typeFlowAnalysis.hierarchyCache);
+          result = result!
+              .union(invalidatedResult!, typeFlowAnalysis.hierarchyCache);
         }
       }
       invalidatedResult = null;
@@ -190,11 +192,12 @@
     // they could fail bounds checks.
     //
     // TODO(sjindel): Use [TypeCheck] to avoid bounds checks.
-    if (selector.member.function != null) {
-      typeChecksNeeded = selector.member.function.typeParameters
-          .any((t) => t.isGenericCovariantImpl);
+    final function = selector.member.function;
+    if (function != null) {
+      typeChecksNeeded =
+          function.typeParameters.any((t) => t.isGenericCovariantImpl);
     } else {
-      Field field = selector.member;
+      Field field = selector.member as Field;
       if (selector.callKind == CallKind.PropertySet) {
         // TODO(dartbug.com/40615): Use TFA results to improve this criterion.
         typeChecksNeeded = field.isGenericCovariantImpl;
@@ -275,13 +278,10 @@
         fieldValue.isInitialized = true;
         return const EmptyType();
     }
-
-    // Make dartanalyzer happy.
-    throw 'Unexpected call kind ${selector.callKind}';
   }
 
   Type _processFunction(TypeFlowAnalysis typeFlowAnalysis) {
-    final Member member = selector.member;
+    final Member member = selector.member!;
     if (selector.memberAgreesToCallKind(member)) {
       if (_argumentsValid()) {
         final summary = typeFlowAnalysis.getSummary(member);
@@ -324,13 +324,12 @@
   }
 
   bool _argumentsValid() {
-    final function = selector.member.function;
-    assert(function != null);
-
+    final member = selector.member!;
+    final function = member.function!;
     final int positionalArguments = args.positionalCount;
 
-    final int firstParamIndex = numTypeParams(selector.member) +
-        (hasReceiverArg(selector.member) ? 1 : 0);
+    final int firstParamIndex =
+        numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
     final int requiredParameters =
         firstParamIndex + function.requiredParameterCount;
     if (positionalArguments < requiredParameters) {
@@ -359,9 +358,9 @@
 
 class _DispatchableInvocation extends _Invocation {
   bool _isPolymorphic = false;
-  Set<Call> _callSites; // Populated only if not polymorphic.
-  Member _monomorphicTarget;
-  _DirectInvocation _monomorphicDirectInvocation;
+  Set<Call>? _callSites; // Populated only if not polymorphic.
+  Member? _monomorphicTarget;
+  _DirectInvocation? _monomorphicDirectInvocation;
 
   @override
   set typeChecksNeeded(bool value) {
@@ -432,7 +431,8 @@
 
           if (!_isPolymorphic) {
             assert(target == _monomorphicTarget);
-            _monomorphicDirectInvocation = directInvocation;
+            _monomorphicDirectInvocation =
+                directInvocation as _DirectInvocation;
           }
 
           type = typeFlowAnalysis.workList.processInvocation(directInvocation);
@@ -484,13 +484,13 @@
 
     final bool isNullableReceiver = receiver is NullableType;
     if (isNullableReceiver) {
-      receiver = (receiver as NullableType).baseType;
+      receiver = receiver.baseType;
       assert(receiver is! NullableType);
     }
 
     if (selector is InterfaceSelector) {
       final staticReceiverType = new ConeType(typeFlowAnalysis.hierarchyCache
-          .getTFClass(selector.member.enclosingClass));
+          .getTFClass(selector.member!.enclosingClass!));
       receiver = receiver.intersection(
           staticReceiverType, typeFlowAnalysis.hierarchyCache);
       assert(receiver is! NullableType);
@@ -505,7 +505,7 @@
       // invocation to the receiver class. A new allocated class discovered
       // in the receiver cone will invalidate this invocation.
       receiver = typeFlowAnalysis.hierarchyCache
-          .specializeTypeCone((receiver as ConeType).cls, allowWideCone: false);
+          .specializeTypeCone(receiver.cls, allowWideCone: false);
     }
 
     assert(targets.isEmpty);
@@ -533,7 +533,7 @@
     Class nullClass =
         typeFlowAnalysis.environment.coreTypes.deprecatedNullClass;
 
-    Member target = typeFlowAnalysis.hierarchyCache.hierarchy
+    Member? target = typeFlowAnalysis.hierarchyCache.hierarchy
         .getDispatchTarget(nullClass, selector.name, setter: selector.isSetter);
 
     if (target != null) {
@@ -550,7 +550,7 @@
       TypeFlowAnalysis typeFlowAnalysis) {
     final TFClass cls = receiver.cls;
 
-    Member target =
+    Member? target =
         (cls as _TFClassImpl).getDispatchTarget(selector, typeFlowAnalysis);
 
     if (target != null) {
@@ -645,8 +645,9 @@
     if (_isPolymorphic) {
       callSite.setPolymorphic();
     } else {
-      if (_monomorphicTarget != null) {
-        callSite.addTarget(_monomorphicTarget);
+      final monomorphicTarget = _monomorphicTarget;
+      if (monomorphicTarget != null) {
+        callSite.addTarget(monomorphicTarget);
       }
     }
 
@@ -658,18 +659,20 @@
   /// Notify call sites monitoring this invocation about changes in
   /// polymorphism of this invocation.
   void _notifyCallSites() {
-    if (_callSites != null) {
-      _callSites.forEach(_notifyCallSite);
+    final callSites = _callSites;
+    if (callSites != null) {
+      callSites.forEach(_notifyCallSite);
     }
   }
 
   @override
-  Type get resultForRecursiveInvocation {
+  Type? get resultForRecursiveInvocation {
     if (result != null) {
       return result;
     }
-    if (_monomorphicDirectInvocation != null) {
-      return _monomorphicDirectInvocation.resultForRecursiveInvocation;
+    final monomorphicDirectInvocation = _monomorphicDirectInvocation;
+    if (monomorphicDirectInvocation != null) {
+      return monomorphicDirectInvocation.resultForRecursiveInvocation;
     }
     return null;
   }
@@ -681,30 +684,30 @@
 /// 1) Add 1..N concrete types ordered by classId OR add 1 arbitrary type.
 /// 2) Make type nullable.
 class _ReceiverTypeBuilder {
-  Type _type;
-  List<ConcreteType> _list;
+  Type? _type;
+  List<ConcreteType>? _list;
   bool _nullable = false;
 
   /// Appends a ConcreteType. May be called multiple times.
   /// Should not be used in conjunction with [addType].
   void addConcreteType(ConcreteType type) {
-    if (_list == null) {
-      if (_type == null) {
+    final list = _list;
+    if (list == null) {
+      final Type? t = _type;
+      if (t == null) {
         _type = type;
         return;
       }
+      final ct = t as ConcreteType;
 
-      assert(_type is ConcreteType);
-      assert(_type != type);
-
-      _list = <ConcreteType>[];
-      _list.add(_type);
-
+      assert(ct != type);
+      assert(ct.cls.id < type.cls.id);
+      _list = <ConcreteType>[ct, type];
       _type = null;
+    } else {
+      assert(list.last.cls.id < type.cls.id);
+      list.add(type);
     }
-
-    assert(_list.last.cls.id < type.cls.id);
-    _list.add(type);
   }
 
   /// Appends an arbitrary Type. May be called only once.
@@ -721,12 +724,13 @@
 
   /// Returns union of added types.
   Type toType() {
-    Type t = _type;
+    Type? t = _type;
     if (t == null) {
-      if (_list == null) {
+      final list = _list;
+      if (list == null) {
         t = const EmptyType();
       } else {
-        t = new SetType(_list);
+        t = SetType(list);
       }
     } else {
       assert(_list == null);
@@ -751,7 +755,7 @@
   static const int maxInvocationsPerSelector = 5000;
 
   int count = 0;
-  _Invocation approximation;
+  _Invocation? approximation;
 }
 
 /// Maintains ([Selector], [Args]) => [_Invocation] cache.
@@ -769,7 +773,7 @@
     _Invocation invocation = (selector is DirectSelector)
         ? new _DirectInvocation(selector, args)
         : new _DispatchableInvocation(selector, args);
-    _Invocation result = _invocations.lookup(invocation);
+    _Invocation? result = _invocations.lookup(invocation);
     if (result != null) {
       return result;
     }
@@ -782,14 +786,16 @@
       final sa = (_approximations[selector] ??= new _SelectorApproximation());
 
       if (sa.count >= _SelectorApproximation.maxInvocationsPerSelector) {
-        if (sa.approximation == null) {
+        _Invocation? approximation = sa.approximation;
+        if (approximation == null) {
           final rawArgs =
               _typeFlowAnalysis.summaryCollector.rawArguments(selector);
-          sa.approximation = new _DispatchableInvocation(selector, rawArgs);
+          sa.approximation =
+              approximation = _DispatchableInvocation(selector, rawArgs);
           Statistics.approximateInvocationsCreated++;
         }
         Statistics.approximateInvocationsUsed++;
-        return sa.approximation;
+        return approximation;
       }
 
       ++sa.count;
@@ -807,8 +813,8 @@
 class _FieldValue extends _DependencyTracker {
   final Field field;
   final Type staticType;
-  final Summary typeGuardSummary;
-  Type value;
+  final Summary? typeGuardSummary;
+  Type value = const EmptyType();
 
   /// Flag indicating if field initializer was executed.
   bool isInitialized = false;
@@ -823,8 +829,6 @@
       : staticType = typesBuilder.fromStaticType(field.type, true) {
     if (field.initializer == null && _isDefaultValueOfFieldObservable()) {
       value = new Type.nullable(const EmptyType());
-    } else {
-      value = const EmptyType();
     }
   }
 
@@ -837,8 +841,7 @@
       return true;
     }
 
-    final enclosingClass = field.enclosingClass;
-    assert(enclosingClass != null);
+    final enclosingClass = field.enclosingClass!;
 
     // Default value is not observable if every generative constructor
     // is redirecting or initializes the field.
@@ -854,10 +857,11 @@
     });
   }
 
-  void ensureInitialized(TypeFlowAnalysis typeFlowAnalysis, Type receiverType) {
+  void ensureInitialized(
+      TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) {
     if (field.initializer != null) {
       assert(field.isStatic == (receiverType == null));
-      final args = !field.isStatic ? <Type>[receiverType] : const <Type>[];
+      final args = !field.isStatic ? <Type>[receiverType!] : const <Type>[];
       final initializerInvocation = typeFlowAnalysis._invocationsCache
           .getInvocation(
               new DirectSelector(field, callKind: CallKind.FieldInitializer),
@@ -868,17 +872,18 @@
     }
   }
 
-  Type getValue(TypeFlowAnalysis typeFlowAnalysis, Type receiverType) {
+  Type getValue(TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) {
     ensureInitialized(typeFlowAnalysis, receiverType);
     addDependentInvocation(typeFlowAnalysis.currentInvocation);
+    final typeGuardSummary = this.typeGuardSummary;
     return (typeGuardSummary != null)
-        ? typeGuardSummary.apply(Args([receiverType, value]),
+        ? typeGuardSummary.apply(Args([receiverType!, value]),
             typeFlowAnalysis.hierarchyCache, typeFlowAnalysis)
         : value;
   }
 
   void setValue(
-      Type newValue, TypeFlowAnalysis typeFlowAnalysis, Type receiverType) {
+      Type newValue, TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) {
     // Make sure type cones are specialized before putting them into field
     // value, in order to ensure that dependency is established between
     // cone's base type and corresponding field setter.
@@ -905,10 +910,11 @@
     //
     final hierarchy = typeFlowAnalysis.hierarchyCache;
     // TODO(sjindel/tfa): Perform narrowing inside 'TypeCheck'.
+    final typeGuardSummary = this.typeGuardSummary;
     final narrowedNewValue = typeGuardSummary != null
         ? typeGuardSummary
-            .apply(
-                new Args([receiverType, newValue]), hierarchy, typeFlowAnalysis)
+            .apply(new Args([receiverType!, newValue]), hierarchy,
+                typeFlowAnalysis)
             .intersection(staticType, hierarchy)
         : newValue.specialize(hierarchy).intersection(staticType, hierarchy);
     Type newType =
@@ -950,28 +956,26 @@
   /// Flag indicating if this class has a noSuchMethod() method not inherited
   /// from Object.
   /// Lazy initialized by ClassHierarchyCache.hasNonTrivialNoSuchMethod().
-  bool hasNonTrivialNoSuchMethod;
+  bool? hasNonTrivialNoSuchMethod;
 
   _TFClassImpl(int id, Class classNode, this.supertypes)
       : super(id, classNode) {
     supertypes.add(this);
   }
 
-  ConcreteType _concreteType;
-  ConcreteType get concreteType =>
-      _concreteType ??= new ConcreteType(this, null);
+  late final ConcreteType concreteType = ConcreteType(this, null);
 
-  Type _specializedConeType;
+  Type? _specializedConeType;
   Type get specializedConeType =>
       _specializedConeType ??= _calculateConeTypeSpecialization();
 
   bool get hasWideCone =>
       _allocatedSubtypes.length > maxAllocatedTypesInSetSpecializations;
 
-  WideConeType _wideConeType;
+  late final WideConeType _wideConeType = WideConeType(this);
   WideConeType get wideConeType {
     assert(hasWideCone);
-    return _wideConeType ??= new WideConeType(this);
+    return _wideConeType;
   }
 
   Type _calculateConeTypeSpecialization() {
@@ -997,14 +1001,16 @@
     _specializedConeType = null; // Reset cached specialization.
   }
 
-  Member getDispatchTarget(
+  Member? getDispatchTarget(
       Selector selector, TypeFlowAnalysis typeFlowAnalysis) {
-    Member target = _dispatchTargets[selector];
+    Member? target = _dispatchTargets[selector];
     if (target == null) {
       target = typeFlowAnalysis.hierarchyCache.hierarchy.getDispatchTarget(
           classNode, selector.name,
           setter: selector.isSetter);
-      _dispatchTargets[selector] = target;
+      if (target != null) {
+        _dispatchTargets[selector] = target;
+      }
     }
     return target;
   }
@@ -1019,10 +1025,11 @@
   final cachedFlattenedTypeArgs = <Class, List<DartType>>{};
   final cachedFlattenedTypeArgsForNonGeneric = <Class, List<Type>>{};
 
-  RuntimeTypeTranslatorImpl closedTypeTranslator;
+  late final RuntimeTypeTranslatorImpl closedTypeTranslator;
 
-  GenericInterfacesInfoImpl(this.hierarchy) {
-    closedTypeTranslator = RuntimeTypeTranslatorImpl.forClosedTypes(this);
+  GenericInterfacesInfoImpl(CoreTypes coreTypes, this.hierarchy) {
+    closedTypeTranslator =
+        RuntimeTypeTranslatorImpl.forClosedTypes(coreTypes, this);
   }
 
   List<DartType> flattenedTypeArgumentsFor(Class klass, {bool useCache: true}) {
@@ -1047,7 +1054,7 @@
     if (klass == iface) return 0;
 
     final pair = new SubtypePair(klass, iface);
-    int offset = supertypeOffsetsCache[pair];
+    int? offset = supertypeOffsetsCache[pair];
 
     if (offset != null) return offset;
 
@@ -1062,16 +1069,16 @@
   }
 
   List<Type> flattenedTypeArgumentsForNonGeneric(Class klass) {
-    List<Type> result = cachedFlattenedTypeArgsForNonGeneric[klass];
+    List<Type>? result = cachedFlattenedTypeArgsForNonGeneric[klass];
     if (result != null) return result;
 
     List<DartType> flattenedTypeArgs =
         flattenedTypeArgumentsFor(klass, useCache: false);
-    result = new List<Type>.filled(flattenedTypeArgs.length, null);
-    for (int i = 0; i < flattenedTypeArgs.length; ++i) {
-      final translated = closedTypeTranslator.translate(flattenedTypeArgs[i]);
+    result = <Type>[];
+    for (DartType arg in flattenedTypeArgs) {
+      final translated = closedTypeTranslator.translate(arg);
       assert(translated is RuntimeType || translated is UnknownType);
-      result[i] = translated;
+      result.add(translated as Type);
     }
     cachedFlattenedTypeArgsForNonGeneric[klass] = result;
     return result;
@@ -1106,10 +1113,8 @@
   _ClassHierarchyCache(this._typeFlowAnalysis, this.hierarchy,
       this.genericInterfacesInfo, this.environment, bool nullSafety)
       : objectNoSuchMethod = hierarchy.getDispatchTarget(
-            environment.coreTypes.objectClass, noSuchMethodName),
-        super(environment.coreTypes, nullSafety) {
-    assert(objectNoSuchMethod != null);
-  }
+            environment.coreTypes.objectClass, noSuchMethodName)!,
+        super(environment.coreTypes, nullSafety);
 
   @override
   _TFClassImpl getTFClass(Class c) {
@@ -1196,10 +1201,13 @@
 
   bool hasNonTrivialNoSuchMethod(TFClass c) {
     final classImpl = c as _TFClassImpl;
-    classImpl.hasNonTrivialNoSuchMethod ??=
-        (hierarchy.getDispatchTarget(c.classNode, noSuchMethodName) !=
-            objectNoSuchMethod);
-    return classImpl.hasNonTrivialNoSuchMethod;
+    bool? value = classImpl.hasNonTrivialNoSuchMethod;
+    if (value == null) {
+      classImpl.hasNonTrivialNoSuchMethod = value =
+          (hierarchy.getDispatchTarget(c.classNode, noSuchMethodName) !=
+              objectNoSuchMethod);
+    }
+    return value;
   }
 
   _DynamicTargetSet getDynamicTargetSet(DynamicSelector selector) {
@@ -1292,10 +1300,11 @@
   }
 
   bool invalidateProtobufFields() {
-    if (_typeFlowAnalysis.protobufHandler == null) {
+    final protobufHandler = _typeFlowAnalysis.protobufHandler;
+    if (protobufHandler == null) {
       return false;
     }
-    final fields = _typeFlowAnalysis.protobufHandler.getInvalidatedFields();
+    final fields = protobufHandler.getInvalidatedFields();
     if (fields.isEmpty) {
       return false;
     }
@@ -1303,7 +1312,7 @@
     for (var field in fields) {
       assert(field.isStatic);
       // Reset summary in order to rebuild it.
-      _typeFlowAnalysis._summaries[field] = null;
+      _typeFlowAnalysis._summaries.remove(field);
       // Invalidate (and enqueue) field initializer invocation.
       final initializerInvocation = _typeFlowAnalysis._invocationsCache
           .getInvocation(
@@ -1326,10 +1335,11 @@
   }
 
   Type processInvocation(_Invocation invocation) {
-    if (invocation.result != null) {
+    Type? result = invocation.result;
+    if (result != null) {
       // Already processed.
       Statistics.usedCachedResultsOfInvocations++;
-      return invocation.result;
+      return result;
     }
 
     // Test if tracing is enabled to avoid expensive message formatting.
@@ -1372,18 +1382,18 @@
               -1);
         }
         processing.remove(invocation);
-        return invocation.invalidatedResult;
+        return invocation.invalidatedResult!;
       }
 
       callStack.add(invocation);
       pending.remove(invocation);
 
-      Type result = invocation.process(_typeFlowAnalysis);
+      result = invocation.process(_typeFlowAnalysis);
 
       invocation.setResult(_typeFlowAnalysis, result);
 
       // setResult may saturate result to ensure convergence.
-      result = invocation.result;
+      result = invocation.result!;
 
       // Invocation is still pending - it was invalidated while being processed.
       // Move result to invalidatedResult.
@@ -1432,12 +1442,12 @@
   final TypeEnvironment environment;
   final LibraryIndex libraryIndex;
   final PragmaAnnotationParser annotationMatcher;
-  final ProtobufHandler protobufHandler;
-  NativeCodeOracle nativeCodeOracle;
-  _ClassHierarchyCache hierarchyCache;
-  SummaryCollector summaryCollector;
-  _InvocationsCache _invocationsCache;
-  _WorkList workList;
+  final ProtobufHandler? protobufHandler;
+  late NativeCodeOracle nativeCodeOracle;
+  late _ClassHierarchyCache hierarchyCache;
+  late SummaryCollector summaryCollector;
+  late _InvocationsCache _invocationsCache;
+  late _WorkList workList;
   GenericInterfacesInfo _genericInterfacesInfo;
 
   final Map<Member, Summary> _summaries = <Member, Summary>{};
@@ -1457,7 +1467,7 @@
       this.environment,
       this.libraryIndex,
       this.protobufHandler,
-      PragmaAnnotationParser matcher)
+      PragmaAnnotationParser? matcher)
       : annotationMatcher =
             matcher ?? new ConstantPragmaAnnotationParser(coreTypes) {
     nativeCodeOracle = new NativeCodeOracle(libraryIndex, annotationMatcher);
@@ -1486,9 +1496,9 @@
   }
 
   _FieldValue getFieldValue(Field field) {
-    _FieldValue fieldValue = _fieldValues[field];
+    _FieldValue? fieldValue = _fieldValues[field];
     if (fieldValue == null) {
-      Summary typeGuardSummary = null;
+      Summary? typeGuardSummary = null;
       if (field.isGenericCovariantImpl) {
         typeGuardSummary = summaryCollector.createSummary(field,
             fieldSummaryType: FieldSummaryType.kFieldGuard);
@@ -1546,22 +1556,24 @@
 
   bool isClassAllocated(Class c) => hierarchyCache.allocatedClasses.contains(c);
 
-  Call callSite(TreeNode node) => summaryCollector.callSites[node];
+  Call? callSite(TreeNode node) => summaryCollector.callSites[node];
 
-  TypeCheck explicitCast(AsExpression cast) =>
+  TypeCheck? explicitCast(AsExpression cast) =>
       summaryCollector.explicitCasts[cast];
 
-  NarrowNotNull nullTest(TreeNode node) => summaryCollector.nullTests[node];
+  TypeCheck? isTest(IsExpression node) => summaryCollector.isTests[node];
 
-  Type fieldType(Field field) => _fieldValues[field]?.value;
+  NarrowNotNull? nullTest(TreeNode node) => summaryCollector.nullTests[node];
 
-  Args<Type> argumentTypes(Member member) => _summaries[member]?.argumentTypes;
+  Type? fieldType(Field field) => _fieldValues[field]?.value;
 
-  Type argumentType(Member member, VariableDeclaration memberParam) {
+  Args<Type>? argumentTypes(Member member) => _summaries[member]?.argumentTypes;
+
+  Type? argumentType(Member member, VariableDeclaration memberParam) {
     return _summaries[member]?.argumentType(member, memberParam);
   }
 
-  List<VariableDeclaration> uncheckedParameters(Member member) =>
+  List<VariableDeclaration>? uncheckedParameters(Member member) =>
       _summaries[member]?.uncheckedParameters;
 
   bool isTearOffTaken(Member member) => _tearOffTaken.contains(member);
@@ -1595,7 +1607,7 @@
   /// ---- Implementation of [CallHandler] interface. ----
 
   @override
-  Type applyCall(Call callSite, Selector selector, Args<Type> args,
+  Type applyCall(Call? callSite, Selector selector, Args<Type> args,
       {bool isResultUsed: true, bool processImmediately: true}) {
     _Invocation invocation = _invocationsCache.getInvocation(selector, args);
 
@@ -1625,7 +1637,7 @@
         workList.enqueueInvocation(invocation);
       }
 
-      return null;
+      return const EmptyType();
     }
   }
 
@@ -1676,7 +1688,7 @@
   }
 
   @override
-  void recordTearOff(Procedure target) {
+  void recordTearOff(Member target) {
     _tearOffTaken.add(target);
   }
 }
diff --git a/pkg/vm/lib/transformations/type_flow/calls.dart b/pkg/vm/lib/transformations/type_flow/calls.dart
index 6fa64e8..dd16279d 100644
--- a/pkg/vm/lib/transformations/type_flow/calls.dart
+++ b/pkg/vm/lib/transformations/type_flow/calls.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Declares classes which describe a call: selectors and arguments.
-library vm.transformations.type_flow.calls;
 
 import 'dart:core' hide Type;
 
@@ -28,10 +27,10 @@
   Selector(this.callKind);
 
   /// Interface or concrete target, may be null.
-  Member get member;
+  Member? get member;
 
   /// Selector name.
-  Name get name => member.name;
+  Name get name => member!.name;
 
   bool get isSetter => (callKind == CallKind.PropertySet);
 
@@ -44,6 +43,7 @@
 
   /// Static approximation of Dart return type.
   DartType get staticReturnType {
+    final member = this.member;
     if (member == null) {
       return const DynamicType();
     }
@@ -59,7 +59,6 @@
       case CallKind.SetFieldInConstructor:
         return const NeverType.nonNullable();
     }
-    return null;
   }
 
   bool memberAgreesToCallKind(Member member) {
@@ -77,7 +76,6 @@
       case CallKind.SetFieldInConstructor:
         return member is Field;
     }
-    return false;
   }
 
   String get _callKindPrefix {
@@ -92,7 +90,6 @@
       case CallKind.FieldInitializer:
         return 'init ';
     }
-    return '';
   }
 }
 
@@ -167,7 +164,7 @@
   DynamicSelector(CallKind callKind, this.name) : super(callKind);
 
   @override
-  Member get member => null;
+  Member? get member => null;
 
   @override
   int get hashCode => (super.hashCode ^ name.hashCode + 37) & kHashMask;
@@ -187,7 +184,8 @@
   final List<T> values;
   final List<String> names;
 
-  int _hashCode;
+  @override
+  late final int hashCode = _computeHashCode();
 
   Args(this.values, {this.names = const <String>[]}) {
     assert(isSorted(names));
@@ -204,9 +202,6 @@
 
   T get receiver => values[0];
 
-  @override
-  int get hashCode => _hashCode ??= _computeHashCode();
-
   int _computeHashCode() {
     int hash = 1231;
     for (var v in values) {
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index e24408b..0611379 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Handling of native code and entry points.
-library vm.transformations.type_flow.native_code;
 
 import 'dart:core' hide Type;
 
@@ -33,24 +32,21 @@
   /// Record the fact that given member is called from this.
   void recordMemberCalledViaThis(Member target);
 
-  /// Record the fact that given method is torn off.
-  void recordTearOff(Procedure target) {}
+  /// Record the fact that given member is torn off.
+  void recordTearOff(Member target) {}
 }
 
 class PragmaEntryPointsVisitor extends RecursiveVisitor {
   final EntryPointsListener entryPoints;
   final NativeCodeOracle nativeCodeOracle;
   final PragmaAnnotationParser matcher;
-  Class currentClass = null;
 
   PragmaEntryPointsVisitor(
-      this.entryPoints, this.nativeCodeOracle, this.matcher) {
-    assert(matcher != null);
-  }
+      this.entryPoints, this.nativeCodeOracle, this.matcher);
 
-  PragmaEntryPointType _annotationsDefineRoot(List<Expression> annotations) {
+  PragmaEntryPointType? _annotationsDefineRoot(List<Expression> annotations) {
     for (var annotation in annotations) {
-      ParsedPragma pragma = matcher.parsePragma(annotation);
+      ParsedPragma? pragma = matcher.parsePragma(annotation);
       if (pragma == null) continue;
       if (pragma is ParsedEntryPointPragma) return pragma.type;
     }
@@ -70,7 +66,6 @@
       }
       nativeCodeOracle.addClassReferencedFromNativeCode(klass);
     }
-    currentClass = klass;
     klass.visitChildren(this);
   }
 
@@ -79,15 +74,14 @@
     var type = _annotationsDefineRoot(proc.annotations);
     if (type == null) return;
 
-    if (proc.isRedirectingFactoryConstructor) {
+    if (proc.isRedirectingFactory) {
       if (type != PragmaEntryPointType.CallOnly &&
           type != PragmaEntryPointType.Default) {
         throw "Error: factory $proc doesn't have a setter or getter";
       }
       Member target = proc;
-      while (target is Procedure && target.isRedirectingFactoryConstructor) {
-        target = getRedirectingFactoryBody(target).target;
-        assert(target != null);
+      while (target is Procedure && target.isRedirectingFactory) {
+        target = getRedirectingFactoryBody(target)!.target!;
         assert(
             (target is Procedure && target.isFactory) || target is Constructor);
       }
@@ -150,7 +144,7 @@
       }
       entryPoints
           .addRawCall(new DirectSelector(ctor, callKind: CallKind.Method));
-      entryPoints.addAllocatedClass(currentClass);
+      entryPoints.addAllocatedClass(ctor.enclosingClass);
       nativeCodeOracle.setMemberReferencedFromNativeCode(ctor);
     }
   }
@@ -199,9 +193,7 @@
   final Set<Class> _classesReferencedFromNativeCode = new Set<Class>();
   final PragmaAnnotationParser _matcher;
 
-  NativeCodeOracle(this._libraryIndex, this._matcher) {
-    assert(_matcher != null);
-  }
+  NativeCodeOracle(this._libraryIndex, this._matcher);
 
   void addClassReferencedFromNativeCode(Class klass) {
     _classesReferencedFromNativeCode.add(klass);
@@ -217,9 +209,9 @@
   bool isMemberReferencedFromNativeCode(Member member) =>
       _membersReferencedFromNativeCode.contains(member);
 
-  PragmaRecognizedType recognizedType(Member member) {
+  PragmaRecognizedType? recognizedType(Member member) {
     for (var annotation in member.annotations) {
-      ParsedPragma pragma = _matcher.parsePragma(annotation);
+      ParsedPragma? pragma = _matcher.parsePragma(annotation);
       if (pragma is ParsedRecognized) {
         return pragma.type;
       }
@@ -227,15 +219,16 @@
     return null;
   }
 
-  bool isRecognized(Member member, [List<PragmaRecognizedType> expectedTypes]) {
-    PragmaRecognizedType type = recognizedType(member);
+  bool isRecognized(Member member,
+      [List<PragmaRecognizedType>? expectedTypes]) {
+    PragmaRecognizedType? type = recognizedType(member);
     return type != null &&
         (expectedTypes == null || expectedTypes.contains(type));
   }
 
   bool hasDisableUnboxedParameters(Member member) {
     for (var annotation in member.annotations) {
-      ParsedPragma pragma = _matcher.parsePragma(annotation);
+      ParsedPragma? pragma = _matcher.parsePragma(annotation);
       if (pragma is ParsedDisableUnboxedParameters) {
         if (member.enclosingLibrary.importUri.scheme != "dart") {
           throw "ERROR: Cannot use @pragma(vm:disable-unboxed-parameters) outside core libraries.";
@@ -253,11 +246,11 @@
       EntryPointsListener entryPointsListener,
       TypesBuilder typesBuilder,
       RuntimeTypeTranslator translator) {
-    TypeExpr returnType = null;
-    bool nullable = null;
+    TypeExpr? returnType = null;
+    bool? nullable = null;
 
     for (var annotation in member.annotations) {
-      ParsedPragma pragma = _matcher.parsePragma(annotation);
+      ParsedPragma? pragma = _matcher.parsePragma(annotation);
       if (pragma == null) continue;
       if (pragma is ParsedResultTypeByTypePragma ||
           pragma is ParsedResultTypeByPathPragma ||
@@ -276,8 +269,8 @@
           returnType = entryPointsListener.addAllocatedClass(type.classNode);
           if (pragma.resultTypeUsesPassedTypeArguments) {
             returnType = translator.instantiateConcreteType(
-                returnType,
-                member.function.typeParameters
+                returnType as ConcreteType,
+                member.function!.typeParameters
                     .map((t) => TypeParameterType(
                         t, TypeParameterType.computeNullabilityFromBound(t)))
                     .toList());
@@ -312,7 +305,7 @@
       return returnType;
     } else {
       return typesBuilder.fromStaticType(
-          member.function.returnType, nullable ?? true);
+          member.function!.returnType, nullable ?? true);
     }
   }
 }
diff --git a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart b/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
index 5bd8db7..c0175a4 100644
--- a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
+++ b/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
@@ -45,14 +45,14 @@
   final Procedure _builderInfoAddMethod;
 
   // Type of BuilderInfo.add<Null>().
-  FunctionType _typeOfBuilderInfoAddOfNull;
+  late FunctionType _typeOfBuilderInfoAddOfNull;
 
   final _messageClasses = <Class, _MessageClass>{};
   final _invalidatedClasses = <_MessageClass>{};
 
   /// Creates [ProtobufHandler] instance for [component].
   /// Returns null if protobuf library is not used.
-  static ProtobufHandler forComponent(
+  static ProtobufHandler? forComponent(
       Component component, CoreTypes coreTypes) {
     final libraryIndex = LibraryIndex(component, [protobufLibraryUri]);
     if (!libraryIndex.containsLibrary(protobufLibraryUri)) {
@@ -66,12 +66,12 @@
             libraryIndex.getClass(protobufLibraryUri, 'GeneratedMessage'),
         _tagNumberClass =
             libraryIndex.getClass(protobufLibraryUri, 'TagNumber'),
-        _tagNumberField = libraryIndex.getMember(
-            protobufLibraryUri, 'TagNumber', 'tagNumber'),
+        _tagNumberField =
+            libraryIndex.getField(protobufLibraryUri, 'TagNumber', 'tagNumber'),
         _builderInfoClass =
             libraryIndex.getClass(protobufLibraryUri, 'BuilderInfo'),
-        _builderInfoAddMethod =
-            libraryIndex.getMember(protobufLibraryUri, 'BuilderInfo', 'add') {
+        _builderInfoAddMethod = libraryIndex.getProcedure(
+            protobufLibraryUri, 'BuilderInfo', 'add') {
     final functionType = _builderInfoAddMethod.getterType as FunctionType;
     _typeOfBuilderInfoAddOfNull = Substitution.fromPairs(
             functionType.typeParameters, const <DartType>[NullType()])
@@ -128,8 +128,9 @@
   List<Field> getInvalidatedFields() {
     final fields = <Field>[];
     for (var cls in _invalidatedClasses) {
-      if (cls._metadataField != null) {
-        fields.add(cls._metadataField);
+      final field = cls._metadataField;
+      if (field != null) {
+        fields.add(field);
       }
     }
     _invalidatedClasses.clear();
@@ -141,14 +142,15 @@
     ++Statistics.protobufMetadataInitializersUpdated;
     Statistics.protobufMetadataFieldsPruned -= cls.numberOfFieldsPruned;
 
-    final field = cls._metadataField;
-    if (cls._originalInitializer == null) {
-      cls._originalInitializer = field.initializer;
+    final field = cls._metadataField!;
+    Expression? originalInitializer = cls._originalInitializer;
+    if (originalInitializer == null) {
+      cls._originalInitializer = originalInitializer = field.initializer!;
     }
     final cloner = CloneVisitorNotMembers();
-    field.initializer = cloner.clone(cls._originalInitializer)..parent = field;
+    field.initializer = cloner.clone(originalInitializer)..parent = field;
     final transformer = _MetadataTransformer(this, cls);
-    field.initializer.accept(transformer);
+    field.initializer!.accept(transformer);
     _invalidatedClasses.remove(cls);
 
     cls.numberOfFieldsPruned = transformer.numberOfFieldsPruned;
@@ -166,8 +168,8 @@
 }
 
 class _MessageClass {
-  Field _metadataField;
-  Expression _originalInitializer;
+  Field? _metadataField;
+  Expression? _originalInitializer;
   final _usedTags = <int>{};
   int numberOfFieldsPruned = 0;
 }
diff --git a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
index 2d16a7b..5ae2e16 100644
--- a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
+++ b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
@@ -55,7 +55,7 @@
 
   SignatureShaker(this.typeFlowAnalysis, this.tableSelectorAssigner);
 
-  _ProcedureInfo _infoForMember(Member member) {
+  _ProcedureInfo? _infoForMember(Member member) {
     if (!(member is Procedure &&
             (member.kind == ProcedureKind.Method ||
                 member.kind == ProcedureKind.Factory) ||
@@ -87,7 +87,7 @@
     }
     while (worklist.isNotEmpty) {
       _ParameterInfo param = worklist.removeLast();
-      for (_ParameterInfo dependencyParam in param.useDependencies) {
+      for (_ParameterInfo dependencyParam in param.useDependencies!) {
         if (!dependencyParam.isRead) {
           dependencyParam.isRead = true;
           if (dependencyParam.useDependencies != null) {
@@ -139,7 +139,7 @@
     return positional.any((param) =>
             param.canBeEliminated ||
             (param.isAlwaysPassed &&
-                param.index >= function.requiredParameterCount)) ||
+                param.index! >= function.requiredParameterCount)) ||
         named.values
             .any((param) => param.canBeEliminated || param.isAlwaysPassed);
   }
@@ -147,7 +147,7 @@
 
 class _ParameterInfo {
   final _ProcedureInfo info;
-  final int index;
+  final int? index;
 
   int passCount = 0;
   bool isRead = false;
@@ -158,7 +158,7 @@
   /// List of parameter variables which were passed as arguments via this
   /// parameter. When this parameter is considered used, all [useDependencies]
   /// parameters should be transitively marked as read.
-  List<_ParameterInfo> useDependencies = null;
+  List<_ParameterInfo>? useDependencies = null;
 
   _ParameterInfo(this.info, this.index);
 
@@ -175,7 +175,7 @@
 
   void observeParameter(
       Member member, VariableDeclaration param, SignatureShaker shaker) {
-    final Type type = shaker.typeFlowAnalysis.argumentType(member, param);
+    final Type? type = shaker.typeFlowAnalysis.argumentType(member, param);
 
     // A parameter is considered constant if the TFA has inferred it to have a
     // constant value in every implementation. The constant value inferred does
@@ -212,19 +212,19 @@
   _Collect(this.shaker);
 
   void enterFunction(Member member) {
-    final _ProcedureInfo info = shaker._infoForMember(member);
+    final _ProcedureInfo? info = shaker._infoForMember(member);
     if (info == null) return;
 
     localParameters.clear();
     useDependencies.clear();
-    final FunctionNode fun = member.function;
+    final FunctionNode fun = member.function!;
     for (int i = 0; i < fun.positionalParameters.length; i++) {
       final VariableDeclaration param = fun.positionalParameters[i];
       localParameters[param] = info.ensurePositional(i)
         ..observeParameter(member, param, shaker);
     }
     for (VariableDeclaration param in fun.namedParameters) {
-      localParameters[param] = info.ensureNamed(param.name)
+      localParameters[param] = info.ensureNamed(param.name!)
         ..observeParameter(member, param, shaker);
     }
 
@@ -268,19 +268,22 @@
 
   void addUseDependency(Expression arg, _ParameterInfo param) {
     if (arg is VariableGet) {
-      _ParameterInfo localParam = localParameters[arg.variable];
+      _ParameterInfo? localParam = localParameters[arg.variable];
       if (localParam != null && !localParam.isUsed) {
         // This is a parameter passed as an argument. Mark it as a use
         // dependency.
-        param.useDependencies ??= [];
-        param.useDependencies.add(localParam);
+        var paramUseDependencies = param.useDependencies;
+        if (paramUseDependencies == null) {
+          param.useDependencies = paramUseDependencies = [];
+        }
+        paramUseDependencies.add(localParam);
         useDependencies.add(arg);
       }
     }
   }
 
   void collectCall(Member member, Arguments args) {
-    final _ProcedureInfo info = shaker._infoForMember(member);
+    final _ProcedureInfo? info = shaker._infoForMember(member);
     if (info == null) return;
 
     for (int i = 0; i < args.positional.length; i++) {
@@ -304,7 +307,10 @@
 
   @override
   void visitSuperMethodInvocation(SuperMethodInvocation node) {
-    collectCall(node.interfaceTarget, node.arguments);
+    final interfaceTarget = node.interfaceTarget;
+    if (interfaceTarget != null) {
+      collectCall(interfaceTarget, node.arguments);
+    }
     super.visitSuperMethodInvocation(node);
   }
 
@@ -336,7 +342,7 @@
 class _Transform extends RecursiveVisitor {
   final SignatureShaker shaker;
 
-  StaticTypeContext typeContext;
+  late StaticTypeContext typeContext;
   final Map<VariableDeclaration, Constant> eliminatedParams = {};
   final Set<VariableDeclaration> unusedParams = {};
   final List<LocalInitializer> addedInitializers = [];
@@ -347,16 +353,15 @@
       Member member, _ParameterInfo param, VariableDeclaration variable) {
     Constant value;
     if (param.isConstant) {
-      Type type = shaker.typeFlowAnalysis.argumentType(member, variable);
+      Type type = shaker.typeFlowAnalysis.argumentType(member, variable)!;
       if (type is ConcreteType) {
-        assert(type.constant != null);
-        value = type.constant;
+        value = type.constant!;
       } else {
         assert(type is NullableType && type.baseType is EmptyType);
         value = NullConstant();
       }
     } else {
-      value = (variable.initializer as ConstantExpression)?.constant ??
+      value = (variable.initializer as ConstantExpression?)?.constant ??
           NullConstant();
     }
     eliminatedParams[variable] = value;
@@ -368,10 +373,10 @@
     eliminatedParams.clear();
     unusedParams.clear();
 
-    final _ProcedureInfo info = shaker._infoForMember(member);
+    final _ProcedureInfo? info = shaker._infoForMember(member);
     if (info == null || !info.eligible || info.callCount == 0) return;
 
-    final FunctionNode function = member.function;
+    final FunctionNode function = member.function!;
 
     if (!info.transformNeeded(function)) return;
 
@@ -402,9 +407,9 @@
     //    as required positional parameters, alphabetically by name.
     final List<VariableDeclaration> sortedNamed = function.namedParameters
         .toList()
-          ..sort((var1, var2) => var1.name.compareTo(var2.name));
+      ..sort((var1, var2) => var1.name!.compareTo(var2.name!));
     for (VariableDeclaration variable in sortedNamed) {
-      final _ParameterInfo param = info.named[variable.name];
+      final _ParameterInfo param = info.named[variable.name!]!;
       if (param.isAlwaysPassed) {
         if (param.isUsed) {
           if (param.canBeEliminated) {
@@ -449,7 +454,7 @@
     // 4. All named parameters that are not always passed and can't be
     //    eliminated, as named parameters in alphabetical order.
     for (VariableDeclaration variable in sortedNamed) {
-      final _ParameterInfo param = info.named[variable.name];
+      final _ParameterInfo param = info.named[variable.name!]!;
       if (!param.isAlwaysPassed) {
         if (param.isUsed) {
           if (param.canBeEliminated) {
@@ -473,7 +478,7 @@
 
   @override
   void visitVariableGet(VariableGet node) {
-    Constant constantValue = eliminatedParams[node.variable];
+    Constant? constantValue = eliminatedParams[node.variable];
     if (constantValue != null) {
       node.replaceWith(ConstantExpression(constantValue));
     }
@@ -509,7 +514,7 @@
       void Function(Expression, _ParameterInfo) fun) {
     for (int i = args.named.length - 1; i >= 0; i--) {
       final NamedExpression namedExp = args.named[i];
-      fun(namedExp.value, info.named[namedExp.name]);
+      fun(namedExp.value, info.named[namedExp.name]!);
     }
     for (int i = args.positional.length - 1; i >= 0; i--) {
       fun(args.positional[i], info.positional[i]);
@@ -517,8 +522,8 @@
   }
 
   void transformCall(
-      Member target, TreeNode call, Expression receiver, Arguments args) {
-    final _ProcedureInfo info = shaker._infoForMember(target);
+      Member target, TreeNode call, Expression? receiver, Arguments args) {
+    final _ProcedureInfo? info = shaker._infoForMember(target);
     if (info == null || !info.eligible) return;
 
     bool transformNeeded = false;
@@ -542,7 +547,7 @@
     Map<Expression, VariableDeclaration> hoisted = {};
     if (hoistingNeeded) {
       if (call is Initializer) {
-        final Constructor constructor = call.parent;
+        final Constructor constructor = call.parent as Constructor;
         forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) {
           if (mayHaveOrSeeSideEffects(arg) && !isUnusedParam(arg)) {
             VariableDeclaration argVar = VariableDeclaration(null,
@@ -555,8 +560,8 @@
           }
         });
       } else {
-        final TreeNode parent = call.parent;
-        Expression current = call;
+        final TreeNode parent = call.parent!;
+        Expression current = call as Expression;
         forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) {
           if (mayHaveOrSeeSideEffects(arg) && !isUnusedParam(arg)) {
             VariableDeclaration argVar = VariableDeclaration(null,
@@ -604,7 +609,7 @@
     final List<NamedExpression> sortedNamed = args.named.toList()
       ..sort((var1, var2) => var1.name.compareTo(var2.name));
     for (NamedExpression arg in sortedNamed) {
-      final _ParameterInfo param = info.named[arg.name];
+      final _ParameterInfo param = info.named[arg.name]!;
       if (param.isAlwaysPassed && !param.canBeEliminated) {
         positional.add(getMaybeHoistedArg(arg.value));
       }
@@ -623,7 +628,7 @@
     //    eliminated, as named parameters in alphabetical order.
     //    (Arguments are kept in original order.)
     for (NamedExpression arg in args.named) {
-      final _ParameterInfo param = info.named[arg.name];
+      final _ParameterInfo param = info.named[arg.name]!;
       if (!param.isAlwaysPassed && !param.canBeEliminated) {
         arg.value = getMaybeHoistedArg(arg.value)..parent = arg;
         named.add(arg);
@@ -642,7 +647,10 @@
   @override
   void visitSuperMethodInvocation(SuperMethodInvocation node) {
     super.visitSuperMethodInvocation(node);
-    transformCall(node.interfaceTarget, node, null, node.arguments);
+    final interfaceTarget = node.interfaceTarget;
+    if (interfaceTarget != null) {
+      transformCall(interfaceTarget, node, null, node.arguments);
+    }
   }
 
   @override
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index b8033f9..fb18cec 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Type flow summary of a member, function or initializer.
-library vm.transformations.type_flow.summary;
 
 import 'dart:core' hide Type;
 
@@ -16,22 +15,19 @@
 
 abstract class CallHandler {
   Type applyCall(Call callSite, Selector selector, Args<Type> args,
-      {bool isResultUsed});
+      {required bool isResultUsed});
   void typeCheckTriggered();
+  void addAllocatedClass(Class c);
 }
 
 /// Base class for all statements in a summary.
 abstract class Statement extends TypeExpr {
   /// Index of this statement in the [Summary].
   int index = -1;
-  Summary summary;
+  late Summary summary;
 
   @override
-  Type getComputedType(List<Type> types) {
-    final type = types[index];
-    assert(type != null);
-    return type;
-  }
+  Type getComputedType(List<Type?> types) => types[index]!;
 
   String get label => "t$index";
 
@@ -45,7 +41,7 @@
   void accept(StatementVisitor visitor);
 
   /// Execute this statement and compute its resulting type.
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler);
 }
 
@@ -71,9 +67,9 @@
   // [staticType] is null if no narrowing should be performed. This happens for
   // type parameters and for parameters whose type is narrowed by a [TypeCheck]
   // statement.
-  final Type staticTypeForNarrowing;
+  final Type? staticTypeForNarrowing;
 
-  Type defaultValue;
+  Type? defaultValue;
   Type _argumentType = const EmptyType();
 
   Parameter(this.name, this.staticTypeForNarrowing);
@@ -94,7 +90,7 @@
   }
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
           CallHandler callHandler) =>
       throw 'Unable to apply _Parameter';
 
@@ -107,7 +103,7 @@
   }
 
   Type _observeNotPassed(TypeHierarchy typeHierarchy) {
-    final Type argType = defaultValue.specialize(typeHierarchy);
+    final Type argType = defaultValue!.specialize(typeHierarchy);
     _observeArgumentType(argType, typeHierarchy);
     return argType;
   }
@@ -127,7 +123,7 @@
   String dump() => "$label = _Narrow ($arg to $type)";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
           CallHandler callHandler) =>
       arg.getComputedType(computedTypes).intersection(type, typeHierarchy);
 }
@@ -144,11 +140,11 @@
 
   // Shared NarrowNotNull instances which are used when the outcome is
   // known at summary creation time.
-  static final NarrowNotNull alwaysNotNull = NarrowNotNull(null)
+  static final NarrowNotNull alwaysNotNull = NarrowNotNull(const EmptyType())
     .._flags = canBeNotNullFlag;
-  static final NarrowNotNull alwaysNull = NarrowNotNull(null)
+  static final NarrowNotNull alwaysNull = NarrowNotNull(const EmptyType())
     .._flags = canBeNullFlag;
-  static final NarrowNotNull unknown = NarrowNotNull(null)
+  static final NarrowNotNull unknown = NarrowNotNull(const EmptyType())
     .._flags = canBeNullFlag | canBeNotNullFlag;
 
   bool get isAlwaysNull => (_flags & canBeNotNullFlag) == 0;
@@ -170,14 +166,14 @@
   }
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
           CallHandler callHandler) =>
       handleArgument(arg.getComputedType(computedTypes));
 }
 
 /// Joins values from multiple sources. Its type is a union of [values].
 class Join extends Statement {
-  final String _name;
+  final String? _name;
   final DartType staticType;
   final List<TypeExpr> values = <TypeExpr>[]; // TODO(alexmarkov): Set
 
@@ -194,15 +190,14 @@
       " (${values.join(", ")})";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
-    Type type = null;
-    assert(values.isNotEmpty);
+    Type? type = null;
     for (var value in values) {
       final valueType = value.getComputedType(computedTypes);
       type = type != null ? type.union(valueType, typeHierarchy) : valueType;
     }
-    return type;
+    return type!;
   }
 }
 
@@ -219,7 +214,7 @@
   String dump() => "$label = _Use ($arg)";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
           CallHandler callHandler) =>
       throw 'Use statements should be removed during summary normalization';
 }
@@ -228,14 +223,18 @@
 class Call extends Statement {
   final Selector selector;
   final Args<TypeExpr> args;
-  final Type staticResultType;
+  final Type? staticResultType;
 
-  Call(this.selector, this.args, this.staticResultType) {
+  Call(this.selector, this.args, this.staticResultType,
+      bool isInstanceCreation) {
     // TODO(sjindel/tfa): Support inferring unchecked entry-points for dynamic
     // and direct calls as well.
     if (selector is DynamicSelector || selector is DirectSelector) {
       setUseCheckedEntry();
     }
+    if (isInstanceCreation) {
+      setInstanceCreation();
+    }
   }
 
   @override
@@ -245,9 +244,10 @@
   String dump() => "$label${isResultUsed ? '*' : ''} = _Call $selector $args";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
-    final List<Type> argTypes = new List<Type>.filled(args.values.length, null);
+    final List<Type> argTypes =
+        new List<Type>.filled(args.values.length, const EmptyType());
     for (int i = 0; i < args.values.length; i++) {
       final Type type = args.values[i].getComputedType(computedTypes);
       if (type == const EmptyType()) {
@@ -260,12 +260,19 @@
     if (selector is! DirectSelector) {
       _observeReceiverType(argTypes[0], typeHierarchy);
     }
-    final Stopwatch timer = kPrintTimings ? (new Stopwatch()..start()) : null;
+    if (isInstanceCreation) {
+      callHandler
+          .addAllocatedClass((argTypes[0] as ConcreteType).cls.classNode);
+    }
+    final Stopwatch? timer = kPrintTimings ? (new Stopwatch()..start()) : null;
     Type result = callHandler.applyCall(
         this, selector, new Args<Type>(argTypes, names: args.names),
         isResultUsed: isResultUsed);
-    summary.calleeTime += kPrintTimings ? timer.elapsedMicroseconds : 0;
-    if (isResultUsed) {
+    summary.calleeTime += kPrintTimings ? timer!.elapsedMicroseconds : 0;
+    if (isInstanceCreation) {
+      result = argTypes[0];
+    } else if (isResultUsed) {
+      final staticResultType = this.staticResultType;
       if (staticResultType != null) {
         result = result.intersection(staticResultType, typeHierarchy);
       }
@@ -287,10 +294,11 @@
   static const int kReachable = (1 << 4);
   static const int kUseCheckedEntry = (1 << 5);
   static const int kReceiverMayBeInt = (1 << 6);
+  static const int kInstanceCreation = (1 << 7);
 
-  Member _monomorphicTarget;
+  Member? _monomorphicTarget;
 
-  Member get monomorphicTarget => _monomorphicTarget;
+  Member? get monomorphicTarget => _monomorphicTarget;
 
   bool get isMonomorphic => (_flags & kMonomorphic) != 0;
 
@@ -306,6 +314,8 @@
 
   bool get useCheckedEntry => (_flags & kUseCheckedEntry) != 0;
 
+  bool get isInstanceCreation => (_flags & kInstanceCreation) != 0;
+
   Type get resultType => _resultType;
 
   void setUseCheckedEntry() {
@@ -320,6 +330,10 @@
     _flags |= kReachable;
   }
 
+  void setInstanceCreation() {
+    _flags |= kInstanceCreation;
+  }
+
   void setPolymorphic() {
     _flags = (_flags & ~kMonomorphic) | kPolymorphic;
     _monomorphicTarget = null;
@@ -376,18 +390,19 @@
       "/$paramIndex]${nullability.suffix})";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
     Type argType = arg.getComputedType(computedTypes);
-    Type extractedType;
+    Type? extractedType;
 
     void extractType(ConcreteType c) {
-      if (c.typeArgs == null) {
+      final typeArgs = c.typeArgs;
+      if (typeArgs == null) {
         extractedType = const UnknownType();
       } else {
         final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor(
             c.cls.classNode, referenceClass);
-        final typeArg = c.typeArgs[interfaceOffset + paramIndex];
+        final typeArg = typeArgs[interfaceOffset + paramIndex];
         Type extracted = typeArg;
         if (typeArg is RuntimeType) {
           final argNullability = typeArg.nullability;
@@ -452,16 +467,15 @@
   }
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
     bool hasRuntimeType = false;
-    final types = new List<Type>.filled(flattenedTypeArgs.length, null);
-    for (int i = 0; i < types.length; ++i) {
+    final types = List<Type>.generate(flattenedTypeArgs.length, (int i) {
       final computed = flattenedTypeArgs[i].getComputedType(computedTypes);
       assert(computed is RuntimeType || computed is UnknownType);
       if (computed is RuntimeType) hasRuntimeType = true;
-      types[i] = computed;
-    }
+      return computed;
+    });
     return new ConcreteType(cls, hasRuntimeType ? types : null);
   }
 }
@@ -485,14 +499,13 @@
       "${nullability.suffix})";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
-    final types = new List<RuntimeType>.filled(flattenedTypeArgs.length, null);
-    for (int i = 0; i < types.length; ++i) {
-      final computed = flattenedTypeArgs[i].getComputedType(computedTypes);
-      assert(computed is RuntimeType || computed is UnknownType);
+    final types = <RuntimeType>[];
+    for (TypeExpr arg in flattenedTypeArgs) {
+      final computed = arg.getComputedType(computedTypes);
       if (computed is UnknownType) return const UnknownType();
-      types[i] = computed;
+      types.add(computed as RuntimeType);
     }
     DartType dartType;
     if (klass == typeHierarchy.coreTypes.deprecatedFutureOrClass) {
@@ -518,22 +531,22 @@
   final TreeNode node;
 
   final Type staticType;
+  final SubtypeTestKind kind;
 
   // 'isTestedOnlyOnCheckedEntryPoint' is whether or not this parameter's type-check will
   // occur on the "checked" entrypoint in the VM but will be skipped on
   // "unchecked" entrypoint.
   bool isTestedOnlyOnCheckedEntryPoint;
 
-  VariableDeclaration get parameter =>
-      node is VariableDeclaration ? node : null;
+  bool get isParameterCheck => node is VariableDeclaration;
+  VariableDeclaration get parameterVariable => node as VariableDeclaration;
 
-  bool canAlwaysSkip = true;
+  bool alwaysPass = true;
+  bool alwaysFail = true;
 
-  TypeCheck(this.arg, this.type, this.node, this.staticType) {
-    assert(node != null);
-    isTestedOnlyOnCheckedEntryPoint =
-        parameter != null && !parameter.isCovariant;
-  }
+  TypeCheck(this.arg, this.type, this.node, this.staticType, this.kind)
+      : isTestedOnlyOnCheckedEntryPoint =
+            node is VariableDeclaration && !node.isCovariant;
 
   @override
   void accept(StatementVisitor visitor) => visitor.visitTypeCheck(this);
@@ -546,21 +559,21 @@
   }
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
     Type argType = arg.getComputedType(computedTypes);
     Type checkType = type.getComputedType(computedTypes);
     // TODO(sjindel/tfa): Narrow the result if possible.
     assert(checkType is UnknownType || checkType is RuntimeType);
 
-    bool canSkip = true; // Can this check be skipped on this invocation.
+    bool pass = true; // Can this check be skipped on this invocation.
 
     if (checkType is UnknownType) {
       // If we don't know what the RHS of the check is going to be, we can't
       // guarantee that it will pass.
-      canSkip = false;
+      pass = false;
     } else if (checkType is RuntimeType) {
-      canSkip = argType.isSubtypeOfRuntimeType(typeHierarchy, checkType);
+      pass = argType.isSubtypeOfRuntimeType(typeHierarchy, checkType, kind);
       argType = argType.intersection(
           typeHierarchy.fromStaticType(checkType.representedTypeRaw, true),
           typeHierarchy);
@@ -571,8 +584,8 @@
     // If this check might be skipped on an
     // unchecked entry-point, we need to signal that the call-site must be
     // checked.
-    if (!canSkip) {
-      canAlwaysSkip = false;
+    if (!pass) {
+      alwaysPass = false;
       if (isTestedOnlyOnCheckedEntryPoint) {
         callHandler.typeCheckTriggered();
       }
@@ -581,7 +594,13 @@
       }
     }
 
-    argType = argType.intersection(staticType, typeHierarchy);
+    argType = argType
+        .intersection(staticType, typeHierarchy)
+        .specialize(typeHierarchy);
+
+    if (argType is! EmptyType) {
+      alwaysFail = false;
+    }
 
     return argType;
   }
@@ -596,11 +615,11 @@
   int requiredParameterCount;
 
   List<Statement> _statements = <Statement>[];
-  TypeExpr result = null;
-  Type resultType = EmptyType();
+  TypeExpr result = const EmptyType();
+  Type resultType = const EmptyType();
 
   // Analysis time of callees. Populated only if kPrintTimings.
-  int calleeTime;
+  int calleeTime = 0;
 
   Summary(this.name,
       {this.parameterCount: 0,
@@ -630,7 +649,7 @@
   /// Apply this summary to the given arguments and return the resulting type.
   Type apply(Args<Type> arguments, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
-    final Stopwatch timer = kPrintTimings ? (new Stopwatch()..start()) : null;
+    final Stopwatch? timer = kPrintTimings ? (new Stopwatch()..start()) : null;
     final int oldCalleeTime = calleeTime;
     calleeTime = 0;
     final args = arguments.values;
@@ -649,7 +668,7 @@
     //
     // The first `parameterCount` statements are Parameters.
 
-    List<Type> types = new List<Type>.filled(_statements.length, null);
+    List<Type?> types = new List<Type?>.filled(_statements.length, null);
 
     for (int i = 0; i < positionalArgCount; i++) {
       final Parameter param = _statements[i] as Parameter;
@@ -659,9 +678,9 @@
       }
       final argType = args[i].specialize(typeHierarchy);
       param._observeArgumentType(argType, typeHierarchy);
-      if (param.staticTypeForNarrowing != null) {
-        types[i] =
-            argType.intersection(param.staticTypeForNarrowing, typeHierarchy);
+      final staticTypeForNarrowing = param.staticTypeForNarrowing;
+      if (staticTypeForNarrowing != null) {
+        types[i] = argType.intersection(staticTypeForNarrowing, typeHierarchy);
       } else {
         // TODO(sjindel/tfa): Narrowing is performed inside a [TypeCheck] later.
         types[i] = args[i];
@@ -682,9 +701,10 @@
             args[positionalArgCount + argIndex].specialize(typeHierarchy);
         argIndex++;
         param._observeArgumentType(argType, typeHierarchy);
-        if (param.staticTypeForNarrowing != null) {
+        final staticTypeForNarrowing = param.staticTypeForNarrowing;
+        if (staticTypeForNarrowing != null) {
           types[i] =
-              argType.intersection(param.staticTypeForNarrowing, typeHierarchy);
+              argType.intersection(staticTypeForNarrowing, typeHierarchy);
         } else {
           types[i] = argType;
         }
@@ -713,7 +733,7 @@
     resultType = resultType.union(computedType, typeHierarchy);
 
     if (kPrintTimings) {
-      final dirtyTime = timer.elapsedMicroseconds;
+      final dirtyTime = timer!.elapsedMicroseconds;
       final pureTime = dirtyTime < calleeTime ? 0 : (dirtyTime - calleeTime);
       Statistics.numSummaryApplications.add(name);
       Statistics.dirtySummaryAnalysisTime.add(name, dirtyTime);
@@ -725,9 +745,9 @@
   }
 
   Args<Type> get argumentTypes {
-    final argTypes = new List<Type>.filled(parameterCount, null);
-    final argNames = new List<String>.filled(
-        parameterCount - positionalParameterCount, null);
+    final argTypes = new List<Type>.filled(parameterCount, const EmptyType());
+    final argNames =
+        new List<String>.filled(parameterCount - positionalParameterCount, '');
     for (int i = 0; i < parameterCount; i++) {
       Parameter param = _statements[i] as Parameter;
       argTypes[i] = param.argumentType;
@@ -741,7 +761,7 @@
   Type argumentType(Member member, VariableDeclaration memberParam) {
     final int firstParamIndex =
         numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
-    final positional = member.function.positionalParameters;
+    final positional = member.function!.positionalParameters;
     for (int i = 0; i < positional.length; i++) {
       if (positional[i] == memberParam) {
         final Parameter param = _statements[firstParamIndex + i] as Parameter;
@@ -762,9 +782,9 @@
     final params = <VariableDeclaration>[];
     for (Statement statement in _statements) {
       if (statement is TypeCheck &&
-          statement.canAlwaysSkip &&
-          statement.parameter != null) {
-        params.add(statement.parameter);
+          statement.alwaysPass &&
+          statement.isParameterCheck) {
+        params.add(statement.parameterVariable);
       }
     }
     return params;
@@ -780,17 +800,17 @@
         (hasReceiverArg(member) ? 1 : 0) + numTypeParams(member);
     final Map<String, Parameter> paramsByName = {};
     for (int i = implicit; i < parameterCount; i++) {
-      final Parameter param = statements[i];
+      final Parameter param = statements[i] as Parameter;
       paramsByName[param.name] = param;
     }
-    FunctionNode function = member.function;
+    FunctionNode function = member.function!;
     statements.length = implicit;
     for (VariableDeclaration param in function.positionalParameters) {
-      statements.add(paramsByName[param.name]);
+      statements.add(paramsByName[param.name]!);
     }
     positionalParameterCount = statements.length;
     for (VariableDeclaration param in function.namedParameters) {
-      statements.add(paramsByName[param.name]);
+      statements.add(paramsByName[param.name]!);
     }
     parameterCount = statements.length;
     requiredParameterCount = implicit + function.requiredParameterCount;
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index fac8e00..9905fcc 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Creation of type flow summaries out of kernel AST.
-library vm.transformations.type_flow.summary_collector;
 
 import 'dart:core' hide Type;
 
@@ -12,6 +11,7 @@
 import 'package:kernel/ast.dart' as ast show Statement, StatementVisitor;
 import 'package:kernel/class_hierarchy.dart'
     show ClassHierarchy, ClosedWorldClassHierarchy;
+import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:kernel/type_environment.dart'
     show StaticTypeContext, SubtypeCheckMode, TypeEnvironment;
 import 'package:kernel/type_algebra.dart' show Substitution;
@@ -127,8 +127,13 @@
           // This pattern may appear after approximations during summary
           // normalization (so it's not enough to handle it in _makeNarrow).
           final arg = st.arg;
-          if (arg is Type && st.type == const AnyType()) {
-            return (arg is NullableType) ? arg.baseType : arg;
+          if (st.type is AnyType) {
+            if (arg is Type) {
+              return (arg is NullableType) ? arg.baseType : arg;
+            }
+            if (arg is Call && arg.isInstanceCreation) {
+              return arg;
+            }
           }
         }
 
@@ -232,7 +237,7 @@
   // function and checks if control can fall through them or not.
 
   bool controlCanFallThrough(FunctionNode function) {
-    return function.body.accept(this);
+    return function.body!.accept(this);
   }
 
   @override
@@ -278,11 +283,11 @@
   bool visitContinueSwitchStatement(ContinueSwitchStatement node) => false;
 
   @override
-  bool visitIfStatement(IfStatement node) =>
-      node.then == null ||
-      node.otherwise == null ||
-      node.then.accept(this) ||
-      node.otherwise.accept(this);
+  bool visitIfStatement(IfStatement node) {
+    final otherwise = node.otherwise;
+    if (otherwise == null) return true;
+    return node.then.accept(this) || otherwise.accept(this);
+  }
 
   @override
   bool visitReturnStatement(ReturnStatement node) => false;
@@ -316,7 +321,7 @@
   final List<VariableDeclaration> varDeclarations = <VariableDeclaration>[];
 
   /// Set of captured variables.
-  Set<VariableDeclaration> captured;
+  Set<VariableDeclaration>? captured;
 
   /// Set of variables which were modified for each loop, switch statement
   /// and try block statement. Doesn't include captured variables and
@@ -327,10 +332,10 @@
   int numVariablesAtFunctionEntry = 0;
 
   /// Active loops, switch statements and try blocks.
-  List<ast.Statement> activeStatements;
+  List<ast.Statement>? activeStatements;
 
   /// Number of variables at entry of active statements.
-  List<int> numVariablesAtActiveStatements;
+  List<int>? numVariablesAtActiveStatements;
 
   _VariablesInfoCollector(Member member) {
     member.accept(this);
@@ -338,8 +343,10 @@
 
   int get numVariables => varDeclarations.length;
 
-  bool isCaptured(VariableDeclaration variable) =>
-      captured != null && captured.contains(variable);
+  bool isCaptured(VariableDeclaration variable) {
+    final captured = this.captured;
+    return captured != null && captured.contains(variable);
+  }
 
   Set<int> getModifiedVariables(ast.Statement st) {
     return modifiedSets[st] ?? const <int>{};
@@ -380,14 +387,15 @@
   }
 
   void _useVariable(VariableDeclaration variable, bool isVarAssignment) {
-    final index = varIndex[variable];
+    final index = varIndex[variable]!;
     if (_isDeclaredBefore(index, numVariablesAtFunctionEntry)) {
       _captureVariable(variable);
       return;
     }
+    final activeStatements = this.activeStatements;
     if (isVarAssignment && activeStatements != null) {
       for (int i = activeStatements.length - 1; i >= 0; --i) {
-        if (_isDeclaredBefore(index, numVariablesAtActiveStatements[i])) {
+        if (_isDeclaredBefore(index, numVariablesAtActiveStatements![i])) {
           final st = activeStatements[i];
           (modifiedSets[st] ??= <int>{}).add(index);
         } else {
@@ -403,8 +411,8 @@
   }
 
   void _endCollectingModifiedVariables() {
-    activeStatements.removeLast();
-    numVariablesAtActiveStatements.removeLast();
+    activeStatements!.removeLast();
+    numVariablesAtActiveStatements!.removeLast();
   }
 
   @override
@@ -450,7 +458,7 @@
   @override
   visitTryCatch(TryCatch node) {
     _startCollectingModifiedVariables(node);
-    node.body?.accept(this);
+    node.body.accept(this);
     _endCollectingModifiedVariables();
     visitList(node.catches, this);
   }
@@ -458,9 +466,9 @@
   @override
   visitTryFinally(TryFinally node) {
     _startCollectingModifiedVariables(node);
-    node.body?.accept(this);
+    node.body.accept(this);
     _endCollectingModifiedVariables();
-    node.finalizer?.accept(this);
+    node.finalizer.accept(this);
   }
 
   @override
@@ -482,7 +490,7 @@
     visitList(node.variables, this);
     _startCollectingModifiedVariables(node);
     node.condition?.accept(this);
-    node.body?.accept(this);
+    node.body.accept(this);
     visitList(node.updates, this);
     _endCollectingModifiedVariables();
   }
@@ -514,7 +522,7 @@
 enum FieldSummaryType { kFieldGuard, kInitializer }
 
 /// Create a type flow summary for a member from the kernel AST.
-class SummaryCollector extends RecursiveResultVisitor<TypeExpr> {
+class SummaryCollector extends RecursiveResultVisitor<TypeExpr?> {
   final Target target;
   final TypeEnvironment _environment;
   final ClosedWorldClassHierarchy _hierarchy;
@@ -522,23 +530,24 @@
   final TypesBuilder _typesBuilder;
   final NativeCodeOracle _nativeCodeOracle;
   final GenericInterfacesInfo _genericInterfacesInfo;
-  final ProtobufHandler _protobufHandler;
+  final ProtobufHandler? _protobufHandler;
 
   final Map<TreeNode, Call> callSites = <TreeNode, Call>{};
   final Map<AsExpression, TypeCheck> explicitCasts =
       <AsExpression, TypeCheck>{};
+  final Map<IsExpression, TypeCheck> isTests = <IsExpression, TypeCheck>{};
   final Map<TreeNode, NarrowNotNull> nullTests = <TreeNode, NarrowNotNull>{};
   final _FallthroughDetector _fallthroughDetector = new _FallthroughDetector();
   final Set<Name> _nullMethodsAndGetters = <Name>{};
   final Set<Name> _nullSetters = <Name>{};
 
-  Summary _summary;
-  _VariablesInfoCollector _variablesInfo;
+  Summary _summary = Summary('<unused>');
+  late _VariablesInfoCollector _variablesInfo;
 
   // Current value of each variable. May contain null if variable is not
   // declared yet, or EmptyType if current location is unreachable
   // (e.g. after return or throw).
-  List<TypeExpr> _variableValues;
+  List<TypeExpr?> _variableValues = const <TypeExpr?>[];
 
   // Contains Joins which accumulate all values of certain variables.
   // Used only when all variable values should be merged regardless of control
@@ -550,30 +559,30 @@
   // If _variableCells[i] != null, then all values are accumulated in the
   // _variableCells[i]. _variableValues[i] does not change and remains equal
   // to _variableCells[i].
-  List<Join> _variableCells;
+  List<Join?> _variableCells = const <Join?>[];
 
   // Counts number of Joins inserted for each variable. Only used to set
   // readable names for such joins (foo_0, foo_1 etc.)
-  List<int> _variableVersions;
+  List<int> _variableVersions = const <int>[];
 
   // State of variables after corresponding LabeledStatement.
   // Used to collect states from BreakStatements.
-  Map<LabeledStatement, List<TypeExpr>> _variableValuesAfterLabeledStatements;
+  Map<LabeledStatement, List<TypeExpr?>>? _variableValuesAfterLabeledStatements;
 
   // Joins corresponding to variables on entry to switch cases.
   // Used to propagate state from ContinueSwitchStatement to a target case.
-  Map<SwitchCase, List<Join>> _joinsAtSwitchCases;
+  Map<SwitchCase, List<Join?>>? _joinsAtSwitchCases;
 
   // Join which accumulates all return values.
-  Join _returnValue;
+  Join? _returnValue;
 
-  Parameter _receiver;
-  ConstantAllocationCollector constantAllocationCollector;
-  RuntimeTypeTranslatorImpl _translator;
-  StaticTypeContext _staticTypeContext;
+  Parameter? _receiver;
+  late ConstantAllocationCollector constantAllocationCollector;
+  late RuntimeTypeTranslatorImpl _translator;
+  StaticTypeContext? _staticTypeContext;
 
   // Currently only used for factory constructors.
-  Map<TypeParameter, TypeExpr> _fnTypeVariables;
+  Map<TypeParameter, TypeExpr>? _fnTypeVariables;
 
   SummaryCollector(
       this.target,
@@ -584,7 +593,6 @@
       this._nativeCodeOracle,
       this._genericInterfacesInfo,
       this._protobufHandler) {
-    assert(_genericInterfacesInfo != null);
     constantAllocationCollector = new ConstantAllocationCollector(this);
     _nullMethodsAndGetters.addAll(getSelectors(
         _hierarchy, _environment.coreTypes.deprecatedNullClass,
@@ -600,15 +608,15 @@
         "${member}${fieldSummaryType == FieldSummaryType.kFieldGuard ? " (guard)" : ""}";
     debugPrint("===== $summaryName =====");
     assert(!member.isAbstract);
-    assert(!(member is Procedure && member.isRedirectingFactoryConstructor));
+    assert(!(member is Procedure && member.isRedirectingFactory));
 
     _protobufHandler?.beforeSummaryCreation(member);
 
     _staticTypeContext = new StaticTypeContext(member, _environment);
     _variablesInfo = new _VariablesInfoCollector(member);
     _variableValues =
-        new List<TypeExpr>.filled(_variablesInfo.numVariables, null);
-    _variableCells = new List<Join>.filled(_variablesInfo.numVariables, null);
+        new List<TypeExpr?>.filled(_variablesInfo.numVariables, null);
+    _variableCells = new List<Join?>.filled(_variablesInfo.numVariables, null);
     _variableVersions = new List<int>.filled(_variablesInfo.numVariables, 0);
     _variableValuesAfterLabeledStatements = null;
     _joinsAtSwitchCases = null;
@@ -625,25 +633,24 @@
             parameterCount: numArgs, positionalParameterCount: numArgs);
         // TODO(alexmarkov): subclass cone
         _receiver = _declareParameter("this",
-            _environment.coreTypes.legacyRawType(member.enclosingClass), null,
+            _environment.coreTypes.legacyRawType(member.enclosingClass!), null,
             isReceiver: true);
       } else {
         _summary = new Summary(summaryName);
       }
 
-      _translator = new RuntimeTypeTranslatorImpl(
-          this, _summary, _receiver, null, _genericInterfacesInfo);
+      _translator = new RuntimeTypeTranslatorImpl(_environment.coreTypes,
+          _summary, _receiver, null, _genericInterfacesInfo);
 
       if (fieldSummaryType == FieldSummaryType.kInitializer) {
-        assert(member.initializer != null);
-        _summary.result = _visit(member.initializer);
+        _summary.result = _visit(member.initializer!);
       } else {
         final Parameter valueParam =
             _declareParameter("value", member.type, null);
         _summary.result = _typeCheck(valueParam, member.type, member);
       }
     } else {
-      FunctionNode function = member.function;
+      final FunctionNode function = member.function!;
 
       final numTypeParameters = numTypeParams(member);
       final firstParamIndex = (hasReceiver ? 1 : 0) + numTypeParameters;
@@ -658,43 +665,42 @@
               firstParamIndex + function.requiredParameterCount);
 
       if (numTypeParameters > 0) {
-        _fnTypeVariables = <TypeParameter, TypeExpr>{};
-        for (int i = 0; i < numTypeParameters; ++i) {
-          _fnTypeVariables[function.typeParameters[i]] =
-              _declareParameter(function.typeParameters[i].name, null, null);
-        }
+        _fnTypeVariables = <TypeParameter, TypeExpr>{
+          for (TypeParameter tp in function.typeParameters)
+            tp: _declareParameter(tp.name!, null, null)
+        };
       }
 
       if (hasReceiver) {
         // TODO(alexmarkov): subclass cone
         _receiver = _declareParameter("this",
-            _environment.coreTypes.legacyRawType(member.enclosingClass), null,
+            _environment.coreTypes.legacyRawType(member.enclosingClass!), null,
             isReceiver: true);
       }
 
-      _translator = new RuntimeTypeTranslatorImpl(
-          this, _summary, _receiver, _fnTypeVariables, _genericInterfacesInfo);
+      _translator = new RuntimeTypeTranslatorImpl(_environment.coreTypes,
+          _summary, _receiver, _fnTypeVariables, _genericInterfacesInfo);
 
       // Handle forwarding stubs. We need to check types against the types of
       // the forwarding stub's target, [member.concreteForwardingStubTarget].
-      FunctionNode useTypesFrom = member.function;
-      if (member is Procedure &&
-          member.isForwardingStub &&
-          member.concreteForwardingStubTarget != null) {
+      FunctionNode useTypesFrom = function;
+      if (member is Procedure && member.isForwardingStub) {
         final target = member.concreteForwardingStubTarget;
-        if (target is Field) {
-          useTypesFrom = FunctionNode(null, positionalParameters: [
-            VariableDeclaration("value", type: target.type)
-          ]);
-        } else {
-          useTypesFrom = member.concreteForwardingStubTarget.function;
+        if (target != null) {
+          if (target is Field) {
+            useTypesFrom = FunctionNode(null, positionalParameters: [
+              VariableDeclaration("value", type: target.type)
+            ]);
+          } else {
+            useTypesFrom = target.function!;
+          }
         }
       }
 
       for (int i = 0; i < function.positionalParameters.length; ++i) {
         final decl = function.positionalParameters[i];
         _declareParameter(
-            decl.name,
+            decl.name!,
             _useTypeCheckForParameter(decl)
                 ? null
                 : useTypesFrom.positionalParameters[i].type,
@@ -703,7 +709,7 @@
       for (int i = 0; i < function.namedParameters.length; ++i) {
         final decl = function.namedParameters[i];
         _declareParameter(
-            decl.name,
+            decl.name!,
             _useTypeCheckForParameter(decl)
                 ? null
                 : useTypesFrom.namedParameters[i].type,
@@ -732,7 +738,7 @@
       assert(count == _summary.parameterCount);
 
       _returnValue = new Join("%result", function.returnType);
-      _summary.add(_returnValue);
+      _summary.add(_returnValue!);
 
       if (member is Constructor) {
         // Make sure instance field initializers are visited.
@@ -742,7 +748,7 @@
                 new DirectSelector(f, callKind: CallKind.FieldInitializer));
           }
         }
-        member.initializers.forEach(_visit);
+        member.initializers.forEach(_visitWithoutResult);
       }
 
       if (function.body == null) {
@@ -752,15 +758,15 @@
           // Runtime type could be more precise than static type, so
           // calculate intersection.
           final typeCheck = _typeCheck(type, function.returnType, function);
-          _returnValue.values.add(typeCheck);
+          _returnValue!.values.add(typeCheck);
         } else {
-          _returnValue.values.add(type);
+          _returnValue!.values.add(type);
         }
       } else {
-        _visit(function.body);
+        _visitWithoutResult(function.body!);
 
         if (_fallthroughDetector.controlCanFallThrough(function)) {
-          _returnValue.values.add(_nullType);
+          _returnValue!.values.add(_nullType);
         }
       }
 
@@ -768,15 +774,15 @@
         // In addition to what is returned from the function body,
         // operator == performs implicit comparison with null
         // and returns bool.
-        _returnValue.values.add(_boolType);
+        _returnValue!.values.add(_boolType);
       }
 
-      _summary.result = _returnValue;
+      _summary.result = _returnValue!;
     }
 
     member.annotations.forEach(_visit);
-    member.enclosingClass?.annotations?.forEach(_visit);
-    member.enclosingLibrary?.annotations?.forEach(_visit);
+    member.enclosingClass?.annotations.forEach(_visit);
+    member.enclosingLibrary.annotations.forEach(_visit);
 
     _staticTypeContext = null;
 
@@ -800,9 +806,7 @@
   }
 
   Args<Type> rawArguments(Selector selector) {
-    final member = selector.member;
-    assert(member != null);
-
+    final member = selector.member!;
     final List<Type> args = <Type>[];
     final List<String> names = <String>[];
 
@@ -814,15 +818,14 @@
     if (hasReceiverArg(member)) {
       assert(member.enclosingClass != null);
       final receiver =
-          new ConeType(_typesBuilder.getTFClass(member.enclosingClass));
+          new ConeType(_typesBuilder.getTFClass(member.enclosingClass!));
       args.add(receiver);
     }
 
     switch (selector.callKind) {
       case CallKind.Method:
         if (member is! Field) {
-          final function = member.function;
-          assert(function != null);
+          final function = member.function!;
 
           final int paramCount = function.positionalParameters.length +
               function.namedParameters.length;
@@ -832,7 +835,7 @@
 
           if (function.namedParameters.isNotEmpty) {
             for (var param in function.namedParameters) {
-              names.add(param.name);
+              names.add(param.name!);
             }
             // TODO(dartbug.com/32292): make sure parameters are sorted in
             // kernel AST and remove this sorting.
@@ -856,11 +859,15 @@
     return new Args<Type>(args, names: names);
   }
 
-  TypeExpr _visit(TreeNode node) => node.accept(this);
+  TypeExpr _visit(Expression node) => node.accept(this)!;
 
-  Args<TypeExpr> _visitArguments(TypeExpr receiver, Arguments arguments,
+  void _visitWithoutResult(TreeNode node) {
+    node.accept(this);
+  }
+
+  Args<TypeExpr> _visitArguments(TypeExpr? receiver, Arguments arguments,
       {bool passTypeArguments: false}) {
-    final args = <TypeExpr>[];
+    final List<TypeExpr> args = <TypeExpr>[];
     if (passTypeArguments) {
       for (var type in arguments.types) {
         args.add(_translator.translate(type));
@@ -882,7 +889,7 @@
       }
       names.sort();
       for (var name in names) {
-        args.add(map[name]);
+        args.add(map[name]!);
       }
       return new Args<TypeExpr>(args, names: names);
     } else {
@@ -891,9 +898,9 @@
   }
 
   Parameter _declareParameter(
-      String name, DartType type, Expression initializer,
+      String name, DartType? type, Expression? initializer,
       {bool isReceiver: false}) {
-    Type staticType;
+    Type? staticType;
     if (type != null) {
       staticType = _typesBuilder.fromStaticType(type, !isReceiver);
     }
@@ -908,7 +915,7 @@
         } else if (initializer is BasicLiteral ||
             initializer is SymbolLiteral ||
             initializer is TypeLiteral) {
-          param.defaultValue = _visit(initializer);
+          param.defaultValue = _visit(initializer) as Type;
         } else {
           throw 'Unexpected parameter $name default value ${initializer.runtimeType} $initializer';
         }
@@ -922,8 +929,7 @@
   }
 
   void _declareVariable(VariableDeclaration decl, TypeExpr initialValue) {
-    final int varIndex = _variablesInfo.varIndex[decl];
-    assert(varIndex != null);
+    final int varIndex = _variablesInfo.varIndex[decl]!;
     assert(_variablesInfo.varDeclarations[varIndex] == decl);
     assert(_variableValues[varIndex] == null);
     if (_variablesInfo.isCaptured(decl)) {
@@ -936,8 +942,8 @@
   }
 
   void _writeVariable(VariableDeclaration variable, TypeExpr value) {
-    final int varIndex = _variablesInfo.varIndex[variable];
-    final Join join = _variableCells[varIndex];
+    final int varIndex = _variablesInfo.varIndex[variable]!;
+    final Join? join = _variableCells[varIndex];
     if (join != null) {
       join.values.add(value);
     } else {
@@ -945,11 +951,12 @@
     }
   }
 
-  List<TypeExpr> _cloneVariableValues(List<TypeExpr> values) =>
-      new List<TypeExpr>.from(values);
+  List<TypeExpr?> _cloneVariableValues(List<TypeExpr?> values) =>
+      new List<TypeExpr?>.from(values);
 
-  List<TypeExpr> _makeEmptyVariableValues() {
-    final values = new List<TypeExpr>.filled(_variablesInfo.numVariables, null);
+  List<TypeExpr?> _makeEmptyVariableValues() {
+    final values =
+        new List<TypeExpr?>.filled(_variablesInfo.numVariables, null);
     for (int i = 0; i < values.length; ++i) {
       if (_variableCells[i] != null) {
         values[i] = _variableValues[i];
@@ -970,11 +977,11 @@
     return join;
   }
 
-  void _mergeVariableValues(List<TypeExpr> dst, List<TypeExpr> src) {
+  void _mergeVariableValues(List<TypeExpr?> dst, List<TypeExpr?> src) {
     assert(dst.length == src.length);
     for (int i = 0; i < dst.length; ++i) {
-      final TypeExpr dstValue = dst[i];
-      final TypeExpr srcValue = src[i];
+      final TypeExpr? dstValue = dst[i];
+      final TypeExpr? srcValue = src[i];
       if (identical(dstValue, srcValue)) {
         continue;
       }
@@ -989,21 +996,21 @@
       } else if (srcValue is Join && srcValue.values.contains(dstValue)) {
         dst[i] = srcValue;
       } else {
-        final Join join = _makeJoin(i, dst[i]);
-        join.values.add(src[i]);
+        final Join join = _makeJoin(i, dstValue);
+        join.values.add(srcValue);
         dst[i] = join;
       }
     }
   }
 
-  void _copyVariableValues(List<TypeExpr> dst, List<TypeExpr> src) {
+  void _copyVariableValues(List<TypeExpr?> dst, List<TypeExpr?> src) {
     assert(dst.length == src.length);
     for (int i = 0; i < dst.length; ++i) {
       dst[i] = src[i];
     }
   }
 
-  bool _isIdenticalState(List<TypeExpr> state1, List<TypeExpr> state2) {
+  bool _isIdenticalState(List<TypeExpr?> state1, List<TypeExpr?> state2) {
     assert(state1.length == state2.length);
     for (int i = 0; i < state1.length; ++i) {
       if (!identical(state1[i], state2[i])) {
@@ -1013,14 +1020,14 @@
     return true;
   }
 
-  List<Join> _insertJoinsForModifiedVariables(TreeNode node, bool isTry) {
-    final List<Join> joins =
-        new List<Join>.filled(_variablesInfo.numVariables, null);
+  List<Join?> _insertJoinsForModifiedVariables(ast.Statement node, bool isTry) {
+    final List<Join?> joins =
+        new List<Join?>.filled(_variablesInfo.numVariables, null);
     for (var i in _variablesInfo.getModifiedVariables(node)) {
       if (_variableCells[i] != null) {
         assert(_variableCells[i] == _variableValues[i]);
       } else {
-        final join = _makeJoin(i, _variableValues[i]);
+        final join = _makeJoin(i, _variableValues[i]!);
         joins[i] = join;
         _variableValues[i] = join;
         if (isTry) {
@@ -1036,7 +1043,7 @@
 
   /// Stops accumulating values in [joins] by removing them from
   /// _variableCells.
-  void _restoreVariableCellsAfterTry(List<Join> joins) {
+  void _restoreVariableCellsAfterTry(List<Join?> joins) {
     for (int i = 0; i < joins.length; ++i) {
       if (joins[i] != null) {
         assert(_variableCells[i] == joins[i]);
@@ -1045,37 +1052,43 @@
     }
   }
 
-  void _mergeVariableValuesToJoins(List<TypeExpr> values, List<Join> joins) {
+  void _mergeVariableValuesToJoins(List<TypeExpr?> values, List<Join?> joins) {
     for (int i = 0; i < joins.length; ++i) {
       final join = joins[i];
       final value = values[i];
       if (join != null &&
           !identical(join, value) &&
           !identical(join.values.first, value)) {
-        join.values.add(value);
+        join.values.add(value!);
       }
     }
   }
 
-  TypeCheck _typeCheck(TypeExpr value, DartType type, TreeNode node) {
+  TypeCheck _typeCheck(TypeExpr value, DartType type, TreeNode node,
+      [SubtypeTestKind kind = SubtypeTestKind.Subtype]) {
     final TypeExpr runtimeType = _translator.translate(type);
-    final typeCheck = new TypeCheck(
-        value, runtimeType, node, _typesBuilder.fromStaticType(type, true));
+    final bool canBeNull = (kind == SubtypeTestKind.IsTest)
+        ? _canBeNullAfterSuccessfulIsCheck(type)
+        : true;
+    final typeCheck = new TypeCheck(value, runtimeType, node,
+        _typesBuilder.fromStaticType(type, canBeNull), kind);
     _summary.add(typeCheck);
     return typeCheck;
   }
 
   // TODO(alexmarkov): Avoid declaring variables with static types.
   void _declareVariableWithStaticType(VariableDeclaration decl) {
-    if (decl.initializer != null) {
-      _visit(decl.initializer);
+    final initializer = decl.initializer;
+    if (initializer != null) {
+      _visit(initializer);
     }
     _declareVariable(decl, _typesBuilder.fromStaticType(decl.type, true));
   }
 
-  Call _makeCall(TreeNode node, Selector selector, Args<TypeExpr> args) {
-    Type staticResultType = null;
-    Member target;
+  Call _makeCall(TreeNode node, Selector selector, Args<TypeExpr> args,
+      {bool isInstanceCreation = false}) {
+    Type? staticResultType = null;
+    Member? target;
     if (selector is DirectSelector) {
       target = selector.member;
     } else if (selector is InterfaceSelector) {
@@ -1086,11 +1099,9 @@
         node is Expression) {
       staticResultType = _staticType(node);
     }
-    Call call = new Call(selector, args, staticResultType);
+    Call call = new Call(selector, args, staticResultType, isInstanceCreation);
     _summary.add(call);
-    if (node != null) {
-      callSites[node] = call;
-    }
+    callSites[node] = call;
     return call;
   }
 
@@ -1109,6 +1120,8 @@
       if (type == const AnyType()) {
         return (arg is NullableType) ? arg.baseType : arg;
       }
+    } else if (arg is Call && arg.isInstanceCreation && type is AnyType) {
+      return arg;
     }
     if (type is NullableType && type.baseType == const AnyType()) {
       return arg;
@@ -1118,19 +1131,17 @@
     return narrow;
   }
 
-  // Narrow type of [arg] after successful 'is' test against [type].
-  TypeExpr _makeNarrowAfterSuccessfulIsCheck(TypeExpr arg, DartType type) {
+  bool _canBeNullAfterSuccessfulIsCheck(DartType type) {
     // 'x is type' can succeed for null if type is
     //  - a top type (dynamic, void, Object? or Object*)
     //  - nullable (including Null)
     //  - a type parameter (it can be instantiated with Null)
     //  - legacy Never
     final nullability = type.nullability;
-    final bool canBeNull = _environment.isTop(type) ||
+    return _environment.isTop(type) ||
         nullability == Nullability.nullable ||
         type is TypeParameterType ||
         (type is NeverType && nullability == Nullability.legacy);
-    return _makeNarrow(arg, _typesBuilder.fromStaticType(type, canBeNull));
   }
 
   TypeExpr _makeNarrowNotNull(TreeNode node, TypeExpr arg) {
@@ -1176,53 +1187,43 @@
   }
 
   DartType _staticDartType(Expression node) =>
-      node.getStaticType(_staticTypeContext);
+      node.getStaticType(_staticTypeContext!);
 
   Type _staticType(Expression node) =>
       _typesBuilder.fromStaticType(_staticDartType(node), true);
 
-  ConcreteType _cachedBoolType;
-  ConcreteType get _boolType => _cachedBoolType ??=
+  late final ConcreteType _boolType =
       _entryPointsListener.addAllocatedClass(_environment.coreTypes.boolClass);
 
-  ConcreteType _cachedBoolTrue;
-  ConcreteType get _boolTrue => _cachedBoolTrue ??=
-      new ConcreteType(_boolType.cls, null, BoolConstant(true));
+  late final ConcreteType _boolTrue =
+      ConcreteType(_boolType.cls, null, BoolConstant(true));
 
-  ConcreteType _cachedBoolFalse;
-  ConcreteType get _boolFalse => _cachedBoolFalse ??=
-      new ConcreteType(_boolType.cls, null, BoolConstant(false));
+  late final ConcreteType _boolFalse =
+      ConcreteType(_boolType.cls, null, BoolConstant(false));
 
-  Type _cachedDoubleType;
-  Type get _doubleType => _cachedDoubleType ??= new ConeType(
-      _typesBuilder.getTFClass(_environment.coreTypes.doubleClass));
+  late final Type _doubleType =
+      ConeType(_typesBuilder.getTFClass(_environment.coreTypes.doubleClass));
 
-  Type _cachedIntType;
-  Type get _intType => _cachedIntType ??=
-      new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.intClass));
+  late final Type _intType =
+      ConeType(_typesBuilder.getTFClass(_environment.coreTypes.intClass));
 
-  Type _cachedStringType;
-  Type get _stringType => _cachedStringType ??= new ConeType(
-      _typesBuilder.getTFClass(_environment.coreTypes.stringClass));
+  late final Type _stringType =
+      ConeType(_typesBuilder.getTFClass(_environment.coreTypes.stringClass));
 
-  Type _cachedSymbolType;
-  Type get _symbolType => _cachedSymbolType ??= new ConeType(
-      _typesBuilder.getTFClass(_environment.coreTypes.symbolClass));
+  late final Type _symbolType =
+      ConeType(_typesBuilder.getTFClass(_environment.coreTypes.symbolClass));
 
-  Type _cachedTypeType;
-  Type get _typeType => _cachedTypeType ??=
-      new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.typeClass));
+  late final Type _typeType =
+      ConeType(_typesBuilder.getTFClass(_environment.coreTypes.typeClass));
 
-  Type _cachedNullType;
-  Type get _nullType =>
-      _cachedNullType ??= new Type.nullable(const EmptyType());
+  late final Type _nullType = Type.nullable(const EmptyType());
 
-  Class get _superclass => _staticTypeContext.thisType.classNode.superclass;
+  Class get _superclass => _staticTypeContext!.thisType!.classNode.superclass!;
 
   Type _boolLiteralType(bool value) => value ? _boolTrue : _boolFalse;
 
-  Type _intLiteralType(int value, Constant constant) {
-    final Class concreteClass =
+  Type _intLiteralType(int value, Constant? constant) {
+    final Class? concreteClass =
         target.concreteIntLiteralClass(_environment.coreTypes, value);
     if (concreteClass != null) {
       constant ??= IntConstant(value);
@@ -1234,8 +1235,8 @@
     return _intType;
   }
 
-  Type _doubleLiteralType(double value, Constant constant) {
-    final Class concreteClass =
+  Type _doubleLiteralType(double value, Constant? constant) {
+    final Class? concreteClass =
         target.concreteDoubleLiteralClass(_environment.coreTypes, value);
     if (concreteClass != null) {
       constant ??= DoubleConstant(value);
@@ -1247,8 +1248,8 @@
     return _doubleType;
   }
 
-  Type _stringLiteralType(String value, Constant constant) {
-    final Class concreteClass =
+  Type _stringLiteralType(String value, Constant? constant) {
+    final Class? concreteClass =
         target.concreteStringLiteralClass(_environment.coreTypes, value);
     if (concreteClass != null) {
       constant ??= StringConstant(value);
@@ -1271,7 +1272,7 @@
     node.positionalParameters.forEach(_declareVariableWithStaticType);
     node.namedParameters.forEach(_declareVariableWithStaticType);
 
-    _visit(node.body);
+    _visitWithoutResult(node.body!);
 
     _variableValues = savedVariableValues;
     _returnValue = savedReturn;
@@ -1294,8 +1295,7 @@
       for (Class c
           in _hierarchy.computeSubtypesInformation().getSubtypesOf(cls)) {
         if (!c.isAbstract) {
-          final candidate = _hierarchy.getDispatchTarget(c, _equalsName);
-          assert(candidate != null);
+          final candidate = _hierarchy.getDispatchTarget(c, _equalsName)!;
           assert(!candidate.isAbstract);
           if (candidate != _environment.coreTypes.objectEquals) {
             _cachedHasOverriddenEquals[cls] = true;
@@ -1315,12 +1315,12 @@
   // On exit _variableValues is null, so caller should explicitly pick
   // either trueState or falseState.
   void _visitCondition(
-      Expression node, List<TypeExpr> trueState, List<TypeExpr> falseState) {
+      Expression node, List<TypeExpr?> trueState, List<TypeExpr?> falseState) {
     assert(_isIdenticalState(_variableValues, trueState));
     assert(_isIdenticalState(_variableValues, falseState));
     if (node is Not) {
       _visitCondition(node.operand, falseState, trueState);
-      _variableValues = null;
+      _variableValues = const <TypeExpr?>[]; // Should not be used.
       return;
     } else if (node is LogicalExpression) {
       final isOR = (node.operatorEnum == LogicalExpressionOperator.OR);
@@ -1338,7 +1338,7 @@
         _visitCondition(node.right, trueState, falseStateAfterRHS);
         _mergeVariableValues(falseState, falseStateAfterRHS);
       }
-      _variableValues = null;
+      _variableValues = const <TypeExpr?>[]; // Should not be used.
       return;
     } else if (node is VariableGet ||
         (node is AsExpression && node.operand is VariableGet)) {
@@ -1346,12 +1346,12 @@
       _addUse(_visit(node));
       final variableGet =
           (node is AsExpression ? node.operand : node) as VariableGet;
-      final int varIndex = _variablesInfo.varIndex[variableGet.variable];
+      final int varIndex = _variablesInfo.varIndex[variableGet.variable]!;
       if (_variableCells[varIndex] == null) {
         trueState[varIndex] = _boolTrue;
         falseState[varIndex] = _boolFalse;
       }
-      _variableValues = null;
+      _variableValues = const <TypeExpr?>[]; // Should not be used.
       return;
     } else if (node is EqualsCall && node.left is VariableGet) {
       final lhs = node.left as VariableGet;
@@ -1366,11 +1366,11 @@
               !_hasOverriddenEquals(lhs.variable.type))) {
         // 'x == c', where x is a variable and c is a constant.
         _addUse(_visit(node));
-        final int varIndex = _variablesInfo.varIndex[lhs.variable];
+        final int varIndex = _variablesInfo.varIndex[lhs.variable]!;
         if (_variableCells[varIndex] == null) {
           trueState[varIndex] = _visit(rhs);
         }
-        _variableValues = null;
+        _variableValues = const <TypeExpr?>[]; // Should not be used.
         return;
       }
     } else if (node is EqualsNull && node.expression is VariableGet) {
@@ -1380,29 +1380,30 @@
       _makeCall(node, DirectSelector(_environment.coreTypes.objectEquals),
           Args<TypeExpr>([expr, _nullType]));
       final narrowedNotNull = _makeNarrowNotNull(node, expr);
-      final int varIndex = _variablesInfo.varIndex[lhs.variable];
+      final int varIndex = _variablesInfo.varIndex[lhs.variable]!;
       if (_variableCells[varIndex] == null) {
         trueState[varIndex] = _nullType;
         falseState[varIndex] = narrowedNotNull;
       }
-      _variableValues = null;
+      _variableValues = const <TypeExpr?>[]; // Should not be used.
       return;
     } else if (node is IsExpression && node.operand is VariableGet) {
       // Handle 'x is T', where x is a variable.
       final operand = node.operand as VariableGet;
-      _addUse(_visit(operand));
-      final int varIndex = _variablesInfo.varIndex[operand.variable];
+      final TypeCheck typeCheck =
+          _typeCheck(_visit(operand), node.type, node, SubtypeTestKind.IsTest);
+      isTests[node] = typeCheck;
+      final int varIndex = _variablesInfo.varIndex[operand.variable]!;
       if (_variableCells[varIndex] == null) {
-        trueState[varIndex] =
-            _makeNarrowAfterSuccessfulIsCheck(_visit(operand), node.type);
+        trueState[varIndex] = typeCheck;
       }
-      _variableValues = null;
+      _variableValues = const <TypeExpr?>[]; // Should not be used.
       return;
     }
     _addUse(_visit(node));
     _copyVariableValues(trueState, _variableValues);
     _copyVariableValues(falseState, _variableValues);
-    _variableValues = null;
+    _variableValues = const <TypeExpr?>[]; // Should not be used.
   }
 
   void _updateReceiverAfterCall(
@@ -1411,7 +1412,7 @@
     if (receiverNode is VariableGet) {
       final nullSelectors = isSetter ? _nullSetters : _nullMethodsAndGetters;
       if (!nullSelectors.contains(selector)) {
-        final int varIndex = _variablesInfo.varIndex[receiverNode.variable];
+        final int varIndex = _variablesInfo.varIndex[receiverNode.variable]!;
         if (_variableCells[varIndex] == null) {
           _variableValues[varIndex] =
               _makeNarrow(receiverValue, const AnyType());
@@ -1420,9 +1421,8 @@
     }
   }
 
-  Procedure _cachedUnsafeCast;
-  Procedure get unsafeCast => _cachedUnsafeCast ??= _environment.coreTypes.index
-      .getTopLevelMember('dart:_internal', 'unsafeCast');
+  late final Procedure unsafeCast = _environment.coreTypes.index
+      .getTopLevelProcedure('dart:_internal', 'unsafeCast');
 
   @override
   defaultTreeNode(TreeNode node) =>
@@ -1432,10 +1432,10 @@
   TypeExpr visitAsExpression(AsExpression node) {
     final operandNode = node.operand;
     final TypeExpr operand = _visit(operandNode);
-    final TypeExpr result = _typeCheck(operand, node.type, node);
+    final TypeCheck result = _typeCheck(operand, node.type, node);
     explicitCasts[node] = result;
     if (operandNode is VariableGet) {
-      final int varIndex = _variablesInfo.varIndex[operandNode.variable];
+      final int varIndex = _variablesInfo.varIndex[operandNode.variable]!;
       if (_variableCells[varIndex] == null) {
         _variableValues[varIndex] = result;
       }
@@ -1448,7 +1448,7 @@
     final operandNode = node.operand;
     final TypeExpr result = _makeNarrowNotNull(node, _visit(operandNode));
     if (operandNode is VariableGet) {
-      final int varIndex = _variablesInfo.varIndex[operandNode.variable];
+      final int varIndex = _variablesInfo.varIndex[operandNode.variable]!;
       if (_variableCells[varIndex] == null) {
         _variableValues[varIndex] = result;
       }
@@ -1495,12 +1495,12 @@
   @override
   TypeExpr visitConstructorInvocation(ConstructorInvocation node) {
     ConcreteType klass =
-        _entryPointsListener.addAllocatedClass(node.constructedType.classNode);
+        _typesBuilder.getTFClass(node.constructedType.classNode).concreteType;
     TypeExpr receiver =
         _translator.instantiateConcreteType(klass, node.arguments.types);
     final args = _visitArguments(receiver, node.arguments);
-    _makeCall(node, new DirectSelector(node.target), args);
-    return receiver;
+    return _makeCall(node, new DirectSelector(node.target), args,
+        isInstanceCreation: true);
   }
 
   @override
@@ -1525,26 +1525,30 @@
 
   @override
   TypeExpr visitIsExpression(IsExpression node) {
-    _visit(node.operand);
+    final operandNode = node.operand;
+    final TypeExpr operand = _visit(operandNode);
+    final TypeCheck typeCheck =
+        _typeCheck(operand, node.type, node, SubtypeTestKind.IsTest);
+    isTests[node] = typeCheck;
     return _boolType;
   }
 
   @override
   TypeExpr visitLet(Let node) {
-    _declareVariable(node.variable, _visit(node.variable.initializer));
+    _declareVariable(node.variable, _visit(node.variable.initializer!));
     return _visit(node.body);
   }
 
   @override
   TypeExpr visitBlockExpression(BlockExpression node) {
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     return _visit(node.value);
   }
 
   @override
   TypeExpr visitListLiteral(ListLiteral node) {
     node.expressions.forEach(_visit);
-    Class concreteClass =
+    Class? concreteClass =
         target.concreteListLiteralClass(_environment.coreTypes);
     if (concreteClass != null) {
       return _translator.instantiateConcreteType(
@@ -1570,7 +1574,7 @@
       _visit(entry.key);
       _visit(entry.value);
     }
-    Class concreteClass =
+    Class? concreteClass =
         target.concreteMapLiteralClass(_environment.coreTypes);
     if (concreteClass != null) {
       return _translator.instantiateConcreteType(
@@ -1672,7 +1676,7 @@
   }
 
   TypeExpr _handlePropertyGet(
-      TreeNode node, Expression receiverNode, Member target, Name selector) {
+      TreeNode node, Expression receiverNode, Member? target, Name selector) {
     var receiver = _visit(receiverNode);
     var args = new Args<TypeExpr>([receiver]);
     TypeExpr result;
@@ -1761,8 +1765,7 @@
   @override
   TypeExpr visitSuperPropertyGet(SuperPropertyGet node) {
     assert(kPartialMixinResolution);
-    assert(_receiver != null, "Should have receiver. Node: $node");
-    final args = new Args<TypeExpr>([_receiver]);
+    final args = new Args<TypeExpr>([_receiver!]);
     // Re-resolve target due to partial mixin resolution.
     final target = _hierarchy.getDispatchTarget(_superclass, node.name);
     if (target == null) {
@@ -1776,9 +1779,8 @@
   @override
   TypeExpr visitSuperPropertySet(SuperPropertySet node) {
     assert(kPartialMixinResolution);
-    assert(_receiver != null, "Should have receiver. Node: $node");
     final value = _visit(node.value);
-    final args = new Args<TypeExpr>([_receiver, value]);
+    final args = new Args<TypeExpr>([_receiver!, value]);
     // Re-resolve target due to partial mixin resolution.
     final target =
         _hierarchy.getDispatchTarget(_superclass, node.name, setter: true);
@@ -1864,8 +1866,7 @@
 
   @override
   TypeExpr visitThisExpression(ThisExpression node) {
-    assert(_receiver != null, "Should have receiver. Node: $node");
-    return _receiver;
+    return _receiver!;
   }
 
   @override
@@ -1882,7 +1883,7 @@
 
   @override
   TypeExpr visitVariableGet(VariableGet node) {
-    final v = _variableValues[_variablesInfo.varIndex[node.variable]];
+    final v = _variableValues[_variablesInfo.varIndex[node.variable]!];
     if (v == null) {
       throw 'Unable to find variable ${node.variable} at ${node.location}';
     }
@@ -1907,56 +1908,60 @@
   }
 
   @override
-  TypeExpr visitAssertStatement(AssertStatement node) {
+  TypeExpr? visitAssertStatement(AssertStatement node) {
     if (!kRemoveAsserts) {
       _addUse(_visit(node.condition));
-      if (node.message != null) {
-        _visit(node.message);
+      final message = node.message;
+      if (message != null) {
+        _visit(message);
       }
     }
     return null;
   }
 
   @override
-  TypeExpr visitBlock(Block node) {
-    node.statements.forEach(_visit);
+  TypeExpr? visitBlock(Block node) {
+    node.statements.forEach(_visitWithoutResult);
     return null;
   }
 
   @override
-  TypeExpr visitAssertBlock(AssertBlock node) {
+  TypeExpr? visitAssertBlock(AssertBlock node) {
     if (!kRemoveAsserts) {
-      node.statements.forEach(_visit);
+      node.statements.forEach(_visitWithoutResult);
     }
     return null;
   }
 
   @override
-  TypeExpr visitBreakStatement(BreakStatement node) {
-    _variableValuesAfterLabeledStatements ??=
-        <LabeledStatement, List<TypeExpr>>{};
-    final state = _variableValuesAfterLabeledStatements[node.target];
+  TypeExpr? visitBreakStatement(BreakStatement node) {
+    var afterLabels = _variableValuesAfterLabeledStatements;
+    if (afterLabels == null) {
+      _variableValuesAfterLabeledStatements =
+          afterLabels = <LabeledStatement, List<TypeExpr?>>{};
+    }
+    final state = afterLabels[node.target];
     if (state != null) {
       _mergeVariableValues(state, _variableValues);
     } else {
-      _variableValuesAfterLabeledStatements[node.target] = _variableValues;
+      afterLabels[node.target] = _variableValues;
     }
     _variableValues = _makeEmptyVariableValues();
     return null;
   }
 
   @override
-  TypeExpr visitContinueSwitchStatement(ContinueSwitchStatement node) {
+  TypeExpr? visitContinueSwitchStatement(ContinueSwitchStatement node) {
     _mergeVariableValuesToJoins(
-        _variableValues, _joinsAtSwitchCases[node.target]);
+        _variableValues, _joinsAtSwitchCases![node.target]!);
     _variableValues = _makeEmptyVariableValues();
     return null;
   }
 
   @override
-  TypeExpr visitDoStatement(DoStatement node) {
-    final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
-    _visit(node.body);
+  TypeExpr? visitDoStatement(DoStatement node) {
+    final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
+    _visitWithoutResult(node.body);
     final trueState = _cloneVariableValues(_variableValues);
     final falseState = _cloneVariableValues(_variableValues);
     _visitCondition(node.condition, trueState, falseState);
@@ -1970,39 +1975,39 @@
   }
 
   @override
-  TypeExpr visitEmptyStatement(EmptyStatement node) => null;
+  TypeExpr? visitEmptyStatement(EmptyStatement node) => null;
 
   @override
-  TypeExpr visitExpressionStatement(ExpressionStatement node) {
+  TypeExpr? visitExpressionStatement(ExpressionStatement node) {
     _visit(node.expression);
     return null;
   }
 
   @override
-  TypeExpr visitForInStatement(ForInStatement node) {
+  TypeExpr? visitForInStatement(ForInStatement node) {
     _visit(node.iterable);
     // TODO(alexmarkov): try to infer more precise type from 'iterable'
     _declareVariableWithStaticType(node.variable);
 
-    final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
+    final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
     final stateAfterLoop = _cloneVariableValues(_variableValues);
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     _mergeVariableValuesToJoins(_variableValues, joins);
     _variableValues = stateAfterLoop;
     return null;
   }
 
   @override
-  TypeExpr visitForStatement(ForStatement node) {
+  TypeExpr? visitForStatement(ForStatement node) {
     node.variables.forEach(visitVariableDeclaration);
-    final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
+    final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
     final trueState = _cloneVariableValues(_variableValues);
     final falseState = _cloneVariableValues(_variableValues);
     if (node.condition != null) {
-      _visitCondition(node.condition, trueState, falseState);
+      _visitCondition(node.condition!, trueState, falseState);
     }
     _variableValues = trueState;
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     node.updates.forEach(_visit);
     _mergeVariableValuesToJoins(_variableValues, joins);
     // Kernel represents 'break;' as a BreakStatement referring to a
@@ -2014,7 +2019,7 @@
   }
 
   @override
-  TypeExpr visitFunctionDeclaration(FunctionDeclaration node) {
+  TypeExpr? visitFunctionDeclaration(FunctionDeclaration node) {
     // TODO(alexmarkov): support function types.
     node.variable.annotations.forEach(_visit);
     _declareVariableWithStaticType(node.variable);
@@ -2023,18 +2028,18 @@
   }
 
   @override
-  TypeExpr visitIfStatement(IfStatement node) {
+  TypeExpr? visitIfStatement(IfStatement node) {
     final trueState = _cloneVariableValues(_variableValues);
     final falseState = _cloneVariableValues(_variableValues);
     _visitCondition(node.condition, trueState, falseState);
 
     _variableValues = trueState;
-    _visit(node.then);
+    _visitWithoutResult(node.then);
     final stateAfter = _variableValues;
 
     _variableValues = falseState;
     if (node.otherwise != null) {
-      _visit(node.otherwise);
+      _visitWithoutResult(node.otherwise!);
     }
 
     _mergeVariableValues(stateAfter, _variableValues);
@@ -2043,8 +2048,8 @@
   }
 
   @override
-  TypeExpr visitLabeledStatement(LabeledStatement node) {
-    _visit(node.body);
+  TypeExpr? visitLabeledStatement(LabeledStatement node) {
+    _visitWithoutResult(node.body);
     final state = _variableValuesAfterLabeledStatements?.remove(node);
     if (state != null) {
       _mergeVariableValues(_variableValues, state);
@@ -2053,34 +2058,35 @@
   }
 
   @override
-  TypeExpr visitReturnStatement(ReturnStatement node) {
-    TypeExpr ret =
-        (node.expression != null) ? _visit(node.expression) : _nullType;
-    if (_returnValue != null) {
-      _returnValue.values.add(ret);
-    }
+  TypeExpr? visitReturnStatement(ReturnStatement node) {
+    final expression = node.expression;
+    TypeExpr ret = (expression != null) ? _visit(expression) : _nullType;
+    _returnValue?.values.add(ret);
     _variableValues = _makeEmptyVariableValues();
     return null;
   }
 
   @override
-  TypeExpr visitSwitchStatement(SwitchStatement node) {
+  TypeExpr? visitSwitchStatement(SwitchStatement node) {
     _visit(node.expression);
     // Insert joins at each case in case there are 'continue' statements.
     final stateOnEntry = _variableValues;
-    final variableValuesAtCaseEntry = <SwitchCase, List<TypeExpr>>{};
-    _joinsAtSwitchCases ??= <SwitchCase, List<Join>>{};
+    final variableValuesAtCaseEntry = <SwitchCase, List<TypeExpr?>>{};
+    Map<SwitchCase, List<Join?>>? joinsAtSwitchCases = _joinsAtSwitchCases;
+    if (joinsAtSwitchCases == null) {
+      _joinsAtSwitchCases = joinsAtSwitchCases = <SwitchCase, List<Join?>>{};
+    }
     for (var switchCase in node.cases) {
       _variableValues = _cloneVariableValues(stateOnEntry);
-      _joinsAtSwitchCases[switchCase] =
+      joinsAtSwitchCases[switchCase] =
           _insertJoinsForModifiedVariables(node, false);
       variableValuesAtCaseEntry[switchCase] = _variableValues;
     }
     bool hasDefault = false;
     for (var switchCase in node.cases) {
-      _variableValues = variableValuesAtCaseEntry[switchCase];
+      _variableValues = variableValuesAtCaseEntry[switchCase]!;
       switchCase.expressions.forEach(_visit);
-      _visit(switchCase.body);
+      _visitWithoutResult(switchCase.body);
       hasDefault = hasDefault || switchCase.isDefault;
     }
     if (!hasDefault) {
@@ -2090,21 +2096,21 @@
   }
 
   @override
-  TypeExpr visitTryCatch(TryCatch node) {
+  TypeExpr? visitTryCatch(TryCatch node) {
     final joins = _insertJoinsForModifiedVariables(node, true);
     final stateAfterTry = _cloneVariableValues(_variableValues);
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     _restoreVariableCellsAfterTry(joins);
-    List<TypeExpr> stateAfterCatch;
+    List<TypeExpr?>? stateAfterCatch;
     for (var catchClause in node.catches) {
       _variableValues = _cloneVariableValues(stateAfterTry);
       if (catchClause.exception != null) {
-        _declareVariableWithStaticType(catchClause.exception);
+        _declareVariableWithStaticType(catchClause.exception!);
       }
       if (catchClause.stackTrace != null) {
-        _declareVariableWithStaticType(catchClause.stackTrace);
+        _declareVariableWithStaticType(catchClause.stackTrace!);
       }
-      _visit(catchClause.body);
+      _visitWithoutResult(catchClause.body);
       if (stateAfterCatch == null) {
         stateAfterCatch = _variableValues;
       } else {
@@ -2112,38 +2118,39 @@
       }
     }
     _variableValues = stateAfterTry;
-    _mergeVariableValues(_variableValues, stateAfterCatch);
+    _mergeVariableValues(_variableValues, stateAfterCatch!);
     return null;
   }
 
   @override
-  TypeExpr visitTryFinally(TryFinally node) {
+  TypeExpr? visitTryFinally(TryFinally node) {
     final joins = _insertJoinsForModifiedVariables(node, true);
     final stateAfterTry = _cloneVariableValues(_variableValues);
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     _restoreVariableCellsAfterTry(joins);
     _variableValues = stateAfterTry;
-    _visit(node.finalizer);
+    _visitWithoutResult(node.finalizer);
     return null;
   }
 
   @override
-  TypeExpr visitVariableDeclaration(VariableDeclaration node) {
+  TypeExpr? visitVariableDeclaration(VariableDeclaration node) {
     node.annotations.forEach(_visit);
+    final initializer = node.initializer;
     final TypeExpr initialValue =
-        node.initializer == null ? _nullType : _visit(node.initializer);
+        initializer == null ? _nullType : _visit(initializer);
     _declareVariable(node, initialValue);
     return null;
   }
 
   @override
-  TypeExpr visitWhileStatement(WhileStatement node) {
-    final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
+  TypeExpr? visitWhileStatement(WhileStatement node) {
+    final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
     final trueState = _cloneVariableValues(_variableValues);
     final falseState = _cloneVariableValues(_variableValues);
     _visitCondition(node.condition, trueState, falseState);
     _variableValues = trueState;
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     _mergeVariableValuesToJoins(_variableValues, joins);
     // Kernel represents 'break;' as a BreakStatement referring to a
     // LabeledStatement. We are therefore guaranteed to always have the
@@ -2154,15 +2161,15 @@
   }
 
   @override
-  TypeExpr visitYieldStatement(YieldStatement node) {
+  TypeExpr? visitYieldStatement(YieldStatement node) {
     _visit(node.expression);
     return null;
   }
 
   @override
-  TypeExpr visitFieldInitializer(FieldInitializer node) {
+  TypeExpr? visitFieldInitializer(FieldInitializer node) {
     final value = _visit(node.value);
-    final args = new Args<TypeExpr>([_receiver, value]);
+    final args = new Args<TypeExpr>([_receiver!, value]);
     _makeCall(
         node,
         new DirectSelector(node.field,
@@ -2172,17 +2179,17 @@
   }
 
   @override
-  TypeExpr visitRedirectingInitializer(RedirectingInitializer node) {
+  TypeExpr? visitRedirectingInitializer(RedirectingInitializer node) {
     final args = _visitArguments(_receiver, node.arguments);
     _makeCall(node, new DirectSelector(node.target), args);
     return null;
   }
 
   @override
-  TypeExpr visitSuperInitializer(SuperInitializer node) {
+  TypeExpr? visitSuperInitializer(SuperInitializer node) {
     final args = _visitArguments(_receiver, node.arguments);
 
-    Constructor target = null;
+    Constructor? target = null;
     if (kPartialMixinResolution) {
       // Re-resolve target due to partial mixin resolution.
       for (var replacement in _superclass.constructors) {
@@ -2194,27 +2201,26 @@
     } else {
       target = node.target;
     }
-    assert(target != null);
-    _makeCall(node, new DirectSelector(target), args);
+    _makeCall(node, new DirectSelector(target!), args);
     return null;
   }
 
   @override
-  TypeExpr visitLocalInitializer(LocalInitializer node) {
+  TypeExpr? visitLocalInitializer(LocalInitializer node) {
     visitVariableDeclaration(node.variable);
     return null;
   }
 
   @override
-  TypeExpr visitAssertInitializer(AssertInitializer node) {
+  TypeExpr? visitAssertInitializer(AssertInitializer node) {
     if (!kRemoveAsserts) {
-      _visit(node.statement);
+      _visitWithoutResult(node.statement);
     }
     return null;
   }
 
   @override
-  TypeExpr visitInvalidInitializer(InvalidInitializer node) {
+  TypeExpr? visitInvalidInitializer(InvalidInitializer node) {
     return null;
   }
 
@@ -2226,21 +2232,21 @@
 
 class RuntimeTypeTranslatorImpl extends DartTypeVisitor<TypeExpr>
     implements RuntimeTypeTranslator {
-  final Summary summary;
-  final Map<TypeParameter, TypeExpr> functionTypeVariables;
+  final CoreTypes coreTypes;
+  final Summary? summary;
+  final Map<TypeParameter, TypeExpr>? functionTypeVariables;
   final Map<DartType, TypeExpr> typesCache = <DartType, TypeExpr>{};
-  final TypeExpr receiver;
+  final TypeExpr? receiver;
   final GenericInterfacesInfo genericInterfacesInfo;
-  final SummaryCollector summaryCollector;
 
-  RuntimeTypeTranslatorImpl(this.summaryCollector, this.summary, this.receiver,
+  RuntimeTypeTranslatorImpl(this.coreTypes, this.summary, this.receiver,
       this.functionTypeVariables, this.genericInterfacesInfo) {}
 
   // Create a type translator which can be used only for types with no free type
   // variables.
-  RuntimeTypeTranslatorImpl.forClosedTypes(this.genericInterfacesInfo)
-      : summaryCollector = null,
-        summary = null,
+  RuntimeTypeTranslatorImpl.forClosedTypes(
+      this.coreTypes, this.genericInterfacesInfo)
+      : summary = null,
         functionTypeVariables = null,
         receiver = null {}
 
@@ -2253,8 +2259,7 @@
     final substitution = Substitution.fromPairs(klass.typeParameters, typeArgs);
     final flattenedTypeArgs =
         genericInterfacesInfo.flattenedTypeArgumentsFor(klass);
-    final flattenedTypeExprs =
-        new List<TypeExpr>.filled(flattenedTypeArgs.length, null);
+    final flattenedTypeExprs = <TypeExpr>[];
 
     bool createConcreteType = true;
     bool allUnknown = true;
@@ -2263,7 +2268,7 @@
           translate(substitution.substituteType(flattenedTypeArgs[i]));
       if (typeExpr is! UnknownType) allUnknown = false;
       if (typeExpr is Statement) createConcreteType = false;
-      flattenedTypeExprs[i] = typeExpr;
+      flattenedTypeExprs.add(typeExpr);
     }
 
     if (allUnknown) return type;
@@ -2273,7 +2278,7 @@
           type.cls, new List<Type>.from(flattenedTypeExprs));
     } else {
       final instantiate = new CreateConcreteType(type.cls, flattenedTypeExprs);
-      summary.add(instantiate);
+      summary!.add(instantiate);
       return instantiate;
     }
   }
@@ -2323,8 +2328,7 @@
         type.classNode.typeParameters, type.typeArguments);
     final flattenedTypeArgs =
         genericInterfacesInfo.flattenedTypeArgumentsFor(type.classNode);
-    final flattenedTypeExprs =
-        new List<TypeExpr>.filled(flattenedTypeArgs.length, null);
+    final flattenedTypeExprs = <TypeExpr>[];
 
     bool createRuntimeType = true;
     for (var i = 0; i < flattenedTypeArgs.length; ++i) {
@@ -2332,7 +2336,7 @@
           translate(substitution.substituteType(flattenedTypeArgs[i]));
       if (typeExpr == const UnknownType()) return const UnknownType();
       if (typeExpr is! RuntimeType) createRuntimeType = false;
-      flattenedTypeExprs[i] = typeExpr;
+      flattenedTypeExprs.add(typeExpr);
     }
 
     if (createRuntimeType) {
@@ -2342,7 +2346,7 @@
     } else {
       final instantiate = new CreateRuntimeType(
           type.classNode, type.nullability, flattenedTypeExprs);
-      summary.add(instantiate);
+      summary!.add(instantiate);
       return instantiate;
     }
   }
@@ -2357,32 +2361,32 @@
           <RuntimeType>[typeArg]);
     } else {
       final instantiate = new CreateRuntimeType(
-          summaryCollector._environment.coreTypes.deprecatedFutureOrClass,
+          coreTypes.deprecatedFutureOrClass,
           type.nullability,
           <TypeExpr>[typeArg]);
-      summary.add(instantiate);
+      summary!.add(instantiate);
       return instantiate;
     }
   }
 
   @override
   visitTypeParameterType(TypeParameterType type) {
+    final functionTypeVariables = this.functionTypeVariables;
     if (functionTypeVariables != null) {
       final result = functionTypeVariables[type.parameter];
       if (result != null) return result;
     }
     if (type.parameter.parent is! Class) return const UnknownType();
     final interfaceClass = type.parameter.parent as Class;
-    assert(receiver != null);
     // Undetermined nullability is equivalent to nonNullable when
     // instantiating type parameter, so convert it right away.
     Nullability nullability = type.nullability;
     if (nullability == Nullability.undetermined) {
       nullability = Nullability.nonNullable;
     }
-    final extract = new Extract(receiver, interfaceClass,
+    final extract = new Extract(receiver!, interfaceClass,
         interfaceClass.typeParameters.indexOf(type.parameter), nullability);
-    summary.add(extract);
+    summary!.add(extract);
     return extract;
   }
 }
@@ -2402,7 +2406,7 @@
 
   Type _getStaticType(Constant constant) =>
       summaryCollector._typesBuilder.fromStaticType(
-          constant.getType(summaryCollector._staticTypeContext), false);
+          constant.getType(summaryCollector._staticTypeContext!), false);
 
   @override
   defaultConstant(Constant constant) {
@@ -2449,7 +2453,7 @@
     for (final Constant entry in constant.entries) {
       typeFor(entry);
     }
-    final Class concreteClass = summaryCollector.target
+    final Class? concreteClass = summaryCollector.target
         .concreteConstListLiteralClass(summaryCollector._environment.coreTypes);
     if (concreteClass != null) {
       return new ConcreteType(
@@ -2475,7 +2479,16 @@
 
   @override
   Type visitStaticTearOffConstant(StaticTearOffConstant constant) {
-    final Member member = constant.procedure;
+    final Procedure member = constant.target;
+    summaryCollector._entryPointsListener
+        .addRawCall(new DirectSelector(member));
+    summaryCollector._entryPointsListener.recordTearOff(member);
+    return _getStaticType(constant);
+  }
+
+  @override
+  Type visitConstructorTearOffConstant(ConstructorTearOffConstant constant) {
+    final Member member = constant.target;
     summaryCollector._entryPointsListener
         .addRawCall(new DirectSelector(member));
     if (member is Constructor) {
diff --git a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
index 2cfe329..0080748 100644
--- a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
+++ b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
@@ -16,7 +16,7 @@
   final Map<Class, Map<Name, int>> _methodOrSetterMemberIds = {};
 
   final UnionFind _unionFind = UnionFind();
-  List<int> _selectorIdForMemberId;
+  late List<int?> _selectorIdForMemberId;
 
   TableSelectorAssigner(Component component) {
     for (Library library in component.libraries) {
@@ -42,20 +42,21 @@
     }
   }
 
-  Map<Name, int> _memberIdsForClass(Class cls, {bool getter}) {
+  Map<Name, int> _memberIdsForClass(Class? cls, {required bool getter}) {
     if (cls == null) return {};
 
     final cache = getter ? _getterMemberIds : _methodOrSetterMemberIds;
 
     // Already computed for this class?
-    Map<Name, int> memberIds = cache[cls];
-    if (memberIds != null) return memberIds;
+    final cachedMemberIds = cache[cls];
+    if (cachedMemberIds != null) return cachedMemberIds;
 
     // Merge maps from supertypes.
-    memberIds = Map.from(_memberIdsForClass(cls.superclass, getter: getter));
+    final memberIds =
+        Map<Name, int>.from(_memberIdsForClass(cls.superclass, getter: getter));
     for (Supertype impl in cls.implementedTypes) {
       _memberIdsForClass(impl.classNode, getter: getter).forEach((name, id) {
-        final int firstId = memberIds[name];
+        final int? firstId = memberIds[name];
         if (firstId == null) {
           memberIds[name] = id;
         } else if (firstId != id) {
@@ -97,9 +98,9 @@
     return cache[cls] = memberIds;
   }
 
-  int _selectorIdForMember(Member member, {bool getter}) {
+  int _selectorIdForMember(Member member, {required bool getter}) {
     final map = getter ? _getterMemberIds : _methodOrSetterMemberIds;
-    int memberId = map[member.enclosingClass][member.name];
+    int? memberId = map[member.enclosingClass!]![member.name];
     if (memberId == null) {
       assert(member is Procedure &&
               ((identical(map, _getterMemberIds) &&
@@ -113,7 +114,7 @@
       return ProcedureAttributesMetadata.kInvalidSelectorId;
     }
     memberId = _unionFind.find(memberId);
-    int selectorId = _selectorIdForMemberId[memberId];
+    int? selectorId = _selectorIdForMemberId[memberId];
     if (selectorId == null) {
       _selectorIdForMemberId[memberId] = selectorId = metadata.addSelector();
     }
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index e9473dd..e964f61 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -3,15 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Transformations based on type flow analysis.
-library vm.transformations.type_flow.transformer;
 
 import 'dart:core' hide Type;
 
 import 'package:kernel/target/targets.dart';
 import 'package:kernel/ast.dart' hide Statement, StatementVisitor;
+import 'package:kernel/ast.dart' as ast show Statement;
 import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
 import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+import 'package:kernel/class_hierarchy.dart'
+    show ClassHierarchy, ClosedWorldClassHierarchy;
 import 'package:kernel/library_index.dart' show LibraryIndex;
 import 'package:kernel/type_environment.dart';
 
@@ -40,16 +41,18 @@
 /// Assumes strong mode and closed world.
 Component transformComponent(
     Target target, CoreTypes coreTypes, Component component,
-    {PragmaAnnotationParser matcher,
+    {PragmaAnnotationParser? matcher,
     bool treeShakeSignatures: true,
     bool treeShakeWriteOnlyFields: true,
     bool treeShakeProtobufs: false}) {
   void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
   final hierarchy = new ClassHierarchy(component, coreTypes,
-      onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
+          onAmbiguousSupertypes: ignoreAmbiguousSupertypes)
+      as ClosedWorldClassHierarchy;
   final types = new TypeEnvironment(coreTypes, hierarchy);
   final libraryIndex = new LibraryIndex.all(component);
-  final genericInterfacesInfo = new GenericInterfacesInfoImpl(hierarchy);
+  final genericInterfacesInfo =
+      new GenericInterfacesInfoImpl(coreTypes, hierarchy);
   final protobufHandler = treeShakeProtobufs
       ? ProtobufHandler.forComponent(component, coreTypes)
       : null;
@@ -70,7 +73,7 @@
       protobufHandler,
       matcher);
 
-  Procedure main = component.mainMethod;
+  Procedure? main = component.mainMethod;
 
   // `main` can be null, roots can also come from @pragma("vm:entry-point").
   if (main != null) {
@@ -146,7 +149,7 @@
         if (!f.isStatic &&
             !f.isLate &&
             f.initializer != null &&
-            mayHaveSideEffects(f.initializer))
+            mayHaveSideEffects(f.initializer!))
           f
     ];
     if (fields.isEmpty) return;
@@ -170,7 +173,7 @@
       };
       final List<Initializer> newInitializers = [];
       for (Field f in fields) {
-        Expression initExpr = f.initializer;
+        Expression initExpr = f.initializer!;
         if (!isFirst) {
           initExpr = CloneVisitorNotMembers().clone(initExpr);
         }
@@ -201,7 +204,7 @@
 class CleanupAnnotations extends RecursiveVisitor {
   final Class externalNameClass;
   final Class pragmaClass;
-  final ProtobufHandler protobufHandler;
+  final ProtobufHandler? protobufHandler;
 
   CleanupAnnotations(
       CoreTypes coreTypes, LibraryIndex index, this.protobufHandler)
@@ -235,7 +238,7 @@
         return (cls == externalNameClass) ||
             (cls == pragmaClass) ||
             (protobufHandler != null &&
-                protobufHandler.usesAnnotationClass(cls));
+                protobufHandler!.usesAnnotationClass(cls));
       }
     }
     return false;
@@ -252,11 +255,11 @@
       : super(_typeFlowAnalysis.environment.coreTypes, component, hierarchy);
 
   @override
-  DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget,
+  DirectCallMetadata? getDirectCall(TreeNode node, Member? interfaceTarget,
       {bool setter = false}) {
     final callSite = _typeFlowAnalysis.callSite(node);
     if (callSite != null) {
-      final Member singleTarget = fieldMorpher
+      final Member? singleTarget = fieldMorpher
           .getMorphedMember(callSite.monomorphicTarget, isSetter: setter);
       if (singleTarget != null) {
         return new DirectCallMetadata(
@@ -280,12 +283,13 @@
   final UnboxingInfoMetadataRepository _unboxingInfoMetadata;
   final UnboxingInfoManager _unboxingInfo;
   final Class _intClass;
-  Constant _nullConstant;
+  late final Constant _nullConstant = NullConstant();
 
   AnnotateKernel(Component component, this._typeFlowAnalysis, this.fieldMorpher,
       this._tableSelectorAssigner, this._unboxingInfo)
       : _directCallMetadataRepository =
-            component.metadata[DirectCallMetadataRepository.repositoryTag],
+            component.metadata[DirectCallMetadataRepository.repositoryTag]
+                as DirectCallMetadataRepository,
         _inferredTypeMetadata = new InferredTypeMetadataRepository(),
         _unreachableNodeMetadata = new UnreachableNodeMetadataRepository(),
         _procedureAttributesMetadata =
@@ -305,12 +309,10 @@
     return _directCallMetadataRepository.mapping.containsKey(node);
   }
 
-  InferredType _convertType(Type type,
+  InferredType? _convertType(Type type,
       {bool skipCheck: false, bool receiverNotInt: false}) {
-    assert(type != null);
-
-    Class concreteClass;
-    Constant constantValue;
+    Class? concreteClass;
+    Constant? constantValue;
     bool isInt = false;
 
     final nullable = type is NullableType;
@@ -321,7 +323,7 @@
     if (nullable && type == const EmptyType()) {
       concreteClass =
           _typeFlowAnalysis.environment.coreTypes.deprecatedNullClass;
-      constantValue = _nullConstant ??= new NullConstant();
+      constantValue = _nullConstant;
     } else {
       concreteClass = type.getConcreteClass(_typeFlowAnalysis.hierarchyCache);
 
@@ -334,9 +336,9 @@
       }
     }
 
-    List<DartType> typeArgs;
+    List<DartType?>? typeArgs;
     if (type is ConcreteType && type.typeArgs != null) {
-      typeArgs = type.typeArgs
+      typeArgs = type.typeArgs!
           .take(type.numImmediateTypeArgs)
           .map((t) =>
               t is UnknownType ? null : (t as RuntimeType).representedType)
@@ -371,7 +373,7 @@
     _unreachableNodeMetadata.mapping[node] = const UnreachableNode();
   }
 
-  void _annotateCallSite(TreeNode node, Member interfaceTarget) {
+  void _annotateCallSite(TreeNode node, Member? interfaceTarget) {
     final callSite = _typeFlowAnalysis.callSite(node);
     if (callSite == null) return;
     if (!callSite.isReachable) {
@@ -402,7 +404,7 @@
         if (interfaceTarget == null ||
             _typeFlowAnalysis.hierarchyCache.hierarchy.isSubtypeOf(
                 _typeFlowAnalysis.hierarchyCache.coreTypes.intClass,
-                interfaceTarget.enclosingClass)) {
+                interfaceTarget.enclosingClass!)) {
           markReceiverNotInt = true;
         }
       }
@@ -443,35 +445,33 @@
   void _annotateMember(Member member) {
     if (_typeFlowAnalysis.isMemberUsed(member)) {
       if (member is Field) {
-        _setInferredType(member, _typeFlowAnalysis.fieldType(member));
+        _setInferredType(member, _typeFlowAnalysis.fieldType(member)!);
       } else {
-        Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member);
+        Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member)!;
         final uncheckedParameters =
             _typeFlowAnalysis.uncheckedParameters(member);
-        assert(argTypes != null);
 
         final int firstParamIndex =
             numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
 
-        final positionalParams = member.function.positionalParameters;
+        final positionalParams = member.function!.positionalParameters;
         assert(argTypes.positionalCount ==
             firstParamIndex + positionalParams.length);
 
         for (int i = 0; i < positionalParams.length; i++) {
           _setInferredType(
               positionalParams[i], argTypes.values[firstParamIndex + i],
-              skipCheck: uncheckedParameters.contains(positionalParams[i]));
+              skipCheck: uncheckedParameters!.contains(positionalParams[i]));
         }
 
         // TODO(dartbug.com/32292): make sure parameters are sorted in kernel
         // AST and iterate parameters in parallel, without lookup.
         final names = argTypes.names;
         for (int i = 0; i < names.length; i++) {
-          final param = findNamedParameter(member.function, names[i]);
-          assert(param != null);
+          final param = findNamedParameter(member.function!, names[i])!;
           _setInferredType(param,
               argTypes.values[firstParamIndex + positionalParams.length + i],
-              skipCheck: uncheckedParameters.contains(param));
+              skipCheck: uncheckedParameters!.contains(param));
         }
 
         // TODO(alexmarkov): figure out how to pass receiver type.
@@ -518,7 +518,7 @@
     // interface target, and table dispatch calls need selector IDs for all
     // interface targets.
     if (member.isInstanceMember) {
-      final original = fieldMorpher.getOriginalMember(member);
+      final original = fieldMorpher.getOriginalMember(member)!;
       final attrs = new ProcedureAttributesMetadata(
           methodOrSetterCalledDynamically:
               _typeFlowAnalysis.isCalledDynamically(original),
@@ -686,11 +686,11 @@
   final Set<Member> _usedMembers = new Set<Member>();
   final Set<Extension> _usedExtensions = new Set<Extension>();
   final Set<Typedef> _usedTypedefs = new Set<Typedef>();
-  FieldMorpher fieldMorpher;
-  _TreeShakerTypeVisitor typeVisitor;
-  _TreeShakerConstantVisitor constantVisitor;
-  _TreeShakerPass1 _pass1;
-  _TreeShakerPass2 _pass2;
+  late final FieldMorpher fieldMorpher;
+  late final _TreeShakerTypeVisitor typeVisitor;
+  late final _TreeShakerConstantVisitor constantVisitor;
+  late final _TreeShakerPass1 _pass1;
+  late final _TreeShakerPass2 _pass2;
 
   TreeShaker(Component component, this.typeFlowAnalysis,
       {this.treeShakeWriteOnlyFields: true}) {
@@ -731,7 +731,7 @@
               (!f.isStatic &&
                   f.initializer != null &&
                   isFieldInitializerReachable(f) &&
-                  mayHaveSideEffects(f.initializer)) ||
+                  mayHaveSideEffects(f.initializer!)) ||
               (f.isLate && f.isFinal)) ||
       isMemberReferencedFromNativeCode(f) ||
       _isInstanceFieldOfAllocatedEnum(f);
@@ -742,8 +742,8 @@
   bool _isInstanceFieldOfAllocatedEnum(Field node) =>
       !node.isStatic &&
       node.enclosingClass != null &&
-      node.enclosingClass.isEnum &&
-      isClassAllocated(node.enclosingClass);
+      node.enclosingClass!.isEnum &&
+      isClassAllocated(node.enclosingClass!);
 
   void addClassUsedInType(Class c) {
     if (_classesUsedInType.add(c)) {
@@ -774,7 +774,7 @@
         _usedClasses.add(enclosingClass);
       }
 
-      FunctionNode func = null;
+      FunctionNode? func = null;
       if (m is Field) {
         m.type.accept(typeVisitor);
       } else if (m is Procedure) {
@@ -783,19 +783,19 @@
           m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
               m.concreteForwardingStubTarget,
               isSetter: m.isSetter);
-          addUsedMember(m.concreteForwardingStubTarget);
+          addUsedMember(m.concreteForwardingStubTarget!);
         }
         if (m.abstractForwardingStubTarget != null) {
           m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
               m.abstractForwardingStubTarget,
               isSetter: m.isSetter);
-          addUsedMember(m.abstractForwardingStubTarget);
+          addUsedMember(m.abstractForwardingStubTarget!);
         }
         if (m.memberSignatureOrigin != null) {
           m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
               m.memberSignatureOrigin,
               isSetter: m.isSetter);
-          addUsedMember(m.memberSignatureOrigin);
+          addUsedMember(m.memberSignatureOrigin!);
         }
       } else if (m is Constructor) {
         func = m.function;
@@ -818,8 +818,7 @@
         final extension = m.enclosingLibrary.extensions.firstWhere((extension) {
           return extension.members
               .any((descriptor) => descriptor.member.asMember == m);
-        }, orElse: () => null);
-        assert(extension != null);
+        });
 
         // Ensure we retain the [Extension] itself (though members might be
         // shaken)
@@ -841,7 +840,7 @@
     if (_usedExtensions.add(node)) {
       node.annotations = const <Expression>[];
       _pass1.transformTypeParameterList(node.typeParameters, node);
-      node.onType?.accept(typeVisitor);
+      node.onType.accept(typeVisitor);
     }
   }
 
@@ -895,7 +894,7 @@
           isAbstract: true, fileUri: field.fileUri);
     }
     accessor.fileOffset = field.fileOffset;
-    field.enclosingClass.addProcedure(accessor);
+    field.enclosingClass!.addProcedure(accessor);
     _removedFields[accessor] = field;
     shaker.addUsedMember(accessor);
     return accessor;
@@ -905,7 +904,7 @@
   /// If necessary, creates a getter or setter as a replacement if target is a
   /// field which is going to be removed by the tree shaker.
   /// This method is used during tree shaker pass 1.
-  Member adjustInstanceCallTarget(Member target, {bool isSetter = false}) {
+  Member? adjustInstanceCallTarget(Member? target, {bool isSetter = false}) {
     if (target is Field && !shaker.retainField(target)) {
       final targets =
           isSetter ? _settersForRemovedFields : _gettersForRemovedFields;
@@ -920,9 +919,9 @@
 
   /// Return a member which replaced [target] in instance calls.
   /// This method can be used after tree shaking to discover replacement.
-  Member getMorphedMember(Member target, {bool isSetter = false}) {
-    if (target == null) {
-      return null;
+  Member? getMorphedMember(Member? target, {bool isSetter = false}) {
+    if (target is! Field) {
+      return target;
     }
     final targets =
         isSetter ? _settersForRemovedFields : _gettersForRemovedFields;
@@ -931,7 +930,7 @@
 
   /// Return original member which was replaced by [target] in instance calls.
   /// This method can be used after tree shaking.
-  Member getOriginalMember(Member target) {
+  Member? getOriginalMember(Member? target) {
     if (target == null) {
       return null;
     }
@@ -991,16 +990,15 @@
   final TreeShaker shaker;
   final FieldMorpher fieldMorpher;
   final TypeEnvironment environment;
-  Procedure _unsafeCast;
 
-  StaticTypeContext _staticTypeContext;
-  Member _currentMember;
+  StaticTypeContext? _staticTypeContext;
+  Member? _currentMember;
 
   StaticTypeContext get staticTypeContext =>
       _staticTypeContext ??= StaticTypeContext(currentMember, environment);
 
-  Member get currentMember => _currentMember;
-  set currentMember(Member m) {
+  Member get currentMember => _currentMember!;
+  set currentMember(Member? m) {
     _currentMember = m;
     _staticTypeContext = null;
   }
@@ -1019,7 +1017,7 @@
   }
 
   List<Expression> _flattenArguments(Arguments arguments,
-      {Expression receiver}) {
+      {Expression? receiver}) {
     final args = <Expression>[];
     if (receiver != null) {
       args.add(receiver);
@@ -1030,23 +1028,42 @@
   }
 
   bool _isThrowExpression(Expression expr) {
-    while (expr is Let) {
-      expr = (expr as Let).body;
+    for (;;) {
+      if (expr is Let) {
+        expr = expr.body;
+      } else if (expr is BlockExpression) {
+        expr = expr.value;
+      } else {
+        break;
+      }
     }
     return expr is Throw;
   }
 
-  TreeNode _evaluateArguments(List<Expression> args, Expression result) {
-    Expression node = result;
-    for (var arg in args.reversed) {
+  Expression _evaluateArguments(List<Expression> args, Expression result) {
+    final List<ast.Statement> statements = <ast.Statement>[];
+    for (var arg in args) {
       if (mayHaveSideEffects(arg)) {
-        node = Let(VariableDeclaration(null, initializer: arg), node);
+        if (arg is BlockExpression && !mayHaveSideEffects(arg.value)) {
+          statements.add(arg.body);
+        } else {
+          statements.add(ExpressionStatement(arg));
+        }
       }
     }
-    return node;
+    if (statements.isEmpty) {
+      return result;
+    }
+    // Merge nested BlockExpression nodes.
+    Expression value = result;
+    if (result is BlockExpression) {
+      statements.addAll(result.body.statements);
+      value = result.value;
+    }
+    return BlockExpression(Block(statements), value);
   }
 
-  TreeNode _makeUnreachableCall(List<Expression> args) {
+  Expression _makeUnreachableCall(List<Expression> args) {
     Expression node;
     final int last = args.indexWhere(_isThrowExpression);
     if (last >= 0) {
@@ -1068,12 +1085,12 @@
         new VariableDeclaration(null, initializer: _makeUnreachableCall(args)));
   }
 
-  NarrowNotNull _getNullTest(TreeNode node) =>
+  NarrowNotNull? _getNullTest(TreeNode node) =>
       shaker.typeFlowAnalysis.nullTest(node);
 
-  TreeNode _visitAssertNode(TreeNode node, TreeNode removalSentinel) {
+  TreeNode _visitAssertNode(TreeNode node, TreeNode? removalSentinel) {
     if (kRemoveAsserts) {
-      return removalSentinel;
+      return removalSentinel!;
     } else {
       node.transformOrRemoveChildren(this);
       return node;
@@ -1081,31 +1098,31 @@
   }
 
   @override
-  DartType visitDartType(DartType node, DartType removalSentinel) {
+  DartType visitDartType(DartType node, DartType? removalSentinel) {
     node.accept(shaker.typeVisitor);
     return node;
   }
 
   @override
-  Supertype visitSupertype(Supertype node, Supertype removalSentinel) {
+  Supertype visitSupertype(Supertype node, Supertype? removalSentinel) {
     node.accept(shaker.typeVisitor);
     return node;
   }
 
   @override
-  TreeNode visitTypedef(Typedef node, TreeNode removalSentinel) {
+  TreeNode visitTypedef(Typedef node, TreeNode? removalSentinel) {
     return node; // Do not go deeper.
   }
 
   @override
-  Extension visitExtension(Extension node, TreeNode removalSentinel) {
+  TreeNode visitExtension(Extension node, TreeNode? removalSentinel) {
     // The extension can be considered a weak node, we'll only retain it if
     // normal code references any of it's members.
     return node;
   }
 
   @override
-  TreeNode visitClass(Class node, TreeNode removalSentinel) {
+  TreeNode visitClass(Class node, TreeNode? removalSentinel) {
     if (shaker.isClassAllocated(node) ||
         shaker.isClassReferencedFromNativeCode(node)) {
       shaker.addClassUsedInType(node);
@@ -1113,13 +1130,12 @@
     transformConstructorList(node.constructors, node);
     transformProcedureList(node.procedures, node);
     transformFieldList(node.fields, node);
-    transformRedirectingFactoryConstructorList(
-        node.redirectingFactoryConstructors, node);
+    transformRedirectingFactoryList(node.redirectingFactories, node);
     return node;
   }
 
   @override
-  TreeNode defaultMember(Member node, TreeNode removalSentinel) {
+  TreeNode defaultMember(Member node, TreeNode? removalSentinel) {
     currentMember = node;
     if (shaker.isMemberBodyReachable(node)) {
       if (kPrintTrace) {
@@ -1139,7 +1155,7 @@
   }
 
   @override
-  TreeNode visitField(Field node, TreeNode removalSentinel) {
+  TreeNode visitField(Field node, TreeNode? removalSentinel) {
     currentMember = node;
     if (shaker.retainField(node)) {
       if (kPrintTrace) {
@@ -1164,21 +1180,21 @@
 
   @override
   TreeNode visitInstanceInvocation(
-      InstanceInvocation node, TreeNode removalSentinel) {
+      InstanceInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(
           _flattenArguments(node.arguments, receiver: node.receiver));
     }
-    node.interfaceTarget =
-        fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+    node.interfaceTarget = fieldMorpher
+        .adjustInstanceCallTarget(node.interfaceTarget) as Procedure;
     shaker.addUsedMember(node.interfaceTarget);
     return node;
   }
 
   @override
   TreeNode visitDynamicInvocation(
-      DynamicInvocation node, TreeNode removalSentinel) {
+      DynamicInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(
@@ -1189,7 +1205,7 @@
 
   @override
   TreeNode visitLocalFunctionInvocation(
-      LocalFunctionInvocation node, TreeNode removalSentinel) {
+      LocalFunctionInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(_flattenArguments(node.arguments));
@@ -1199,7 +1215,7 @@
 
   @override
   TreeNode visitFunctionInvocation(
-      FunctionInvocation node, TreeNode removalSentinel) {
+      FunctionInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(
@@ -1209,39 +1225,39 @@
   }
 
   @override
-  TreeNode visitEqualsCall(EqualsCall node, TreeNode removalSentinel) {
+  TreeNode visitEqualsCall(EqualsCall node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.left, node.right]);
     }
-    node.interfaceTarget =
-        fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+    node.interfaceTarget = fieldMorpher
+        .adjustInstanceCallTarget(node.interfaceTarget) as Procedure;
     shaker.addUsedMember(node.interfaceTarget);
     return node;
   }
 
   @override
-  TreeNode visitEqualsNull(EqualsNull node, TreeNode removalSentinel) {
+  TreeNode visitEqualsNull(EqualsNull node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.expression]);
     }
-    final nullTest = _getNullTest(node);
+    final nullTest = _getNullTest(node)!;
     if (nullTest.isAlwaysNull || nullTest.isAlwaysNotNull) {
-      return _evaluateArguments(
-          [node.expression], BoolLiteral(nullTest.isAlwaysNull));
+      return _evaluateArguments([node.expression],
+          BoolLiteral(nullTest.isAlwaysNull)..fileOffset = node.fileOffset);
     }
     return node;
   }
 
   @override
-  TreeNode visitInstanceGet(InstanceGet node, TreeNode removalSentinel) {
+  TreeNode visitInstanceGet(InstanceGet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver]);
     } else {
       node.interfaceTarget =
-          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget)!;
       shaker.addUsedMember(node.interfaceTarget);
       return node;
     }
@@ -1249,20 +1265,20 @@
 
   @override
   TreeNode visitInstanceTearOff(
-      InstanceTearOff node, TreeNode removalSentinel) {
+      InstanceTearOff node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver]);
     } else {
-      node.interfaceTarget =
-          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+      node.interfaceTarget = fieldMorpher
+          .adjustInstanceCallTarget(node.interfaceTarget) as Procedure;
       shaker.addUsedMember(node.interfaceTarget);
       return node;
     }
   }
 
   @override
-  TreeNode visitDynamicGet(DynamicGet node, TreeNode removalSentinel) {
+  TreeNode visitDynamicGet(DynamicGet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver]);
@@ -1273,7 +1289,7 @@
 
   @override
   TreeNode visitFunctionTearOff(
-      FunctionTearOff node, TreeNode removalSentinel) {
+      FunctionTearOff node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver]);
@@ -1283,20 +1299,20 @@
   }
 
   @override
-  TreeNode visitInstanceSet(InstanceSet node, TreeNode removalSentinel) {
+  TreeNode visitInstanceSet(InstanceSet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver, node.value]);
     } else {
       node.interfaceTarget = fieldMorpher
-          .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true);
+          .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true)!;
       shaker.addUsedMember(node.interfaceTarget);
       return node;
     }
   }
 
   @override
-  TreeNode visitDynamicSet(DynamicSet node, TreeNode removalSentinel) {
+  TreeNode visitDynamicSet(DynamicSet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver, node.value]);
@@ -1307,15 +1323,15 @@
 
   @override
   TreeNode visitSuperMethodInvocation(
-      SuperMethodInvocation node, TreeNode removalSentinel) {
+      SuperMethodInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(_flattenArguments(node.arguments));
     } else {
-      node.interfaceTarget =
-          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+      node.interfaceTarget = fieldMorpher
+          .adjustInstanceCallTarget(node.interfaceTarget) as Procedure?;
       if (node.interfaceTarget != null) {
-        shaker.addUsedMember(node.interfaceTarget);
+        shaker.addUsedMember(node.interfaceTarget!);
       }
       return node;
     }
@@ -1323,7 +1339,7 @@
 
   @override
   TreeNode visitSuperPropertyGet(
-      SuperPropertyGet node, TreeNode removalSentinel) {
+      SuperPropertyGet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([]);
@@ -1331,7 +1347,7 @@
       node.interfaceTarget =
           fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
       if (node.interfaceTarget != null) {
-        shaker.addUsedMember(node.interfaceTarget);
+        shaker.addUsedMember(node.interfaceTarget!);
       }
       return node;
     }
@@ -1339,7 +1355,7 @@
 
   @override
   TreeNode visitSuperPropertySet(
-      SuperPropertySet node, TreeNode removalSentinel) {
+      SuperPropertySet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.value]);
@@ -1347,7 +1363,7 @@
       node.interfaceTarget = fieldMorpher
           .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true);
       if (node.interfaceTarget != null) {
-        shaker.addUsedMember(node.interfaceTarget);
+        shaker.addUsedMember(node.interfaceTarget!);
       }
       return node;
     }
@@ -1355,7 +1371,7 @@
 
   @override
   TreeNode visitStaticInvocation(
-      StaticInvocation node, TreeNode removalSentinel) {
+      StaticInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(_flattenArguments(node.arguments));
@@ -1369,7 +1385,7 @@
   }
 
   @override
-  TreeNode visitStaticGet(StaticGet node, TreeNode removalSentinel) {
+  TreeNode visitStaticGet(StaticGet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([]);
@@ -1384,13 +1400,13 @@
   }
 
   @override
-  Constant visitConstant(Constant node, Constant removalSentinel) {
+  Constant visitConstant(Constant node, Constant? removalSentinel) {
     shaker.constantVisitor.analyzeConstant(node);
     return node;
   }
 
   @override
-  TreeNode visitStaticSet(StaticSet node, TreeNode removalSentinel) {
+  TreeNode visitStaticSet(StaticSet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.value]);
@@ -1407,7 +1423,7 @@
 
   @override
   TreeNode visitConstructorInvocation(
-      ConstructorInvocation node, TreeNode removalSentinel) {
+      ConstructorInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(_flattenArguments(node.arguments));
@@ -1423,7 +1439,7 @@
 
   @override
   TreeNode visitRedirectingInitializer(
-      RedirectingInitializer node, TreeNode removalSentinel) {
+      RedirectingInitializer node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableInitializer(_flattenArguments(node.arguments));
@@ -1436,7 +1452,7 @@
 
   @override
   TreeNode visitSuperInitializer(
-      SuperInitializer node, TreeNode removalSentinel) {
+      SuperInitializer node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableInitializer(_flattenArguments(node.arguments));
@@ -1448,7 +1464,7 @@
 
   @override
   TreeNode visitFieldInitializer(
-      FieldInitializer node, TreeNode removalSentinel) {
+      FieldInitializer node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableInitializer([node.value]);
@@ -1461,7 +1477,7 @@
           return LocalInitializer(
               VariableDeclaration(null, initializer: node.value));
         } else {
-          return removalSentinel;
+          return removalSentinel!;
         }
       }
       return node;
@@ -1470,26 +1486,153 @@
 
   @override
   TreeNode visitAssertStatement(
-      AssertStatement node, TreeNode removalSentinel) {
+      AssertStatement node, TreeNode? removalSentinel) {
     return _visitAssertNode(node, removalSentinel);
   }
 
   @override
-  TreeNode visitAssertBlock(AssertBlock node, TreeNode removalSentinel) {
+  TreeNode visitAssertBlock(AssertBlock node, TreeNode? removalSentinel) {
     return _visitAssertNode(node, removalSentinel);
   }
 
   @override
   TreeNode visitAssertInitializer(
-      AssertInitializer node, TreeNode removalSentinel) {
+      AssertInitializer node, TreeNode? removalSentinel) {
     return _visitAssertNode(node, removalSentinel);
   }
 
+  // Expression is an extended bool literal if it is
+  //  - a BoolLiteral
+  //  - a BlockExpression with a BoolLiteral value.
+  bool _isExtendedBoolLiteral(Expression expr) =>
+      expr is BoolLiteral ||
+      (expr is BlockExpression && expr.value is BoolLiteral);
+
+  // Returns value of an extended bool literal.
+  bool _getExtendedBoolLiteralValue(Expression expr) => (expr is BoolLiteral)
+      ? expr.value
+      : ((expr as BlockExpression).value as BoolLiteral).value;
+
+  // Returns Block corresponding to the given extended bool literal,
+  // or null if the expression is a simple bool literal.
+  Block? _getExtendedBoolLiteralBlock(Expression expr) =>
+      (expr is BoolLiteral) ? null : (expr as BlockExpression).body;
+
   @override
-  TreeNode visitAsExpression(AsExpression node, TreeNode removalSentinel) {
+  TreeNode visitIfStatement(IfStatement node, TreeNode? removalSentinel) {
+    final condition = transform(node.condition);
+    if (_isExtendedBoolLiteral(condition)) {
+      final bool conditionValue = _getExtendedBoolLiteralValue(condition);
+      final Block? conditionBlock = _getExtendedBoolLiteralBlock(condition);
+      ast.Statement? body;
+      if (conditionValue) {
+        body = transform(node.then);
+      } else {
+        if (node.otherwise != null) {
+          body = transformOrRemoveStatement(node.otherwise!);
+        }
+      }
+      if (conditionBlock != null) {
+        if (body != null) {
+          conditionBlock.addStatement(body);
+        }
+        return conditionBlock;
+      } else {
+        return body ?? EmptyStatement();
+      }
+    }
+    node.condition = condition..parent = node;
+    node.then = transform(node.then)..parent = node;
+    if (node.otherwise != null) {
+      node.otherwise = transformOrRemoveStatement(node.otherwise!);
+      node.otherwise?.parent = node;
+    }
+    return node;
+  }
+
+  @override
+  visitConditionalExpression(
+      ConditionalExpression node, TreeNode? removalSentinel) {
+    final condition = transform(node.condition);
+    if (_isExtendedBoolLiteral(condition)) {
+      final bool value = _getExtendedBoolLiteralValue(condition);
+      final Expression expr = transform(value ? node.then : node.otherwise);
+      if (condition is BlockExpression) {
+        condition.value = expr;
+        expr.parent = condition;
+        return condition;
+      } else {
+        return expr;
+      }
+    }
+    node.condition = condition..parent = node;
+    node.then = transform(node.then)..parent = node;
+    node.otherwise = transform(node.otherwise)..parent = node;
+    node.staticType = visitDartType(node.staticType, cannotRemoveSentinel);
+    return node;
+  }
+
+  @override
+  TreeNode visitNot(Not node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
-    TypeCheck check = shaker.typeFlowAnalysis.explicitCast(node);
-    if (check != null && check.canAlwaysSkip) {
+    final operand = node.operand;
+    if (_isExtendedBoolLiteral(operand)) {
+      final bool value = _getExtendedBoolLiteralValue(operand);
+      if (operand is BlockExpression) {
+        (operand.value as BoolLiteral).value = !value;
+      } else {
+        (operand as BoolLiteral).value = !value;
+      }
+      return operand;
+    }
+    return node;
+  }
+
+  @override
+  TreeNode visitLogicalExpression(
+      LogicalExpression node, TreeNode? removalSentinel) {
+    final left = transform(node.left);
+    final operatorEnum = node.operatorEnum;
+    if (_isExtendedBoolLiteral(left)) {
+      final leftValue = _getExtendedBoolLiteralValue(left);
+      if (leftValue && operatorEnum == LogicalExpressionOperator.OR) {
+        return left;
+      } else if (!leftValue && operatorEnum == LogicalExpressionOperator.AND) {
+        return left;
+      }
+    }
+    final right = transform(node.right);
+    // Without sound null safety arguments of logical expression
+    // are implicitly checked for null, so transform the node only
+    // if using sound null safety or it evaluates to a bool literal.
+    if (_isExtendedBoolLiteral(left) &&
+        (shaker.typeFlowAnalysis.target.flags.enableNullSafety ||
+            _isExtendedBoolLiteral(right))) {
+      return _evaluateArguments([left], right);
+    }
+    node.left = left..parent = node;
+    node.right = right..parent = node;
+    return node;
+  }
+
+  @override
+  TreeNode visitIsExpression(IsExpression node, TreeNode? removalSentinel) {
+    TypeCheck? check = shaker.typeFlowAnalysis.isTest(node);
+    if (check != null && (check.alwaysFail || check.alwaysPass)) {
+      final operand = transform(node.operand);
+      final result = BoolLiteral(!check.alwaysFail)
+        ..fileOffset = node.fileOffset;
+      return _evaluateArguments([operand], result);
+    }
+    node.transformOrRemoveChildren(this);
+    return node;
+  }
+
+  @override
+  TreeNode visitAsExpression(AsExpression node, TreeNode? removalSentinel) {
+    node.transformOrRemoveChildren(this);
+    TypeCheck? check = shaker.typeFlowAnalysis.explicitCast(node);
+    if (check != null && check.alwaysPass) {
       return StaticInvocation(
           unsafeCast, Arguments([node.operand], types: [node.type]))
         ..fileOffset = node.fileOffset;
@@ -1498,9 +1641,9 @@
   }
 
   @override
-  TreeNode visitNullCheck(NullCheck node, TreeNode removalSentinel) {
+  TreeNode visitNullCheck(NullCheck node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
-    final nullTest = _getNullTest(node);
+    final nullTest = _getNullTest(node)!;
     if (nullTest.isAlwaysNotNull) {
       return StaticInvocation(
           unsafeCast,
@@ -1511,12 +1654,9 @@
     return node;
   }
 
-  Procedure get unsafeCast {
-    _unsafeCast ??= shaker.typeFlowAnalysis.environment.coreTypes.index
-        .getTopLevelMember('dart:_internal', 'unsafeCast');
-    assert(_unsafeCast != null);
-    return _unsafeCast;
-  }
+  late final Procedure unsafeCast = shaker
+      .typeFlowAnalysis.environment.coreTypes.index
+      .getTopLevelProcedure('dart:_internal', 'unsafeCast');
 }
 
 /// The second pass of [TreeShaker]. It is called after set of used
@@ -1532,7 +1672,7 @@
   void transformComponent(Component component) {
     component.transformOrRemoveChildren(this);
     for (Source source in component.uriToSource.values) {
-      source?.constantCoverageConstructors?.removeWhere((Reference reference) {
+      source.constantCoverageConstructors?.removeWhere((Reference reference) {
         Member node = reference.asMember;
         return !shaker.isMemberUsed(node);
       });
@@ -1540,7 +1680,7 @@
   }
 
   @override
-  TreeNode visitLibrary(Library node, TreeNode removalSentinel) {
+  TreeNode visitLibrary(Library node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     // The transformer API does not iterate over `Library.additionalExports`,
     // so we manually delete the references to shaken nodes.
@@ -1560,12 +1700,12 @@
   }
 
   @override
-  Typedef visitTypedef(Typedef node, TreeNode removalSentinel) {
-    return shaker.isTypedefUsed(node) ? node : removalSentinel;
+  TreeNode visitTypedef(Typedef node, TreeNode? removalSentinel) {
+    return shaker.isTypedefUsed(node) ? node : removalSentinel!;
   }
 
   @override
-  Class visitClass(Class node, TreeNode removalSentinel) {
+  TreeNode visitClass(Class node, TreeNode? removalSentinel) {
     if (!shaker.isClassUsed(node)) {
       debugPrint('Dropped class ${node.name}');
       // Ensure that kernel file writer will not be able to
@@ -1576,7 +1716,7 @@
           "been repurposed for ${node.reference.node}.");
       node.reference.canonicalName?.unbind();
       Statistics.classesDropped++;
-      return removalSentinel; // Remove the class.
+      return removalSentinel!; // Remove the class.
     }
 
     if (!shaker.isClassUsedInType(node)) {
@@ -1607,7 +1747,7 @@
   }
 
   @override
-  Member defaultMember(Member node, TreeNode removalSentinel) {
+  TreeNode defaultMember(Member node, TreeNode? removalSentinel) {
     if (!shaker.isMemberUsed(node)) {
       // Ensure that kernel file writer will not be able to
       // write a dangling reference to the deleted member.
@@ -1619,10 +1759,10 @@
         node.getterReference.canonicalName?.unbind();
         if (node.hasSetter) {
           assert(
-              node.setterReference.node == node,
+              node.setterReference!.node == node,
               "Trying to remove canonical name from reference on $node which "
-              "has been repurposed for ${node.setterReference.node}.");
-          node.setterReference.canonicalName?.unbind();
+              "has been repurposed for ${node.setterReference!.node}.");
+          node.setterReference!.canonicalName?.unbind();
         }
       } else {
         assert(
@@ -1632,13 +1772,13 @@
         node.reference.canonicalName?.unbind();
       }
       Statistics.membersDropped++;
-      return removalSentinel;
+      return removalSentinel!;
     }
 
     if (!shaker.isMemberBodyReachable(node)) {
       if (node is Procedure) {
         // Remove body of unused member.
-        if (!node.isStatic && node.enclosingClass.isAbstract) {
+        if (!node.isStatic && node.enclosingClass!.isAbstract) {
           node.isAbstract = true;
           node.function.body = null;
         } else {
@@ -1681,7 +1821,7 @@
   }
 
   @override
-  Extension visitExtension(Extension node, TreeNode removalSentinel) {
+  TreeNode visitExtension(Extension node, TreeNode? removalSentinel) {
     if (shaker.isExtensionUsed(node)) {
       int writeIndex = 0;
       for (int i = 0; i < node.members.length; ++i) {
@@ -1692,7 +1832,7 @@
         // member was already removed or it will be removed later.
         final Reference memberReference = descriptor.member;
         final bool isBound = memberReference.node != null;
-        if (isBound && shaker.isMemberUsed(memberReference.node)) {
+        if (isBound && shaker.isMemberUsed(memberReference.asMember)) {
           node.members[writeIndex++] = descriptor;
         }
       }
@@ -1702,7 +1842,7 @@
       assert(node.members.length > 0);
       return node;
     }
-    return removalSentinel;
+    return removalSentinel!;
   }
 
   void _makeUnreachableBody(FunctionNode function) {
@@ -1723,7 +1863,7 @@
   }
 
   @override
-  TreeNode defaultTreeNode(TreeNode node, TreeNode removalSentinel) {
+  TreeNode defaultTreeNode(TreeNode node, TreeNode? removalSentinel) {
     return node; // Do not traverse into other nodes.
   }
 }
@@ -1795,7 +1935,12 @@
 
   @override
   visitStaticTearOffConstant(StaticTearOffConstant constant) {
-    shaker.addUsedMember(constant.procedure);
+    shaker.addUsedMember(constant.target);
+  }
+
+  @override
+  visitConstructorTearOffConstant(ConstructorTearOffConstant constant) {
+    shaker.addUsedMember(constant.target);
   }
 
   @override
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index a5e9561..3ed7b9b 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Declares the type system used by global type flow analysis.
-library vm.transformations.type_flow.types;
 
 import 'dart:core' hide Type;
 
@@ -136,10 +135,7 @@
   /// values can flow through the program.
   Type specializeTypeCone(TFClass base, {bool allowWideCone = false});
 
-  Type _cachedIntType;
-  Type get intType {
-    return _cachedIntType ??= fromStaticType(coreTypes.intLegacyRawType, true);
-  }
+  late final Type intType = fromStaticType(coreTypes.intLegacyRawType, true);
 }
 
 /// Base class for type expressions.
@@ -149,7 +145,14 @@
 
   /// Returns computed type of this type expression.
   /// [types] is the list of types computed for the statements in the summary.
-  Type getComputedType(List<Type> types);
+  Type getComputedType(List<Type?> types);
+}
+
+/// Kind of a subtype test: subtype/cast/'as' test or instance check/'is' test.
+/// There is a subtle difference in how these tests handle null value.
+enum SubtypeTestKind {
+  Subtype,
+  IsTest,
 }
 
 /// Base class for types inferred by the type flow analysis.
@@ -165,18 +168,18 @@
   /// Create a type representing arbitrary nullable object (`dynamic`).
   factory Type.nullableAny() => new NullableType(const AnyType());
 
-  Class getConcreteClass(TypeHierarchy typeHierarchy) => null;
+  Class? getConcreteClass(TypeHierarchy typeHierarchy) => null;
 
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) => false;
 
   // Returns 'true' if this type will definitely pass a runtime type-check
   // against 'runtimeType'. Returns 'false' if the test might fail (e.g. due to
   // an approximation).
-  bool isSubtypeOfRuntimeType(
-      TypeHierarchy typeHierarchy, RuntimeType runtimeType);
+  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+      RuntimeType runtimeType, SubtypeTestKind kind);
 
   @override
-  Type getComputedType(List<Type> types) => this;
+  Type getComputedType(List<Type?> types) => this;
 
   /// Order of precedence for evaluation of union/intersection.
   int get order;
@@ -239,7 +242,8 @@
   @override
   Type intersection(Type other, TypeHierarchy typeHierarchy) => this;
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+  bool isSubtypeOfRuntimeType(
+      TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
     return true;
   }
 }
@@ -250,7 +254,6 @@
   final Type baseType;
 
   NullableType(this.baseType) {
-    assert(baseType != null);
     assert(baseType is! NullableType);
   }
 
@@ -269,12 +272,27 @@
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
       baseType.isSubtypeOf(typeHierarchy, cls);
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
-    if (typeHierarchy.nullSafety &&
-        other.nullability == Nullability.nonNullable) {
-      return false;
+  bool isSubtypeOfRuntimeType(
+      TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
+    switch (kind) {
+      case SubtypeTestKind.Subtype:
+        if (typeHierarchy.nullSafety &&
+            other.nullability == Nullability.nonNullable) {
+          return false;
+        }
+        break;
+      case SubtypeTestKind.IsTest:
+        if (other.nullability != Nullability.nullable) {
+          final rhs = other._type;
+          if (!(rhs is InterfaceType &&
+              rhs.nullability == Nullability.legacy &&
+              rhs.classNode == typeHierarchy.coreTypes.objectClass)) {
+            return false;
+          }
+        }
+        break;
     }
-    return baseType.isSubtypeOfRuntimeType(typeHierarchy, other);
+    return baseType.isSubtypeOfRuntimeType(typeHierarchy, other, kind);
   }
 
   @override
@@ -347,7 +365,8 @@
     return other;
   }
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+  bool isSubtypeOfRuntimeType(
+      TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
     final rhs = other._type;
     return (rhs is DynamicType) ||
         (rhs is VoidType) ||
@@ -361,7 +380,9 @@
 class SetType extends Type {
   /// List of concrete types, sorted by classId.
   final List<ConcreteType> types;
-  int _hashCode;
+
+  @override
+  late final int hashCode = _computeHashCode();
 
   /// Creates a new SetType using list of concrete types sorted by classId.
   SetType(this.types) {
@@ -369,9 +390,6 @@
     assert(isSorted(types));
   }
 
-  @override
-  int get hashCode => _hashCode ??= _computeHashCode();
-
   int _computeHashCode() {
     int hash = 1237;
     for (var t in types) {
@@ -401,8 +419,9 @@
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
       types.every((ConcreteType t) => t.isSubtypeOf(typeHierarchy, cls));
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) =>
-      types.every((t) => t.isSubtypeOfRuntimeType(typeHierarchy, other));
+  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other,
+          SubtypeTestKind kind) =>
+      types.every((t) => t.isSubtypeOfRuntimeType(typeHierarchy, other, kind));
 
   @override
   int get order => TypeOrder.Set.index;
@@ -443,8 +462,8 @@
     return types;
   }
 
-  static List<ConcreteType> _intersectLists(
-      List<ConcreteType> types1, List<ConcreteType> types2) {
+  static List<ConcreteType> _intersectLists(List<ConcreteType> types1,
+      List<ConcreteType> types2, TypeHierarchy typeHierarchy) {
     int i1 = 0;
     int i2 = 0;
     List<ConcreteType> types = <ConcreteType>[];
@@ -464,9 +483,9 @@
             t2.constant == null) {
           types.add(t1);
         } else {
-          final intersect = t1.intersection(t2, null);
+          final intersect = t1.intersection(t2, typeHierarchy);
           if (intersect is! EmptyType) {
-            types.add(intersect);
+            types.add(intersect as ConcreteType);
           }
         }
         ++i1;
@@ -531,7 +550,8 @@
       return other.intersection(this, typeHierarchy);
     }
     if (other is SetType) {
-      List<ConcreteType> list = _intersectLists(types, other.types);
+      List<ConcreteType> list =
+          _intersectLists(types, other.types, typeHierarchy);
       final size = list.length;
       if (size == 0) {
         return const EmptyType();
@@ -567,7 +587,7 @@
   ConeType(this.cls);
 
   @override
-  Class getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy
+  Class? getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy
       .specializeTypeCone(cls, allowWideCone: true)
       .getConcreteClass(typeHierarchy);
 
@@ -575,7 +595,8 @@
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
       typeHierarchy.isSubtype(this.cls.classNode, cls);
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+  bool isSubtypeOfRuntimeType(
+      TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
     final rhs = other._type;
     if (rhs is DynamicType || rhs is VoidType) return true;
     if (rhs is InterfaceType) {
@@ -668,7 +689,7 @@
   WideConeType(TFClass cls) : super(cls);
 
   @override
-  Class getConcreteClass(TypeHierarchy typeHierarchy) => null;
+  Class? getConcreteClass(TypeHierarchy typeHierarchy) => null;
 
   @override
   int get hashCode => (cls.id + 41) & kHashMask;
@@ -755,7 +776,9 @@
 /// or `null` object).
 class ConcreteType extends Type implements Comparable<ConcreteType> {
   final TFClass cls;
-  int _hashCode;
+
+  @override
+  late final int hashCode = _computeHashCode();
 
   // May be null if there are no type arguments constraints. The type arguments
   // should represent type sets, i.e. `UnknownType` or `RuntimeType`. The type
@@ -768,19 +791,19 @@
   // 'numImmediateTypeArgs' is the length of the prefix of 'typeArgs' which
   // holds the type arguments to the class itself.
   final int numImmediateTypeArgs;
-  final List<Type> typeArgs;
+  final List<Type>? typeArgs;
 
   // May be null if constant value is not inferred.
-  final Constant constant;
+  final Constant? constant;
 
-  ConcreteType(this.cls, [List<Type> typeArgs_, this.constant])
+  ConcreteType(this.cls, [List<Type>? typeArgs_, this.constant])
       : typeArgs = typeArgs_,
         numImmediateTypeArgs =
             typeArgs_ != null ? cls.classNode.typeParameters.length : 0 {
     // TODO(alexmarkov): support closures
     assert(!cls.classNode.isAbstract);
     assert(typeArgs == null || cls.classNode.typeParameters.isNotEmpty);
-    assert(typeArgs == null || typeArgs.any((t) => t is RuntimeType));
+    assert(typeArgs == null || typeArgs!.any((t) => t is RuntimeType));
   }
 
   ConcreteType get raw => cls.concreteType;
@@ -793,8 +816,8 @@
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class other) =>
       typeHierarchy.isSubtype(cls.classNode, other);
 
-  bool isSubtypeOfRuntimeType(
-      TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
+  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+      RuntimeType runtimeType, SubtypeTestKind kind) {
     final rhs = runtimeType._type;
     if (rhs is DynamicType || rhs is VoidType) return true;
     if (rhs is InterfaceType) {
@@ -811,7 +834,7 @@
 
       if (rhs.typeArguments.isEmpty) return true;
 
-      List<Type> usableTypeArgs = typeArgs;
+      List<Type>? usableTypeArgs = typeArgs;
       if (usableTypeArgs == null) {
         if (cls.classNode.typeParameters.isEmpty) {
           usableTypeArgs =
@@ -834,7 +857,7 @@
         }
         assert(ta is RuntimeType);
         if (!ta.isSubtypeOfRuntimeType(
-            typeHierarchy, runtimeType.typeArgs[i])) {
+            typeHierarchy, runtimeType.typeArgs![i], SubtypeTestKind.Subtype)) {
           return false;
         }
       }
@@ -849,28 +872,26 @@
         } else {
           final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor(
               cls.classNode, typeHierarchy.coreTypes.futureClass);
-          typeArg = typeArgs[interfaceOffset];
+          typeArg = typeArgs![interfaceOffset];
         }
         final RuntimeType lhs =
             typeArg is RuntimeType ? typeArg : RuntimeType(DynamicType(), null);
         return lhs.isSubtypeOfRuntimeType(
-            typeHierarchy, runtimeType.typeArgs[0]);
+            typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
       } else {
-        return isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+        return isSubtypeOfRuntimeType(
+            typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
       }
     }
     return false;
   }
 
-  @override
-  int get hashCode => _hashCode ??= _computeHashCode();
-
   int _computeHashCode() {
     int hash = cls.hashCode ^ 0x1234 & kHashMask;
     // We only need to hash the first type arguments vector, since the type
     // arguments of the implemented interfaces are implied by it.
     for (int i = 0; i < numImmediateTypeArgs; ++i) {
-      hash = (((hash * 31) & kHashMask) + typeArgs[i].hashCode) & kHashMask;
+      hash = (((hash * 31) & kHashMask) + typeArgs![i].hashCode) & kHashMask;
     }
     hash = ((hash * 31) & kHashMask) + constant.hashCode;
     return hash;
@@ -886,7 +907,7 @@
       }
       if (this.typeArgs != null) {
         for (int i = 0; i < numImmediateTypeArgs; ++i) {
-          if (this.typeArgs[i] != other.typeArgs[i]) {
+          if (this.typeArgs![i] != other.typeArgs![i]) {
             return false;
           }
         }
@@ -913,10 +934,10 @@
     final StringBuffer buf = new StringBuffer();
     buf.write("_T (${cls}");
     if (typeArgs != null) {
-      buf.write("<${typeArgs.take(numImmediateTypeArgs).join(', ')}>");
+      buf.write("<${typeArgs!.take(numImmediateTypeArgs).join(', ')}>");
     }
     if (constant != null) {
-      buf.write(", ${nodeToText(constant)}");
+      buf.write(", ${nodeToText(constant!)}");
     }
     buf.write(")");
     return buf.toString();
@@ -968,17 +989,21 @@
         return this;
       }
 
-      List<Type> mergedTypeArgs;
-      if (typeArgs == null) {
-        mergedTypeArgs = other.typeArgs;
-      } else if (other.typeArgs == null) {
-        mergedTypeArgs = typeArgs;
+      List<Type>? mergedTypeArgs;
+      final thisTypeArgs = this.typeArgs;
+      final otherTypeArgs = other.typeArgs;
+      if (thisTypeArgs == null) {
+        mergedTypeArgs = otherTypeArgs;
+      } else if (otherTypeArgs == null) {
+        mergedTypeArgs = thisTypeArgs;
       } else {
-        mergedTypeArgs = new List<Type>.filled(typeArgs.length, null);
+        assert(thisTypeArgs.length == otherTypeArgs.length);
+        mergedTypeArgs =
+            new List<Type>.filled(thisTypeArgs.length, const EmptyType());
         bool hasRuntimeType = false;
-        for (int i = 0; i < typeArgs.length; ++i) {
+        for (int i = 0; i < thisTypeArgs.length; ++i) {
           final merged =
-              typeArgs[i].intersection(other.typeArgs[i], typeHierarchy);
+              thisTypeArgs[i].intersection(otherTypeArgs[i], typeHierarchy);
           if (merged is EmptyType) {
             return const EmptyType();
           } else if (merged is RuntimeType) {
@@ -991,7 +1016,7 @@
         }
       }
 
-      Constant mergedConstant;
+      Constant? mergedConstant;
       if (constant == null) {
         mergedConstant = other.constant;
       } else if (other.constant == null || constant == other.constant) {
@@ -1033,7 +1058,7 @@
   final DartType _type; // Doesn't contain type args.
 
   final int numImmediateTypeArgs;
-  final List<RuntimeType> typeArgs;
+  final List<RuntimeType>? typeArgs;
 
   RuntimeType(DartType type, this.typeArgs)
       : _type = type,
@@ -1041,14 +1066,12 @@
             ? type.classNode.typeParameters.length
             : (type is FutureOrType ? 1 : 0) {
     if (_type is InterfaceType && numImmediateTypeArgs > 0) {
-      assert(typeArgs != null);
-      assert(typeArgs.length >= numImmediateTypeArgs);
+      assert(typeArgs!.length >= numImmediateTypeArgs);
       assert((_type as InterfaceType)
           .typeArguments
           .every((t) => t == const DynamicType()));
     } else if (_type is FutureOrType) {
-      assert(typeArgs != null);
-      assert(typeArgs.length >= numImmediateTypeArgs);
+      assert(typeArgs!.length >= numImmediateTypeArgs);
       DartType typeArgument = (_type as FutureOrType).typeArgument;
       assert(typeArgument == const DynamicType());
     } else {
@@ -1069,25 +1092,27 @@
     final type = _type;
     if (type is InterfaceType && typeArgs != null) {
       final klass = type.classNode;
-      final typeArguments = typeArgs
+      final typeArguments = typeArgs!
           .take(klass.typeParameters.length)
           .map((pt) => pt.representedType)
           .toList();
       return new InterfaceType(klass, type.nullability, typeArguments);
     } else if (type is FutureOrType) {
-      return new FutureOrType(typeArgs[0].representedType, type.nullability);
+      return new FutureOrType(typeArgs![0].representedType, type.nullability);
     } else {
       return type;
     }
   }
 
   @override
-  int get hashCode {
+  late final int hashCode = _computeHashCode();
+
+  int _computeHashCode() {
     int hash = _type.hashCode ^ 0x1234 & kHashMask;
     // Only hash by the type arguments of the class. The type arguments of
     // supertypes are are implied by them.
     for (int i = 0; i < numImmediateTypeArgs; ++i) {
-      hash = (((hash * 31) & kHashMask) + typeArgs[i].hashCode) & kHashMask;
+      hash = (((hash * 31) & kHashMask) + typeArgs![i].hashCode) & kHashMask;
     }
     return hash;
   }
@@ -1098,7 +1123,7 @@
     if (other is RuntimeType) {
       if (other._type != _type) return false;
       assert(numImmediateTypeArgs == other.numImmediateTypeArgs);
-      return typeArgs == null || listEquals(typeArgs, other.typeArgs);
+      return typeArgs == null || listEquals(typeArgs!, other.typeArgs!);
     }
     return false;
   }
@@ -1110,7 +1135,7 @@
         : "${nodeToText(_type)}";
     final typeArgsStrs = (numImmediateTypeArgs == 0)
         ? ""
-        : "<${typeArgs.take(numImmediateTypeArgs).map((t) => "$t").join(", ")}>";
+        : "<${typeArgs!.take(numImmediateTypeArgs).map((t) => "$t").join(", ")}>";
     final nullability = _type.nullability.suffix;
     return "$head$typeArgsStrs$nullability";
   }
@@ -1147,8 +1172,11 @@
   Class getConcreteClass(TypeHierarchy typeHierarchy) =>
       throw "ERROR: ConcreteClass does not support getConcreteClass.";
 
-  bool isSubtypeOfRuntimeType(
-      TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
+  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+      RuntimeType runtimeType, SubtypeTestKind kind) {
+    if (kind != SubtypeTestKind.Subtype) {
+      throw 'RuntimeType could be only tested for subtyping.';
+    }
     final rhs = runtimeType._type;
     if (typeHierarchy.nullSafety &&
         _type.nullability == Nullability.nullable &&
@@ -1168,14 +1196,15 @@
       if (_type is InterfaceType) {
         Class thisClass = (_type as InterfaceType).classNode;
         if (thisClass == typeHierarchy.coreTypes.futureClass) {
-          return typeArgs[0]
-              .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+          return typeArgs![0].isSubtypeOfRuntimeType(
+              typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
         } else {
-          return isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+          return isSubtypeOfRuntimeType(
+              typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
         }
       } else if (_type is FutureOrType) {
-        return typeArgs[0]
-            .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+        return typeArgs![0].isSubtypeOfRuntimeType(
+            typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
       }
     }
 
@@ -1203,7 +1232,7 @@
       return true;
     }
 
-    List<Type> usableTypeArgs = typeArgs;
+    List<Type>? usableTypeArgs = typeArgs;
     if (usableTypeArgs == null) {
       assert(thisClass.typeParameters.isEmpty);
       usableTypeArgs =
@@ -1214,8 +1243,8 @@
     assert(usableTypeArgs.length - interfaceOffset >=
         runtimeType.numImmediateTypeArgs);
     for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) {
-      if (!usableTypeArgs[interfaceOffset + i]
-          .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[i])) {
+      if (!usableTypeArgs[interfaceOffset + i].isSubtypeOfRuntimeType(
+          typeHierarchy, runtimeType.typeArgs![i], SubtypeTestKind.Subtype)) {
         return false;
       }
     }
@@ -1262,7 +1291,11 @@
     throw "ERROR: UnknownType does not support intersection with ${other.runtimeType}";
   }
 
-  bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+  bool isSubtypeOfRuntimeType(
+      TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
+    if (kind != SubtypeTestKind.Subtype) {
+      throw 'UnknownType could be only tested for subtyping.';
+    }
     final rhs = other._type;
     return (rhs is DynamicType) ||
         (rhs is VoidType) ||
diff --git a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
index 03f7ef2..682cf58 100644
--- a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
+++ b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
@@ -28,12 +28,12 @@
         _coreTypes = typeFlowAnalysis.environment.coreTypes,
         _nativeCodeOracle = typeFlowAnalysis.nativeCodeOracle;
 
-  UnboxingInfoMetadata getUnboxingInfoOfMember(Member member) {
-    final UnboxingInfoMetadata info = _memberInfo[member];
+  UnboxingInfoMetadata? getUnboxingInfoOfMember(Member member) {
+    final UnboxingInfoMetadata? info = _memberInfo[member];
     if (member is Procedure && member.isGetter) {
       // Remove placeholder parameter info slot for setters that the getter is
       // grouped with.
-      return UnboxingInfoMetadata(0)..returnInfo = info.returnInfo;
+      return UnboxingInfoMetadata(0)..returnInfo = info!.returnInfo;
     }
     return info;
   }
@@ -79,8 +79,8 @@
           ? (member.hasSetter ? 1 : 0)
           : member is Procedure && member.isGetter
               ? 1
-              : member.function.requiredParameterCount;
-      UnboxingInfoMetadata info;
+              : member.function!.requiredParameterCount;
+      UnboxingInfoMetadata? info;
       if (member.isInstanceMember) {
         int selectorId =
             member is Field || member is Procedure && member.isGetter
@@ -119,20 +119,18 @@
   void _updateUnboxingInfoOfMember(
       Member member, TypeFlowAnalysis typeFlowAnalysis) {
     if (typeFlowAnalysis.isMemberUsed(member)) {
-      final UnboxingInfoMetadata unboxingInfo = _memberInfo[member];
+      final UnboxingInfoMetadata unboxingInfo = _memberInfo[member]!;
       if (_cannotUnbox(member)) {
         unboxingInfo.unboxedArgsInfo.length = 0;
         unboxingInfo.returnInfo = UnboxingInfoMetadata.kBoxed;
         return;
       }
       if (member is Procedure || member is Constructor) {
-        final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member);
-        assert(argTypes != null);
-
+        final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member)!;
         final int firstParamIndex =
             numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
 
-        final positionalParams = member.function.positionalParameters;
+        final positionalParams = member.function!.positionalParameters;
         assert(argTypes.positionalCount ==
             firstParamIndex + positionalParams.length);
 
diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart
index 815736c..c85dfc7 100644
--- a/pkg/vm/lib/transformations/type_flow/utils.dart
+++ b/pkg/vm/lib/transformations/type_flow/utils.dart
@@ -6,6 +6,7 @@
 /// analysis.
 library vm.transformations.type_flow.utils;
 
+import 'package:collection/collection.dart' show IterableExtension;
 import 'package:kernel/ast.dart';
 import 'package:kernel/src/printer.dart';
 
@@ -121,9 +122,8 @@
   return true;
 }
 
-VariableDeclaration findNamedParameter(FunctionNode function, String name) {
-  return function.namedParameters
-      .firstWhere((p) => p.name == name, orElse: () => null);
+VariableDeclaration? findNamedParameter(FunctionNode function, String name) {
+  return function.namedParameters.firstWhereOrNull((p) => p.name == name);
 }
 
 class Histogram<K> {
@@ -141,7 +141,7 @@
     print(
         '-------------------------------------------------------------------');
     List<K> keys = values.keys.toList();
-    keys.sort((k1, k2) => values[k1].compareTo(values[k2]));
+    keys.sort((k1, k2) => values[k1]!.compareTo(values[k2]!));
     final cut = keys.length < n ? 0 : keys.length - n;
     for (int i = keys.length - 1; i >= cut; --i) {
       final k = keys[i];
@@ -374,7 +374,7 @@
 };
 
 extension NullabilitySuffix on Nullability {
-  String get suffix => nullabilitySuffix[this];
+  String get suffix => nullabilitySuffix[this]!;
 }
 
 bool mayHaveSideEffects(Expression node) {
diff --git a/pkg/vm/lib/transformations/unreachable_code_elimination.dart b/pkg/vm/lib/transformations/unreachable_code_elimination.dart
index 10bd958..d61b8f4 100644
--- a/pkg/vm/lib/transformations/unreachable_code_elimination.dart
+++ b/pkg/vm/lib/transformations/unreachable_code_elimination.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.12
-
 import 'package:kernel/ast.dart';
 
 /// Simple unreachable code elimination: removes asserts and if statements
diff --git a/pkg/vm/pubspec.yaml b/pkg/vm/pubspec.yaml
index 95341eb..20b2cd7 100644
--- a/pkg/vm/pubspec.yaml
+++ b/pkg/vm/pubspec.yaml
@@ -4,7 +4,7 @@
 publish_to: none
 
 environment:
-  sdk: "^2.7.0"
+  sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
   args: ^1.4.4
@@ -15,9 +15,8 @@
     path: ../front_end
   kernel:
     path: ../kernel
-  meta:
-    path: ../meta
   package_config: any
+  collection: ^1.15.0
 
 dev_dependencies:
   expect:
diff --git a/pkg/vm/test/common_test_utils.dart b/pkg/vm/test/common_test_utils.dart
index a45a95d..1ff586a 100644
--- a/pkg/vm/test/common_test_utils.dart
+++ b/pkg/vm/test/common_test_utils.dart
@@ -35,11 +35,11 @@
 }
 
 Future<Component> compileTestCaseToKernelProgram(Uri sourceUri,
-    {Target target,
+    {Target? target,
     bool enableSuperMixins = false,
-    List<String> experimentalFlags,
-    Map<String, String> environmentDefines,
-    Uri packagesFileUri}) async {
+    List<String>? experimentalFlags,
+    Map<String, String>? environmentDefines,
+    Uri? packagesFileUri}) async {
   final platformKernel =
       computePlatformBinariesLocation().resolve('vm_platform_strong.dill');
   target ??= new TestingVmTarget(new TargetFlags())
@@ -60,11 +60,11 @@
     };
 
   final Component component =
-      (await kernelForProgram(sourceUri, options)).component;
+      (await kernelForProgram(sourceUri, options))!.component!;
 
   // Make sure the library name is the same and does not depend on the order
   // of test cases.
-  component.mainMethod.enclosingLibrary.name = '#lib';
+  component.mainMethod!.enclosingLibrary.name = '#lib';
 
   return component;
 }
@@ -73,19 +73,19 @@
   final StringBuffer buffer = new StringBuffer();
   final printer = new Printer(buffer, showMetadata: true);
   printer.writeLibraryFile(library);
-  printer.writeConstantTable(library.enclosingComponent);
+  printer.writeConstantTable(library.enclosingComponent!);
   return buffer
       .toString()
-      .replaceAll(library.importUri.toString(), library.name);
+      .replaceAll(library.importUri.toString(), library.name!);
 }
 
 String kernelComponentToString(Component component) {
   final StringBuffer buffer = new StringBuffer();
   new Printer(buffer, showMetadata: true).writeComponentFile(component);
-  final mainLibrary = component.mainMethod.enclosingLibrary;
+  final mainLibrary = component.mainMethod!.enclosingLibrary;
   return buffer
       .toString()
-      .replaceAll(mainLibrary.importUri.toString(), mainLibrary.name);
+      .replaceAll(mainLibrary.importUri.toString(), mainLibrary.name!);
 }
 
 class DevNullSink<T> extends Sink<T> {
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 2fc1928..5b175e4 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -6,6 +6,7 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:collection/collection.dart' show IterableExtension;
 import 'package:front_end/src/api_unstable/vm.dart'
     show
         CompilerOptions,
@@ -45,8 +46,8 @@
   final options = getFreshOptions();
 
   group('basic', () {
-    Directory mytest;
-    File main;
+    late Directory mytest;
+    late File main;
 
     setUpAll(() {
       mytest = Directory.systemTemp.createTempSync('incremental');
@@ -68,7 +69,7 @@
 
       final StringBuffer buffer = new StringBuffer();
       new Printer(buffer, showMetadata: true)
-          .writeLibraryFile(component.mainMethod.enclosingLibrary);
+          .writeLibraryFile(component.mainMethod!.enclosingLibrary);
       expect(
           buffer.toString(),
           equals('library /*isNonNullableByDefault*/;\n'
@@ -90,7 +91,7 @@
 
       final StringBuffer buffer = new StringBuffer();
       new Printer(buffer, showMetadata: true)
-          .writeLibraryFile(component.mainMethod.enclosingLibrary);
+          .writeLibraryFile(component.mainMethod!.enclosingLibrary);
       expect(
           buffer.toString(),
           equals('library /*isNonNullableByDefault*/;\n'
@@ -111,13 +112,13 @@
       await compiler.compile();
       compiler.accept();
       {
-        Procedure procedure = await compiler.compileExpression(
+        Procedure? procedure = await compiler.compileExpression(
             'main', <String>[], <String>[], main.uri.toString(), null, true);
         expect(procedure, isNotNull);
         expect(errorsReported, equals(0));
       }
       {
-        Procedure procedure = await compiler.compileExpression(
+        Procedure? procedure = await compiler.compileExpression(
             'main1', <String>[], <String>[], main.uri.toString(), null, true);
         expect(procedure, isNotNull);
         expect(errorsReported, equals(1));
@@ -136,7 +137,7 @@
   Future<Set<int>> collectAndCheckCoverageData(int port, bool getAllSources,
       {bool resume: true,
       bool onGetAllVerifyCount: true,
-      Set<int> coverageForLines}) async {
+      Set<int>? coverageForLines}) async {
     RemoteVm remoteVm = new RemoteVm(port);
 
     // Wait for the script to have finished.
@@ -175,7 +176,7 @@
     // Ensure that we can get a line and column number for all reported
     // positions in the scripts we care about.
     for (Map sourceReport in sourceReports) {
-      List scripts = sourceReport["scripts"];
+      List<Map> scripts = sourceReport["scripts"].cast<Map>();
       Map<String, int> scriptIdToIndex = new Map<String, int>();
       Set<int> lib1scriptIndices = new Set<int>();
       int i = 0;
@@ -199,9 +200,9 @@
       Map<int, Map> scriptIndexToScript = new Map<int, Map>();
       for (String scriptId in scriptIdToIndex.keys) {
         Map script = await remoteVm.getObject(scriptId);
-        int scriptIdx = scriptIdToIndex[scriptId];
+        int scriptIdx = scriptIdToIndex[scriptId]!;
         scriptIndexToScript[scriptIdx] = script;
-        List tokenPosTable = script["tokenPosTable"];
+        List? tokenPosTable = script["tokenPosTable"];
         if (tokenPosTable == null) {
           errorMessages.add("Script with uri ${script['uri']} "
               "and id ${script['id']} "
@@ -213,7 +214,7 @@
         }
       }
 
-      List ranges = sourceReport["ranges"];
+      List<Map> ranges = sourceReport["ranges"].cast<Map>();
       Set<int> scriptIndexesSet = new Set<int>.from(scriptIndexToScript.keys);
       for (Map range in ranges) {
         if (scriptIndexesSet.contains(range["scriptIndex"])) {
@@ -231,7 +232,7 @@
           if (range["possibleBreakpoints"] != null) {
             for (int pos in range["possibleBreakpoints"]) positions.add(pos);
           }
-          Map script = scriptIndexToScript[range["scriptIndex"]];
+          Map script = scriptIndexToScript[range["scriptIndex"]]!;
           Set<int> knownPositions = new Set<int>();
           Map<int, int> tokenPosToLine = {};
           if (script["tokenPosTable"] != null) {
@@ -254,7 +255,7 @@
           if (coverageForLines != null) {
             for (int pos in coverage["hits"]) {
               if (lib1scriptIndices.contains(range["scriptIndex"])) {
-                coverageForLines.add(tokenPosToLine[pos]);
+                coverageForLines.add(tokenPosToLine[pos]!);
               }
             }
           }
@@ -269,10 +270,10 @@
   }
 
   group('multiple kernels', () {
-    Directory mytest;
-    File main;
-    File lib;
-    Process vm;
+    late Directory mytest;
+    late File main;
+    late File lib;
+    late Process vm;
     setUpAll(() {
       mytest = Directory.systemTemp.createTempSync('incremental');
       main = new File('${mytest.path}/main.dart')..createSync();
@@ -483,8 +484,8 @@
           .listen((String s) async {
         if (s.startsWith(kObservatoryListening)) {
           expect(observatoryPortRegExp.hasMatch(s), isTrue);
-          final match = observatoryPortRegExp.firstMatch(s);
-          port = int.parse(match.group(1));
+          final match = observatoryPortRegExp.firstMatch(s)!;
+          port = int.parse(match.group(1)!);
           await collectAndCheckCoverageData(port, true);
           if (!portLineCompleter.isCompleted) {
             portLineCompleter.complete("done");
@@ -501,12 +502,12 @@
   });
 
   group('multiple kernels constant coverage', () {
-    Directory mytest;
-    File main;
-    File lib1;
-    int lineForUnnamedConstructor;
-    int lineForNamedConstructor;
-    Process vm;
+    late Directory mytest;
+    late File main;
+    late File lib1;
+    late int lineForUnnamedConstructor;
+    late int lineForNamedConstructor;
+    late Process vm;
     setUpAll(() {
       mytest = Directory.systemTemp.createTempSync('incremental');
       main = new File('${mytest.path}/main.dart')..createSync();
@@ -592,8 +593,8 @@
         }
         if (s.startsWith(kObservatoryListening)) {
           expect(observatoryPortRegExp.hasMatch(s), isTrue);
-          final match = observatoryPortRegExp.firstMatch(s);
-          port = int.parse(match.group(1));
+          final match = observatoryPortRegExp.firstMatch(s)!;
+          port = int.parse(match.group(1)!);
           await collectAndCheckCoverageData(port, true,
               onGetAllVerifyCount: false, coverageForLines: coverageLines);
           if (!portLineCompleter.isCompleted) {
@@ -738,11 +739,11 @@
   });
 
   group('multiple kernels 2', () {
-    Directory mytest;
-    File main;
-    File lib1;
-    File lib2;
-    Process vm;
+    late Directory mytest;
+    late File main;
+    late File lib1;
+    late File lib2;
+    late Process vm;
     setUpAll(() {
       mytest = Directory.systemTemp.createTempSync('incremental');
       main = new File('${mytest.path}/main.dart')..createSync();
@@ -847,8 +848,8 @@
           .listen((String s) async {
         if (s.startsWith(kObservatoryListening)) {
           expect(observatoryPortRegExp.hasMatch(s), isTrue);
-          final match = observatoryPortRegExp.firstMatch(s);
-          port = int.parse(match.group(1));
+          final match = observatoryPortRegExp.firstMatch(s)!;
+          port = int.parse(match.group(1)!);
           Set<int> hits1 =
               await collectAndCheckCoverageData(port, true, resume: false);
           Set<int> hits2 =
@@ -869,7 +870,7 @@
   });
 
   group('reload', () {
-    Directory mytest;
+    late Directory mytest;
 
     setUpAll(() {
       mytest = Directory.systemTemp.createTempSync('incremental');
@@ -939,8 +940,8 @@
       final RegExp observatoryPortRegExp =
           new RegExp("Observatory listening on http://127.0.0.1:\([0-9]*\)");
       expect(observatoryPortRegExp.hasMatch(portLine), isTrue);
-      final match = observatoryPortRegExp.firstMatch(portLine);
-      final port = int.parse(match.group(1));
+      final match = observatoryPortRegExp.firstMatch(portLine)!;
+      final port = int.parse(match.group(1)!);
 
       var remoteVm = new RemoteVm(port);
       await remoteVm.resume();
@@ -976,7 +977,7 @@
   });
 
   group('reject', () {
-    Directory mytest;
+    late Directory mytest;
     setUpAll(() {
       mytest = Directory.systemTemp.createTempSync('incremental_reject');
     });
@@ -1023,7 +1024,7 @@
       }
       compiler.accept();
       {
-        Procedure procedure = await compiler.compileExpression(
+        Procedure? procedure = await compiler.compileExpression(
             'a', <String>[], <String>[], 'package:foo/bar.dart', 'A', true);
         expect(procedure, isNotNull);
       }
@@ -1038,7 +1039,7 @@
       }
       await compiler.reject();
       {
-        Procedure procedure = await compiler.compileExpression(
+        Procedure? procedure = await compiler.compileExpression(
             'a', <String>[], <String>[], 'package:foo/bar.dart', 'A', true);
         expect(procedure, isNotNull);
       }
@@ -1086,9 +1087,8 @@
       }
       compiler.accept();
       {
-        final Procedure procedure = await compiler.compileExpression(
-            'a', <String>[], <String>[], barUri.toString(), 'A', true);
-        expect(procedure, isNotNull);
+        final Procedure procedure = (await compiler.compileExpression(
+            'a', <String>[], <String>[], barUri.toString(), 'A', true))!;
         // Verify that the expression only has links to the only bar we know
         // about.
         final LibraryReferenceCollector lrc = new LibraryReferenceCollector();
@@ -1105,8 +1105,8 @@
       compiler.invalidate(barUri);
       {
         final Component component = await compiler.compile(entryPoint: fooUri);
-        final Library fooLib2 = component.libraries
-            .firstWhere((lib) => lib.fileUri == fooUri, orElse: () => null);
+        final Library? fooLib2 = component.libraries
+            .firstWhereOrNull((lib) => lib.fileUri == fooUri);
         expect(fooLib2, isNull);
         final Library barLib2 =
             component.libraries.firstWhere((lib) => lib.fileUri == barUri);
@@ -1128,13 +1128,12 @@
         // Verify that the saved "last known good" compnent only contains links
         // to the original 'foo' and 'bar' libraries.
         final LibraryReferenceCollector lrc = new LibraryReferenceCollector();
-        compiler.lastKnownGoodComponent.accept(lrc);
+        compiler.lastKnownGoodComponent!.accept(lrc);
         expect(lrc.librariesReferenced, equals(<Library>{fooLib, barLib}));
       }
       {
-        final Procedure procedure = await compiler.compileExpression(
-            'a', <String>[], <String>[], barUri.toString(), 'A', true);
-        expect(procedure, isNotNull);
+        final Procedure procedure = (await compiler.compileExpression(
+            'a', <String>[], <String>[], barUri.toString(), 'A', true))!;
         // Verify that the expression only has links to the original bar.
         final LibraryReferenceCollector lrc = new LibraryReferenceCollector();
         procedure.accept(lrc);
@@ -1144,8 +1143,8 @@
   });
 
   group('expression evaluation', () {
-    Directory mytest;
-    Process vm;
+    late Directory mytest;
+    late Process vm;
 
     setUpAll(() {
       mytest = Directory.systemTemp.createTempSync('expression_evaluation');
@@ -1166,7 +1165,7 @@
 
     launchBreakAndEvaluate(File scriptOrDill, String scriptUriToBreakIn,
         int lineToBreakAt, List<String> expressionsAndExpectedResults,
-        {Future Function(RemoteVm remoteVm) callback}) async {
+        {Future Function(RemoteVm remoteVm)? callback}) async {
       vm = await Process.start(Platform.resolvedExecutable, <String>[
         "--pause-isolates-on-start",
         "--enable-vm-service:0",
@@ -1188,8 +1187,8 @@
         print("vm stdout: $s");
         if (s.startsWith(kObservatoryListening)) {
           expect(observatoryPortRegExp.hasMatch(s), isTrue);
-          final match = observatoryPortRegExp.firstMatch(s);
-          port = int.parse(match.group(1));
+          final match = observatoryPortRegExp.firstMatch(s)!;
+          port = int.parse(match.group(1)!);
           RemoteVm remoteVm = new RemoteVm(port);
 
           // Wait for the script to have loaded.
@@ -1589,7 +1588,7 @@
     RemoteVm remoteVm, String scriptUriToBreakIn, int lineToBreakAt) async {
   Map scriptsMap = await remoteVm.getScripts();
   List scripts = scriptsMap["scripts"];
-  String scriptId;
+  String? scriptId;
   for (int i = 0; i < scripts.length; i++) {
     Map script = scripts[i];
     String scriptUri = script["uri"];
@@ -1600,7 +1599,7 @@
   }
   expect(scriptId, isNotNull);
 
-  return await remoteVm.addBreakpoint(scriptId, lineToBreakAt);
+  return await remoteVm.addBreakpoint(scriptId!, lineToBreakAt);
 }
 
 Future deletePossibleBreakpoint(
@@ -1641,12 +1640,12 @@
   /// An peer point used to send service protocol messages. The service
   /// protocol uses JSON rpc on top of web-sockets.
   json_rpc.Peer get rpc => _rpc ??= _createPeer();
-  json_rpc.Peer _rpc;
+  json_rpc.Peer? _rpc;
 
   /// The main isolate ID of the running VM. Needed to indicate to the VM which
   /// isolate to reload.
   FutureOr<String> get mainId async => _mainId ??= await _computeMainId();
-  String _mainId;
+  String? _mainId;
 
   RemoteVm([this.port = 8181]);
 
@@ -1699,41 +1698,34 @@
     await rpc.sendRequest('resume', {'isolateId': id});
   }
 
-  Future getIsolate() async {
+  Future<Map> getIsolate() async {
     var id = await mainId;
-    return await rpc.sendRequest('getIsolate', {'isolateId': id});
+    return (await rpc.sendRequest('getIsolate', {'isolateId': id})) as Map;
   }
 
-  Future getScripts() async {
+  Future<Map> getScripts() async {
     var id = await mainId;
-    return await rpc.sendRequest('getScripts', {
+    return (await rpc.sendRequest('getScripts', {
       'isolateId': id,
-    });
+    })) as Map;
   }
 
-  Future getSourceReport([String scriptId]) async {
+  Future<Map> getSourceReport([String? scriptId]) async {
     var id = await mainId;
-    if (scriptId != null) {
-      return await rpc.sendRequest('getSourceReport', {
-        'isolateId': id,
-        'scriptId': scriptId,
-        'reports': ['Coverage', 'PossibleBreakpoints'],
-        'forceCompile': true
-      });
-    }
-    return await rpc.sendRequest('getSourceReport', {
+    return (await rpc.sendRequest('getSourceReport', {
       'isolateId': id,
+      if (scriptId != null) 'scriptId': scriptId,
       'reports': ['Coverage', 'PossibleBreakpoints'],
-      'forceCompile': true
-    });
+      'forceCompile': true,
+    })) as Map;
   }
 
-  Future getObject(String objectId) async {
+  Future<Map> getObject(String objectId) async {
     var id = await mainId;
-    return await rpc.sendRequest('getObject', {
+    return (await rpc.sendRequest('getObject', {
       'isolateId': id,
       'objectId': objectId,
-    });
+    })) as Map;
   }
 
   Future addBreakpoint(String scriptId, int line) async {
@@ -1767,21 +1759,22 @@
     int expectGcAfter = new DateTime.now().millisecondsSinceEpoch;
     while (true) {
       var id = await mainId;
-      Map result = await rpc.sendRequest('getAllocationProfile', {
+      Map result = (await rpc.sendRequest('getAllocationProfile', {
         'isolateId': id,
         "gc": true,
-      });
-      String lastGc = result["dateLastServiceGC"];
+      })) as Map;
+      String? lastGc = result["dateLastServiceGC"];
       if (lastGc != null && int.parse(lastGc) >= expectGcAfter) return;
     }
   }
 
   /// Close any connections used to communicate with the VM.
   Future disconnect() async {
-    if (_rpc == null) return null;
+    final rpc = this._rpc;
+    if (rpc == null) return null;
     this._mainId = null;
-    if (!_rpc.isClosed) {
-      var future = _rpc.close();
+    if (!rpc.isClosed) {
+      var future = rpc.close();
       _rpc = null;
       return future;
     }
diff --git a/pkg/vm/test/kernel_front_end_test.dart b/pkg/vm/test/kernel_front_end_test.dart
index 711b616..effa84d 100644
--- a/pkg/vm/test/kernel_front_end_test.dart
+++ b/pkg/vm/test/kernel_front_end_test.dart
@@ -20,14 +20,14 @@
 const String packagesFile = '.packages';
 const String packageConfigFile = '.dart_tool/package_config.json';
 
-void testCompile(List<String> args) async {
+Future<void> testCompile(List<String> args) async {
   final compilerExitCode =
       await runCompiler(createCompilerArgParser().parse(args), '');
   expect(compilerExitCode, successExitCode);
 }
 
 main() {
-  Directory tempDir;
+  late Directory tempDir;
   setUp(() {
     var systemTempDir = Directory.systemTemp;
     tempDir = systemTempDir.createTempSync('kernel_front_end_test');
diff --git a/pkg/vm/test/modular_kernel_plus_aot_test.dart b/pkg/vm/test/modular_kernel_plus_aot_test.dart
index 8d9419d..c853b01 100644
--- a/pkg/vm/test/modular_kernel_plus_aot_test.dart
+++ b/pkg/vm/test/modular_kernel_plus_aot_test.dart
@@ -33,14 +33,14 @@
   await withTempDirectory((Uri uri) async {
     final mixinFilename = uri.resolve('mixin.dart');
     final mixinDillFilename = uri.resolve('mixin.dart.dill');
-    await File.fromUri(mixinFilename).writeAsStringSync(mixinFile);
+    File.fromUri(mixinFilename).writeAsStringSync(mixinFile);
 
     await compileToKernel(vmTarget, librariesFile, sdkSummary, packagesFile,
         mixinDillFilename, <Uri>[mixinFilename], <Uri>[]);
 
     final mainFilename = uri.resolve('main.dart');
     final mainDillFilename = uri.resolve('main.dart.dill');
-    await File.fromUri(mainFilename).writeAsStringSync(mainFile);
+    File.fromUri(mainFilename).writeAsStringSync(mainFile);
 
     await compileToKernel(vmTarget, librariesFile, sdkSummary, packagesFile,
         mainDillFilename, <Uri>[mainFilename], <Uri>[mixinDillFilename]);
@@ -96,9 +96,9 @@
     message.plainTextFormatted.forEach(print);
   }
 
-  final Component component =
+  final Component? component =
       await fe.compileComponent(state, sources, onDiagnostic);
-  final Uint8List kernel = fe.serializeComponent(component,
+  final Uint8List kernel = fe.serializeComponent(component!,
       filter: (library) => sources.contains(library.importUri));
   await File(outputFile.toFilePath()).writeAsBytes(kernel);
 }
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 023c93e..741c2b9 100644
--- a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
+++ b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
@@ -36,7 +36,7 @@
       .expand(
         (lib) => lib.classes.where((klass) =>
             klass.superclass != null &&
-            klass.superclass.name == "GeneratedMessage"),
+            klass.superclass!.name == "GeneratedMessage"),
       )
       .toList();
 
diff --git a/pkg/vm/test/transformations/to_string_transformer_test.dart b/pkg/vm/test/transformations/to_string_transformer_test.dart
index ef94ca8..34f775f 100644
--- a/pkg/vm/test/transformations/to_string_transformer_test.dart
+++ b/pkg/vm/test/transformations/to_string_transformer_test.dart
@@ -27,7 +27,7 @@
   transformComponent(component, packageUris);
   verifyComponent(component);
 
-  final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
+  final actual = kernelLibraryToString(component.mainMethod!.enclosingLibrary);
 
   compareResultWithExpectationsFile(
       testCasesUri.resolve(expectationName), actual);
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index cad4936..09831bd8 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -58,11 +58,11 @@
   void recordMemberCalledViaThis(Member target) {}
 
   @override
-  void recordTearOff(Procedure target) {}
+  void recordTearOff(Member target) {}
 }
 
 class PrintSummaries extends RecursiveVisitor {
-  SummaryCollector _summaryCollector;
+  late SummaryCollector _summaryCollector;
   final StringBuffer _buf = new StringBuffer();
 
   PrintSummaries(Target target, TypeEnvironment environment,
@@ -75,12 +75,12 @@
         new FakeEntryPointsListener(typesBuilder),
         typesBuilder,
         new NativeCodeOracle(
-            null, new ConstantPragmaAnnotationParser(coreTypes)),
-        new GenericInterfacesInfoImpl(hierarchy),
+            coreTypes.index, new ConstantPragmaAnnotationParser(coreTypes)),
+        new GenericInterfacesInfoImpl(coreTypes, hierarchy),
         /*_protobufHandler=*/ null);
   }
 
-  String print(TreeNode node) {
+  String print(Library node) {
     visitLibrary(node);
     return _buf.toString();
   }
@@ -99,10 +99,11 @@
 runTestCase(Uri source) async {
   final Target target = new TestingVmTarget(new TargetFlags());
   final Component component = await compileTestCaseToKernelProgram(source);
-  final Library library = component.mainMethod.enclosingLibrary;
+  final Library library = component.mainMethod!.enclosingLibrary;
   final CoreTypes coreTypes = new CoreTypes(component);
 
-  final ClassHierarchy hierarchy = new ClassHierarchy(component, coreTypes);
+  final ClosedWorldClassHierarchy hierarchy =
+      new ClassHierarchy(component, coreTypes) as ClosedWorldClassHierarchy;
   final typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
 
   final actual =
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
index b1e876fe..0fee483 100644
--- a/pkg/vm/test/transformations/type_flow/transformer_test.dart
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -18,12 +18,11 @@
 
 final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
 
-runTestCase(
-    Uri source, List<String> experimentalFlags, bool enableNullSafety) async {
+runTestCase(Uri source, bool enableNullSafety) async {
   final target =
       new TestingVmTarget(new TargetFlags(enableNullSafety: enableNullSafety));
-  Component component = await compileTestCaseToKernelProgram(source,
-      target: target, experimentalFlags: experimentalFlags);
+  Component component =
+      await compileTestCaseToKernelProgram(source, target: target);
 
   final coreTypes = new CoreTypes(component);
 
@@ -31,7 +30,7 @@
       matcher: new ConstantPragmaAnnotationParser(coreTypes),
       treeShakeProtobufs: true);
 
-  String actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
+  String actual = kernelLibraryToString(component.mainMethod!.enclosingLibrary);
 
   // Tests in /protobuf_handler consist of multiple libraries.
   // Include libraries with protobuf generated messages into the result.
@@ -53,7 +52,7 @@
   ensureKernelCanBeSerializedToBinary(component);
 }
 
-String argsTestName(List<String> args) {
+String? argsTestName(List<String> args) {
   if (args.length > 0) {
     return args.last;
   }
@@ -74,12 +73,7 @@
           !path.endsWith('.pb.dart') &&
           (testNameFilter == null || path.contains(testNameFilter))) {
         final bool enableNullSafety = path.endsWith('_nnbd_strong.dart');
-        final bool enableNNBD = enableNullSafety || path.endsWith('_nnbd.dart');
-        final List<String> experimentalFlags = [
-          if (enableNNBD) 'non-nullable',
-        ];
-        test(path,
-            () => runTestCase(entry.uri, experimentalFlags, enableNullSafety));
+        test(path, () => runTestCase(entry.uri, enableNullSafety));
       }
     }
   }, timeout: Timeout.none);
diff --git a/pkg/vm/test/transformations/type_flow/types_test.dart b/pkg/vm/test/transformations/type_flow/types_test.dart
index 0945917..203700be 100644
--- a/pkg/vm/test/transformations/type_flow/types_test.dart
+++ b/pkg/vm/test/transformations/type_flow/types_test.dart
@@ -21,15 +21,12 @@
 
   @override
   bool isSubtype(Class sub, Class sup) {
-    return subtypes[sup].contains(sub);
+    return subtypes[sup]!.contains(sub);
   }
 
   @override
   Type specializeTypeCone(TFClass base, {bool allowWideCone = false}) {
-    Type result = specializations[base.classNode];
-    expect(result, isNotNull,
-        reason: "specializeTypeCone($base) is not defined");
-    return result;
+    return specializations[base.classNode]!;
   }
 
   @override
@@ -102,10 +99,10 @@
   test('union-intersection', () {
     // T1 <: T3, T2 <: T3
 
-    final c1 = new Class(name: 'T1', fileUri: dummyUri);
-    final c2 = new Class(name: 'T2', fileUri: dummyUri);
-    final c3 = new Class(name: 'T3', fileUri: dummyUri);
-    final c4 = new Class(name: 'T4', fileUri: dummyUri);
+    final c1 = new Class(name: 'T1', fileUri: dummyUri)..parent = dummyLibrary;
+    final c2 = new Class(name: 'T2', fileUri: dummyUri)..parent = dummyLibrary;
+    final c3 = new Class(name: 'T3', fileUri: dummyUri)..parent = dummyLibrary;
+    final c4 = new Class(name: 'T4', fileUri: dummyUri)..parent = dummyLibrary;
 
     final tfc1 = new TFClass(1, c1);
     final tfc2 = new TFClass(2, c2);
@@ -293,9 +290,9 @@
   });
 
   test('hashcode-equals', () {
-    final c1 = new Class(name: 'C1', fileUri: dummyUri);
-    final c2 = new Class(name: 'C2', fileUri: dummyUri);
-    final c3 = new Class(name: 'C3', fileUri: dummyUri);
+    final c1 = new Class(name: 'C1', fileUri: dummyUri)..parent = dummyLibrary;
+    final c2 = new Class(name: 'C2', fileUri: dummyUri)..parent = dummyLibrary;
+    final c3 = new Class(name: 'C3', fileUri: dummyUri)..parent = dummyLibrary;
 
     final tfc1 = new TFClass(1, c1);
     final tfc2 = new TFClass(2, c2);
diff --git a/pkg/vm/test/transformations/unreachable_code_elimination_test.dart b/pkg/vm/test/transformations/unreachable_code_elimination_test.dart
index d1471bb..c433611 100644
--- a/pkg/vm/test/transformations/unreachable_code_elimination_test.dart
+++ b/pkg/vm/test/transformations/unreachable_code_elimination_test.dart
@@ -28,7 +28,7 @@
   component = transformComponent(component, /* enableAsserts = */ false);
   verifyComponent(component);
 
-  final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
+  final actual = kernelLibraryToString(component.mainMethod!.enclosingLibrary);
 
   compareResultWithExpectationsFile(source, actual);
 }
diff --git a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
index 0d07eae..328e71f 100644
--- a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
+++ b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
@@ -46,12 +46,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/a.dart" as a;
 
   static method j() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
@@ -62,12 +62,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
@@ -77,12 +77,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/g.dart" as g;
 
   static method h() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
@@ -93,12 +93,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
@@ -109,12 +109,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/b.dart" as b;
 
   static method i() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
@@ -130,12 +130,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
@@ -145,12 +145,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/h.dart" as h;
 
   static method g() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
@@ -161,12 +161,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
@@ -177,12 +177,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/i.dart" deferred as i;
 
   static method f() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
@@ -202,12 +202,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
@@ -217,12 +217,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/g.dart" deferred as g;
 
   static method e() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
@@ -238,12 +238,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
@@ -254,12 +254,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/f.dart" deferred as f;
 
   static method c() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
@@ -275,12 +275,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
@@ -290,12 +290,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/e.dart" as e;
 
   static method d() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
@@ -308,12 +308,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
@@ -323,12 +323,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/c.dart" as c;
 
   static method b() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
@@ -341,12 +341,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
@@ -356,12 +356,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/d.dart" deferred as d;
 
   static method a() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
@@ -377,12 +377,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
@@ -393,12 +393,12 @@
   import "#pkg/vm/testcases/transformations/deferred_loading/b.dart";
 
   static method main() → dynamic /* originally async */ {
-    final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+    final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
-    dart.core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+    dart.core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
@@ -413,12 +413,12 @@
         dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
         dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
     :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
index a22bad2..64dbb46 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 dynamic foo() => null;
-bool bar() => null;
+bool bar() => false;
 
 void bool_expressions() {
   if (foo()) {}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
index 625d97f..85822829 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
@@ -3,25 +3,26 @@
 RESULT: _T {}?
 ------------ bar ------------
 
-RESULT: _T {}?
+RESULT: _T (dart.core::bool, false)
 ------------ bool_expressions ------------
 t0* = _Call direct [#lib::foo] ()
-t1 = _TypeCheck (t0 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
+t1 = _TypeCheck (t0 against dart.core::bool) (for #lib::foo() as dart.core::bool)
 t2* = _Call direct [#lib::bar] ()
 t3* = _Call [dart.core::num.+] (_T (dart.core::int)+, _T (dart.core::_Smi, 1))
-i_0 = _Join [dart.core::int*] (_T (dart.core::_Smi, 0), t3)
+i_0 = _Join [dart.core::int] (_T (dart.core::_Smi, 0), t3)
 t5* = _Call [dart.core::num.<] (i_0, _T (dart.core::_Smi, 10))
 t6* = _Call direct [#lib::bar] ()
-t7* = _Call direct [#lib::foo] ()
-t8 = _Join [dynamic] (_T (dart.core::bool, true), t7)
-t9 = _TypeCheck (t8 against dart.core::bool*) (for (x ?{dynamic} true : #lib::foo()) as dart.core::bool*)
-t10* = _Call direct [#lib::bar] ()
+t7 = _TypeCheck (t6 against dart.core::bool) (for x is dart.core::bool)
+t8* = _Call direct [#lib::foo] ()
+t9 = _Join [dynamic] (_T (dart.core::bool, true), t8)
+t10 = _TypeCheck (t9 against dart.core::bool) (for (x ?{dynamic} true : #lib::foo()) as dart.core::bool)
 t11* = _Call direct [#lib::bar] ()
-t12* = _Call direct [#lib::foo] ()
-t13 = _TypeCheck (t12 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
-t14* = _Call direct [#lib::foo] ()
-t15 = _TypeCheck (t14 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
-y_0 = _Join [dart.core::bool*] (_T (dart.core::bool), _T (dart.core::bool, true))
+t12* = _Call direct [#lib::bar] ()
+t13* = _Call direct [#lib::foo] ()
+t14 = _TypeCheck (t13 against dart.core::bool) (for #lib::foo() as dart.core::bool)
+t15* = _Call direct [#lib::foo] ()
+t16 = _TypeCheck (t15 against dart.core::bool) (for #lib::foo() as dart.core::bool)
+y_0 = _Join [dart.core::bool] (_T (dart.core::bool), _T (dart.core::bool, true))
 RESULT: _T {}?
 ------------ main ------------
 
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
index 06cf7ea..d507ee0 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
@@ -11,19 +11,19 @@
 class B {
   void bar1(Object arg) {}
   dynamic get bar2 => null;
-  set bar3(int y) {}
-  int bar4;
+  set bar3(int? y) {}
+  int? bar4;
 }
 
 class C {
-  interfaceCalls(A aa, Object a2, Object a3, Object a4) {
+  interfaceCalls(A aa, Object a2, Object a3, Object? a4) {
     aa.foo1(new B());
     aa.foo3 = aa.foo2;
     a4 = aa.foo2(a2, a3, aa.foo1);
     return a4;
   }
 
-  dynamicCalls(dynamic aa, Object a2, Object a3, Object a4) {
+  dynamicCalls(dynamic aa, Object a2, Object a3, Object? a4) {
     aa.foo1(new B());
     aa.foo3 = aa.foo2;
     a4 = aa.foo2(a2, a3, aa.foo1);
@@ -32,7 +32,7 @@
 }
 
 class D extends B {
-  superCalls(Object a1, Object a2, Object a3, Object a4) {
+  superCalls(Object a1, Object a2, Object a3, Object? a4) {
     super.bar1(a1);
     super.bar3 = super.bar4;
     a4 = super.bar2(a2, a3, super.bar1);
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
index bbd410a..2731094 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
@@ -34,11 +34,11 @@
 %a2 = _Parameter #2 [_T (dart.core::Object)+?]
 %a3 = _Parameter #3 [_T (dart.core::Object)+?]
 %a4 = _Parameter #4 [_T (dart.core::Object)+?]
-t5 = _Call direct [#lib::B.] (_T (#lib::B))
-t6 = _Call [#lib::A.foo1] (%aa, _T (#lib::B))
+t5* = _Call direct [#lib::B.] (_T (#lib::B))
+t6 = _Call [#lib::A.foo1] (%aa, t5)
 t7 = _Narrow (%aa to _T ANY)
 t8* = _Call get [#lib::A.foo2] (t7)
-t9 = _TypeCheck (t8 against dart.core::int*) (for aa.{#lib::A.foo2} as dart.core::int*)
+t9 = _TypeCheck (t8 against dart.core::int) (for aa.{#lib::A.foo2} as dart.core::int)
 t10 = _Call set [#lib::A.foo3] (t7, t9)
 t11* = _Call get [#lib::A.foo1] (t7)
 t12* = _Call get [#lib::A.foo2] (t7)
@@ -50,8 +50,8 @@
 %a2 = _Parameter #2 [_T (dart.core::Object)+?]
 %a3 = _Parameter #3 [_T (dart.core::Object)+?]
 %a4 = _Parameter #4 [_T (dart.core::Object)+?]
-t5 = _Call direct [#lib::B.] (_T (#lib::B))
-t6 = _Call dynamic [foo1] (%aa, _T (#lib::B))
+t5* = _Call direct [#lib::B.] (_T (#lib::B))
+t6 = _Call dynamic [foo1] (%aa, t5)
 t7 = _Narrow (%aa to _T ANY)
 t8* = _Call dynamic get [foo2] (t7)
 t9 = _Call dynamic set [foo3] (t7, t8)
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect
index 6f36339..18d97a8 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect
@@ -4,21 +4,21 @@
 RESULT: _T {}?
 ------------ C.foo ------------
 %this = _Parameter #0 [_T (#lib::C)+]
-t1 = _Extract (%this[#lib::C/0]*)
+t1 = _Extract (%this[#lib::C/0])
 t2 = _CreateConcreteType (#lib::D @ (t1))
-t3 = _Call direct [#lib::D.] (t2)
-RESULT: t2
+t3* = _Call direct [#lib::D.] (t2)
+RESULT: t3
 ------------ C.id1 ------------
 %this = _Parameter #0 [_T (#lib::C)+]
 %x = _Parameter #1
-t2 = _Extract (%this[#lib::C/0]*)
-t3 = _TypeCheck (%x against t2) (for #lib::C.T* x;)
+t2 = _Extract (%this[#lib::C/0])
+t3 = _TypeCheck (%x against t2) (for #lib::C.T% x;)
 RESULT: t3
 ------------ C.id2 ------------
 %this = _Parameter #0 [_T (#lib::C)+]
 %x = _Parameter #1
-t2 = _Extract (%this[#lib::C/0]*)
-t3 = _TypeCheck (%x against t2) (for #lib::C.T* x;)
+t2 = _Extract (%this[#lib::C/0])
+t3 = _TypeCheck (%x against t2) (for #lib::C.T% x;)
 RESULT: t3
 ------------ D. ------------
 %this = _Parameter #0 [_T (#lib::D)+]
@@ -34,16 +34,16 @@
 RESULT: t1
 ------------ E.bar ------------
 %this = _Parameter #0 [_T (#lib::E)+]
-t1 = _Extract (%this[#lib::E/0]*)
+t1 = _Extract (%this[#lib::E/0])
 t2 = _CreateConcreteType (#lib::D @ (t1))
-t3 = _Call direct [#lib::D.] (t2)
-RESULT: t2
+t3* = _Call direct [#lib::D.] (t2)
+RESULT: t3
 ------------ E.baz ------------
 %this = _Parameter #0 [_T (#lib::E)+]
-t1 = _Extract (%this[#lib::E/1]*)
+t1 = _Extract (%this[#lib::E/1])
 t2 = _CreateConcreteType (#lib::D @ (t1))
-t3 = _Call direct [#lib::D.] (t2)
-RESULT: t2
+t3* = _Call direct [#lib::D.] (t2)
+RESULT: t3
 ------------ X. ------------
 %this = _Parameter #0 [_T (#lib::X)+]
 t1 = _Call direct [dart.core::Object.] (%this)
@@ -75,34 +75,34 @@
 ------------ C2.id3 ------------
 %this = _Parameter #0 [_T (#lib::C2)+]
 %x = _Parameter #1
-t2 = _Extract (%this[#lib::C2/0]*)
-t3 = _CreateRuntimeType (dart.core::Comparable @ (t2)*)
-t4 = _TypeCheck (%x against t3) (for dart.core::Comparable<#lib::C2.T*>* x;)
+t2 = _Extract (%this[#lib::C2/0])
+t3 = _CreateRuntimeType (dart.core::Comparable @ (t2))
+t4 = _TypeCheck (%x against t3) (for dart.core::Comparable<#lib::C2.T%> x;)
 RESULT: t4
 ------------ C2.id4 ------------
 %this = _Parameter #0 [_T (#lib::C2)+]
 %x = _Parameter #1
-t2 = _Extract (%this[#lib::C2/0]*)
-t3 = _CreateRuntimeType (#lib::I @ (t2)*)
-t4 = _CreateRuntimeType (#lib::K @ (t3)*)
-t5 = _TypeCheck (%x against t4) (for #lib::K<#lib::I<#lib::C2.T*>*>* x;)
+t2 = _Extract (%this[#lib::C2/0])
+t3 = _CreateRuntimeType (#lib::I @ (t2))
+t4 = _CreateRuntimeType (#lib::K @ (t3))
+t5 = _TypeCheck (%x against t4) (for #lib::K<#lib::I<#lib::C2.T%>> x;)
 RESULT: t5
 ------------ main ------------
-t0 = _Call direct [#lib::C.] (_T (#lib::C<dart.core::int*>))
-t1 = _Call [#lib::C.foo] (_T (#lib::C<dart.core::int*>))
-t2 = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t3 = _Call [#lib::E.foo] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t4 = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t5 = _Call [#lib::E.bar] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t6 = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t7* = _Call [#lib::E.baz] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t8 = _Call direct [#lib::C.] (_T (#lib::C<#lib::Y*>))
-t9 = _Call direct [#lib::Y.] (_T (#lib::Y))
-t10 = _Call [#lib::C.id1] (_T (#lib::C<#lib::Y*>), _T (#lib::Y))
-t11 = _Call direct [#lib::Z.] (_T (#lib::Z))
-t12 = _Call [#lib::C.id2] (_T (#lib::C<#lib::Y*>), _T (#lib::Z))
-t13 = _Call direct [#lib::C2.] (_T (#lib::C2<dart.core::num*>))
-t14 = _Call [#lib::C2.id3] (_T (#lib::C2<dart.core::num*>), _T (dart.core::_Double, 3.0))
-t15 = _Call direct [#lib::K.] (_T (#lib::K<#lib::J*>))
-t16 = _Call [#lib::C2.id4] (_T (#lib::C2<dart.core::num*>), _T (#lib::K<#lib::J*>))
+t0* = _Call direct [#lib::C.] (_T (#lib::C<dart.core::int>))
+t1 = _Call [#lib::C.foo] (t0)
+t2* = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int, dart.core::String>))
+t3 = _Call [#lib::E.foo] (t2)
+t4* = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int, dart.core::String>))
+t5 = _Call [#lib::E.bar] (t4)
+t6* = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int, dart.core::String>))
+t7* = _Call [#lib::E.baz] (t6)
+t8* = _Call direct [#lib::C.] (_T (#lib::C<#lib::Y>))
+t9* = _Call direct [#lib::Y.] (_T (#lib::Y))
+t10 = _Call [#lib::C.id1] (t8, t9)
+t11* = _Call direct [#lib::Z.] (_T (#lib::Z))
+t12 = _Call [#lib::C.id2] (t8, t11)
+t13* = _Call direct [#lib::C2.] (_T (#lib::C2<dart.core::num>))
+t14 = _Call [#lib::C2.id3] (t13, _T (dart.core::_Double, 3.0))
+t15* = _Call direct [#lib::K.] (_T (#lib::K<#lib::J>))
+t16 = _Call [#lib::C2.id4] (t13, t15)
 RESULT: t7
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart
index 3b211f3..fe65bb4 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart
@@ -30,10 +30,10 @@
 class InheritedElement extends Element {
   // The inferred type for '_dependents' needs to be concrete and have exact
   // type arguments.
-  final MockHashMap<Element, Object> _dependents =
-      MockHashMap<Element, Object>();
+  final MockHashMap<Element, Object?> _dependents =
+      MockHashMap<Element, Object?>();
 
-  void setDependencies(Element dependent, Object value) {
+  void setDependencies(Element dependent, Object? value) {
     _dependents.setEntry(dependent, value);
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
index 0eea29d..f833ff4 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
@@ -6,8 +6,8 @@
 %K = _Parameter #0
 %V = _Parameter #1
 t2 = _CreateConcreteType (#lib::_NotRealHashMap @ (%K, %V))
-t3 = _Call direct [#lib::_NotRealHashMap.] (t2)
-RESULT: t2
+t3* = _Call direct [#lib::_NotRealHashMap.] (t2)
+RESULT: t3
 ------------ _NotRealHashMap. ------------
 %this = _Parameter #0 [_T (#lib::_NotRealHashMap)+]
 t1 = _Call direct [dart.core::Object.] (%this)
@@ -16,10 +16,10 @@
 %this = _Parameter #0 [_T (#lib::_NotRealHashMap)+]
 %key = _Parameter #1
 %value = _Parameter #2
-t3 = _Extract (%this[#lib::_NotRealHashMap/0]*)
-t4 = _TypeCheck (%key against t3) (for #lib::_NotRealHashMap.K* key;)
-t5 = _Extract (%this[#lib::_NotRealHashMap/1]*)
-t6 = _TypeCheck (%value against t5) (for #lib::_NotRealHashMap.V* value;)
+t3 = _Extract (%this[#lib::_NotRealHashMap/0])
+t4 = _TypeCheck (%key against t3) (for #lib::_NotRealHashMap.K% key;)
+t5 = _Extract (%this[#lib::_NotRealHashMap/1])
+t6 = _TypeCheck (%value against t5) (for #lib::_NotRealHashMap.V% value;)
 RESULT: _T {}?
 ------------ InheritedElement. ------------
 %this = _Parameter #0 [_T (#lib::InheritedElement)+]
@@ -34,11 +34,11 @@
 RESULT: _T {}?
 ------------ InheritedElement._dependents ------------
 %this = _Parameter #0 [_T (#lib::InheritedElement)+]
-t1* = _Call direct [#lib::MockHashMap.] (#lib::Element*, dart.core::Object*)
+t1* = _Call direct [#lib::MockHashMap.] (#lib::Element, dart.core::Object?)
 RESULT: t1
 ------------ main ------------
-t0 = _Call direct [#lib::InheritedElement.] (_T (#lib::InheritedElement))
-t1 = _Call [#lib::InheritedElement.setDependencies] (_T (#lib::InheritedElement), _T (#lib::InheritedElement), _T (dart.core::_Smi, 0))
-t2 = _Call direct [#lib::Element.] (_T (#lib::Element))
-t3 = _Call [#lib::InheritedElement.setDependencies] (_T (#lib::InheritedElement), _T (#lib::Element), _T {}?)
+t0* = _Call direct [#lib::InheritedElement.] (_T (#lib::InheritedElement))
+t1 = _Call [#lib::InheritedElement.setDependencies] (t0, t0, _T (dart.core::_Smi, 0))
+t2* = _Call direct [#lib::Element.] (_T (#lib::Element))
+t3 = _Call [#lib::InheritedElement.setDependencies] (t0, t2, _T {}?)
 RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
index a894b41..010aa92 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
@@ -13,7 +13,7 @@
 RESULT: t1
 ------------ indexingIntoConstantList2 ------------
 %i = _Parameter #0 [_T (dart.core::int)+?]
-t1 = _Join [dart.core::Object*] (_T (dart.core::_OneByteString, "hi"), _T (dart.core::_Smi, 33), _T {}?, _T (dart.core::_Smi, -5))
+t1 = _Join [dart.core::Object?] (_T (dart.core::_OneByteString, "hi"), _T (dart.core::_Smi, 33), _T {}?, _T (dart.core::_Smi, -5))
 RESULT: t1
 ------------ main ------------
 
@@ -23,4 +23,4 @@
 RESULT: _T (dart.core::_ImmutableList, const <dart.core::int*>[1, 2, 3])
 ------------ _constList2 ------------
 
-RESULT: _T (dart.core::_ImmutableList, const <dart.core::Object*>["hi", 33, null, -5])
+RESULT: _T (dart.core::_ImmutableList, const <dart.core::Object?>["hi", 33, null, -5])
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
index d0227dd..80bbada 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
@@ -47,64 +47,64 @@
 ------------ sequence ------------
 t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
 t1 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t2 = _Call direct [#lib::C3.] (_T (#lib::C3))
-RESULT: _T (#lib::C3)
+t2* = _Call direct [#lib::C3.] (_T (#lib::C3))
+RESULT: t2
 ------------ if1 ------------
 %cond = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t2 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t3 = _Call direct [#lib::foo] (_T (#lib::C2))
-x_0 = _Join [dynamic] (_T (#lib::C2), _T (#lib::C1))
+t1* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t2* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t3 = _Call direct [#lib::foo] (t2)
+x_0 = _Join [dynamic] (t2, t1)
 RESULT: x_0
 ------------ if2 ------------
 %cond1 = _Parameter #0 [_T (dart.core::bool)+?]
 %cond2 = _Parameter #1 [_T (dart.core::bool)+?]
-t2 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t3 = _Call direct [#lib::foo] (_T (#lib::C1))
-t4 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t5 = _Call direct [#lib::bar] (_T (#lib::C2))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2))
+t2* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t3 = _Call direct [#lib::foo] (t2)
+t4* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t5 = _Call direct [#lib::bar] (t4)
+x_0 = _Join [dynamic] (t2, t4)
 RESULT: x_0
 ------------ if3 ------------
 %cond1 = _Parameter #0 [_T (dart.core::bool)+?]
 %cond2 = _Parameter #1 [_T (dart.core::bool)+?]
 t2 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t3 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t4* = _Call direct [#lib::foo] (_T (#lib::C2))
-t5 = _TypeCheck (t4 against dart.core::bool*) (for #lib::foo(x = new #lib::C2()) as dart.core::bool*)
-t6 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t7* = _Call direct [#lib::foo] (_T (#lib::C3))
-t8 = _TypeCheck (t7 against dart.core::bool*) (for #lib::foo(x = new #lib::C3()) as dart.core::bool*)
-x_0 = _Join [dynamic] (_T (#lib::C2), _T (#lib::C3))
+t3* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t4* = _Call direct [#lib::foo] (t3)
+t5 = _TypeCheck (t4 against dart.core::bool) (for #lib::foo(x = new #lib::C2()) as dart.core::bool)
+t6* = _Call direct [#lib::C3.] (_T (#lib::C3))
+t7* = _Call direct [#lib::foo] (t6)
+t8 = _TypeCheck (t7 against dart.core::bool) (for #lib::foo(x = new #lib::C3()) as dart.core::bool)
+x_0 = _Join [dynamic] (t3, t6)
 t10 = _Call direct [#lib::bar] (x_0)
 RESULT: x_0
 ------------ if4 ------------
 t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t1 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t2* = _Call direct [#lib::foo] (_T (#lib::C2))
-t3 = _TypeCheck (t2 against dart.core::bool*) (for #lib::foo(x = new #lib::C2()) as dart.core::bool*)
-t4 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t5* = _Call direct [#lib::foo] (_T (#lib::C3))
-t6 = _TypeCheck (t5 against dart.core::bool*) (for #lib::foo(x = new #lib::C3()) as dart.core::bool*)
-t7 = _Call direct [#lib::bar] (_T (#lib::C3))
-x_0 = _Join [dynamic] (_T (#lib::C2), _T (#lib::C3))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t2* = _Call direct [#lib::foo] (t1)
+t3 = _TypeCheck (t2 against dart.core::bool) (for #lib::foo(x = new #lib::C2()) as dart.core::bool)
+t4* = _Call direct [#lib::C3.] (_T (#lib::C3))
+t5* = _Call direct [#lib::foo] (t4)
+t6 = _TypeCheck (t5 against dart.core::bool) (for #lib::foo(x = new #lib::C3()) as dart.core::bool)
+t7 = _Call direct [#lib::bar] (t4)
+x_0 = _Join [dynamic] (t1, t4)
 RESULT: x_0
 ------------ if5 ------------
 %cond = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C1.] (_T (#lib::C1))
 t2 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t3 = _Call direct [#lib::foo] (_T (#lib::C1))
+t3 = _Call direct [#lib::foo] (t1)
 RESULT: _T {}?
 ------------ if6a ------------
 %x = _Parameter #0 [_T (dart.core::bool)+?]
 t1 = _Call direct [#lib::foo] (_T (dart.core::bool, true))
 t2 = _Call direct [#lib::bar] (_T (dart.core::bool, false))
-x_0 = _Join [dart.core::bool*] (_T (dart.core::bool, true), _T (dart.core::bool, false))
+x_0 = _Join [dart.core::bool] (_T (dart.core::bool, true), _T (dart.core::bool, false))
 t4 = _Call direct [#lib::baz] (x_0)
 RESULT: _T {}?
 ------------ if6b ------------
 %x = _Parameter #0 [_T ANY?]
-t1 = _TypeCheck (%x against dart.core::bool*) (for x as dart.core::bool*)
+t1 = _TypeCheck (%x against dart.core::bool) (for x as dart.core::bool)
 t2 = _Call direct [#lib::foo] (_T (dart.core::bool, true))
 t3 = _Call direct [#lib::bar] (_T (dart.core::bool, false))
 x_0 = _Join [dynamic] (_T (dart.core::bool, true), _T (dart.core::bool, false))
@@ -124,26 +124,26 @@
 RESULT: _T {}?
 ------------ if8 ------------
 %x = _Parameter #0 [_T ANY?]
-t1 = _Narrow (%x to _T (dart.core::String)+)
+t1 = _TypeCheck (%x against dart.core::String) (for x is dart.core::String)
 t2 = _Call direct [#lib::foo] (t1)
 RESULT: _T {}?
 ------------ if9 ------------
 %x = _Parameter #0 [_T (#lib::TestEnum)+?]
-t1* = _Call [#lib::TestEnum.==] (%x, _T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: "TestEnum.v1"}))
+t1* = _Call [dart.core::Object.==] (%x, _T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: "TestEnum.v1"}))
 t2 = _Call direct [#lib::foo] (_T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: "TestEnum.v1"}))
 RESULT: _T {}?
 ------------ conditional1 ------------
 %cond1 = _Parameter #0 [_T (dart.core::bool)+?]
 %cond2 = _Parameter #1 [_T (dart.core::bool)+?]
 t2 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t3 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t4* = _Call direct [#lib::foo] (_T (#lib::C2))
-t5 = _TypeCheck (t4 against dart.core::bool*) (for #lib::foo(x = new #lib::C2()) as dart.core::bool*)
-t6 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t7 = _Call direct [#lib::C4.] (_T (#lib::C4))
-x_0 = _Join [dynamic] (_T (#lib::C3), _T (#lib::C4))
+t3* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t4* = _Call direct [#lib::foo] (t3)
+t5 = _TypeCheck (t4 against dart.core::bool) (for #lib::foo(x = new #lib::C2()) as dart.core::bool)
+t6* = _Call direct [#lib::C3.] (_T (#lib::C3))
+t7* = _Call direct [#lib::C4.] (_T (#lib::C4))
+x_0 = _Join [dynamic] (t6, t7)
 t9 = _Call direct [#lib::foo] (x_0)
-t10 = _Join [dart.core::Object*] (_T (#lib::C3), _T (#lib::C4))
+t10 = _Join [dart.core::Object] (t6, t7)
 t11 = _Narrow (t10 to _T (dart.core::Object)+?)
 t12 = _Call direct [#lib::bar] (t11)
 RESULT: _T {}?
@@ -151,129 +151,129 @@
 %cond1 = _Parameter #0 [_T (dart.core::bool)+?]
 %cond2 = _Parameter #1 [_T (dart.core::bool)+?]
 t2 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t3 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t4* = _Call direct [#lib::foo] (_T (#lib::C2))
-t5 = _TypeCheck (t4 against dart.core::bool*) (for #lib::foo(x = new #lib::C2()) as dart.core::bool*)
-t6 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t7 = _Call direct [#lib::C4.] (_T (#lib::C4))
-t8* = _Call direct [dart.core::_GrowableList._literal2] (#lib::C4*, _T (#lib::C4), _T {})
+t3* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t4* = _Call direct [#lib::foo] (t3)
+t5 = _TypeCheck (t4 against dart.core::bool) (for #lib::foo(x = new #lib::C2()) as dart.core::bool)
+t6* = _Call direct [#lib::C3.] (_T (#lib::C3))
+t7* = _Call direct [#lib::C4.] (_T (#lib::C4))
+t8* = _Call direct [dart.core::_GrowableList._literal2] (#lib::C4, t7, _T {})
 t9* = _Call direct [#lib::foo] (t8)
-t10 = _Call direct [#lib::foo] (_T (#lib::C3))
-t11 = _Join [dynamic] (_T (#lib::C3), t9)
+t10 = _Call direct [#lib::foo] (t6)
+t11 = _Join [dynamic] (t6, t9)
 t12 = _Call direct [#lib::bar] (t11)
 RESULT: _T {}?
 ------------ loop1 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2))
-t2* = _Call direct [#lib::foo] (x_0)
-t3 = _TypeCheck (t2 against dart.core::bool*) (for #lib::foo(x) as dart.core::bool*)
-t4 = _Call direct [#lib::C2.] (_T (#lib::C2))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+x_0 = _Join [dynamic] (t0, t1)
+t3* = _Call direct [#lib::foo] (x_0)
+t4 = _TypeCheck (t3 against dart.core::bool) (for #lib::foo(x) as dart.core::bool)
 t5 = _Call direct [#lib::bar] (x_0)
 RESULT: x_0
 ------------ loop2 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C3))
-t2 = _Call direct [#lib::foo] (x_0)
-t3 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t4 = _Call direct [#lib::bar] (_T (#lib::C2))
-t5 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t6* = _Call direct [#lib::bar] (_T (#lib::C3))
-t7 = _TypeCheck (t6 against dart.core::bool*) (for #lib::bar(x = new #lib::C3()) as dart.core::bool*)
-RESULT: _T (#lib::C3)
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_0 = _Join [dynamic] (t0, t1)
+t3 = _Call direct [#lib::foo] (x_0)
+t4* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t5 = _Call direct [#lib::bar] (t4)
+t6* = _Call direct [#lib::bar] (t1)
+t7 = _TypeCheck (t6 against dart.core::bool) (for #lib::bar(x = new #lib::C3()) as dart.core::bool)
+RESULT: t1
 ------------ loop3 ------------
 t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t1 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t2* = _Call direct [#lib::foo] (_T (#lib::C2))
-t3 = _TypeCheck (t2 against dart.core::bool*) (for #lib::foo(x = new #lib::C2()) as dart.core::bool*)
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t2* = _Call direct [#lib::foo] (t1)
+t3 = _TypeCheck (t2 against dart.core::bool) (for #lib::foo(x = new #lib::C2()) as dart.core::bool)
 t4 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t5 = _Call direct [#lib::bar] (_T (#lib::C2))
-RESULT: _T (#lib::C2)
+t5 = _Call direct [#lib::bar] (t1)
+RESULT: t1
 ------------ loop4 ------------
 t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t1 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t2* = _Call direct [#lib::foo] (_T (#lib::C2))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t2* = _Call direct [#lib::foo] (t1)
 t3* = _Call direct [dart.core::_GrowableList._literal1] (dynamic?, t2)
 t4* = _Call get [dart.core::Iterable.iterator] (t3)
 t5* = _Call [dart.core::Iterator.moveNext] (t4)
 t6 = _Narrow (t4 to _T ANY)
 t7 = _Call get [dart.core::Iterator.current] (t6)
-x_0 = _Join [dynamic] (_T (#lib::C2), _T (#lib::C3))
-t9 = _Call direct [#lib::foo] (x_0)
-t10 = _Call direct [#lib::C3.] (_T (#lib::C3))
+t8* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_0 = _Join [dynamic] (t1, t8)
+t10 = _Call direct [#lib::foo] (x_0)
 RESULT: x_0
 ------------ loop5 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C3))
-t2* = _Call direct [#lib::foo] (x_0)
-t3 = _TypeCheck (t2 against dart.core::bool*) (for #lib::foo(x) as dart.core::bool*)
-t4 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t5* = _Call direct [#lib::bar] (_T (#lib::C2))
-t6 = _TypeCheck (t5 against dart.core::bool*) (for #lib::bar(x) as dart.core::bool*)
-t7 = _Call direct [#lib::C3.] (_T (#lib::C3))
-x_1 = _Join [dynamic] (x_0, _T (#lib::C2))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_0 = _Join [dynamic] (t0, t1)
+t3* = _Call direct [#lib::foo] (x_0)
+t4 = _TypeCheck (t3 against dart.core::bool) (for #lib::foo(x) as dart.core::bool)
+t5* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t6* = _Call direct [#lib::bar] (t5)
+t7 = _TypeCheck (t6 against dart.core::bool) (for #lib::bar(x) as dart.core::bool)
+x_1 = _Join [dynamic] (x_0, t5)
 RESULT: x_1
 ------------ loop6 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_1 = _Join [dynamic] (_T (#lib::C3), _T (#lib::C2))
-x_0 = _Join [dynamic] (_T (#lib::C1), x_1)
-t3* = _Call direct [#lib::foo] (x_0)
-t4 = _TypeCheck (t3 against dart.core::bool*) (for #lib::foo(x) as dart.core::bool*)
-t5 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t6* = _Call direct [#lib::bar] (_T (#lib::C2))
-t7 = _TypeCheck (t6 against dart.core::bool*) (for #lib::bar(x) as dart.core::bool*)
-t8 = _Call direct [#lib::C3.] (_T (#lib::C3))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C3.] (_T (#lib::C3))
+t2* = _Call direct [#lib::C2.] (_T (#lib::C2))
+x_1 = _Join [dynamic] (t1, t2)
+x_0 = _Join [dynamic] (t0, x_1)
+t5* = _Call direct [#lib::foo] (x_0)
+t6 = _TypeCheck (t5 against dart.core::bool) (for #lib::foo(x) as dart.core::bool)
+t7* = _Call direct [#lib::bar] (t2)
+t8 = _TypeCheck (t7 against dart.core::bool) (for #lib::bar(x) as dart.core::bool)
 RESULT: x_0
 ------------ try1 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t1 = _Call direct [#lib::C2.] (_T (#lib::C2))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2), _T (#lib::C3))
-t3 = _Call direct [#lib::foo] (x_0)
-t4 = _Call direct [#lib::C3.] (_T (#lib::C3))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t2* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_0 = _Join [dynamic] (t0, t1, t2)
+t4 = _Call direct [#lib::foo] (x_0)
 t5 = _Call direct [#lib::bar] (x_0)
-t6 = _Call direct [#lib::C4.] (_T (#lib::C4))
-RESULT: _T (#lib::C4)
+t6* = _Call direct [#lib::C4.] (_T (#lib::C4))
+RESULT: t6
 ------------ closure1 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2))
-t2 = _Call direct [#lib::foo] (x_0)
-t3 = _Call direct [#lib::bar] (x_0)
-t4 = _Call direct [#lib::foo] (_T ANY?)
-t5 = _Call direct [#lib::C2.] (_T (#lib::C2))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+x_0 = _Join [dynamic] (t0, t1)
+t3 = _Call direct [#lib::foo] (x_0)
+t4 = _Call direct [#lib::bar] (x_0)
+t5 = _Call direct [#lib::foo] (_T ANY?)
 RESULT: _T {}?
 ------------ closure2 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2))
-t2 = _Call direct [#lib::foo] (x_0)
-t3 = _Call direct [#lib::C2.] (_T (#lib::C2))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+x_0 = _Join [dynamic] (t0, t1)
+t3 = _Call direct [#lib::foo] (x_0)
 t4 = _Call direct [#lib::foo] (_T ANY?)
 RESULT: x_0
 ------------ switch1 ------------
 %selector = _Parameter #0 [_T (dart.core::int)+?]
-t1 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t2 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t3 = _Call direct [#lib::C3.] (_T (#lib::C3))
-x_2 = _Join [dynamic] (_T (#lib::C3), _T (#lib::C1))
-x_3 = _Join [dynamic] (x_2, _T (#lib::C2))
+t1* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t2* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t3* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_2 = _Join [dynamic] (t3, t1)
+x_3 = _Join [dynamic] (x_2, t2)
 RESULT: x_3
 ------------ switch2 ------------
 %selector = _Parameter #0 [_T (dart.core::int)+?]
 t1 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t2 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t3 = _Call direct [#lib::C3.] (_T (#lib::C3))
-x_2 = _Join [dynamic] (_T (#lib::C3), _T (#lib::C2))
+t2* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t3* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_2 = _Join [dynamic] (t3, t2)
 RESULT: x_2
 ------------ switch3 ------------
 %selector = _Parameter #0 [_T (dart.core::int)+?]
-t1 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t2 = _Call direct [#lib::C2.] (_T (#lib::C2))
-x_1 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2))
+t1* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t2* = _Call direct [#lib::C2.] (_T (#lib::C2))
+x_1 = _Join [dynamic] (t1, t2)
 t4 = _Call direct [#lib::foo] (x_1)
-t5 = _Call direct [#lib::C3.] (_T (#lib::C3))
-x_2 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C3))
+t5* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_2 = _Join [dynamic] (t1, t5)
 RESULT: x_2
 ------------ cast1 ------------
 %x = _Parameter #0 [_T ANY?]
-t1 = _TypeCheck (%x against #lib::C1*) (for x as #lib::C1*)
+t1 = _TypeCheck (%x against #lib::C1) (for x as #lib::C1)
 t2 = _Call direct [#lib::foo] (t1)
 t3 = _Call direct [#lib::bar] (t1)
 RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart
index 11518c5..3757ca5 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart
@@ -7,7 +7,7 @@
 empty1() {}
 void empty2() {}
 dynamic empty3() {} // ignore: missing_return
-Object empty4() {} // ignore: missing_return
+Object? empty4() {} // ignore: missing_return
 
 Object return1() {
   return new T();
@@ -184,7 +184,8 @@
   if (c) {
     return new T();
   }
-  try {} on ArgumentError {} finally {
+  try {} on ArgumentError {
+  } finally {
     throw 'Error!';
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect
index b584c86..8b3a909 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect
@@ -15,16 +15,16 @@
 
 RESULT: _T {}?
 ------------ return1 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t0
 ------------ return2 ------------
 %i = _Parameter #0 [_T (dart.core::int)+?]
 t1* = _Call [dart.core::num.-] (%i, _T (dart.core::_Smi, 1))
 t2* = _Call direct [#lib::return2] (t1)
 RESULT: t2
 ------------ return3 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t0
 ------------ return4 ------------
 
 RESULT: _T {}?
@@ -33,16 +33,16 @@
 RESULT: _T {}?
 ------------ expr2 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
 t2 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+%result = _Join [dynamic] (t1, _T {}?)
 RESULT: %result
 ------------ expr3 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
 %x = _Parameter #1 [_T (dart.core::Object)+?]
-t2 = _Call direct [#lib::T.] (_T (#lib::T))
+t2* = _Call direct [#lib::T.] (_T (#lib::T))
 t3 = _Call [dart.core::Object.toString] (%x)
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+%result = _Join [dynamic] (t2, _T {}?)
 RESULT: %result
 ------------ throw1 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
@@ -51,8 +51,8 @@
 ------------ throw2 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
 %x = _Parameter #1 [_T (dart.core::Object)+?]
-t2 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t2* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t2
 ------------ loop1 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
 %x = _Parameter #1 [_T (dart.core::Object)+?]
@@ -60,29 +60,29 @@
 ------------ loop2 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
 %x = _Parameter #1 [_T (dart.core::Object)+?]
-t2 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t2* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t2, _T {}?)
 RESULT: %result
 ------------ loop3 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
 %x = _Parameter #1 [_T (dart.core::Object)+?]
-t2 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t2* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t2, _T {}?)
 RESULT: %result
 ------------ switch_ ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
 %i = _Parameter #1 [_T (dart.core::int)+?]
-t2 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t2* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t2, _T {}?)
 RESULT: %result
 ------------ if1 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t1
 ------------ if2 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t1, _T {}?)
 RESULT: %result
 ------------ if3 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
@@ -98,36 +98,36 @@
 RESULT: %result
 ------------ label1 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t1, _T {}?)
 RESULT: %result
 ------------ try1 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t1, _T {}?)
 RESULT: %result
 ------------ try2 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t0, _T {}?)
 RESULT: %result
 ------------ try3 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t0
 ------------ try4 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t1, _T {}?)
 RESULT: %result
 ------------ try5 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t0
 ------------ try6 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t0
 ------------ try7 ------------
 %c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t1
 ------------ main ------------
 
 RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
index 753486f..4101ae0 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
@@ -2,13 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-bool someStatic;
+late bool someStatic;
 
 class A {}
 
 class B {}
 
-Object foo(Object a1, [Object a2]) {
+Object? foo(Object a1, [Object? a2]) {
   if (someStatic) {
     a1 = new A();
   }
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
index d46d957..b559883 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
@@ -10,22 +10,22 @@
 %a1 = _Parameter #0 [_T (dart.core::Object)+?]
 %a2 = _Parameter #1 [_T (dart.core::Object)+?]
 t2* = _Call direct get [#lib::someStatic] ()
-t3 = _Call direct [#lib::A.] (_T (#lib::A))
-a1_0 = _Join [dart.core::Object*] (_T (#lib::A), %a1)
+t3* = _Call direct [#lib::A.] (_T (#lib::A))
+a1_0 = _Join [dart.core::Object] (t3, %a1)
 t5 = _Call direct [#lib::bar] (a1_0, _T (dart.core::_Smi, 42))
-t6 = _Call direct [#lib::B.] (_T (#lib::B))
-t7* = _Call [dart.core::Object.==] (_T (#lib::B), %a2)
-t8 = _Join [dart.core::Object*] (_T (#lib::B), %a2)
+t6* = _Call direct [#lib::B.] (_T (#lib::B))
+t7* = _Call [dart.core::Object.==] (t6, %a2)
+t8 = _Join [dart.core::Object?] (t6, %a2)
 t9 = _Narrow (t8 to _T (dart.core::Object)+?)
 RESULT: t9
 ------------ bar ------------
 %a1 = _Parameter #0 [_T (dart.core::Object)+?]
 %a2 = _Parameter #1 [_T (dart.core::int)+?]
-t2 = _Narrow (%a1 to _T (dart.core::int)+)
+t2 = _TypeCheck (%a1 against dart.core::int) (for v1 is dart.core::int)
 t3* = _Call [dart.core::num.+] (t2, %a2)
 t4* = _Call [dart.core::num.*] (t3, _T (dart.core::_Smi, 3))
 t5* = _Call [dart.core::int.unary-] (_T (dart.core::_Smi, 1))
-%result = _Join [dart.core::int*] (t4, t5)
+%result = _Join [dart.core::int] (t4, t5)
 RESULT: %result
 ------------ loop1 ------------
 %a1 = _Parameter #0 [_T (dart.core::Object)+?]
@@ -35,10 +35,10 @@
 ------------ loop2 ------------
 %x = _Parameter #0 [_T (dart.core::int)+?]
 t1* = _Call [dart.core::num.+] (_T (dart.core::int)+, _T (dart.core::_Smi, 1))
-i_0 = _Join [dart.core::int*] (_T (dart.core::_Smi, 0), t1)
+i_0 = _Join [dart.core::int] (_T (dart.core::_Smi, 0), t1)
 t3* = _Call [dart.core::num.<] (i_0, _T (dart.core::_Smi, 5))
 t4* = _Call [dart.core::num.+] (_T (dart.core::int)+?, _T (dart.core::_Smi, 10))
-x_0 = _Join [dart.core::int*] (%x, t4)
+x_0 = _Join [dart.core::int] (%x, t4)
 RESULT: x_0
 ------------ main ------------
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/abstract_class_entry_point.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/abstract_class_entry_point.dart.expect
index 02a29c4..46131e7 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/abstract_class_entry_point.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/abstract_class_entry_point.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart
index b5b68eb..5fbfc30 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart
@@ -45,7 +45,7 @@
 @TypedefAnnotation([1, 2, 3])
 typedef void SomeType<T>(List<T> arg);
 
-int foo(SomeType<int> a) {
+int foo(SomeType<int>? a) {
   @VarAnnotation()
   int x = 2;
   return x + 2;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
index 70239f8..a86774c 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
@@ -1,23 +1,23 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
-typedef SomeType<contravariant T extends core::Object* = dynamic> = (core::List<T*>*) →* void;
+typedef SomeType<contravariant T extends core::Object? = dynamic> = (core::List<T%>) → void;
 abstract class A extends core::Object {
   static method staticMethod() → void {}
 }
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method instanceMethod() → void {}
 }
-[@vm.unboxing-info.metadata=()->i]static method foo() → core::int* {
-  core::int* x = 2;
-  return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] x.{core::num::+}(2){(core::num*) →* core::int*};
+[@vm.unboxing-info.metadata=()->i]static method foo() → core::int {
+  core::int x = 2;
+  return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] x.{core::num::+}(2){(core::num) → core::int};
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   self::A::staticMethod();
-  [@vm.direct-call.metadata=#lib::B.instanceMethod] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::instanceMethod}(){() →* void};
+  [@vm.direct-call.metadata=#lib::B.instanceMethod] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::instanceMethod}(){() → void};
   self::foo();
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
index d1f3c4e..fc5a260 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
@@ -1,20 +1,19 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
-import "dart:_internal" as _in;
 
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method bar(dynamic x) → asy::Future<dynamic>* /* originally async */ {
-    final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method bar(dynamic x) → asy::Future<dynamic> /* originally async */ {
+    final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
-    (dynamic) →* dynamic :async_op_then;
-    (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
-    core::int* :await_jump_var = 0;
+    FutureOr<dynamic>? :return_value;
+    (dynamic) → dynamic :async_op_then;
+    (core::Object, core::StackTrace) → dynamic :async_op_error;
+    core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
@@ -26,30 +25,30 @@
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
-      on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
         asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
       }
     :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
     :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
-    :async_op(){() →* dynamic};
+    :async_op(){() → dynamic};
     :is_sync = true;
     return :async_future;
   }
 }
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 }
 static method foo() → dynamic
   return new self::A::•();
-static method baz() → asy::Future<dynamic>* /* originally async */ {
-  final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
+static method baz() → asy::Future<dynamic> /* originally async */ {
+  final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
-  (dynamic) →* dynamic :async_op_then;
-  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
-  core::int* :await_jump_var = 0;
+  FutureOr<dynamic>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
@@ -61,22 +60,22 @@
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
-    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
       asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
     }
   :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
   :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
-  :async_op(){() →* dynamic};
+  :async_op(){() → dynamic};
   :is_sync = true;
   return :async_future;
 }
 static method main() → dynamic /* originally async */ {
-  final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
+  final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
-  (dynamic) →* dynamic :async_op_then;
-  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
-  core::int* :await_jump_var = 0;
+  FutureOr<dynamic>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
   dynamic :async_temporary_0;
@@ -86,18 +85,18 @@
       {
         :async_temporary_0 = [@vm.inferred-type.metadata=#lib::A] self::foo();
         [yield] let dynamic #t1 = asy::_awaitHelper([@vm.inferred-type.metadata=dart.async::_Future<dynamic>] self::baz(), :async_op_then, :async_op_error, :async_op) in null;
-        [yield] let dynamic #t2 = asy::_awaitHelper([@vm.direct-call.metadata=#lib::A.bar??] [@vm.inferred-type.metadata=dart.async::_Future<dynamic> (receiver not int)] _in::unsafeCast<dynamic>(:async_temporary_0){dynamic}.bar(:result), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t2 = asy::_awaitHelper([@vm.direct-call.metadata=#lib::A.bar??] [@vm.inferred-type.metadata=dart.async::_Future<dynamic> (receiver not int)] :async_temporary_0{dynamic}.bar(:result), :async_op_then, :async_op_error, :async_op) in null;
         :result;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
-    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
       asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
     }
   :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
   :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
-  :async_op(){() →* dynamic};
+  :async_op(){() → dynamic};
   :is_sync = true;
   return :async_future;
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect
index dc738d5..0a0c97a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect
@@ -1,43 +1,43 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-[@vm.unboxing-info.metadata=(i)->b]static method isPrime([@vm.inferred-type.metadata=int] dynamic n) → core::bool* {
-  if(_in::unsafeCast<core::bool*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool] n{dynamic}.<(2)))
+[@vm.unboxing-info.metadata=(i)->b]static method isPrime([@vm.inferred-type.metadata=int] dynamic n) → core::bool {
+  if(_in::unsafeCast<core::bool>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool] n{dynamic}.<(2)))
     return false;
-  for (core::int* i = 2; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<=] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation.*] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::*}(i){(core::num*) →* core::int*}.{core::num::<=}(_in::unsafeCast<core::num*>(n)){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
-    if([@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation.%] [@vm.inferred-type.metadata=int] n{dynamic}.%(i) =={core::Object::==}{(core::Object*) →* core::bool*} 0)
+  for (core::int i = 2; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<=] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation.*] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::*}(i){(core::num) → core::int}.{core::num::<=}(_in::unsafeCast<core::num>(n)){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
+    if([@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation.%] [@vm.inferred-type.metadata=int] n{dynamic}.%(i) =={core::Object::==}{(core::Object) → core::bool} 0)
       return false;
   }
   return true;
 }
-static method nThPrimeNumber() → core::int* {
-  core::int* counter = 0;
-  for (core::int* i = 1; ; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
+static method nThPrimeNumber() → core::int {
+  core::int counter = 0;
+  for (core::int i = 1; ; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
     if([@vm.inferred-type.metadata=dart.core::bool] self::isPrime(i))
-      counter = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] counter.{core::num::+}(1){(core::num*) →* core::int*};
-    if([@vm.inferred-type.metadata=dart.core::bool] counter =={core::num::==}{(core::Object*) →* core::bool*} (#C1)) {
+      counter = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] counter.{core::num::+}(1){(core::num) → core::int};
+    if([@vm.inferred-type.metadata=dart.core::bool] counter =={core::num::==}{(core::Object) → core::bool} (#C1)) {
       return i;
     }
   }
 }
 static method run() → void {
-  core::int* e = 611953;
-  core::int* p = [@vm.inferred-type.metadata=int?] self::nThPrimeNumber();
-  if(!([@vm.inferred-type.metadata=dart.core::bool] p =={core::num::==}{(core::Object*) →* core::bool*} e)) {
+  core::int e = 611953;
+  core::int p = [@vm.inferred-type.metadata=int?] self::nThPrimeNumber();
+  if(!([@vm.inferred-type.metadata=dart.core::bool] p =={core::num::==}{(core::Object) → core::bool} e)) {
     throw core::Exception::•("Unexpected result: ${p} != ${e}");
   }
 }
-static method main(core::List<core::String*>* args) → dynamic {
-  core::Stopwatch* timer = let final core::Stopwatch* #t1 = new core::Stopwatch::•() in block {
-    [@vm.direct-call.metadata=dart.core::Stopwatch.start] [@vm.inferred-type.metadata=!? (skip check)] #t1.{core::Stopwatch::start}(){() →* void};
+static method main(core::List<core::String> args) → dynamic {
+  core::Stopwatch timer = let final core::Stopwatch #t1 = new core::Stopwatch::•() in block {
+    [@vm.direct-call.metadata=dart.core::Stopwatch.start] [@vm.inferred-type.metadata=!? (skip check)] #t1.{core::Stopwatch::start}(){() → void};
   } =>#t1;
-  for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
+  for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
     self::run();
   }
-  [@vm.direct-call.metadata=dart.core::Stopwatch.stop] [@vm.inferred-type.metadata=!? (skip check)] timer.{core::Stopwatch::stop}(){() →* void};
-  core::print("Elapsed ${[@vm.direct-call.metadata=dart.core::Stopwatch.elapsedMilliseconds] timer.{core::Stopwatch::elapsedMilliseconds}{core::int*}}ms");
+  [@vm.direct-call.metadata=dart.core::Stopwatch.stop] [@vm.inferred-type.metadata=!? (skip check)] timer.{core::Stopwatch::stop}(){() → void};
+  core::print("Elapsed ${[@vm.direct-call.metadata=dart.core::Stopwatch.elapsedMilliseconds] timer.{core::Stopwatch::elapsedMilliseconds}{core::int}}ms");
 }
 constants  {
   #C1 = 50000
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index 92746ce..370e042 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:typed_data" as typ;
@@ -6,35 +6,38 @@
 import "dart:typed_data";
 
 class _Vector extends core::Object {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i]  final field core::int* _offset;
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  final field core::int* _length;
-[@vm.inferred-type.metadata=dart.typed_data::_Float64List] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  final field core::List<core::double*>* _elements;
-  constructor •() → self::_Vector*
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i]  final field core::int _offset;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  final field core::int _length;
+[@vm.inferred-type.metadata=dart.typed_data::_Float64List] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  final field core::List<core::double> _elements;
+  constructor •() → self::_Vector
     : self::_Vector::_offset = 0, self::_Vector::_length = #C1, self::_Vector::_elements = [@vm.inferred-type.metadata=dart.typed_data::_Float64List] typ::Float64List::•(#C1), super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:4] [@vm.unboxing-info.metadata=(b)->d]  operator []([@vm.inferred-type.metadata=!] core::int* i) → core::double*
-    return [@vm.direct-call.metadata=dart.typed_data::_Float64List.[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double*>*}.{core::List::[]}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int*}){(core::num*) →* core::int*}){(core::int*) →* core::double*};
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5]  operator []=([@vm.inferred-type.metadata=dart.core::_OneByteString] core::int* i, core::double* value) → void {
-    let dynamic #t1 = [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double*>*} in let dynamic #t2 = [@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int*} in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:4] [@vm.unboxing-info.metadata=(b)->d]  operator []([@vm.inferred-type.metadata=!] core::int i) → core::double
+    return [@vm.direct-call.metadata=dart.typed_data::_Float64List.[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double>}.{core::List::[]}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int}){(core::num) → core::int}){(core::int) → core::double};
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5]  operator []=([@vm.inferred-type.metadata=dart.core::_OneByteString] core::int i, core::double value) → void {
+    block {
+      [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double>};
+      [@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int};
+    } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6] [@vm.unboxing-info.metadata=(b)->d]  operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector* a) → core::double* {
-    core::double* result = 0.0;
-    for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector._length] [@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] this.{self::_Vector::_length}{core::int*}){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*})
-      result = [@vm.direct-call.metadata=dart.core::_Double.+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double.*] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector.[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] this.{self::_Vector::[]}(i){(core::int*) →* core::double*}.{core::double::*}([@vm.direct-call.metadata=#lib::_Vector.[]??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] a.{self::_Vector::[]}(i){(core::int*) →* core::double*}){(core::num*) →* core::double*}){(core::num*) →* core::double*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6] [@vm.unboxing-info.metadata=(b)->d]  operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector a) → core::double {
+    core::double result = 0.0;
+    for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector._length] [@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] this.{self::_Vector::_length}{core::int}){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int})
+      result = [@vm.direct-call.metadata=dart.core::_Double.+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double.*] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector.[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] this.{self::_Vector::[]}(i){(core::int) → core::double}.{core::double::*}([@vm.direct-call.metadata=#lib::_Vector.[]??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] a.{self::_Vector::[]}(i){(core::int) → core::double}){(core::num) → core::double}){(core::num) → core::double};
     return result;
   }
 }
-[@vm.inferred-type.metadata=#lib::_Vector?]static field self::_Vector* v = new self::_Vector::•();
-[@vm.inferred-type.metadata=dart.core::_Double?]static field core::double* x = 0.0;
-static method main(core::List<core::String*>* args) → dynamic {
-  core::Stopwatch* timer = let final core::Stopwatch* #t3 = new core::Stopwatch::•() in block {
-    [@vm.direct-call.metadata=dart.core::Stopwatch.start] [@vm.inferred-type.metadata=!? (skip check)] #t3.{core::Stopwatch::start}(){() →* void};
-  } =>#t3;
-  for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100000000){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
-    self::x = [@vm.direct-call.metadata=dart.core::_Double.+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector.*??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v){(self::_Vector*) →* core::double*}){(core::num*) →* core::double*};
+[@vm.inferred-type.metadata=#lib::_Vector?]static field self::_Vector v = new self::_Vector::•();
+[@vm.inferred-type.metadata=dart.core::_Double?]static field core::double x = 0.0;
+static method main(core::List<core::String> args) → dynamic {
+  core::Stopwatch timer = let final core::Stopwatch #t1 = new core::Stopwatch::•() in block {
+    [@vm.direct-call.metadata=dart.core::Stopwatch.start] [@vm.inferred-type.metadata=!? (skip check)] #t1.{core::Stopwatch::start}(){() → void};
+  } =>#t1;
+  for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100000000){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
+    self::x = [@vm.direct-call.metadata=dart.core::_Double.+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector.*??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v){(self::_Vector) → core::double}){(core::num) → core::double};
   }
-  [@vm.direct-call.metadata=dart.core::Stopwatch.stop] [@vm.inferred-type.metadata=!? (skip check)] timer.{core::Stopwatch::stop}(){() →* void};
-  core::print("Elapsed ${[@vm.direct-call.metadata=dart.core::Stopwatch.elapsedMilliseconds] timer.{core::Stopwatch::elapsedMilliseconds}{core::int*}}ms, result ${self::x}");
+  [@vm.direct-call.metadata=dart.core::Stopwatch.stop] [@vm.inferred-type.metadata=!? (skip check)] timer.{core::Stopwatch::stop}(){() → void};
+  core::print("Elapsed ${[@vm.direct-call.metadata=dart.core::Stopwatch.elapsedMilliseconds] timer.{core::Stopwatch::elapsedMilliseconds}{core::int}}ms, result ${self::x}");
 }
 constants  {
   #C1 = 10
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_basic.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_basic.dart.expect
index 00cfa5c..c42f78c 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_basic.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_basic.dart.expect
@@ -1,76 +1,76 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
-class C<T extends core::Object* = dynamic> extends core::Object {
-  synthetic constructor •() → self::C<self::C::T*>*
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
-    return new self::D::•<self::C::T*>();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method id1([@vm.inferred-type.metadata=#lib::Y (skip check)] generic-covariant-impl self::C::T* x) → dynamic
+    return new self::D::•<self::C::T%>();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method id1([@vm.inferred-type.metadata=#lib::Y (skip check)] generic-covariant-impl self::C::T% x) → dynamic
     return x;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method id2([@vm.inferred-type.metadata=#lib::Z] generic-covariant-impl self::C::T* x) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method id2([@vm.inferred-type.metadata=#lib::Z] generic-covariant-impl self::C::T% x) → dynamic
     return x;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
-  synthetic constructor •() → self::D<self::D::T*>*
+class D<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::D<self::D::T%>
     : super core::Object::•()
     ;
 }
-class E<S extends core::Object* = dynamic, T extends core::Object* = dynamic> extends self::C<self::E::T*> {
-  synthetic constructor •() → self::E<self::E::S*, self::E::T*>*
+class E<S extends core::Object? = dynamic, T extends core::Object? = dynamic> extends self::C<self::E::T%> {
+  synthetic constructor •() → self::E<self::E::S%, self::E::T%>
     : super self::C::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
-    return [@vm.inferred-type.metadata=#lib::D<dart.core::String*>] super.{self::C::foo}();
+    return [@vm.inferred-type.metadata=#lib::D<dart.core::String>] super.{self::C::foo}();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method bar() → dynamic
-    return new self::D::•<self::E::S*>();
+    return new self::D::•<self::E::S%>();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method baz() → dynamic
-    return new self::D::•<self::E::T*>();
+    return new self::D::•<self::E::T%>();
 }
 abstract class X extends core::Object {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
 class Y extends self::X {
-  synthetic constructor •() → self::Y*
+  synthetic constructor •() → self::Y
     : super self::X::•()
     ;
 }
 class Z extends self::X {
-  synthetic constructor •() → self::Z*
+  synthetic constructor •() → self::Z
     : super self::X::•()
     ;
 }
-abstract class I<T extends core::Object* = dynamic> extends core::Object {
+abstract class I<T extends core::Object? = dynamic> extends core::Object {
 }
-abstract class J extends self::I<core::int*> {
+abstract class J extends self::I<core::int> {
 }
-class K<T extends core::Object* = dynamic> extends core::Object {
-  synthetic constructor •() → self::K<self::K::T*>*
+class K<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::K<self::K::T%>
     : super core::Object::•()
     ;
 }
-class C2<T extends core::Object* = dynamic> extends core::Object {
-  synthetic constructor •() → self::C2<self::C2::T*>*
+class C2<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C2<self::C2::T%>
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(d)->d]  method id3([@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.0)] generic-covariant-impl core::Comparable<self::C2::T*>* x) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(d)->d]  method id3([@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.0)] generic-covariant-impl core::Comparable<self::C2::T%> x) → dynamic
     return x;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method id4([@vm.inferred-type.metadata=#lib::K<#lib::J*> (skip check)] generic-covariant-impl self::K<self::I<self::C2::T*>*>* x) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method id4([@vm.inferred-type.metadata=#lib::K<#lib::J> (skip check)] generic-covariant-impl self::K<self::I<self::C2::T%>> x) → dynamic
     return x;
 }
 static method main() → dynamic {
-  core::print([@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=#lib::D<dart.core::int*> (skip check)] new self::C::•<core::int*>().{self::C::foo}(){() →* dynamic});
-  core::print([@vm.direct-call.metadata=#lib::E.foo] [@vm.inferred-type.metadata=#lib::D<dart.core::String*> (skip check)] new self::E::•<core::int*, core::String*>().{self::E::foo}(){() →* dynamic});
-  core::print([@vm.direct-call.metadata=#lib::E.bar] [@vm.inferred-type.metadata=#lib::D<dart.core::int*> (skip check)] new self::E::•<core::int*, core::String*>().{self::E::bar}(){() →* dynamic});
-  core::print([@vm.direct-call.metadata=#lib::E.baz] [@vm.inferred-type.metadata=#lib::D<dart.core::String*> (skip check)] new self::E::•<core::int*, core::String*>().{self::E::baz}(){() →* dynamic});
-  self::C<self::X*>* c = new self::C::•<self::Y*>();
-  [@vm.call-site-attributes.metadata=receiverType:#lib::C<#lib::X*>*] [@vm.direct-call.metadata=#lib::C.id1] [@vm.inferred-type.metadata=!? (skip check)] c.{self::C::id1}(new self::Y::•()){(self::X*) →* dynamic};
-  [@vm.call-site-attributes.metadata=receiverType:#lib::C<#lib::X*>*] [@vm.direct-call.metadata=#lib::C.id2] c.{self::C::id2}(new self::Z::•()){(self::X*) →* dynamic};
-  self::C2<core::num*>* c2 = new self::C2::•<core::num*>();
-  [@vm.call-site-attributes.metadata=receiverType:#lib::C2<dart.core::num*>*] [@vm.direct-call.metadata=#lib::C2.id3] [@vm.inferred-type.metadata=!? (skip check)] c2.{self::C2::id3}(3.0){(core::Comparable<core::num*>*) →* dynamic};
-  [@vm.call-site-attributes.metadata=receiverType:#lib::C2<dart.core::num*>*] [@vm.direct-call.metadata=#lib::C2.id4] [@vm.inferred-type.metadata=!? (skip check)] c2.{self::C2::id4}(new self::K::•<self::J*>()){(self::K<self::I<core::num*>*>*) →* dynamic};
+  core::print([@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=#lib::D<dart.core::int> (skip check)] new self::C::•<core::int>().{self::C::foo}(){() → dynamic});
+  core::print([@vm.direct-call.metadata=#lib::E.foo] [@vm.inferred-type.metadata=#lib::D<dart.core::String> (skip check)] new self::E::•<core::int, core::String>().{self::E::foo}(){() → dynamic});
+  core::print([@vm.direct-call.metadata=#lib::E.bar] [@vm.inferred-type.metadata=#lib::D<dart.core::int> (skip check)] new self::E::•<core::int, core::String>().{self::E::bar}(){() → dynamic});
+  core::print([@vm.direct-call.metadata=#lib::E.baz] [@vm.inferred-type.metadata=#lib::D<dart.core::String> (skip check)] new self::E::•<core::int, core::String>().{self::E::baz}(){() → dynamic});
+  self::C<self::X> c = new self::C::•<self::Y>();
+  [@vm.call-site-attributes.metadata=receiverType:#lib::C<#lib::X>] [@vm.direct-call.metadata=#lib::C.id1] [@vm.inferred-type.metadata=!? (skip check)] c.{self::C::id1}(new self::Y::•()){(self::X) → dynamic};
+  [@vm.call-site-attributes.metadata=receiverType:#lib::C<#lib::X>] [@vm.direct-call.metadata=#lib::C.id2] c.{self::C::id2}(new self::Z::•()){(self::X) → dynamic};
+  self::C2<core::num> c2 = new self::C2::•<core::num>();
+  [@vm.call-site-attributes.metadata=receiverType:#lib::C2<dart.core::num>] [@vm.direct-call.metadata=#lib::C2.id3] [@vm.inferred-type.metadata=!? (skip check)] c2.{self::C2::id3}(3.0){(core::Comparable<core::num>) → dynamic};
+  [@vm.call-site-attributes.metadata=receiverType:#lib::C2<dart.core::num>] [@vm.direct-call.metadata=#lib::C2.id4] [@vm.inferred-type.metadata=!? (skip check)] c2.{self::C2::id4}(new self::K::•<self::J>()){(self::K<self::I<core::num>>) → dynamic};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart
index c211e10..b331cb8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart
@@ -7,9 +7,9 @@
 class Element {}
 
 class InheritedElement extends Element {
-  final Map<Element, Object> _dependents = <Element, Object>{};
+  final Map<Element, Object?> _dependents = <Element, Object?>{};
 
-  void setDependencies(Element dependent, Object value) {
+  void setDependencies(Element dependent, Object? value) {
     _dependents[dependent] = value;
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect
index ca4d73c..4a919d4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect
@@ -1,25 +1,25 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 import "dart:collection";
 
 class Element extends core::Object {
-  synthetic constructor •() → self::Element*
+  synthetic constructor •() → self::Element
     : super core::Object::•()
     ;
 }
 class InheritedElement extends self::Element {
-[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element*, dart.core::Object*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::Map<self::Element*, core::Object*>* _dependents;
-  synthetic constructor •() → self::InheritedElement*
-    : self::InheritedElement::_dependents = <self::Element*, core::Object*>{}, super self::Element::•()
+[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element, dart.core::Object?>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::Map<self::Element, core::Object?> _dependents;
+  synthetic constructor •() → self::InheritedElement
+    : self::InheritedElement::_dependents = <self::Element, core::Object?>{}, super self::Element::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method setDependencies([@vm.inferred-type.metadata=!] self::Element* dependent, [@vm.inferred-type.metadata=dart.core::_Smi?] core::Object* value) → void {
-    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<#lib::Element*, dart.core::Object*>*] [@vm.direct-call.metadata=dart.collection::__InternalLinkedHashMap&_HashVMBase&MapMixin&_LinkedHashMapMixin.[]=] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::InheritedElement._dependents] [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element*, dart.core::Object*>] this.{self::InheritedElement::_dependents}{core::Map<self::Element*, core::Object*>*}.{core::Map::[]=}(dependent, value){(self::Element*, core::Object*) →* void};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method setDependencies([@vm.inferred-type.metadata=!] self::Element dependent, [@vm.inferred-type.metadata=dart.core::_Smi?] core::Object? value) → void {
+    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<#lib::Element, dart.core::Object?>] [@vm.direct-call.metadata=dart.collection::__InternalLinkedHashMap&_HashVMBase&MapMixin&_LinkedHashMapMixin.[]=] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::InheritedElement._dependents] [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element, dart.core::Object?>] this.{self::InheritedElement::_dependents}{core::Map<self::Element, core::Object?>}.{core::Map::[]=}(dependent, value){(self::Element, core::Object?) → void};
   }
 }
 static method main() → dynamic {
-  self::InheritedElement* ie = new self::InheritedElement::•();
-  [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(ie, 0){(self::Element*, core::Object*) →* void};
-  [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(new self::Element::•(), null){(self::Element*, core::Object*) →* void};
+  self::InheritedElement ie = new self::InheritedElement::•();
+  [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(ie, 0){(self::Element, core::Object?) → void};
+  [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(new self::Element::•(), null){(self::Element, core::Object?) → void};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
index 1a8dce9..685989f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
@@ -1,21 +1,21 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get foo() → core::String*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get foo() → core::String
     return "foo";
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method getBar() → core::String*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method getBar() → core::String
     return "bar";
 }
 class B extends core::Object implements core::Enum /*isEnum*/  {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  final field core::int* index;
-[@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  final field core::String* _name;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method toString() → core::String*
-    return [@vm.direct-call.metadata=#lib::B._name] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] this.{self::B::_name}{core::String*};
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  final field core::int index;
+[@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  final field core::String _name;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method toString() → core::String
+    return [@vm.direct-call.metadata=#lib::B._name] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] this.{self::B::_name}{core::String};
 }
 static method test0() → void {
   core::print(#C1);
@@ -32,9 +32,9 @@
   core::print(#C4);
   core::print([@vm.inferred-type.metadata=dart.core::_Double (value: 100.0)] self::getD);
 }
-static method testStrings([@vm.inferred-type.metadata=#lib::A] self::A* a0) → void {
-  core::print([@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "foo")] a0.{self::A::foo}{core::String*});
-  core::print([@vm.direct-call.metadata=#lib::A.getBar] [@vm.inferred-type.metadata=dart.core::_OneByteString (skip check) (value: "bar")] a0.{self::A::getBar}(){() →* core::String*});
+static method testStrings([@vm.inferred-type.metadata=#lib::A] self::A a0) → void {
+  core::print([@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "foo")] a0.{self::A::foo}{core::String});
+  core::print([@vm.direct-call.metadata=#lib::A.getBar] [@vm.inferred-type.metadata=dart.core::_OneByteString (skip check) (value: "bar")] a0.{self::A::getBar}(){() → core::String});
   core::print(#C5);
 }
 static method testPassEnum() → void {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
index 515824c..4025830 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
@@ -28,7 +28,7 @@
   aa.foo();
 }
 
-void callerA3({A aa}) {
+void callerA3({required A aa}) {
   aa.foo();
 }
 
@@ -44,7 +44,7 @@
   x.toString();
 }
 
-A dd;
+late A dd;
 E ee = new E();
 
 main(List<String> args) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
index ebf2078..67ffa52 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
@@ -1,65 +1,65 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
     return 1;
 }
 class C extends core::Object implements self::A {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
     return 2;
 }
 class D extends self::C {
-  synthetic constructor •() → self::D*
+  synthetic constructor •() → self::D
     : super self::C::•()
     ;
 }
 class E extends core::Object {
-  synthetic constructor •() → self::E*
+  synthetic constructor •() → self::E
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method toString() → core::String*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method toString() → core::String
     return "D";
 }
-[@vm.inferred-type.metadata=#lib::D?]static field self::A* dd;
-[@vm.inferred-type.metadata=#lib::E?]static field self::E* ee = new self::E::•();
-static method callerA1([@vm.inferred-type.metadata=!] self::A* aa) → void {
-  [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+[@vm.inferred-type.metadata=#lib::D]late static field self::A dd;
+[@vm.inferred-type.metadata=#lib::E?]static field self::E ee = new self::E::•();
+static method callerA1([@vm.inferred-type.metadata=!] self::A aa) → void {
+  [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
 }
-static method callerA2([@vm.inferred-type.metadata=#lib::B] self::A* aa) → void {
-  [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+static method callerA2([@vm.inferred-type.metadata=#lib::B] self::A aa) → void {
+  [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
 }
-static method callerA3([@vm.inferred-type.metadata=#lib::C] self::A* aa) → void {
-  [@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+static method callerA3([@vm.inferred-type.metadata=#lib::C] self::A aa) → void {
+  [@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
 }
-static method callerA4([@vm.inferred-type.metadata=#lib::D?] self::A* aa) → void {
-  [@vm.direct-call.metadata=#lib::C.foo??] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+static method callerA4([@vm.inferred-type.metadata=#lib::D] self::A aa) → void {
+  [@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
 }
 static method callerE1() → void {
-  [@vm.direct-call.metadata=dart.core::_StringBase.toString] [@vm.inferred-type.metadata=!? (skip check) (receiver not int)](#C1).{core::Object::toString}(){() →* core::String*};
+  [@vm.direct-call.metadata=dart.core::_StringBase.toString] [@vm.inferred-type.metadata=!? (skip check) (receiver not int)](#C1).{core::Object::toString}(){() → core::String};
 }
 static method callerE2([@vm.inferred-type.metadata=#lib::E?] dynamic x) → void {
-  [@vm.inferred-type.metadata=!? (receiver not int)] x.{core::Object::toString}(){() →* core::String*};
+  [@vm.inferred-type.metadata=!? (receiver not int)] x.{core::Object::toString}(){() → core::String};
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   self::callerA1(new self::B::•());
   self::callerA1(new self::C::•());
   self::callerA2(new self::B::•());
-  let final self::C* #t1 = new self::C::•() in self::callerA3(#t1);
-  self::callerA4([@vm.inferred-type.metadata=#lib::D?] self::dd);
+  let final self::C #t1 = new self::C::•() in self::callerA3(#t1);
+  self::callerA4([@vm.inferred-type.metadata=#lib::D] self::dd);
   self::dd = new self::D::•();
   self::callerE1();
   self::callerE2([@vm.inferred-type.metadata=#lib::E?] self::ee);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart
index 5f51fa3..5b75823 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart
@@ -1,4 +1,8 @@
+// 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.
+
 main() {
-  dynamic x = List<int>.filled(10, null);
+  dynamic x = List<int?>.filled(10, null);
   x[0] + 10;
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect
index 17a558f..5fa7916 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect
@@ -1,8 +1,8 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 static method main() → dynamic {
-  dynamic x = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] core::_List::•<core::int*>(10);
+  dynamic x = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(10);
   [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.direct-call.metadata=dart.core::_List.[]] [@vm.inferred-type.metadata=int? (receiver not int)] x{dynamic}.[](0){dynamic}.+(10);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect
index ac4bbc2..34740ea 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect
@@ -1,24 +1,21 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
 abstract class Enum extends core::Object implements core::Enum {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  abstract get index() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  abstract get /*isLegacy*/ index() → core::int;
 }
 class Class extends core::Object {
-  synthetic constructor •() → self::Class*
+  synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method method() → core::int*
-    return [@vm.inferred-type.metadata=!](#C1).{self::Enum::index}{core::int*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
+    return [@vm.inferred-type.metadata=!] e.{self::Enum::index}{core::int};
 }
 static method main() → dynamic {
-  core::List<dynamic>* list = [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::•<dynamic>(0);
-  if([@vm.direct-call.metadata=dart.core::_GrowableList.isNotEmpty] [@vm.inferred-type.metadata=dart.core::bool] list.{core::Iterable::isNotEmpty}{core::bool*}) {
-    let final self::Class* #t1 = new self::Class::•() in let final self::Enum* #t2 = _in::unsafeCast<self::Enum*>(_in::unsafeCast<dynamic>(null)) in [@vm.direct-call.metadata=#lib::Class.method] [@vm.inferred-type.metadata=!? (skip check)] #t1.{self::Class::method}(){(self::Enum*) →* core::int*};
+  core::List<dynamic> list = [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::•<dynamic>(0);
+  if([@vm.direct-call.metadata=dart.core::_GrowableList.isNotEmpty] [@vm.inferred-type.metadata=dart.core::bool] list.{core::Iterable::isNotEmpty}{core::bool}) {
+    [@vm.direct-call.metadata=#lib::Class.method] [@vm.inferred-type.metadata=!? (skip check)] new self::Class::•().{self::Class::method}(_in::unsafeCast<self::Enum>(_in::unsafeCast<dynamic>(null))){(self::Enum) → core::int};
   }
 }
-constants  {
-  #C1 = null
-}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart
index fcdd2df..9cfd697 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart
@@ -6,65 +6,65 @@
 
 /// Retained because of being by-value return type in FFI call.
 class Struct1 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Retained because of being by-value return type in FFI call.
 class Struct2 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Retained because of being by-value argument type in FFI callback.
 class Struct3 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Class not retained, not referenced at all.
 class Struct4 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Constructor not retained, only referenced as argument type in FFI
 /// call but never instantiated in Dart code.
 class Struct5 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Constructor not retained, only referenced as argument type in FFI
 /// call but never instantiated in Dart code.
 class Struct6 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Constructor not retained, only referenced as return value type in FFI
 /// callback but never instantiated in Dart code.
 class Struct7 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Not retained because of FFI call not being reachable.
 class Struct8 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Not retained because of FFI call not being reachable.
 class Struct9 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Not tetained because of FFI callback not being reachable.
 class Struct10 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Retained by CFE rewrite of load from pointer.
 class Struct11 extends Struct {
-  Struct12 nested;
+  external Struct12 nested;
 }
 
 /// Retained by rewrite of load from surrounding struct.
 class Struct12 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 void main() {
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 f657ded..9086aa75 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
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:ffi" as ffi;
@@ -39,11 +39,11 @@
   constructor #fromTypedDataBase([@vm.inferred-type.metadata=dart.ffi::Pointer] core::Object #typedDataBase) → self::Struct11
     : super ffi::Struct::_fromTypedDataBase(#typedDataBase)
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get nested() → self::Struct12*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get nested() → self::Struct12
     return new self::Struct12::#fromTypedDataBase( block {
       core::Object #typedDataBase = [@vm.direct-call.metadata=dart.ffi::_Compound._typedDataBase] this.{ffi::_Compound::_typedDataBase}{core::Object};
       core::int #offset = (#C12).{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
-    } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_fromAddress<self::Struct12*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.direct-call.metadata=dart.ffi::Pointer.address] [@vm.inferred-type.metadata=int?] #typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in [@vm.direct-call.metadata=dart.typed_data::_ByteBuffer.asUint8List] [@vm.inferred-type.metadata=dart.typed_data::_Uint8ArrayView (skip check)] [@vm.inferred-type.metadata=dart.typed_data::_ByteBuffer] #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=dart.core::_Smi] #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});
+    } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_fromAddress<self::Struct12>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.direct-call.metadata=dart.ffi::Pointer.address] [@vm.inferred-type.metadata=int?] #typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in [@vm.direct-call.metadata=dart.typed_data::_ByteBuffer.asUint8List] [@vm.inferred-type.metadata=dart.typed_data::_Uint8ArrayView (skip check)] [@vm.inferred-type.metadata=dart.typed_data::_ByteBuffer] #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=dart.core::_Smi] #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});
 }
 @#C6
 class Struct12 extends ffi::Struct {
@@ -51,8 +51,8 @@
     : super ffi::Struct::_fromTypedDataBase(#typedDataBase)
     ;
 }
-[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<(self::Struct3*) →* ffi::Int32*>*>* _#ffiCallback0 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<(self::Struct3*) →* ffi::Int32*>*>(ffi::_nativeCallbackFunction<(self::Struct3*) →* ffi::Int32*>(#C16, 0));
-[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<() →* self::Struct7*>*>* _#ffiCallback1 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<() →* self::Struct7*>*>(ffi::_nativeCallbackFunction<() →* self::Struct7*>(#C17, null));
+[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<(self::Struct3) → ffi::Int32>*>* _#ffiCallback0 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<(self::Struct3) → ffi::Int32>*>(ffi::_nativeCallbackFunction<(self::Struct3) → ffi::Int32>(#C16, 0))/*isLegacy*/;
+[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<() → self::Struct7>*>* _#ffiCallback1 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<() → self::Struct7>*>(ffi::_nativeCallbackFunction<() → self::Struct7>(#C17, null))/*isLegacy*/;
 static method main() → void {
   self::testLookupFunctionReturn();
   self::testLookupFunctionArgument();
@@ -64,56 +64,56 @@
   self::testNestedLoad();
 }
 static method testLookupFunctionReturn() → void {
-  final ffi::DynamicLibrary* dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
-  final () →* self::Struct1* function1 = block {
+  final ffi::DynamicLibrary dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
+  final () → self::Struct1 function1 = block {
     _in::_nativeEffect(new self::Struct1::#fromTypedDataBase([@vm.inferred-type.metadata=dart.typed_data::_Uint8List] typ::Uint8List::•(#C18)));
-  } =>ffi::_asFunctionInternal<() →* self::Struct1*, () →* self::Struct1*>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<() →* self::Struct1*>*>("function1"){(core::String) → ffi::Pointer<ffi::NativeFunction<() →* self::Struct1*>*>}, false);
-  final self::Struct1* struct1 = function1(){() →* self::Struct1*};
+  } =>ffi::_asFunctionInternal<() → self::Struct1, () → self::Struct1>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<() → self::Struct1>*>("function1"){(core::String) → ffi::Pointer<ffi::NativeFunction<() → self::Struct1>*>}, false);
+  final self::Struct1 struct1 = function1(){() → self::Struct1};
   core::print(struct1);
 }
 static method testAsFunctionReturn() → void {
-  final ffi::Pointer<ffi::NativeFunction<() →* self::Struct2*>*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<() →* self::Struct2*>*>(3735928559);
-  final () →* self::Struct2* function2 = block {
+  final ffi::Pointer<ffi::NativeFunction<() → self::Struct2>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<() → self::Struct2>>(3735928559);
+  final () → self::Struct2 function2 = block {
     _in::_nativeEffect(new self::Struct2::#fromTypedDataBase([@vm.inferred-type.metadata=dart.typed_data::_Uint8List] typ::Uint8List::•(#C18)));
-  } =>ffi::_asFunctionInternal<() →* self::Struct2*, () →* self::Struct2*>(pointer, false);
-  final self::Struct2* struct2 = function2(){() →* self::Struct2*};
+  } =>ffi::_asFunctionInternal<() → self::Struct2, () → self::Struct2>(pointer, false);
+  final self::Struct2 struct2 = function2(){() → self::Struct2};
   core::print(struct2);
 }
-[@vm.unboxing-info.metadata=(b)->i]static method useStruct3(self::Struct3* struct3) → core::int* {
+[@vm.unboxing-info.metadata=(b)->i]static method useStruct3(self::Struct3 struct3) → core::int {
   return 42;
 }
 static method testFromFunctionArgument() → void {
-  final ffi::Pointer<ffi::NativeFunction<(self::Struct3*) →* ffi::Int32*>*>* pointer = block {
+  final ffi::Pointer<ffi::NativeFunction<(self::Struct3) → ffi::Int32>> pointer = block {
     _in::_nativeEffect(new self::Struct3::#fromTypedDataBase([@vm.inferred-type.metadata=dart.typed_data::_Uint8List] typ::Uint8List::•(#C18)));
   } =>[@vm.inferred-type.metadata=dart.ffi::Pointer?] self::_#ffiCallback0;
   core::print(pointer);
 }
 static method testLookupFunctionArgument() → void {
-  final ffi::DynamicLibrary* dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
-  final (self::Struct5*) →* void function5 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct5*) →* void, (self::Struct5*) →* ffi::Void*>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<(self::Struct5*) →* ffi::Void*>*>("function5"){(core::String) → ffi::Pointer<ffi::NativeFunction<(self::Struct5*) →* ffi::Void*>*>}, false);
+  final ffi::DynamicLibrary dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
+  final (self::Struct5) → void function5 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct5) → void, (self::Struct5) → ffi::Void>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<(self::Struct5) → ffi::Void>*>("function5"){(core::String) → ffi::Pointer<ffi::NativeFunction<(self::Struct5) → ffi::Void>*>}, false);
   core::print(function5);
 }
 static method testAsFunctionArgument() → void {
-  final ffi::Pointer<ffi::NativeFunction<(self::Struct6*) →* ffi::Void*>*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<(self::Struct6*) →* ffi::Void*>*>(3735928559);
-  final (self::Struct6*) →* void function6 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct6*) →* void, (self::Struct6*) →* ffi::Void*>(pointer, false);
+  final ffi::Pointer<ffi::NativeFunction<(self::Struct6) → ffi::Void>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<(self::Struct6) → ffi::Void>>(3735928559);
+  final (self::Struct6) → void function6 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct6) → void, (self::Struct6) → ffi::Void>(pointer, false);
   core::print(function6);
 }
-static method returnStruct7() → self::Struct7* {
+static method returnStruct7() → self::Struct7 {
   throw "I don't want to create a Struct7!";
 }
 static method testFromFunctionReturn() → void {
-  final ffi::Pointer<ffi::NativeFunction<() →* self::Struct7*>*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] self::_#ffiCallback1;
+  final ffi::Pointer<ffi::NativeFunction<() → self::Struct7>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] self::_#ffiCallback1;
   core::print(pointer);
 }
 static method testPointerLoad() → void {
-  final ffi::Pointer<self::Struct11*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11*>(3735928559);
-  final self::Struct11* struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
+  final ffi::Pointer<self::Struct11> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11>(3735928559);
+  final self::Struct11 struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
   core::print(struct11);
 }
 static method testNestedLoad() → void {
-  final ffi::Pointer<self::Struct11*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11*>(3735928559);
-  final self::Struct11* struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
-  final self::Struct12* struct12 = [@vm.direct-call.metadata=#lib::Struct11.nested] [@vm.inferred-type.metadata=#lib::Struct12] struct11.{self::Struct11::nested}{self::Struct12*};
+  final ffi::Pointer<self::Struct11> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11>(3735928559);
+  final self::Struct11 struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
+  final self::Struct12 struct12 = [@vm.direct-call.metadata=#lib::Struct11.nested] [@vm.inferred-type.metadata=#lib::Struct12] struct11.{self::Struct11::nested}{self::Struct12};
   core::print(struct12);
 }
 constants  {
@@ -132,7 +132,7 @@
   #C13 = 8
   #C14 = 4
   #C15 = <core::int*>[#C13, #C14, #C14]
-  #C16 = tearoff self::useStruct3
-  #C17 = tearoff self::returnStruct7
+  #C16 = static-tearoff self::useStruct3
+  #C17 = static-tearoff self::returnStruct7
   #C18 = 1
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/future.dart.expect
index 8a43ab1..a0447e5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future.dart.expect
@@ -1,35 +1,35 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
 
 import "dart:async";
 
-class C<T extends core::Object* = dynamic> extends core::Object {
-  synthetic constructor •() → self::C<self::C::T*>*
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->b]  method test2c([@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] generic-covariant-impl FutureOr<self::C::T*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method test3c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int*> (skip check)] generic-covariant-impl asy::Future<self::C::T*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method test4c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int*> (skip check)] generic-covariant-impl FutureOr<self::C::T*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method test2r([@vm.inferred-type.metadata=#lib::C<dart.core::int*> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T*>*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method test3r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int*>*> (skip check)] generic-covariant-impl self::C<asy::Future<self::C::T*>*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method test4r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int*>*> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T*>*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method test5r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int*>?>] generic-covariant-impl self::C<asy::Future<self::C::T*>*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method test6r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int*>?> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T*>*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method test7r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int*>?>] generic-covariant-impl self::C<self::C::T*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method test8r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int*>*>] generic-covariant-impl self::C<self::C::T*>* x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->b]  method test2c([@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] generic-covariant-impl FutureOr<self::C::T%>x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method test3c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int> (skip check)] generic-covariant-impl asy::Future<self::C::T%> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method test4c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int> (skip check)] generic-covariant-impl FutureOr<self::C::T%>x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method test2r([@vm.inferred-type.metadata=#lib::C<dart.core::int> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T%>> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method test3r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int>> (skip check)] generic-covariant-impl self::C<asy::Future<self::C::T%>> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method test4r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int>> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T%>> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method test5r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int>?>] generic-covariant-impl self::C<asy::Future<self::C::T%>> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method test6r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int>?> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T%>> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method test7r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int>?>] generic-covariant-impl self::C<self::C::T%> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method test8r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int>>] generic-covariant-impl self::C<self::C::T%> x) → void {}
 }
 static method main() → dynamic {
-  dynamic c = new self::C::•<core::int*>();
+  dynamic c = new self::C::•<core::int>();
   [@vm.direct-call.metadata=#lib::C.test2c] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test2c(3);
-  [@vm.direct-call.metadata=#lib::C.test3c] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test3c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int*>] asy::Future::value<core::int*>(3));
-  [@vm.direct-call.metadata=#lib::C.test4c] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test4c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int*>] asy::Future::value<core::int*>(3));
-  [@vm.direct-call.metadata=#lib::C.test2r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test2r(new self::C::•<core::int*>());
-  [@vm.direct-call.metadata=#lib::C.test3r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test3r(new self::C::•<asy::Future<core::int*>*>());
-  [@vm.direct-call.metadata=#lib::C.test4r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test4r(new self::C::•<asy::Future<core::int*>*>());
-  [@vm.direct-call.metadata=#lib::C.test5r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test5r(new self::C::•<FutureOr<core::int*>*>());
-  [@vm.direct-call.metadata=#lib::C.test6r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test6r(new self::C::•<FutureOr<core::int*>*>());
-  [@vm.direct-call.metadata=#lib::C.test7r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test7r(new self::C::•<FutureOr<core::int*>*>());
-  [@vm.direct-call.metadata=#lib::C.test8r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test8r(new self::C::•<asy::Future<core::int*>*>());
+  [@vm.direct-call.metadata=#lib::C.test3c] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test3c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int>] asy::Future::value<core::int>(3));
+  [@vm.direct-call.metadata=#lib::C.test4c] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test4c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int>] asy::Future::value<core::int>(3));
+  [@vm.direct-call.metadata=#lib::C.test2r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test2r(new self::C::•<core::int>());
+  [@vm.direct-call.metadata=#lib::C.test3r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test3r(new self::C::•<asy::Future<core::int>>());
+  [@vm.direct-call.metadata=#lib::C.test4r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test4r(new self::C::•<asy::Future<core::int>>());
+  [@vm.direct-call.metadata=#lib::C.test5r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test5r(new self::C::•<FutureOr<core::int>>());
+  [@vm.direct-call.metadata=#lib::C.test6r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test6r(new self::C::•<FutureOr<core::int>>());
+  [@vm.direct-call.metadata=#lib::C.test7r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test7r(new self::C::•<FutureOr<core::int>>());
+  [@vm.direct-call.metadata=#lib::C.test8r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test8r(new self::C::•<asy::Future<core::int>>());
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
index f253547..f2136d5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
@@ -53,14 +53,14 @@
   use(x);
 }
 
-void foo2(Future<A> a1, A a2, FutureOr<A> a3, FutureOr<A> a4) {
+void foo2(Future<A>? a1, A? a2, FutureOr<A>? a3, FutureOr<A>? a4) {
   foo2_a1(a1);
   foo2_a2(a2);
   foo2_a3(a3);
   foo2_a4(a4);
 }
 
-Function unknown;
+late Function unknown;
 getDynamic() => unknown.call();
 
 main(List<String> args) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
index 4c9cbc4..c9b4c9f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
@@ -6,33 +6,33 @@
 import "dart:async";
 
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
 }
 static field dynamic usedObject;
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
-static method foo1_a1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] dynamic x) → void {
+static method foo1_a1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] dynamic x) → void {
   self::use(x);
 }
 static method foo1_a2([@vm.inferred-type.metadata=#lib::B] dynamic x) → void {
   self::use(x);
 }
-static method foo1_a3([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] dynamic x) → void {
+static method foo1_a3([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] dynamic x) → void {
   self::use(x);
 }
 static method foo1_a4([@vm.inferred-type.metadata=#lib::B] dynamic x) → void {
   self::use(x);
 }
-static method foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] asy::Future<self::A*>* a1, [@vm.inferred-type.metadata=#lib::B] self::A* a2, [@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] FutureOr<self::A*>* a3, [@vm.inferred-type.metadata=#lib::B] FutureOr<self::A*>* a4) → void {
+static method foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future<self::A> a1, [@vm.inferred-type.metadata=#lib::B] self::A a2, [@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] FutureOr<self::A>a3, [@vm.inferred-type.metadata=#lib::B] FutureOr<self::A>a4) → void {
   self::foo1_a1(a1);
   self::foo1_a2(a2);
   self::foo1_a3(a3);
@@ -50,7 +50,7 @@
 static method foo2_a4(dynamic x) → void {
   self::use(x);
 }
-static method foo2([@vm.inferred-type.metadata=dart.async::_Future?] asy::Future<self::A*>* a1, [@vm.inferred-type.metadata=#lib::B?] self::A* a2, FutureOr<self::A*>* a3, FutureOr<self::A*>* a4) → void {
+static method foo2([@vm.inferred-type.metadata=dart.async::_Future?] asy::Future<self::A>? a1, [@vm.inferred-type.metadata=#lib::B?] self::A? a2, FutureOr<self::A>? a3, FutureOr<self::A>? a4) → void {
   self::foo2_a1(a1);
   self::foo2_a2(a2);
   self::foo2_a3(a3);
@@ -58,7 +58,7 @@
 }
 static method getDynamic() → dynamic
   return self::unknown();
-static method main(core::List<core::String*>* args) → dynamic {
-  self::foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] asy::Future::value<self::B*>(new self::B::•()), new self::B::•(), [@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] asy::Future::value<self::B*>(new self::B::•()), new self::B::•());
-  self::foo2(self::getDynamic() as{TypeError,ForDynamic} asy::Future<self::A*>*, self::getDynamic() as{TypeError,ForDynamic} self::A*, self::getDynamic() as{TypeError,ForDynamic} FutureOr<self::A*>*, self::getDynamic() as{TypeError,ForDynamic} FutureOr<self::A*>*);
+static method main(core::List<core::String> args) → dynamic {
+  self::foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future::value<self::B>(new self::B::•()), new self::B::•(), [@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future::value<self::B>(new self::B::•()), new self::B::•());
+  self::foo2(self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::A>?, self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A?, self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<self::A>?, self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<self::A>?);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect
index 2296f5b..7b1f705 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect
@@ -1,14 +1,14 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 }
-static method foo() → core::Object*
+static method foo() → core::Object
   return new self::A::•();
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   core::print([@vm.inferred-type.metadata=#lib::A] self::foo());
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart
index bb66a2b..67c62c8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart
@@ -4,8 +4,6 @@
 
 // Test for tree shaking of instance fields with initializers.
 
-// @dart = 2.12
-
 int sideEffect(int x) {
   print(x);
   return x;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart
index da1f458..fccae87 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart
@@ -18,11 +18,11 @@
 class _BroadcastSubscription extends StreamSubscription {}
 
 abstract class Stream {
-  StreamSubscription foobar(void onData(event), {Function onError});
+  StreamSubscription foobar(void onData(event)?, {Function? onError});
 }
 
 abstract class _StreamImpl extends Stream {
-  StreamSubscription foobar(void onData(data), {Function onError}) {
+  StreamSubscription foobar(void onData(data)?, {Function? onError}) {
     return _createSubscription();
   }
 
@@ -44,7 +44,7 @@
 
   StreamView(Stream stream) : _stream = stream;
 
-  StreamSubscription foobar(void onData(value), {Function onError}) {
+  StreamSubscription foobar(void onData(value)?, {Function? onError}) {
     return _stream.foobar(onData, onError: onError);
   }
 }
@@ -52,15 +52,15 @@
 class ByteStream extends StreamView {
   ByteStream(Stream stream) : super(stream);
 
-  super_foobar1(void onData(value)) {
+  super_foobar1(void onData(value)?) {
     super.foobar(onData);
   }
 
-  super_foobar2(void onData(value)) {
+  super_foobar2(void onData(value)?) {
     super.foobar(onData);
   }
 
-  super_foobar3({void onData(value), Function onError}) {
+  super_foobar3({void onData(value)?, Function? onError}) {
     super.foobar(onData, onError: onError);
   }
 
@@ -68,7 +68,7 @@
 }
 
 class _HandleErrorStream extends Stream {
-  StreamSubscription foobar(void onData(event), {Function onError}) {
+  StreamSubscription foobar(void onData(event)?, {Function? onError}) {
     return new _BufferingStreamSubscription();
   }
 }
@@ -77,26 +77,26 @@
   new ByteStream(new ByteStream(new _GeneratedStreamImpl()));
 }
 
-void round1({void onData(value)}) {
+void round1({void onData(value)?}) {
   var x = new ByteStream(new ByteStream(new _GeneratedStreamImpl()));
   x.super_foobar1(onData);
 }
 
-void round2({void onData(value), Function onError}) {
+void round2({void onData(value)?, Function? onError}) {
   new _ControllerStream();
   Stream x = new _GeneratedStreamImpl();
   x = new ByteStream(x);
   x.foobar(onData, onError: onError);
 }
 
-void round3({void onData(value), Function onError}) {
+void round3({void onData(value)?, Function? onError}) {
   Stream x = new _GeneratedStreamImpl();
   x = new ByteStream(x);
   x = new _ControllerStream();
   x.foobar(onData, onError: onError);
 }
 
-void round4({void onData(value)}) {
+void round4({void onData(value)?}) {
   var x = new ByteStream(new _ControllerStream());
   var y = x.super_stream;
   var z = x._stream;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
index 4b18c73..4771de1 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
@@ -1,80 +1,79 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class StreamSubscription extends core::Object {
-  synthetic constructor •() → self::StreamSubscription*
+  synthetic constructor •() → self::StreamSubscription
     : super core::Object::•()
     ;
 }
 class _BufferingStreamSubscription extends self::StreamSubscription {
-  synthetic constructor •() → self::_BufferingStreamSubscription*
+  synthetic constructor •() → self::_BufferingStreamSubscription
     : super self::StreamSubscription::•()
     ;
 }
 class _BroadcastSubscription extends self::StreamSubscription {
-  synthetic constructor •() → self::_BroadcastSubscription*
+  synthetic constructor •() → self::_BroadcastSubscription
     : super self::StreamSubscription::•()
     ;
 }
 abstract class Stream extends core::Object {
-  synthetic constructor •() → self::Stream*
+  synthetic constructor •() → self::Stream
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foobar() → self::StreamSubscription*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3]  abstract operator ==(dynamic other) → core::bool*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foobar() → self::StreamSubscription;
 }
 abstract class _StreamImpl extends self::Stream {
-  synthetic constructor •() → self::_StreamImpl*
+  synthetic constructor •() → self::_StreamImpl
     : super self::Stream::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foobar() → self::StreamSubscription* {
-    return [@vm.inferred-type.metadata=! (skip check)] this.{self::_StreamImpl::_createSubscription}(){() →* self::StreamSubscription*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foobar() → self::StreamSubscription {
+    return [@vm.inferred-type.metadata=! (skip check)] this.{self::_StreamImpl::_createSubscription}(){() → self::StreamSubscription};
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  method _createSubscription() → self::StreamSubscription* {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method _createSubscription() → self::StreamSubscription {
     return new self::_BufferingStreamSubscription::•();
   }
 }
 class _ControllerStream extends self::_StreamImpl {
-  synthetic constructor •() → self::_ControllerStream*
+  synthetic constructor •() → self::_ControllerStream
     : super self::_StreamImpl::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  method _createSubscription() → self::StreamSubscription* {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method _createSubscription() → self::StreamSubscription {
     return new self::_BroadcastSubscription::•();
   }
 }
 class _GeneratedStreamImpl extends self::_StreamImpl {
-  synthetic constructor •() → self::_GeneratedStreamImpl*
+  synthetic constructor •() → self::_GeneratedStreamImpl
     : super self::_StreamImpl::•()
     ;
 }
 abstract class StreamView extends self::Stream {
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6]  final field self::Stream* _stream;
-  constructor •([@vm.inferred-type.metadata=!] self::Stream* stream) → self::StreamView*
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  final field self::Stream _stream;
+  constructor •([@vm.inferred-type.metadata=!] self::Stream stream) → self::StreamView
     : self::StreamView::_stream = stream, super self::Stream::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foobar() → self::StreamSubscription* {
-    return [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] this.{self::StreamView::_stream}{self::Stream*}.{self::Stream::foobar}(){((dynamic) →* void, {onError: core::Function*}) →* self::StreamSubscription*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foobar() → self::StreamSubscription {
+    return [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] this.{self::StreamView::_stream}{self::Stream}.{self::Stream::foobar}(){((dynamic) →? void, {onError: core::Function?}) → self::StreamSubscription};
   }
 }
 class ByteStream extends self::StreamView {
-  constructor •([@vm.inferred-type.metadata=!] self::Stream* stream) → self::ByteStream*
+  constructor •([@vm.inferred-type.metadata=!] self::Stream stream) → self::ByteStream
     : super self::StreamView::•(stream)
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method super_foobar1() → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method super_foobar1() → dynamic {
     super.{self::StreamView::foobar}();
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method super_foobar2() → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9]  method super_foobar2() → dynamic {
     super.{self::StreamView::foobar}();
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method super_foobar3() → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10,getterSelectorId:11]  method super_foobar3() → dynamic {
     super.{self::StreamView::foobar}();
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:13]  get super_stream() → self::Stream*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:12]  get super_stream() → self::Stream
     return [@vm.inferred-type.metadata=!] super.{self::StreamView::_stream};
 }
 class _HandleErrorStream extends self::Stream {
-  synthetic constructor •() → self::_HandleErrorStream*
+  synthetic constructor •() → self::_HandleErrorStream
     : super self::Stream::•()
     ;
 }
@@ -82,35 +81,35 @@
   new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
 }
 static method round1() → void {
-  self::ByteStream* x = new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
-  [@vm.direct-call.metadata=#lib::ByteStream.super_foobar1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar1}(){((dynamic) →* void) →* dynamic};
+  self::ByteStream x = new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
+  [@vm.direct-call.metadata=#lib::ByteStream.super_foobar1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar1}(){((dynamic) →? void) → dynamic};
 }
 static method round2() → void {
   new self::_ControllerStream::•();
-  self::Stream* x = new self::_GeneratedStreamImpl::•();
+  self::Stream x = new self::_GeneratedStreamImpl::•();
   x = new self::ByteStream::•(x);
-  [@vm.direct-call.metadata=#lib::StreamView.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →* void, {onError: core::Function*}) →* self::StreamSubscription*};
+  [@vm.direct-call.metadata=#lib::StreamView.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →? void, {onError: core::Function?}) → self::StreamSubscription};
 }
 static method round3() → void {
-  self::Stream* x = new self::_GeneratedStreamImpl::•();
+  self::Stream x = new self::_GeneratedStreamImpl::•();
   x = new self::ByteStream::•(x);
   x = new self::_ControllerStream::•();
-  [@vm.direct-call.metadata=#lib::_StreamImpl.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →* void, {onError: core::Function*}) →* self::StreamSubscription*};
+  [@vm.direct-call.metadata=#lib::_StreamImpl.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →? void, {onError: core::Function?}) → self::StreamSubscription};
 }
 static method round4() → void {
-  self::ByteStream* x = new self::ByteStream::•(new self::_ControllerStream::•());
-  self::Stream* y = [@vm.direct-call.metadata=#lib::ByteStream.super_stream] [@vm.inferred-type.metadata=!] x.{self::ByteStream::super_stream}{self::Stream*};
-  self::Stream* z = [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] x.{self::StreamView::_stream}{self::Stream*};
-  if([@vm.direct-call.metadata=dart.core::Object.==] [@vm.inferred-type.metadata=dart.core::bool (skip check) (receiver not int)] y =={self::Stream::==}{(dynamic) →* core::bool*} z) {
-    [@vm.direct-call.metadata=#lib::ByteStream.super_foobar2] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar2}(){((dynamic) →* void) →* dynamic};
+  self::ByteStream x = new self::ByteStream::•(new self::_ControllerStream::•());
+  self::Stream y = [@vm.direct-call.metadata=#lib::ByteStream.super_stream] [@vm.inferred-type.metadata=!] x.{self::ByteStream::super_stream}{self::Stream};
+  self::Stream z = [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] x.{self::StreamView::_stream}{self::Stream};
+  if([@vm.direct-call.metadata=dart.core::Object.==] [@vm.inferred-type.metadata=dart.core::bool (skip check) (receiver not int)] y =={core::Object::==}{(core::Object) → core::bool} z) {
+    [@vm.direct-call.metadata=#lib::ByteStream.super_foobar2] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar2}(){((dynamic) →? void) → dynamic};
   }
 }
 static method round5() → void {
-  self::ByteStream* x = new self::ByteStream::•(new self::_GeneratedStreamImpl::•());
+  self::ByteStream x = new self::ByteStream::•(new self::_GeneratedStreamImpl::•());
   new self::_HandleErrorStream::•();
-  [@vm.direct-call.metadata=#lib::ByteStream.super_foobar3] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar3}(){({onData: (dynamic) →* void, onError: core::Function*}) →* dynamic};
+  [@vm.direct-call.metadata=#lib::ByteStream.super_foobar3] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar3}(){({onData: (dynamic) →? void, onError: core::Function?}) → dynamic};
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   new self::_GeneratedStreamImpl::•();
   self::round0();
   self::round1();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart
index c4e949c..01188a6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart
@@ -18,7 +18,7 @@
   Object foo() => new T2();
 }
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
index 43bee1f..1723808 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
@@ -1,82 +1,82 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 abstract class A extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → core::Object*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → core::Object;
 }
 class B extends core::Object implements self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → core::Object*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → core::Object
     return new self::T1::•();
 }
 class C extends core::Object implements self::A {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → core::Object*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → core::Object
     return new self::T2::•();
 }
 class DeepCaller1 extends core::Object {
-  synthetic constructor •() → self::DeepCaller1*
+  synthetic constructor •() → self::DeepCaller1
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method barL1() → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL2}(){() →* dynamic};
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL2}(){() → dynamic};
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method barL2() → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL3}(){() →* dynamic};
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL3}(){() → dynamic};
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method barL3() → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL4}(){() →* dynamic};
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL4}(){() → dynamic};
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method barL4() → dynamic
     return self::field1;
 }
 class D extends core::Object {
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  field core::Object* field2;
-  synthetic constructor •() → self::D*
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  field core::Object field2;
+  synthetic constructor •() → self::D
     : self::D::field2 = [@vm.inferred-type.metadata=!] self::getValue(), super core::Object::•()
     ;
 }
 class DeepCaller2 extends core::Object {
-  synthetic constructor •() → self::DeepCaller2*
+  synthetic constructor •() → self::DeepCaller2
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL1([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(dd){(self::D*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL2([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(dd){(self::D*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL3([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(dd){(self::D*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method barL4([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
-    return [@vm.direct-call.metadata=#lib::D.field2] [@vm.inferred-type.metadata=!] dd.{self::D::field2}{core::Object*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL1([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(dd){(self::D) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL2([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(dd){(self::D) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL3([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(dd){(self::D) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method barL4([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+    return [@vm.direct-call.metadata=#lib::D.field2] [@vm.inferred-type.metadata=!] dd.{self::D::field2}{core::Object};
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static field core::Object* field1 = [@vm.inferred-type.metadata=!] self::getValue();
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static field core::Object field1 = [@vm.inferred-type.metadata=!] self::getValue();
 static method getDynamic() → dynamic
   return self::unknown();
-static method getValue() → core::Object* {
-  self::A* aa = self::getDynamic() as{TypeError,ForDynamic} self::A*;
-  return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() →* core::Object*};
+static method getValue() → core::Object {
+  self::A aa = self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A;
+  return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() → core::Object};
 }
-static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1* x) → dynamic
-  return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::DeepCaller1::barL1}(){() →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2* x) → dynamic
-  return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(new self::D::•()){(self::D*) →* dynamic};
+static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1 x) → dynamic
+  return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::DeepCaller1::barL1}(){() → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2 x) → dynamic
+  return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(new self::D::•()){(self::D) → dynamic};
 static method createC() → dynamic {
   new self::C::•();
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   new self::B::•();
   self::use1(new self::DeepCaller1::•());
   self::use2(new self::DeepCaller2::•());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
index b70a6cf..0bc4332 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
@@ -25,7 +25,7 @@
 use1(Intermediate i, A aa) => i.bar(aa);
 use2(Intermediate i, A aa) => i.bar(aa);
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
index 750a33e..e916e0c 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
@@ -1,44 +1,44 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → dynamic;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
     return new self::T1::•();
 }
 class Intermediate extends core::Object {
-  synthetic constructor •() → self::Intermediate*
+  synthetic constructor •() → self::Intermediate
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar([@vm.inferred-type.metadata=#lib::B?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] aa.{self::A::foo}(){() →* dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar([@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] aa.{self::A::foo}(){() → dynamic};
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, [@vm.inferred-type.metadata=#lib::B?] self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, [@vm.inferred-type.metadata=#lib::B?] self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
 static method getDynamic() → dynamic
   return self::unknown();
 static method allocateB() → dynamic {
   new self::B::•();
 }
-static method main(core::List<core::String*>* args) → dynamic {
-  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+static method main(core::List<core::String> args) → dynamic {
+  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
   self::allocateB();
-  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
index 5248ac9..ca439fa 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
@@ -30,7 +30,7 @@
 use2(Intermediate i, A aa) => i.bar(aa);
 use3(Intermediate i, A aa) => i.bar(aa);
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
index 50f57c2..dc456ee 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
@@ -1,25 +1,25 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → dynamic;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
@@ -28,36 +28,36 @@
 abstract class C extends core::Object implements self::B {
 }
 abstract class D extends core::Object {
-  synthetic constructor •() → self::D*
+  synthetic constructor •() → self::D
     : super core::Object::•()
     ;
 }
 abstract class _E&D&C extends self::D implements self::C /*isAnonymousMixin,isEliminatedMixin*/  {
-  synthetic constructor •() → self::_E&D&C*
+  synthetic constructor •() → self::_E&D&C
     : super self::D::•()
     ;
 }
 class E extends self::_E&D&C {
-  synthetic constructor •() → self::E*
+  synthetic constructor •() → self::E
     : super self::_E&D&C::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
     return new self::T2::•();
 }
 class Intermediate extends core::Object {
-  synthetic constructor •() → self::Intermediate*
+  synthetic constructor •() → self::Intermediate
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar(self::A* aa) → dynamic
-    return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() →* dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar(self::A aa) → dynamic
+    return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() → dynamic};
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
-static method use3([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use3([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
 static method getDynamic() → dynamic
   return self::unknown();
 static method allocateB() → dynamic {
@@ -66,10 +66,10 @@
 static method allocateE() → dynamic {
   new self::E::•();
 }
-static method main(core::List<core::String*>* args) → dynamic {
-  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+static method main(core::List<core::String> args) → dynamic {
+  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
   self::allocateB();
-  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
   self::allocateE();
-  self::use3(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+  self::use3(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart
index cd5d128..01417ef 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart
@@ -27,7 +27,7 @@
 
 use_bazz(dynamic x) => x.bazz();
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
index 13a7d78b..c049955 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
@@ -1,24 +1,24 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 class T3 extends core::Object {
-  synthetic constructor •() → self::T3*
+  synthetic constructor •() → self::T3
     : super core::Object::•()
     ;
 }
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
@@ -29,7 +29,7 @@
     return new self::T3::•();
 }
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method foo() → dynamic
@@ -39,7 +39,7 @@
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method bazz() → dynamic
     return new self::T3::•();
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
 static method use_foo1(dynamic x) → dynamic
   return [@vm.inferred-type.metadata=#lib::T1] x{dynamic}.foo();
 static method use_foo2(dynamic x) → dynamic
@@ -56,7 +56,7 @@
 static method allocateB() → dynamic {
   new self::B::•();
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   self::use_foo1(self::getDynamic());
   self::allocateA();
   self::use_foo2(self::getDynamic());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
index 7fb845e..5232b28 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
@@ -30,7 +30,7 @@
 use1(DeepCaller1 x, A aa) => x.barL1(aa);
 use2(DeepCaller2 x, A aa) => x.barL1(aa);
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
index 8a434a8..03a3204 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
@@ -1,65 +1,65 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 class A extends core::Object {
 [@vm.inferred-type.metadata=#lib::T1] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  field dynamic field1;
 [@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field dynamic field2;
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : self::A::field1 = new self::T1::•(), self::A::field2 = new self::T1::•(), super core::Object::•()
     ;
 }
 class DeepCaller1 extends core::Object {
-  synthetic constructor •() → self::DeepCaller1*
+  synthetic constructor •() → self::DeepCaller1
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method barL1([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL2}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method barL2([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL3}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method barL3([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL4}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method barL4([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method barL1([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL2}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method barL2([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL3}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method barL3([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL4}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method barL4([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
     return [@vm.direct-call.metadata=#lib::A.field1??] [@vm.inferred-type.metadata=#lib::T1] aa.{self::A::field1}{dynamic};
 }
 class DeepCaller2 extends core::Object {
-  synthetic constructor •() → self::DeepCaller2*
+  synthetic constructor •() → self::DeepCaller2
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL1([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL2([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL3([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method barL4([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL1([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL2([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL3([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method barL4([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
     return [@vm.direct-call.metadata=#lib::A.field2??] [@vm.inferred-type.metadata=!] aa.{self::A::field2}{dynamic};
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1* x, [@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=#lib::T1 (skip check)] x.{self::DeepCaller1::barL1}(aa){(self::A*) →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2* x, [@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(aa){(self::A*) →* dynamic};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1 x, [@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=#lib::T1 (skip check)] x.{self::DeepCaller1::barL1}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2 x, [@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(aa){(self::A) → dynamic};
 static method getDynamic() → dynamic
   return self::unknown();
-static method setField2([@vm.inferred-type.metadata=#lib::A] self::A* aa, [@vm.inferred-type.metadata=#lib::T2] dynamic value) → void {
+static method setField2([@vm.inferred-type.metadata=#lib::A] self::A aa, [@vm.inferred-type.metadata=#lib::T2] dynamic value) → void {
   [@vm.direct-call.metadata=#lib::A.field2] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::field2} = value;
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   new self::A::•();
   new self::T1::•();
   new self::T2::•();
-  self::use1(new self::DeepCaller1::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
-  self::use2(new self::DeepCaller2::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+  self::use1(new self::DeepCaller1::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
+  self::use2(new self::DeepCaller2::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
   self::setField2(new self::A::•(), new self::T2::•());
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect
index ffc08fe..918c5ae 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect
@@ -1,43 +1,43 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method go() → self::T3*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method go() → self::T3
     return new self::T3::•();
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 class T3 extends core::Object {
-  synthetic constructor •() → self::T3*
+  synthetic constructor •() → self::T3
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method run() → dynamic {
     core::print("hi");
   }
 }
-class Q<T extends core::Object* = dynamic> extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  final field self::Q::T* result;
-  constructor •(self::Q::T* result) → self::Q<self::Q::T*>*
+class Q<T extends core::Object? = dynamic> extends core::Object {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  final field self::Q::T% result;
+  constructor •(self::Q::T% result) → self::Q<self::Q::T%>
     : self::Q::result = result, super core::Object::•()
     ;
 }
-static method foo1([@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::T1*>] core::List<self::T1*>* list) → dynamic {
-  [@vm.direct-call.metadata=#lib::T3.run] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::T1.go??] [@vm.inferred-type.metadata=#lib::T3 (skip check)] [@vm.direct-call.metadata=#lib::Q.result??] [@vm.direct-call.metadata=dart._internal::ListIterable.first] [@vm.inferred-type.metadata=#lib::Q?] [@vm.direct-call.metadata=dart.collection::_ListBase&Object&ListMixin.map] [@vm.inferred-type.metadata=dart._internal::MappedListIterable<#lib::T1*, ?> (skip check)] list.{core::Iterable::map}<self::Q<self::T1*>*>((self::T1* t1) → self::Q<self::T1*>* => new self::Q::•<self::T1*>(t1)){((self::T1*) →* self::Q<self::T1*>*) →* core::Iterable<self::Q<self::T1*>*>*}.{core::Iterable::first}{self::Q<self::T1*>*}.{self::Q::result}{self::T1*}.{self::T1::go}(){() →* self::T3*}.{self::T3::run}(){() →* dynamic};
+static method foo1([@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::T1>] core::List<self::T1> list) → dynamic {
+  [@vm.direct-call.metadata=#lib::T3.run] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::T1.go??] [@vm.inferred-type.metadata=#lib::T3 (skip check)] [@vm.direct-call.metadata=#lib::Q.result??] [@vm.direct-call.metadata=dart._internal::ListIterable.first] [@vm.inferred-type.metadata=#lib::Q?] [@vm.direct-call.metadata=dart.collection::_ListBase&Object&ListMixin.map] [@vm.inferred-type.metadata=dart._internal::MappedListIterable<#lib::T1, ?> (skip check)] list.{core::Iterable::map}<self::Q<self::T1>>((self::T1 t1) → self::Q<self::T1> => new self::Q::•<self::T1>(t1)){((self::T1) → self::Q<self::T1>) → core::Iterable<self::Q<self::T1>>}.{core::Iterable::first}{self::Q<self::T1>}.{self::Q::result}{self::T1}.{self::T1::go}(){() → self::T3}.{self::T3::run}(){() → dynamic};
 }
-static method foo2NewValue() → self::Q<dynamic>*
-  return new self::Q::•<self::T2*>(new self::T2::•());
+static method foo2NewValue() → self::Q<dynamic>
+  return new self::Q::•<self::T2>(new self::T2::•());
 static method foo3NewT1() → dynamic {
   new self::T1::•();
 }
-static method main(core::List<core::String*>* args) → dynamic {
-  self::foo1([@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::T1*>] core::_GrowableList::•<self::T1*>(0));
+static method main(core::List<core::String> args) → dynamic {
+  self::foo1([@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::T1>] core::_GrowableList::•<self::T1>(0));
   self::foo2NewValue();
   self::foo3NewT1();
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect
index 74df479..84447db 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
@@ -6,35 +6,35 @@
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → void;
 }
 class T1 extends core::Object implements self::I {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → void {}
 }
 class T2 extends core::Object implements self::I {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → void {}
 }
 class Point extends core::Object /*hasConstConstructor*/  {
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  final field self::I* x;
-  const constructor •([@vm.inferred-type.metadata=!] self::I* x) → self::Point*
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  final field self::I x;
+  const constructor •([@vm.inferred-type.metadata=!] self::I x) → self::Point
     : self::Point::x = x, super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  method newPoint1() → self::Point*
-    return new self::Point::•([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] this.{self::Point::x}{self::I*});
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method newPoint2() → self::Point*
-    return new self::Point::•([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] this.{self::Point::x}{self::I*});
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  method newPoint1() → self::Point
+    return new self::Point::•([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] this.{self::Point::x}{self::I});
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method newPoint2() → self::Point
+    return new self::Point::•([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] this.{self::Point::x}{self::I});
 }
 static method getX([@vm.inferred-type.metadata=#lib::Point] dynamic point) → dynamic {
   [@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!? (receiver not int)] point{dynamic}.x;
 }
 static method main() → dynamic {
-  self::Point* a = new self::Point::•(new self::T1::•());
-  core::print([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] a.{self::Point::x}{self::I*});
-  self::Point* c = new self::Point::•(new self::T2::•());
-  [@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] c.{self::Point::x}{self::I*}.{self::I::foo}(){() →* void};
-  self::getX([@vm.direct-call.metadata=#lib::Point.newPoint1] [@vm.inferred-type.metadata=#lib::Point (skip check)] a.{self::Point::newPoint1}(){() →* self::Point*});
-  self::getX([@vm.direct-call.metadata=#lib::Point.newPoint2] [@vm.inferred-type.metadata=#lib::Point (skip check)] a.{self::Point::newPoint2}(){() →* self::Point*});
+  self::Point a = new self::Point::•(new self::T1::•());
+  core::print([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] a.{self::Point::x}{self::I});
+  self::Point c = new self::Point::•(new self::T2::•());
+  [@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] c.{self::Point::x}{self::I}.{self::I::foo}(){() → void};
+  self::getX([@vm.direct-call.metadata=#lib::Point.newPoint1] [@vm.inferred-type.metadata=#lib::Point (skip check)] a.{self::Point::newPoint1}(){() → self::Point});
+  self::getX([@vm.direct-call.metadata=#lib::Point.newPoint2] [@vm.inferred-type.metadata=#lib::Point (skip check)] a.{self::Point::newPoint2}(){() → self::Point});
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart
new file mode 100644
index 0000000..723c228
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.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.
+
+// Tests elimination of 'is' tests.
+
+class A {}
+
+class B extends A {
+  void foo() {
+    print('foo');
+  }
+
+  bool get bar => int.parse('1') == 1;
+}
+
+class C implements A {}
+
+A obj = int.parse('2') == 2 ? C() : A();
+A getObj() => obj;
+
+void test1() {
+  var x = getObj();
+  if (x is B) {
+    x.foo();
+  }
+}
+
+void test2(x) {
+  if (x is B && x.bar) {
+    print('bye');
+  }
+}
+
+void test3(x) {
+  if (x is! B) {
+    return;
+  }
+  print('bye');
+}
+
+test4() => (getObj() is B) ? 3 : 4;
+
+void main() {
+  test1();
+  test2(obj);
+  test3(obj);
+  test4();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect
new file mode 100644
index 0000000..3af08e0
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect
@@ -0,0 +1,40 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object implements self::A {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+static field self::A obj = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("2") =={core::num::==}{(core::Object) → core::bool} 2 ?{self::A} new self::C::•() : new self::A::•();
+static method getObj() → self::A
+  return self::obj;
+static method test1() → void {
+  self::A x = self::getObj();
+  ;
+}
+static method test2() → void {
+  ;
+}
+static method test3() → void {
+  {
+    return;
+  }
+  core::print("bye");
+}
+[@vm.unboxing-info.metadata=()->i]static method test4() → dynamic
+  return block {
+    self::getObj();
+  } =>4;
+static method main() → void {
+  self::test1();
+  let final self::A #t1 = self::obj in self::test2();
+  let final self::A #t2 = self::obj in self::test3();
+  self::test4();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart b/pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart
similarity index 96%
rename from pkg/vm/testcases/transformations/type_flow/transformer/lists.dart
rename to pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart
index 62e1f09..dcd8253 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.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.
 
+// This test needs pre-null-safety semantics.
+// @dart=2.9
+
 nonConstant() => int.parse('1') == 1;
 
 class A {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart.expect
similarity index 100%
rename from pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
rename to pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart.expect
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart
index 76fafab..82f93e6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.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.
 
-// This test requires non-nullable experiment.
-// @dart = 2.10
-
 nonConstant() => int.parse('1') == 1;
 
 class A {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
index b941651..d2bc22a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
@@ -15,7 +15,7 @@
 // When converting named parameters to positional parameters, we
 // follow alphabetical order. Ensure that argument evaluation order
 // is unchanged.
-void testNamedOrder(int w, {int z, int y, int x}) {
+void testNamedOrder(int w, {int? z, int? y, int? x}) {
   Expect.equals(w, 1);
   Expect.equals(z, 2);
   Expect.equals(y, 3);
@@ -23,7 +23,7 @@
 }
 
 class TestNamedOrderBase {
-  TestNamedOrderBase(w, {int z, int y, int x}) {
+  TestNamedOrderBase(w, {int? z, int? y, int? x}) {
     testNamedOrder(w, z: z, y: y, x: x);
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
index fda4bf2..76840f2 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
@@ -9,31 +9,31 @@
 import "package:expect/expect.dart";
 
 abstract class TestNamedOrderBase extends core::Object {
-[@vm.unboxing-info.metadata=(i,i,i,i)->b]  constructor •([@vm.inferred-type.metadata=int] dynamic w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → self::TestNamedOrderBase*
+[@vm.unboxing-info.metadata=(i,i,i,i)->b]  constructor •([@vm.inferred-type.metadata=int] dynamic w, [@vm.inferred-type.metadata=int] core::int? x, [@vm.inferred-type.metadata=int] core::int? y, [@vm.inferred-type.metadata=int] core::int? z) → self::TestNamedOrderBase
     : super core::Object::•() {
-    self::testNamedOrder(_in::unsafeCast<core::int*>(w), x, y, z);
+    self::testNamedOrder(_in::unsafeCast<core::int>(w), x, y, z);
   }
 }
 class TestNamedOrderSub extends self::TestNamedOrderBase {
-[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i]  field core::int* x;
-  constructor •() → self::TestNamedOrderSub*
-    : self::TestNamedOrderSub::x = [@vm.inferred-type.metadata=int] self::dec(), final core::int* #t1 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t2 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t3 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t4 = [@vm.inferred-type.metadata=int] self::dec(), super self::TestNamedOrderBase::•(#t1, #t4, #t3, #t2) {
-    exp::Expect::equals([@vm.direct-call.metadata=#lib::TestNamedOrderSub.x] [@vm.inferred-type.metadata=int] this.{self::TestNamedOrderSub::x}{core::int*}, 0);
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i]  field core::int x;
+  constructor •() → self::TestNamedOrderSub
+    : self::TestNamedOrderSub::x = [@vm.inferred-type.metadata=int] self::dec(), final core::int #t1 = [@vm.inferred-type.metadata=int] self::inc(), final core::int #t2 = [@vm.inferred-type.metadata=int] self::inc(), final core::int #t3 = [@vm.inferred-type.metadata=int] self::inc(), final core::int #t4 = [@vm.inferred-type.metadata=int] self::dec(), super self::TestNamedOrderBase::•(#t1, #t4, #t3, #t2) {
+    exp::Expect::equals([@vm.direct-call.metadata=#lib::TestNamedOrderSub.x] [@vm.inferred-type.metadata=int] this.{self::TestNamedOrderSub::x}{core::int}, 0);
   }
 }
-[@vm.inferred-type.metadata=int?]static field core::int* global = 0;
-[@vm.unboxing-info.metadata=()->i]static method inc() → core::int*
-  return self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::+}(1){(core::num*) →* core::int*};
-[@vm.unboxing-info.metadata=()->i]static method dec() → core::int*
-  return self::global = [@vm.inferred-type.metadata=int] math::max<core::int*>(0, self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.-??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::-}(1){(core::num*) →* core::int*});
-[@vm.unboxing-info.metadata=(i,i,i,i)->b]static method testNamedOrder([@vm.inferred-type.metadata=int] core::int* w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → void {
+[@vm.inferred-type.metadata=int?]static field core::int global = 0;
+[@vm.unboxing-info.metadata=()->i]static method inc() → core::int
+  return self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::+}(1){(core::num) → core::int};
+[@vm.unboxing-info.metadata=()->i]static method dec() → core::int
+  return self::global = [@vm.inferred-type.metadata=int] math::max<core::int>(0, self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.-??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::-}(1){(core::num) → core::int});
+[@vm.unboxing-info.metadata=(i,i,i,i)->b]static method testNamedOrder([@vm.inferred-type.metadata=int] core::int w, [@vm.inferred-type.metadata=int] core::int? x, [@vm.inferred-type.metadata=int] core::int? y, [@vm.inferred-type.metadata=int] core::int? z) → void {
   exp::Expect::equals(w, 1);
   exp::Expect::equals(z, 2);
   exp::Expect::equals(y, 3);
   exp::Expect::equals(x, 2);
 }
 static method main() → dynamic {
-  let final core::int* #t5 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t6 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t7 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t8 = [@vm.inferred-type.metadata=int] self::dec() in self::testNamedOrder(#t5, #t8, #t7, #t6);
+  let final core::int #t5 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int #t6 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int #t7 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int #t8 = [@vm.inferred-type.metadata=int] self::dec() in self::testNamedOrder(#t5, #t8, #t7, #t6);
   self::global = 1;
   new self::TestNamedOrderSub::•();
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart
index a85118e..a3c4741 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart
@@ -69,7 +69,7 @@
 A bb = new B();
 A dd = new D();
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
index 719f96e..657e7ba 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
@@ -1,40 +1,40 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 class T4 extends core::Object {
-  synthetic constructor •() → self::T4*
+  synthetic constructor •() → self::T4
     : super core::Object::•()
     ;
 }
 class T5 extends core::Object {
-  synthetic constructor •() → self::T5*
+  synthetic constructor •() → self::T5
     : super core::Object::•()
     ;
 }
 class T6 extends core::Object {
-  synthetic constructor •() → self::T6*
+  synthetic constructor •() → self::T6
     : super core::Object::•()
     ;
 }
 class T7 extends core::Object {
-  synthetic constructor •() → self::T7*
+  synthetic constructor •() → self::T7
     : super core::Object::•()
     ;
 }
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → dynamic;
@@ -42,88 +42,88 @@
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b]  abstract method bazz(dynamic a1, dynamic a2, dynamic a3, dynamic a4) → dynamic;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T1::•();
   }
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  no-such-method-forwarder get bar() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  no-such-method-forwarder method foo() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b]  no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4) → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 }
 abstract class C extends core::Object {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T2::•();
   }
 }
 class D extends self::C implements self::A {
-  synthetic constructor •() → self::D*
+  synthetic constructor •() → self::D
     : super self::C::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  no-such-method-forwarder get bar() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  no-such-method-forwarder method foo() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b]  no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4) → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 }
 class E extends core::Object implements self::A {
-  synthetic constructor •() → self::E*
+  synthetic constructor •() → self::E
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T4::•();
   }
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  no-such-method-forwarder get bar() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E.noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E.noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 }
 class F extends core::Object {
-  synthetic constructor •() → self::F*
+  synthetic constructor •() → self::F
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T2::•();
   }
 }
 class G extends core::Object {
-  synthetic constructor •() → self::G*
+  synthetic constructor •() → self::G
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T5::•();
   }
 }
 class H extends core::Object {
-  synthetic constructor •() → self::H*
+  synthetic constructor •() → self::H
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9]  method foo({[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic left = #C7, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic right = #C7}) → dynamic
     return new self::T6::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T7::•();
   }
 }
-[@vm.inferred-type.metadata=#lib::B?]static field self::A* bb = new self::B::•();
-[@vm.inferred-type.metadata=#lib::D?]static field self::A* dd = new self::D::•();
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
+[@vm.inferred-type.metadata=#lib::B?]static field self::A bb = new self::B::•();
+[@vm.inferred-type.metadata=#lib::D?]static field self::A dd = new self::D::•();
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
 static method getDynamic() → dynamic
   return self::unknown();
-static method main(core::List<core::String*>* args) → dynamic {
-  core::print([@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::foo}(){() →* dynamic});
+static method main(core::List<core::String> args) → dynamic {
+  core::print([@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::foo}(){() → dynamic});
   core::print([@vm.direct-call.metadata=#lib::B.bar??] [@vm.inferred-type.metadata=#lib::T1] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bar}{dynamic});
-  core::print([@vm.direct-call.metadata=#lib::B.bazz??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) →* dynamic});
-  core::print([@vm.direct-call.metadata=#lib::D.foo??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::foo}(){() →* dynamic});
+  core::print([@vm.direct-call.metadata=#lib::B.bazz??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) → dynamic});
+  core::print([@vm.direct-call.metadata=#lib::D.foo??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::foo}(){() → dynamic});
   core::print([@vm.direct-call.metadata=#lib::D.bar??] [@vm.inferred-type.metadata=#lib::T2] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::bar}{dynamic});
-  core::print([@vm.direct-call.metadata=#lib::D.bazz??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) →* dynamic});
+  core::print([@vm.direct-call.metadata=#lib::D.bazz??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) → dynamic});
   new self::E::•();
-  self::A* xx = self::getDynamic() as{TypeError,ForDynamic} self::A*;
+  self::A xx = self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A;
   core::print([@vm.inferred-type.metadata=!] xx.{self::A::bar}{dynamic});
   dynamic yy = self::getDynamic();
   core::print([@vm.inferred-type.metadata=!] yy{dynamic}.twoArg(1, 2, 3));
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart
index b529e22..016fff5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Tests elimination of null checks.
-// This test requires non-nullable experiment.
-
-// @dart = 2.10
 
 class A {
   String? nonNullable;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart
index 98488d3..e3f12b7 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart
@@ -5,9 +5,9 @@
 // Tests elimination of null tests.
 
 class A {
-  String nonNullable;
-  String nullable;
-  String alwaysNull;
+  String? nonNullable;
+  String? nullable;
+  String? alwaysNull;
   A({this.nonNullable, this.nullable, this.alwaysNull});
 }
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
index 7e7de62..461ce24 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
@@ -1,61 +1,70 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
 class A extends core::Object {
-[@vm.inferred-type.metadata=dart.core::_OneByteString] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  field core::String* nonNullable;
-[@vm.inferred-type.metadata=dart.core::_OneByteString?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field core::String* nullable;
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  field core::String* alwaysNull;
-  constructor •([@vm.inferred-type.metadata=dart.core::_OneByteString] core::String* nonNullable, [@vm.inferred-type.metadata=dart.core::_OneByteString?] core::String* nullable) → self::A*
+[@vm.inferred-type.metadata=dart.core::_OneByteString] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  field core::String? nonNullable;
+[@vm.inferred-type.metadata=dart.core::_OneByteString?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field core::String? nullable;
+[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  field core::String? alwaysNull;
+  constructor •([@vm.inferred-type.metadata=dart.core::_OneByteString] core::String? nonNullable, [@vm.inferred-type.metadata=dart.core::_OneByteString?] core::String? nullable) → self::A
     : self::A::nonNullable = nonNullable, self::A::nullable = nullable, self::A::alwaysNull = #C1, super core::Object::•()
     ;
 }
-[@vm.inferred-type.metadata=#lib::A?]static field self::A* staticField = new self::A::•("hi", "bye");
-static method testNonNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if(let dynamic #t1 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*} in false) {
-    core::print("null");
-  }
-}
-static method testNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) {
-    core::print("null");
-  }
-}
-static method testAlwaysNullIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if(let dynamic #t2 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*} in true) {
-    core::print("null");
-  }
-}
-static method testNonNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if(!(let dynamic #t3 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*} in false) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
-    core::print("not null");
-  }
-}
-static method testNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if(!([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
-    core::print("not null");
-  }
-}
-static method testAlwaysNullIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if(!(let dynamic #t4 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*} in true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
-    core::print("not null");
-  }
-}
-static method testNonNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
-  return !(let dynamic #t5 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*} in false) ?{core::String*} "not null" : "null";
-static method testNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
-  return !([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) ?{core::String*} "not null" : "null";
-static method testAlwaysNullCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
-  return !(let dynamic #t6 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*} in true) ?{core::String*} "not null" : "null";
-static method someCondition() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1;
-static method main() → void {
-  final core::List<self::A*>* list = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A*>] core::_GrowableList::_literal2<self::A*>(new self::A::•("foo", null), [@vm.inferred-type.metadata=#lib::A?] self::staticField);
+[@vm.inferred-type.metadata=#lib::A?]static field self::A staticField = new self::A::•("hi", "bye");
+static method testNonNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
   {
-    core::Iterator<self::A*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A*>] list.{core::Iterable::iterator}{core::Iterator<self::A*>*};
+    [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String?};
+  }
+}
+static method testNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+  if([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String?} == null) {
+    core::print("null");
+  }
+}
+static method testAlwaysNullIf1([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+  {
+    [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String?};
+    {
+      core::print("null");
+    }
+  }
+}
+static method testNonNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+  if(( block {
+    [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String?};
+  } =>true) && _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+    core::print("not null");
+  }
+}
+static method testNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+  if(!([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String?} == null) && _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+    core::print("not null");
+  }
+}
+static method testAlwaysNullIf2([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+  {
+    [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String?};
+  }
+}
+static method testNonNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
+  return block {
+    [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String?};
+  } =>"not null";
+static method testNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
+  return !([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String?} == null) ?{core::String} "not null" : "null";
+static method testAlwaysNullCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
+  return block {
+    [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String?};
+  } =>"null";
+static method someCondition() → dynamic
+  return [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1;
+static method main() → void {
+  final core::List<self::A> list = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A>] core::_GrowableList::_literal2<self::A>(new self::A::•("foo", null), [@vm.inferred-type.metadata=#lib::A?] self::staticField);
+  {
+    core::Iterator<self::A> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A>] list.{core::Iterable::iterator}{core::Iterator<self::A>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::A* a = [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=#lib::A?] :sync-for-iterator.{core::Iterator::current}{self::A*};
+      self::A a = [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=#lib::A?] :sync-for-iterator.{core::Iterator::current}{self::A};
       {
         self::testNonNullableIf1(a);
         self::testNullableIf1(a);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart
index b60d23b..1d07acd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart
@@ -54,7 +54,7 @@
   }
 }
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 use(x) => unknown.call(x);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
index 90996865..57eda05 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
@@ -1,63 +1,63 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class T0 extends core::Object {
-  synthetic constructor •() → self::T0*
+  synthetic constructor •() → self::T0
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → void;
 }
 class T2 extends self::T0 {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super self::T0::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → void {}
 }
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method method1(self::T0* t0) → void {
-    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method method1(self::T0 t0) → void {
+    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
   }
 }
 abstract class B extends core::Object {
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  abstract method method2(covariant dynamic arg) → void;
 }
 class C extends core::Object implements self::B {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method method2(covariant self::T0* t0) → void {
-    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method method2(covariant self::T0 t0) → void {
+    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
   }
 }
 class D extends core::Object {
-  synthetic constructor •() → self::D*
+  synthetic constructor •() → self::D
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method method3(self::T0* t0) → void {
-    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method method3(self::T0 t0) → void {
+    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
   }
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method func1([@vm.inferred-type.metadata=#lib::T2?] self::T0* t0) → void {
-  [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method func1([@vm.inferred-type.metadata=#lib::T2?] self::T0 t0) → void {
+  [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
 }
-static method func2(self::T0* t0) → void {
-  [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+static method func2(self::T0 t0) → void {
+  [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
 }
 static method getDynamic() → dynamic
   return self::unknown();
 static method use(dynamic x) → dynamic
   return self::unknown(x);
-static method main(core::List<core::String*>* args) → dynamic {
-  self::func1(self::getDynamic() as{TypeError,ForDynamic} self::T0*);
+static method main(core::List<core::String> args) → dynamic {
+  self::func1(self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::T0);
   self::use(#C1);
-  self::use(new self::A::•().{self::A::method1}{(self::T0*) →* void});
-  self::B* bb = self::getDynamic() as{TypeError,ForDynamic} self::B*;
-  [@vm.direct-call.metadata=#lib::C.method2??] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B::method2}(self::getDynamic()){(dynamic) →* void};
+  self::use(new self::A::•().{self::A::method1}{(self::T0) → void});
+  self::B bb = self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::B;
+  [@vm.direct-call.metadata=#lib::C.method2??] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B::method2}(self::getDynamic()){(dynamic) → void};
   self::getDynamic(){dynamic}.method3(self::getDynamic());
   new self::T2::•();
   new self::A::•();
@@ -65,5 +65,5 @@
   new self::D::•();
 }
 constants  {
-  #C1 = tearoff self::func2
+  #C1 = static-tearoff self::func2
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect
index b832065..9578649 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect
@@ -1,30 +1,30 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object /*hasConstConstructor*/  {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i]  final field core::int* x;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i]  final field core::int x;
 }
 class B extends core::Object /*hasConstConstructor*/  {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 11)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  final field core::int* y;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 11)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  final field core::int y;
 }
 class C extends core::Object /*hasConstConstructor*/  {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 12)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i]  final field core::int* z;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 12)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i]  final field core::int z;
 }
 @#C4
 class Foo extends core::Object {
-  synthetic constructor •() → self::Foo*
+  synthetic constructor •() → self::Foo
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  @#C13
   method bar() → void {
     @#C17
     function bazz() → void {}
-    bazz(){() →* void};
+    bazz(){() → void};
   }
 }
 static method main() → dynamic {
-  [@vm.direct-call.metadata=#lib::Foo.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::Foo::•().{self::Foo::bar}(){() →* void};
+  [@vm.direct-call.metadata=#lib::Foo.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::Foo::•().{self::Foo::bar}(){() → void};
 }
 constants  {
   #C1 = "test1"
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart
index 1912459..929945f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart
@@ -13,7 +13,7 @@
     ..aKeep = 43;
   test('retrieving values', () {
     expect(foo.barKeep.aKeep, 5);
-    expect(foo.mapKeep['foo'].aKeep, 2);
+    expect(foo.mapKeep['foo']!.aKeep, 2);
     expect(foo.hasHasKeep(), false);
     expect(foo.aKeep, 43);
     foo.clearClearKeep();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
index 9dae16a..55a1b78 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "generated/foo.pb.dart" as pb;
 import "dart:core" as core;
@@ -9,21 +9,21 @@
 import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
 
 static method main() → dynamic {
-  pb::FooKeep* foo = let final pb::FooKeep* #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
-    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep* #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+  pb::FooKeep foo = let final pb::FooKeep #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
       [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::aKeep} = 5;
     } =>#t2;
-    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]=}("foo", let final pb::BarKeep* #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep>] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]=}("foo", let final pb::BarKeep #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
       [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pb::BarKeep::aKeep} = 2;
-    } =>#t3){(core::String*, pb::BarKeep*) →* void};
+    } =>#t3){(core::String, pb::BarKeep) → void};
     [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::aKeep} = 43;
   } =>#t1;
   sca::test(() → Null {
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 5);
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]}("foo"){(core::Object*) →* pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 2);
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() →* core::bool*}, false);
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int*}, 43);
-    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() →* void};
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep}.{pb::BarKeep::aKeep}{core::int}, 5);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]}("foo"){(core::Object?) → pb::BarKeep?}!.{pb::BarKeep::aKeep}{core::int}, 2);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() → core::bool}, false);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int}, 43);
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() → void};
   });
 }
 library foo.pb.dart /*isNonNullableByDefault*/;
@@ -38,7 +38,7 @@
 [@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t1 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "FooKeep") in block {
     [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep>(1, (#C1) ?{core::String} "" : "barKeep", "barKeep", #C2){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::BarKeep}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C2){(core::int, core::String, {entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C2){(core::int, core::String, {defaultEnumValue: pro::ProtobufEnum?, entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep"){(core::int, core::String, core::int, {defaultOrMaker: dynamic, enumValues: core::List<pro::ProtobufEnum>?, protoName: core::String?, subBuilder: () →? pro::GeneratedMessage, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep>(6, (#C1) ?{core::String} "" : "hasKeep", "hasKeep", #C3){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::HasKeep}) → void};
@@ -133,9 +133,9 @@
 }
 constants  {
   #C1 = false
-  #C2 = tearoff self::BarKeep::create
-  #C3 = tearoff self::HasKeep::create
-  #C4 = tearoff self::ClearKeep::create
+  #C2 = static-tearoff self::BarKeep::create
+  #C3 = static-tearoff self::HasKeep::create
+  #C4 = static-tearoff self::ClearKeep::create
   #C5 = "dart2js:noInline"
   #C6 = null
   #C7 = core::pragma {name:#C5, options:#C6}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart
index d33289f..7e96839 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart
@@ -19,7 +19,7 @@
 main() {
   FooKeep foo = FooKeep.fromBuffer(buffer);
   test('Kept values are restored correctly', () {
-    expect(foo.mapKeep['foo'].aKeep, 42);
+    expect(foo.mapKeep['foo']!.aKeep, 42);
     expect(foo.barKeep.aKeep, 5);
     expect(foo.aKeep, 43);
     expect(foo.hasHasKeep(), true);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
index 133c846..9dd85ff 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "generated/foo.pb.dart" as pb;
 import "package:test_core/scaffolding.dart" as sca;
@@ -8,15 +8,15 @@
 import "package:test/test.dart";
 import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
 
-[@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>]static field core::List<core::int*>* buffer = <core::int*>[10, 4, 8, 5, 16, 4, 26, 9, 10, 3, 102, 111, 111, 18, 2, 8, 42, 34, 9, 10, 3, 122, 111, 112, 18, 2, 8, 3, 40, 43, 50, 0, 58, 0];
+[@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int>]static field core::List<core::int> buffer = <core::int>[10, 4, 8, 5, 16, 4, 26, 9, 10, 3, 102, 111, 111, 18, 2, 8, 42, 34, 9, 10, 3, 122, 111, 112, 18, 2, 8, 3, 40, 43, 50, 0, 58, 0];
 static method main() → dynamic {
-  pb::FooKeep* foo = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>] self::buffer);
+  pb::FooKeep foo = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int>] self::buffer);
   sca::test(() → Null {
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]}("foo"){(core::Object*) →* pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 42);
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 5);
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int*}, 43);
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() →* core::bool*}, true);
-    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() →* void};
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]}("foo"){(core::Object?) → pb::BarKeep?}!.{pb::BarKeep::aKeep}{core::int}, 42);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep}.{pb::BarKeep::aKeep}{core::int}, 5);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int}, 43);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() → core::bool}, true);
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() → void};
   });
 }
 library foo.pb.dart /*isNonNullableByDefault*/;
@@ -31,7 +31,7 @@
 [@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t1 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "FooKeep", createEmptyInstance: #C2) in block {
     [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep>(1, (#C1) ?{core::String} "" : "barKeep", "barKeep", #C3){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::BarKeep}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C3){(core::int, core::String, {entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C3){(core::int, core::String, {defaultEnumValue: pro::ProtobufEnum?, entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep"){(core::int, core::String, core::int, {defaultOrMaker: dynamic, enumValues: core::List<pro::ProtobufEnum>?, protoName: core::String?, subBuilder: () →? pro::GeneratedMessage, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep>(6, (#C1) ?{core::String} "" : "hasKeep", "hasKeep", #C4){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::HasKeep}) → void};
@@ -41,7 +41,7 @@
   constructor _() → self::FooKeep
     : super pro::GeneratedMessage::•()
     ;
-  static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>] core::List<core::int> i) → self::FooKeep
+  static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int>] core::List<core::int> i) → self::FooKeep
     return let final self::FooKeep #t2 = [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create() in block {
       [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromBuffer] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::GeneratedMessage::mergeFromBuffer}(i){(core::List<core::int>, [pro::ExtensionRegistry]) → void};
     } =>#t2;
@@ -114,10 +114,10 @@
 }
 constants  {
   #C1 = false
-  #C2 = tearoff self::FooKeep::create
-  #C3 = tearoff self::BarKeep::create
-  #C4 = tearoff self::HasKeep::create
-  #C5 = tearoff self::ClearKeep::create
+  #C2 = static-tearoff self::FooKeep::create
+  #C3 = static-tearoff self::BarKeep::create
+  #C4 = static-tearoff self::HasKeep::create
+  #C5 = static-tearoff self::ClearKeep::create
   #C6 = "dart2js:noInline"
   #C7 = null
   #C8 = core::pragma {name:#C6, options:#C7}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
index f223e18..f925ae6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "generated/foo.pb.dart" as pb;
 import "dart:core" as core;
@@ -10,26 +10,26 @@
 import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
 
 static method main() → dynamic {
-  pb::FooKeep* foo = let final pb::FooKeep* #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
-    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep* #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+  pb::FooKeep foo = let final pb::FooKeep #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
       [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::aKeep} = 5;
       [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.bDrop] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::bDrop} = 4;
     } =>#t2;
-    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]=}("foo", let final pb::BarKeep* #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep>] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]=}("foo", let final pb::BarKeep #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
       [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pb::BarKeep::aKeep} = 42;
-    } =>#t3){(core::String*, pb::BarKeep*) →* void};
-    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapDrop] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapDrop}{core::Map<core::String*, pb::ZopDrop*>*}.{core::Map::[]=}("zop", let final pb::ZopDrop* #t4 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop] pb::ZopDrop::•() in block {
+    } =>#t3){(core::String, pb::BarKeep) → void};
+    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop>] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapDrop] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapDrop}{core::Map<core::String, pb::ZopDrop>}.{core::Map::[]=}("zop", let final pb::ZopDrop #t4 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop] pb::ZopDrop::•() in block {
       [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop.aDrop] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pb::ZopDrop::aDrop} = 3;
-    } =>#t4){(core::String*, pb::ZopDrop*) →* void};
+    } =>#t4){(core::String, pb::ZopDrop) → void};
     [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::aKeep} = 43;
     [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::hasKeep} = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::HasKeep] pb::HasKeep::•();
     [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::clearKeep} = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ClearKeep] pb::ClearKeep::•();
   } =>#t1;
-  final typ::Uint8List* buffer = [@vm.direct-call.metadata=protobuf::GeneratedMessage.writeToBuffer] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] foo.{pro::GeneratedMessage::writeToBuffer}(){() →* typ::Uint8List*};
+  final typ::Uint8List buffer = [@vm.direct-call.metadata=protobuf::GeneratedMessage.writeToBuffer] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] foo.{pro::GeneratedMessage::writeToBuffer}(){() → typ::Uint8List};
   core::print("List<int> buffer = <int>[");
-  for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=dart.typed_data::_TypedListBase.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int*}){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num*) →* core::int*}) {
-    final core::String* numbers = [@vm.direct-call.metadata=dart.typed_data::_TypedListBase.join] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=dart.typed_data::__Uint8List&_TypedList&_IntListMixin&_TypedIntListMixin.sublist] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] buffer.{typ::Uint8List::sublist}(i, [@vm.inferred-type.metadata=int] math::min<core::int*>([@vm.direct-call.metadata=dart.typed_data::_TypedListBase.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int*}, [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num*) →* core::int*})){(core::int*, [core::int*]) →* typ::Uint8List*}.{core::Iterable::join}(", "){([core::String*]) →* core::String*};
-    core::print("  ${numbers},${[@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i =={core::num::==}{(core::Object*) →* core::bool*} 0 ?{core::String*} " //" : ""}");
+  for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=dart.typed_data::_TypedListBase.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int}){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num) → core::int}) {
+    final core::String numbers = [@vm.direct-call.metadata=dart.typed_data::_TypedListBase.join] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=dart.typed_data::__Uint8List&_TypedList&_IntListMixin&_TypedIntListMixin.sublist] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] buffer.{typ::Uint8List::sublist}(i, [@vm.inferred-type.metadata=int] math::min<core::int>([@vm.direct-call.metadata=dart.typed_data::_TypedListBase.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int}, [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num) → core::int})){(core::int, [core::int?]) → typ::Uint8List}.{core::Iterable::join}(", "){([core::String]) → core::String};
+    core::print("  ${numbers},${[@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i =={core::num::==}{(core::Object) → core::bool} 0 ?{core::String} " //" : ""}");
   }
   core::print("];");
 }
@@ -45,8 +45,8 @@
 [@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t1 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "FooKeep") in block {
     [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep>(1, (#C1) ?{core::String} "" : "barKeep", "barKeep", #C2){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::BarKeep}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>(3, (#C1) ?{core::String} "" : "mapKeep", "FooKeep.MapKeepEntry", "mapKeep", #C2){(core::int, core::String, {entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::ZopDrop>(4, (#C1) ?{core::String} "" : "mapDrop", "FooKeep.MapDropEntry", "mapDrop", #C3){(core::int, core::String, {entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>(3, (#C1) ?{core::String} "" : "mapKeep", "FooKeep.MapKeepEntry", "mapKeep", #C2){(core::int, core::String, {defaultEnumValue: pro::ProtobufEnum?, entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::ZopDrop>(4, (#C1) ?{core::String} "" : "mapDrop", "FooKeep.MapDropEntry", "mapDrop", #C3){(core::int, core::String, {defaultEnumValue: pro::ProtobufEnum?, entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep", "aKeep"){(core::int, core::String, core::int, {defaultOrMaker: dynamic, enumValues: core::List<pro::ProtobufEnum>?, protoName: core::String?, subBuilder: () →? pro::GeneratedMessage, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep>(6, (#C1) ?{core::String} "" : "hasKeep", "hasKeep", #C4){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::HasKeep}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep>(7, (#C1) ?{core::String} "" : "clearKeep", "clearKeep", #C5){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::ClearKeep}) → void};
@@ -164,10 +164,10 @@
 }
 constants  {
   #C1 = false
-  #C2 = tearoff self::BarKeep::create
-  #C3 = tearoff self::ZopDrop::create
-  #C4 = tearoff self::HasKeep::create
-  #C5 = tearoff self::ClearKeep::create
+  #C2 = static-tearoff self::BarKeep::create
+  #C3 = static-tearoff self::ZopDrop::create
+  #C4 = static-tearoff self::HasKeep::create
+  #C5 = static-tearoff self::ClearKeep::create
   #C6 = "dart2js:noInline"
   #C7 = null
   #C8 = core::pragma {name:#C6, options:#C7}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart
index 0529e4a..8d7567e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart
@@ -14,7 +14,7 @@
   test('Freezing a message works', () {
     foo.freeze();
     expect(foo.barKeep.aKeep, 5);
-    expect(foo.mapKeep['foo'].aKeep, 2);
+    expect(foo.mapKeep['foo']!.aKeep, 2);
     expect(foo.hasHasKeep(), false);
     expect(foo.aKeep, 43);
     expect(() => foo.clearClearKeep(),
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
index ee0cdfc..0071356 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "generated/foo.pb.dart" as pb;
 import "dart:core" as core;
@@ -11,22 +11,22 @@
 import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
 
 static method main() → dynamic {
-  pb::FooKeep* foo = let final pb::FooKeep* #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
-    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep* #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+  pb::FooKeep foo = let final pb::FooKeep #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
       [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::aKeep} = 5;
     } =>#t2;
-    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]=}("foo", let final pb::BarKeep* #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep>] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]=}("foo", let final pb::BarKeep #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
       [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pb::BarKeep::aKeep} = 2;
-    } =>#t3){(core::String*, pb::BarKeep*) →* void};
+    } =>#t3){(core::String, pb::BarKeep) → void};
     [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::aKeep} = 43;
   } =>#t1;
   sca::test(() → Null {
-    [@vm.direct-call.metadata=protobuf::GeneratedMessage.freeze] [@vm.inferred-type.metadata=!? (skip check)] foo.{pro::GeneratedMessage::freeze}(){() →* pro::GeneratedMessage*};
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 5);
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]}("foo"){(core::Object*) →* pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 2);
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() →* core::bool*}, false);
-    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int*}, 43);
-    exp::expect(() → void => [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() →* void}, [@vm.inferred-type.metadata=library package:test_api/src/expect/throws_matcher.dart::Throws] thr::throwsA());
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.freeze] [@vm.inferred-type.metadata=!? (skip check)] foo.{pro::GeneratedMessage::freeze}(){() → pro::GeneratedMessage};
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep}.{pb::BarKeep::aKeep}{core::int}, 5);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]}("foo"){(core::Object?) → pb::BarKeep?}!.{pb::BarKeep::aKeep}{core::int}, 2);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() → core::bool}, false);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int}, 43);
+    exp::expect(() → void => [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() → void}, [@vm.inferred-type.metadata=library package:test_api/src/expect/throws_matcher.dart::Throws] thr::throwsA());
   });
 }
 library foo.pb.dart /*isNonNullableByDefault*/;
@@ -41,7 +41,7 @@
 [@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t1 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "FooKeep") in block {
     [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep>(1, (#C1) ?{core::String} "" : "barKeep", "barKeep", #C2){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::BarKeep}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C2){(core::int, core::String, {entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C2){(core::int, core::String, {defaultEnumValue: pro::ProtobufEnum?, entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep"){(core::int, core::String, core::int, {defaultOrMaker: dynamic, enumValues: core::List<pro::ProtobufEnum>?, protoName: core::String?, subBuilder: () →? pro::GeneratedMessage, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
     [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep>(6, (#C1) ?{core::String} "" : "hasKeep", "hasKeep", #C3){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::HasKeep}) → void};
@@ -136,9 +136,9 @@
 }
 constants  {
   #C1 = false
-  #C2 = tearoff self::BarKeep::create
-  #C3 = tearoff self::HasKeep::create
-  #C4 = tearoff self::ClearKeep::create
+  #C2 = static-tearoff self::BarKeep::create
+  #C3 = static-tearoff self::HasKeep::create
+  #C4 = static-tearoff self::ClearKeep::create
   #C5 = "dart2js:noInline"
   #C6 = null
   #C7 = core::pragma {name:#C5, options:#C6}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
index b52c5dc..c5b7bf4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:test/test.dart';
-
 import 'generated/name_mangling.pb.dart';
 
 main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
index 7489bcb..63e55db 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
@@ -1,14 +1,13 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "generated/name_mangling.pb.dart" as pb;
 import "dart:core" as core;
 
-import "package:test/test.dart";
 import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart";
 
 static method main() → dynamic {
-  pb::NameManglingKeep* n = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart::NameManglingKeep] pb::NameManglingKeep::fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::•<core::int*>(0));
-  if([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart::NameManglingKeep.hasClone_10] [@vm.inferred-type.metadata=dart.core::bool (skip check)] n.{pb::NameManglingKeep::hasClone_10}(){() →* core::bool*}) {
+  pb::NameManglingKeep n = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart::NameManglingKeep] pb::NameManglingKeep::fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::•<core::int>(0));
+  if([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart::NameManglingKeep.hasClone_10] [@vm.inferred-type.metadata=dart.core::bool (skip check)] n.{pb::NameManglingKeep::hasClone_10}(){() → core::bool}) {
     core::print("Has clone field");
   }
 }
@@ -41,7 +40,7 @@
   constructor _() → self::NameManglingKeep
     : super pro::GeneratedMessage::•()
     ;
-  static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::List<core::int> i) → self::NameManglingKeep
+  static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::List<core::int> i) → self::NameManglingKeep
     return let final self::NameManglingKeep #t3 = [@vm.inferred-type.metadata=name_mangling.pb.dart::NameManglingKeep] self::NameManglingKeep::create() in block {
       [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromBuffer] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::GeneratedMessage::mergeFromBuffer}(i){(core::List<core::int>, [pro::ExtensionRegistry]) → void};
     } =>#t3;
@@ -56,11 +55,11 @@
 }
 constants  {
   #C1 = false
-  #C2 = tearoff self::AKeep::create
+  #C2 = static-tearoff self::AKeep::create
   #C3 = "dart2js:noInline"
   #C4 = null
   #C5 = core::pragma {name:#C3, options:#C4}
-  #C6 = tearoff self::NameManglingKeep::create
+  #C6 = static-tearoff self::NameManglingKeep::create
   #C7 = 10
   #C8 = pro::TagNumber {tagNumber:#C7}
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect
index 7512991..0762979 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_37455.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_37455.dart.expect
index 2d0f29f..7de8f83 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_37455.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_37455.dart.expect
@@ -1,31 +1,31 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::List<dynamic>* afield;
-  constructor •(core::List<dynamic>* afield) → self::A*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::List<dynamic> afield;
+  constructor •(core::List<dynamic> afield) → self::A
     : self::A::afield = afield, super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method toString() → core::String*
-    return [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A.afield] this.{self::A::afield}{core::List<dynamic>*}.{core::Object::toString}(){() →* core::String*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method toString() → core::String
+    return [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A.afield] this.{self::A::afield}{core::List<dynamic>}.{core::Object::toString}(){() → core::String};
 }
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  method _foo([@vm.inferred-type.metadata=dart._internal::ListIterator<dart.core::int*>] core::Iterator<core::int*>* iter) → core::List<dynamic>* {
-    core::List<dynamic>* result = [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::•<dynamic>(0);
-    while ([@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] iter.{core::Iterator::moveNext}(){() →* core::bool*}) {
-      if([@vm.direct-call.metadata=dart.core::_IntegerImplementation.<??] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=int?] iter.{core::Iterator::current}{core::int*}.{core::num::<}(0){(core::num*) →* core::bool*}) {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  method _foo([@vm.inferred-type.metadata=dart._internal::ListIterator<dart.core::int>] core::Iterator<core::int> iter) → core::List<dynamic> {
+    core::List<dynamic> result = [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::•<dynamic>(0);
+    while ([@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] iter.{core::Iterator::moveNext}(){() → core::bool}) {
+      if([@vm.direct-call.metadata=dart.core::_IntegerImplementation.<??] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=int?] iter.{core::Iterator::current}{core::int}.{core::num::<}(0){(core::num) → core::bool}) {
         return result;
       }
-      [@vm.call-site-attributes.metadata=receiverType:dart.core::List<dynamic>*] [@vm.direct-call.metadata=dart.core::_GrowableList.add] [@vm.inferred-type.metadata=!? (skip check)] result.{core::List::add}(new self::A::•([@vm.direct-call.metadata=#lib::B._foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::B::_foo}(iter){(core::Iterator<core::int*>*) →* core::List<dynamic>*})){(dynamic) →* void};
+      [@vm.call-site-attributes.metadata=receiverType:dart.core::List<dynamic>] [@vm.direct-call.metadata=dart.core::_GrowableList.add] [@vm.inferred-type.metadata=!? (skip check)] result.{core::List::add}(new self::A::•([@vm.direct-call.metadata=#lib::B._foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::B::_foo}(iter){(core::Iterator<core::int>) → core::List<dynamic>})){(dynamic) → void};
     }
     return result;
   }
 }
 static method main() → void {
-  core::List<dynamic>* list = [@vm.direct-call.metadata=#lib::B._foo] [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic> (skip check)] new self::B::•().{self::B::_foo}([@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<dart.core::int*>] [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator}{core::Iterator<core::int*>*}){(core::Iterator<core::int*>*) →* core::List<dynamic>*};
+  core::List<dynamic> list = [@vm.direct-call.metadata=#lib::B._foo] [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic> (skip check)] new self::B::•().{self::B::_foo}([@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<dart.core::int>] [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::_literal3<core::int>(1, 2, 3).{core::Iterable::iterator}{core::Iterator<core::int>}){(core::Iterator<core::int>) → core::List<dynamic>};
   core::print(list);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_37719.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_37719.dart.expect
index 577315f..35c9ce8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_37719.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_37719.dart.expect
@@ -1,8 +1,8 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
-[@vm.unboxing-info.metadata=(b)->i]static method foo([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::List<core::int*>* x) → dynamic
-  return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=int? (skip check)] x.{core::List::[]}(0){(core::int*) →* core::int*}){(core::num*) →* core::int*};
+[@vm.unboxing-info.metadata=(b)->i]static method foo([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::List<core::int> x) → dynamic
+  return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=int? (skip check)] x.{core::List::[]}(0){(core::int) → core::int}){(core::num) → core::int};
 static method main() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::print([@vm.inferred-type.metadata=int] self::foo([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::_literal1<core::int*>(1)));
+  return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::print([@vm.inferred-type.metadata=int] self::foo([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::_literal1<core::int>(1)));
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart
index bc79497..03ba604 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart
@@ -4,9 +4,7 @@
 
 // Regression test for https://github.com/dart-lang/sdk/issues/41452.
 // Tests handling of null initializer of covariant field.
-// This test requires non-nullable experiment and NNBD strong mode.
-
-// @dart = 2.10
+// This test requires sound null safety.
 
 class _SplayTreeNode<Node extends _SplayTreeNode<Node>> {
   Node? left;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
index 89b2f4f..162174d 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
@@ -19,8 +19,7 @@
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method add(generic-covariant-impl self::_SplayTree::Node n) → dynamic {
     self::_SplayTree::Node? root = [@vm.direct-call.metadata=#lib::SplayTreeMap._root] [@vm.inferred-type.metadata=#lib::_SplayTreeMapNode<dynamic>] this.{self::_SplayTree::_root}{self::_SplayTree::Node?};
-    if(false)
-      return;
+    ;
     core::print([@vm.direct-call.metadata=#lib::_SplayTreeNode.left] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] root{self::_SplayTree::Node}.{self::_SplayTreeNode::left}{self::_SplayTree::Node?});
   }
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  abstract get /*isLegacy*/ _root() → self::_SplayTree::Node?;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42413.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42413.dart.expect
index b0bcba0..e29a055 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42413.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42413.dart.expect
@@ -1,25 +1,25 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i]  get x() → dynamic
     return 0;
 }
 class A extends core::Object {
-[@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  field dynamic list = null;
-  constructor •() → self::A*
+[@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  field dynamic list = null;
+  constructor •() → self::A
     : super core::Object::•() {
-    [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A::list} = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B*>] core::_GrowableList::_literal1<self::B*>(new self::B::•());
+    [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A::list} = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B>] core::_GrowableList::_literal1<self::B>(new self::B::•());
   }
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  @#C3
   method forIn() → void {
     {
-      core::Iterator<dynamic>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator??] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B*>] _in::unsafeCast<core::Iterable<dynamic>*>([@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B*>] this.{self::A::list}{dynamic}).{core::Iterable::iterator}{core::Iterator<dynamic>*};
+      core::Iterator<dynamic> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator??] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B>] _in::unsafeCast<core::Iterable<dynamic>>([@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B>] this.{self::A::list}{dynamic}).{core::Iterable::iterator}{core::Iterator<dynamic>};
       for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
         dynamic e = [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=#lib::B?] :sync-for-iterator.{core::Iterator::current}{dynamic};
         core::print([@vm.direct-call.metadata=#lib::B.x??] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0) (receiver not int)] e{dynamic}.x);
@@ -28,15 +28,15 @@
   }
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  @#C3
   method cLoop() → void {
-    for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=dart.core::_GrowableList.length??] [@vm.inferred-type.metadata=dart.core::_Smi (receiver not int)] [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B*>] this.{self::A::list}{dynamic}{dynamic}.length)){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
-      final dynamic e = [@vm.direct-call.metadata=dart.core::_GrowableList.[]??] [@vm.inferred-type.metadata=#lib::B? (receiver not int)] [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B*>] this.{self::A::list}{dynamic}{dynamic}.[](i);
+    for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=dart.core::_GrowableList.length??] [@vm.inferred-type.metadata=dart.core::_Smi (receiver not int)] [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B>] this.{self::A::list}{dynamic}{dynamic}.length)){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
+      final dynamic e = [@vm.direct-call.metadata=dart.core::_GrowableList.[]??] [@vm.inferred-type.metadata=#lib::B? (receiver not int)] [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B>] this.{self::A::list}{dynamic}{dynamic}.[](i);
       core::print([@vm.direct-call.metadata=#lib::B.x??] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0) (receiver not int)] e{dynamic}.x);
     }
   }
 }
 static method main() → void {
-  [@vm.direct-call.metadata=#lib::A.forIn] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::forIn}(){() →* void};
-  [@vm.direct-call.metadata=#lib::A.cLoop] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::cLoop}(){() →* void};
+  [@vm.direct-call.metadata=#lib::A.forIn] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::forIn}(){() → void};
+  [@vm.direct-call.metadata=#lib::A.cLoop] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::cLoop}(){() → void};
 }
 constants  {
   #C1 = "vm:never-inline"
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
index 65d7485..add07b4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
@@ -10,12 +10,12 @@
 
 class A {
   @pragma("vm:never-inline")
-  void foo(/* boxed */ int x) => Expect.isTrue(x.isOdd);
+  void foo(/* boxed */ int? x) => Expect.isTrue(x!.isOdd);
 }
 
 class B {
   @pragma("vm:never-inline")
-  void foo(/* unboxed */ int x) => Expect.isTrue(x.isOdd);
+  void foo(/* unboxed */ int? x) => Expect.isTrue(x!.isOdd);
 }
 
 class C extends A implements B {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
index 16d4a2a..9d24274 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
@@ -1,48 +1,49 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "package:expect/expect.dart" as exp;
+import "dart:_internal" as _in;
 import "dart:math" as math;
 
 import "dart:math";
 import "package:expect/expect.dart";
 
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
-  method foo([@vm.inferred-type.metadata=int?] core::int* x) → void
-    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd??] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+  method foo([@vm.inferred-type.metadata=int?] core::int? x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x!.{core::int::isOdd}{core::bool});
 }
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
-  method foo([@vm.inferred-type.metadata=int] core::int* x) → void
-    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+  method foo([@vm.inferred-type.metadata=int] core::int? x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] _in::unsafeCast<core::int>(x).{core::int::isOdd}{core::bool});
 }
 class C extends self::A implements self::B {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super self::A::•()
     ;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2;
 static method main() → dynamic {
-  final math::Random* r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
+  final math::Random r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
   if([@vm.inferred-type.metadata=dart.core::bool?] self::alwaysFalse) {
-    [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
-    [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
-    [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}(null){(core::int*) →* void};
+    [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+    [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+    [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}(null){(core::int?) → void};
   }
-  final core::List<self::B*>* l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B*>] core::_GrowableList::_literal2<self::B*>(new self::B::•(), new self::C::•());
+  final core::List<self::B> l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B>] core::_GrowableList::_literal2<self::B>(new self::B::•(), new self::C::•());
   {
-    core::Iterator<self::B*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B*>] l.{core::Iterable::iterator}{core::Iterator<self::B*>*};
+    core::Iterator<self::B> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B>] l.{core::Iterable::iterator}{core::Iterator<self::B>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::B* b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B*};
+      self::B b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B};
       {
-        b.{self::B::foo}(13){(core::int*) →* void};
+        b.{self::B::foo}(13){(core::int?) → void};
       }
     }
   }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
index 824ac78..01bede8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
@@ -10,12 +10,12 @@
 
 class A {
   @pragma("vm:never-inline")
-  void bar(/* unboxed */ int x) => Expect.isTrue(x.isOdd);
+  void bar(/* unboxed */ int? x) => Expect.isTrue(x!.isOdd);
 }
 
 class B {
   @pragma("vm:never-inline")
-  void bar(/* boxed */ int x) => Expect.isTrue(x.isOdd);
+  void bar(/* boxed */ int? x) => Expect.isTrue(x!.isOdd);
 }
 
 class C extends A implements B {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
index dff8e38..ae6258b 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
@@ -1,48 +1,49 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "package:expect/expect.dart" as exp;
+import "dart:_internal" as _in;
 import "dart:math" as math;
 
 import "dart:math";
 import "package:expect/expect.dart";
 
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
-  method bar([@vm.inferred-type.metadata=int] core::int* x) → void
-    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+  method bar([@vm.inferred-type.metadata=int] core::int? x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] _in::unsafeCast<core::int>(x).{core::int::isOdd}{core::bool});
 }
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
-  method bar([@vm.inferred-type.metadata=int?] core::int* x) → void
-    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd??] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+  method bar([@vm.inferred-type.metadata=int?] core::int? x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x!.{core::int::isOdd}{core::bool});
 }
 class C extends self::A implements self::B {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super self::A::•()
     ;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2;
 static method main() → dynamic {
-  final math::Random* r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
+  final math::Random r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
   if([@vm.inferred-type.metadata=dart.core::bool?] self::alwaysFalse) {
-    [@vm.direct-call.metadata=#lib::A.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
-    [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
-    [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}(null){(core::int*) →* void};
+    [@vm.direct-call.metadata=#lib::A.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+    [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+    [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}(null){(core::int?) → void};
   }
-  final core::List<self::B*>* l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B*>] core::_GrowableList::_literal2<self::B*>(new self::B::•(), new self::C::•());
+  final core::List<self::B> l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B>] core::_GrowableList::_literal2<self::B>(new self::B::•(), new self::C::•());
   {
-    core::Iterator<self::B*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B*>] l.{core::Iterable::iterator}{core::Iterator<self::B*>*};
+    core::Iterator<self::B> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B>] l.{core::Iterable::iterator}{core::Iterator<self::B>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::B* b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B*};
+      self::B b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B};
       {
-        b.{self::B::bar}(13){(core::int*) →* void};
+        b.{self::B::bar}(13){(core::int?) → void};
       }
     }
   }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324.dart.expect
index f097822..a7e00ed 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324.dart.expect
@@ -1,20 +1,20 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object /*hasConstConstructor*/  {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i]  final field core::int* targetPlatform;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i]  final field core::int targetPlatform;
 }
 class X extends core::Object implements self::A {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i]  get targetPlatform() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i]  get targetPlatform() → core::int
     return 2;
 }
-[@vm.inferred-type.metadata=#lib::X?]static field self::A* a = new self::X::•();
+[@vm.inferred-type.metadata=#lib::X?]static field self::A a = new self::X::•();
 static method main() → void {
-  core::print([@vm.direct-call.metadata=#lib::X.targetPlatform??] [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] [@vm.inferred-type.metadata=#lib::X?] self::a.{self::A::targetPlatform}{core::int*});
+  core::print([@vm.direct-call.metadata=#lib::X.targetPlatform??] [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] [@vm.inferred-type.metadata=#lib::X?] self::a.{self::A::targetPlatform}{core::int});
   core::print(#C2);
 }
 constants  {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
index 6c4d972..a655aa5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.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.12
-
 class A {
   void doTest(Z a) {
     print(a.appName);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart
index d50e669..4b25bd4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.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.12
-
 enum A { a1, a2 }
 
 class B {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart
index 81c386e..f565760 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart
@@ -7,7 +7,7 @@
 
 import "package:expect/expect.dart";
 
-bool ok;
+bool? ok;
 
 class T1 {
   // Should be reachable.
@@ -17,7 +17,7 @@
 }
 
 class A1 {
-  T1 foo;
+  T1? foo;
 
   void call([a1, a2, a3, a4, a5]) {
     foo = a5;
@@ -33,7 +33,7 @@
   bb.aa1(1, 2, 3, 4, new T1());
 
   ok = false;
-  bb.aa1.foo.doTest1();
+  bb.aa1.foo!.doTest1();
   Expect.isTrue(ok);
 }
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
index 15a6a84..fa24c7a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
@@ -7,7 +7,7 @@
 import "package:expect/expect.dart";
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method doTest1() → void {
@@ -15,22 +15,22 @@
   }
 }
 class A1 extends core::Object {
-[@vm.inferred-type.metadata=#lib::T1?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field self::T1* foo = null;
-  synthetic constructor •() → self::A1*
+[@vm.inferred-type.metadata=#lib::T1?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field self::T1? foo = null;
+  synthetic constructor •() → self::A1
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=#lib::T1?] dynamic a5 = #C1]) → void {
-    [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A1::foo} = _in::unsafeCast<self::T1*>(a5);
+    [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A1::foo} = _in::unsafeCast<self::T1?>(a5);
   }
 }
 class B1 extends core::Object {
-[@vm.inferred-type.metadata=#lib::A1] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  field self::A1* aa1;
-  synthetic constructor •() → self::B1*
+[@vm.inferred-type.metadata=#lib::A1] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  field self::A1 aa1;
+  synthetic constructor •() → self::B1
     : self::B1::aa1 = new self::A1::•(), super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method doTest2() → void {
@@ -39,7 +39,7 @@
 }
 class A2 extends core::Object {
 [@vm.inferred-type.metadata=#lib::T2?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  field dynamic foo = null;
-  synthetic constructor •() → self::A2*
+  synthetic constructor •() → self::A2
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=#lib::T2?] dynamic a6 = #C1]) → void {
@@ -48,14 +48,14 @@
 }
 abstract class B2Base extends core::Object {
 [@vm.inferred-type.metadata=#lib::A2] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  field dynamic _aa;
-  synthetic constructor •() → self::B2Base*
+  synthetic constructor •() → self::B2Base
     : self::B2Base::_aa = new self::A2::•(), super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:17]  get aa2() → dynamic
     return [@vm.direct-call.metadata=#lib::B2Base._aa] [@vm.inferred-type.metadata=#lib::A2] this.{self::B2Base::_aa}{dynamic};
 }
 class B2 extends self::B2Base {
-  synthetic constructor •() → self::B2*
+  synthetic constructor •() → self::B2
     : super self::B2Base::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:18,getterSelectorId:19]  method doSuperCall() → void {
@@ -63,7 +63,7 @@
   }
 }
 class T3 extends core::Object {
-  synthetic constructor •() → self::T3*
+  synthetic constructor •() → self::T3
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:20,getterSelectorId:21]  method doTest3() → void {
@@ -72,7 +72,7 @@
 }
 class A3 extends core::Object {
 [@vm.inferred-type.metadata=#lib::T3?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:22,getterSelectorId:23]  field dynamic foo = null;
-  synthetic constructor •() → self::A3*
+  synthetic constructor •() → self::A3
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:24,getterSelectorId:25]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=#lib::T3?] dynamic a7 = #C1]) → void {
@@ -80,13 +80,13 @@
   }
 }
 class B3 extends core::Object {
-[@vm.inferred-type.metadata=#lib::A3] [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:26,getterSelectorId:27]  field self::A3* aa3;
-  synthetic constructor •() → self::B3*
+[@vm.inferred-type.metadata=#lib::A3] [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:26,getterSelectorId:27]  field self::A3 aa3;
+  synthetic constructor •() → self::B3
     : self::B3::aa3 = new self::A3::•(), super core::Object::•()
     ;
 }
 class T4 extends core::Object {
-  synthetic constructor •() → self::T4*
+  synthetic constructor •() → self::T4
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:28,getterSelectorId:29]  method doTest4() → void {
@@ -95,7 +95,7 @@
 }
 class A4 extends core::Object {
 [@vm.inferred-type.metadata=#lib::T4?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:30,getterSelectorId:31]  field dynamic foo = null;
-  synthetic constructor •() → self::A4*
+  synthetic constructor •() → self::A4
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:32,getterSelectorId:33]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a7 = #C1, [@vm.inferred-type.metadata=#lib::T4?] dynamic a8 = #C1]) → void {
@@ -104,27 +104,27 @@
 }
 class B4 extends core::Object {
 [@vm.inferred-type.metadata=#lib::A4] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:34,getterSelectorId:35]  field dynamic _aa;
-  synthetic constructor •() → self::B4*
+  synthetic constructor •() → self::B4
     : self::B4::_aa = new self::A4::•(), super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,getterSelectorId:36]  get aa4() → dynamic
     return [@vm.direct-call.metadata=#lib::B4._aa] [@vm.inferred-type.metadata=#lib::A4] this.{self::B4::_aa}{dynamic};
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static field core::bool* ok;
+[@vm.inferred-type.metadata=dart.core::bool?]static field core::bool? ok;
 [@vm.inferred-type.metadata=#lib::B3?]static field dynamic bb3 = new self::B3::•();
-[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function* unknown3 = () → dynamic => self::bb3;
+[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function unknown3 = () → dynamic => self::bb3;
 [@vm.inferred-type.metadata=#lib::B4?]static field dynamic bb4 = new self::B4::•();
-[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function* unknown4 = () → dynamic => self::bb4;
+[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function unknown4 = () → dynamic => self::bb4;
 static method test1() → void {
-  self::B1* bb = new self::B1::•();
-  let final self::B1* #t1 = bb in let final core::int* #t2 = 1 in let final core::int* #t3 = 2 in let final core::int* #t4 = 3 in let final core::int* #t5 = 4 in let final self::T1* #t6 = new self::T1::•() in [@vm.direct-call.metadata=#lib::A1.call] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] #t1.{self::B1::aa1}{self::A1*}.{self::A1::call}(#t2, #t3, #t4, #t5, #t6){([dynamic, dynamic, dynamic, dynamic, dynamic]) →* void};
+  self::B1 bb = new self::B1::•();
+  let final self::B1 #t1 = bb in let final core::int #t2 = 1 in let final core::int #t3 = 2 in let final core::int #t4 = 3 in let final core::int #t5 = 4 in let final self::T1 #t6 = new self::T1::•() in [@vm.direct-call.metadata=#lib::A1.call] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] #t1.{self::B1::aa1}{self::A1}.{self::A1::call}(#t2, #t3, #t4, #t5, #t6){([dynamic, dynamic, dynamic, dynamic, dynamic]) → void};
   self::ok = false;
-  [@vm.direct-call.metadata=#lib::T1.doTest1??] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=#lib::T1?] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] bb.{self::B1::aa1}{self::A1*}.{self::A1::foo}{self::T1*}.{self::T1::doTest1}(){() →* void};
+  [@vm.direct-call.metadata=#lib::T1.doTest1] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=#lib::T1?] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] bb.{self::B1::aa1}{self::A1}.{self::A1::foo}{self::T1?}!.{self::T1::doTest1}(){() → void};
   exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
 }
 static method test2() → void {
-  self::B2* bb = new self::B2::•();
-  [@vm.direct-call.metadata=#lib::B2.doSuperCall] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B2::doSuperCall}(){() →* void};
+  self::B2 bb = new self::B2::•();
+  [@vm.direct-call.metadata=#lib::B2.doSuperCall] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B2::doSuperCall}(){() → void};
   self::ok = false;
   [@vm.direct-call.metadata=#lib::T2.doTest2??] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A2.foo] [@vm.inferred-type.metadata=#lib::T2? (receiver not int)] [@vm.direct-call.metadata=#lib::B2Base.aa2] [@vm.inferred-type.metadata=#lib::A2] bb.{self::B2Base::aa2}{dynamic}{dynamic}.foo{dynamic}.doTest2();
   exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter57213.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter57213.dart.expect
index 4e27a60..a079cbe 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter57213.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter57213.dart.expect
@@ -1,30 +1,30 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 @#C3
 class A extends core::Object {
-  constructor •() → self::A*
+  constructor •() → self::A
     : super core::Object::•()
     ;
 }
 class B extends self::A {
-  constructor •() → self::B*
+  constructor •() → self::B
     : super self::A::•()
     ;
 }
 abstract class C extends core::Object {
-  constructor •() → self::C*
+  constructor •() → self::C
     : super core::Object::•()
     ;
 }
 abstract class D extends self::C {
-  constructor •() → self::D*
+  constructor •() → self::D
     : super self::C::•()
     ;
 }
 class E extends self::D {
-  constructor •() → self::E*
+  constructor •() → self::E
     : super self::D::•()
     ;
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
index a63904b..37b6a68 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
@@ -1,41 +1,41 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
 
 import "dart:async";
 
-abstract class A<T extends core::Object* = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T*>*
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
     : super core::Object::•()
     ;
 }
-class B<T extends core::Object* = dynamic> extends self::A<core::String*> implements asy::Future<self::B::T*> {
-  synthetic constructor •() → self::B<self::B::T*>*
+class B<T extends core::Object? = dynamic> extends self::A<core::String> implements asy::Future<self::B::T%> {
+  synthetic constructor •() → self::B<self::B::T%>
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method noSuchMethod(core::Invocation* i) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method noSuchMethod(core::Invocation i) → dynamic
     return throw "Not implemented";
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  no-such-method-forwarder method then<R extends core::Object* = dynamic>((self::B::T*) →* FutureOr<self::B::then::R*>* onValue, {core::Function* onError = #C1}) → asy::Future<self::B::then::R*>*
-    return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, core::List::unmodifiable<core::Type*>([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Type*>] core::_GrowableList::_literal1<core::Type*>(self::B::then::R*)), core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onValue)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C3: onError}))){(core::Invocation*) →* dynamic} as{TypeError,ForDynamic} asy::Future<self::B::then::R*>*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  no-such-method-forwarder method catchError(core::Function* onError, {[@vm.inferred-type.metadata=dart.core::Null? (value: null)] (core::Object*) →* core::bool* test = #C1}) → asy::Future<self::B::T*>*
-    return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C4, 0, #C5, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onError)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C6: test}))){(core::Invocation*) →* dynamic} as{TypeError,ForDynamic} asy::Future<self::B::T*>*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::B::T*>*
-    return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C5, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(action)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C9))){(core::Invocation*) →* dynamic} as{TypeError,ForDynamic} asy::Future<self::B::T*>*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError) → asy::Future<self::B::T%>
+    return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onError)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C3: #C4}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ whenComplete(() → FutureOr<void>action) → asy::Future<self::B::T%>
+    return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(action)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ then<R extends core::Object? = dynamic>((self::B::T%) → FutureOr<self::B::then::R%>onValue, {core::Function? onError = #C4}) → asy::Future<self::B::then::R%>
+    return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, core::List::unmodifiable<core::Type*>([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Type*>] core::_GrowableList::_literal1<core::Type*>(self::B::then::R%)), core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onValue)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C9: onError}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::then::R%>;
 }
-static method createB<T extends core::Object* = dynamic>() → self::B<dynamic>*
-  return new self::B::•<self::createB::T*>();
+static method createB<T extends core::Object? = dynamic>() → self::B<dynamic>
+  return new self::B::•<self::createB::T%>();
 static method main() → void {
-  core::print([@vm.inferred-type.metadata=#lib::B<?>] self::createB<core::int*>() as FutureOr<core::double*>*);
+  core::print([@vm.inferred-type.metadata=#lib::B<?>] self::createB<core::int>() as{ForNonNullableByDefault} FutureOr<core::double>);
 }
 constants  {
-  #C1 = null
-  #C2 = #then
-  #C3 = #onError
-  #C4 = #catchError
-  #C5 = <core::Type*>[]
-  #C6 = #test
-  #C7 = #whenComplete
-  #C8 = <dynamic>[]
-  #C9 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C8}
+  #C1 = #catchError
+  #C2 = <core::Type*>[]
+  #C3 = #test
+  #C4 = null
+  #C5 = #whenComplete
+  #C6 = <dynamic>[]
+  #C7 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C6}
+  #C8 = #then
+  #C9 = #onError
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/selector_id_assignments.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/selector_id_assignments.dart.expect
index 39043c5..bba93d0 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/selector_id_assignments.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/selector_id_assignments.dart.expect
@@ -1,11 +1,11 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class X extends core::Object {
 }
 class A1 extends core::Object {
-  synthetic constructor •() → self::A1*
+  synthetic constructor •() → self::A1
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → void {
@@ -13,12 +13,12 @@
   }
 }
 class B1 extends self::A1 {
-  synthetic constructor •() → self::B1*
+  synthetic constructor •() → self::B1
     : super self::A1::•()
     ;
 }
 class C1 extends self::B1 {
-  synthetic constructor •() → self::C1*
+  synthetic constructor •() → self::C1
     : super self::B1::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → void {
@@ -26,7 +26,7 @@
   }
 }
 class A2 extends core::Object {
-  synthetic constructor •() → self::A2*
+  synthetic constructor •() → self::A2
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method foo() → void {
@@ -34,7 +34,7 @@
   }
 }
 class B2 extends self::A2 implements self::X {
-  synthetic constructor •() → self::B2*
+  synthetic constructor •() → self::B2
     : super self::A2::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method foo() → void {
@@ -42,13 +42,13 @@
   }
 }
 abstract class A3 extends core::Object {
-  synthetic constructor •() → self::A3*
+  synthetic constructor •() → self::A3
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  abstract method foo() → void;
 }
 class B3 extends self::A3 implements self::X {
-  synthetic constructor •() → self::B3*
+  synthetic constructor •() → self::B3
     : super self::A3::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method foo() → void {
@@ -56,7 +56,7 @@
   }
 }
 class C3 extends core::Object implements self::A3 {
-  synthetic constructor •() → self::C3*
+  synthetic constructor •() → self::C3
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method foo() → void {
@@ -64,7 +64,7 @@
   }
 }
 class A4 extends core::Object {
-  synthetic constructor •() → self::A4*
+  synthetic constructor •() → self::A4
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method foo() → void {
@@ -72,7 +72,7 @@
   }
 }
 class B4 extends core::Object {
-  synthetic constructor •() → self::B4*
+  synthetic constructor •() → self::B4
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method foo() → void {
@@ -80,7 +80,7 @@
   }
 }
 class C4 extends core::Object {
-  synthetic constructor •() → self::C4*
+  synthetic constructor •() → self::C4
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method foo() → void {
@@ -88,7 +88,7 @@
   }
 }
 class D4 extends self::A4 implements self::B4 {
-  synthetic constructor •() → self::D4*
+  synthetic constructor •() → self::D4
     : super self::A4::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method foo() → void {
@@ -96,57 +96,57 @@
   }
 }
 class E4 extends self::C4 implements self::B4 {
-  synthetic constructor •() → self::E4*
+  synthetic constructor •() → self::E4
     : super self::C4::•()
     ;
 }
 static method main() → dynamic {
-  core::List<self::A1*>* x1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A1*>] core::_GrowableList::_literal3<self::A1*>(new self::A1::•(), new self::B1::•(), new self::C1::•());
+  core::List<self::A1> x1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A1>] core::_GrowableList::_literal3<self::A1>(new self::A1::•(), new self::B1::•(), new self::C1::•());
   {
-    core::Iterator<self::A1*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A1*>] x1.{core::Iterable::iterator}{core::Iterator<self::A1*>*};
+    core::Iterator<self::A1> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A1>] x1.{core::Iterable::iterator}{core::Iterator<self::A1>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::A1* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A1*};
-      o.{self::A1::foo}(){() →* void};
+      self::A1 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A1};
+      o.{self::A1::foo}(){() → void};
     }
   }
-  core::List<self::A2*>* x2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A2*>] core::_GrowableList::_literal2<self::A2*>(new self::A2::•(), new self::B2::•());
+  core::List<self::A2> x2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A2>] core::_GrowableList::_literal2<self::A2>(new self::A2::•(), new self::B2::•());
   {
-    core::Iterator<self::A2*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A2*>] x2.{core::Iterable::iterator}{core::Iterator<self::A2*>*};
+    core::Iterator<self::A2> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A2>] x2.{core::Iterable::iterator}{core::Iterator<self::A2>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::A2* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A2*};
-      o.{self::A2::foo}(){() →* void};
+      self::A2 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A2};
+      o.{self::A2::foo}(){() → void};
     }
   }
-  core::List<self::A3*>* x3 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A3*>] core::_GrowableList::_literal2<self::A3*>(new self::B3::•(), new self::C3::•());
+  core::List<self::A3> x3 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A3>] core::_GrowableList::_literal2<self::A3>(new self::B3::•(), new self::C3::•());
   {
-    core::Iterator<self::A3*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A3*>] x3.{core::Iterable::iterator}{core::Iterator<self::A3*>*};
+    core::Iterator<self::A3> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A3>] x3.{core::Iterable::iterator}{core::Iterator<self::A3>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::A3* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A3*};
-      o.{self::A3::foo}(){() →* void};
+      self::A3 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A3};
+      o.{self::A3::foo}(){() → void};
     }
   }
-  core::List<self::A4*>* x4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A4*>] core::_GrowableList::_literal2<self::A4*>(new self::A4::•(), new self::D4::•());
+  core::List<self::A4> x4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A4>] core::_GrowableList::_literal2<self::A4>(new self::A4::•(), new self::D4::•());
   {
-    core::Iterator<self::A4*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A4*>] x4.{core::Iterable::iterator}{core::Iterator<self::A4*>*};
+    core::Iterator<self::A4> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A4>] x4.{core::Iterable::iterator}{core::Iterator<self::A4>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::A4* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A4*};
-      o.{self::A4::foo}(){() →* void};
+      self::A4 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A4};
+      o.{self::A4::foo}(){() → void};
     }
   }
-  core::List<self::B4*>* y4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B4*>] core::_GrowableList::_literal3<self::B4*>(new self::B4::•(), new self::D4::•(), new self::E4::•());
+  core::List<self::B4> y4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B4>] core::_GrowableList::_literal3<self::B4>(new self::B4::•(), new self::D4::•(), new self::E4::•());
   {
-    core::Iterator<self::B4*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B4*>] y4.{core::Iterable::iterator}{core::Iterator<self::B4*>*};
+    core::Iterator<self::B4> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B4>] y4.{core::Iterable::iterator}{core::Iterator<self::B4>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::B4* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B4*};
-      o.{self::B4::foo}(){() →* void};
+      self::B4 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B4};
+      o.{self::B4::foo}(){() → void};
     }
   }
-  core::List<self::C4*>* z4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::C4*>] core::_GrowableList::_literal2<self::C4*>(new self::C4::•(), new self::E4::•());
+  core::List<self::C4> z4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::C4>] core::_GrowableList::_literal2<self::C4>(new self::C4::•(), new self::E4::•());
   {
-    core::Iterator<self::C4*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::C4*>] z4.{core::Iterable::iterator}{core::Iterator<self::C4*>*};
+    core::Iterator<self::C4> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::C4>] z4.{core::Iterable::iterator}{core::Iterator<self::C4>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::C4* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::C4*};
-      [@vm.direct-call.metadata=#lib::C4.foo??] [@vm.inferred-type.metadata=!? (skip check)] o.{self::C4::foo}(){() →* void};
+      self::C4 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::C4};
+      [@vm.direct-call.metadata=#lib::C4.foo??] [@vm.inferred-type.metadata=!? (skip check)] o.{self::C4::foo}(){() → void};
     }
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
index 76714d7..cffe9fc 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:collection" as col;
@@ -6,33 +6,33 @@
 import "dart:collection";
 import "dart:core";
 
-[@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dynamic>]static field core::Set<dynamic>* globalSet = new col::_CompactLinkedHashSet::•<dynamic>();
-[@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet?<dynamic>]static field core::Set<dynamic>* identitySet = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet<dynamic>] col::LinkedHashSet::identity<dynamic>();
-[@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dart.core::String*>]static field core::Set<core::String*>* linkedSet = new col::_CompactLinkedHashSet::•<core::String*>();
-static field core::Set<core::String*>* linkedIdentitySet = [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String*>(#C1, #C2);
-static field core::Set<core::String*>* linkedCustomSet = let final (core::String*, core::String*) →* core::bool* #t1 = (core::String* a, core::String* b) → core::bool* => [@vm.inferred-type.metadata=!? (receiver not int)] a =={core::String::==}{(core::Object*) →* core::bool*} b in let final (core::String*) →* core::int* #t2 = (core::String* o) → core::int* => o.{core::String::hashCode}{core::int*} in let final (dynamic) →* core::bool* #t3 = (dynamic o) → core::bool* => true in [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String*>(#t1, #t2, isValidKey: #t3);
-[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* globalMap = [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<dynamic, dynamic>] core::Map::•<dynamic, dynamic>();
-[@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* identityMap = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap<dynamic, dynamic>] col::LinkedHashMap::identity<dynamic, dynamic>();
-[@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* unmodifiableMap = [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dynamic, dynamic>] core::Map::unmodifiable<dynamic, dynamic>([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>] self::identityMap);
-[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* globalMapLiteral = <dynamic, dynamic>{};
-[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dart.core::String*, dart.core::String*>]static field core::Map<core::String*, core::String*>* linkedMap = new col::_InternalLinkedHashMap::•<core::String*, core::String*>();
-static field core::Map<core::String*, core::String*>* linkedIdentityMap = [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String*, core::String*>(#C1, #C2);
-static field core::Map<core::String*, core::String*>* linkedCustomMap = let final (core::String*, core::String*) →* core::bool* #t4 = (core::String* a, core::String* b) → core::bool* => [@vm.inferred-type.metadata=!? (receiver not int)] a =={core::String::==}{(core::Object*) →* core::bool*} b in let final (core::String*) →* core::int* #t5 = (core::String* o) → core::int* => o.{core::String::hashCode}{core::int*} in let final (dynamic) →* core::bool* #t6 = (dynamic o) → core::bool* => true in [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String*, core::String*>(#t4, #t5, isValidKey: #t6);
+[@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dynamic>]static field core::Set<dynamic> globalSet = new col::_CompactLinkedHashSet::•<dynamic>();
+[@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet?<dynamic>]static field core::Set<dynamic> identitySet = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet<dynamic>] col::LinkedHashSet::identity<dynamic>();
+[@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dart.core::String>]static field core::Set<core::String> linkedSet = new col::_CompactLinkedHashSet::•<core::String>();
+static field core::Set<core::String> linkedIdentitySet = [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String>(#C1, #C2);
+static field core::Set<core::String> linkedCustomSet = let final (core::String, core::String) → core::bool #t1 = (core::String a, core::String b) → core::bool => [@vm.inferred-type.metadata=!? (receiver not int)] a =={core::String::==}{(core::Object) → core::bool} b in let final (core::String) → core::int #t2 = (core::String o) → core::int => o.{core::String::hashCode}{core::int} in let final (dynamic) → core::bool #t3 = (dynamic o) → core::bool => true in [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String>(#t1, #t2, isValidKey: #t3);
+[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic> globalMap = [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<dynamic, dynamic>] core::Map::•<dynamic, dynamic>();
+[@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic> identityMap = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap<dynamic, dynamic>] col::LinkedHashMap::identity<dynamic, dynamic>();
+[@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView?<dynamic, dynamic>]static field core::Map<dynamic, dynamic> unmodifiableMap = [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dynamic, dynamic>] core::Map::unmodifiable<dynamic, dynamic>([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>] self::identityMap);
+[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic> globalMapLiteral = <dynamic, dynamic>{};
+[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dart.core::String, dart.core::String>]static field core::Map<core::String, core::String> linkedMap = new col::_InternalLinkedHashMap::•<core::String, core::String>();
+static field core::Map<core::String, core::String> linkedIdentityMap = [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String, core::String>(#C1, #C2);
+static field core::Map<core::String, core::String> linkedCustomMap = let final (core::String, core::String) → core::bool #t4 = (core::String a, core::String b) → core::bool => [@vm.inferred-type.metadata=!? (receiver not int)] a =={core::String::==}{(core::Object) → core::bool} b in let final (core::String) → core::int #t5 = (core::String o) → core::int => o.{core::String::hashCode}{core::int} in let final (dynamic) → core::bool #t6 = (dynamic o) → core::bool => true in [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String, core::String>(#t4, #t5, isValidKey: #t6);
 static method main() → dynamic {
   core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dynamic>] self::globalSet);
   core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet?<dynamic>] self::identitySet);
-  core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dart.core::String*>] self::linkedSet);
+  core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dart.core::String>] self::linkedSet);
   core::print(self::linkedIdentitySet);
   core::print(self::linkedCustomSet);
   core::print([@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>] self::globalMap);
   core::print([@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>] self::globalMapLiteral);
   core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>] self::identityMap);
   core::print([@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView?<dynamic, dynamic>] self::unmodifiableMap);
-  core::print([@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dart.core::String*, dart.core::String*>] self::linkedMap);
+  core::print([@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dart.core::String, dart.core::String>] self::linkedMap);
   core::print(self::linkedIdentityMap);
   core::print(self::linkedCustomMap);
 }
 constants  {
-  #C1 = tearoff core::identical
-  #C2 = tearoff core::identityHashCode
+  #C1 = static-tearoff core::identical
+  #C2 = static-tearoff core::identityHashCode
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart
index 2d22fe6..e29f9dd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart
@@ -11,11 +11,11 @@
 }
 
 class B extends A {
-  int foo() => 1 + knownResult().foo(); // Should have metadata.
+  int foo() => 1 + knownResult().foo() as int; // Should have metadata.
 }
 
 class C implements A {
-  int foo() => 2 + knownResult().foo(); // Should be unreachable.
+  int foo() => 2 + knownResult().foo() as int; // Should be unreachable.
 }
 
 class TearOffDynamicMethod {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
index 3483f2c..582555f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
@@ -1,29 +1,29 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
-    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=! (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo() as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*} as{TypeError} core::int*;
+[@vm.procedure-attributes.metadata=hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=! (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo() as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num} as{ForNonNullableByDefault} core::int;
 }
 class TearOffDynamicMethod extends core::Object {
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field dynamic bazz;
-  constructor •(dynamic arg) → self::TearOffDynamicMethod*
+  constructor •(dynamic arg) → self::TearOffDynamicMethod
     : self::TearOffDynamicMethod::bazz = arg{dynamic}.foo, super core::Object::•() {
     [@vm.direct-call.metadata=#lib::TearOffDynamicMethod.bazz] this.{self::TearOffDynamicMethod::bazz}{dynamic}{dynamic}.call();
   }
 }
 static method knownResult() → dynamic
   return new self::B::•();
-static method main(core::List<core::String*>* args) → dynamic {
-  core::Function* closure = () → self::B* => new self::B::•();
+static method main(core::List<core::String> args) → dynamic {
+  core::Function closure = () → self::B => new self::B::•();
   new self::TearOffDynamicMethod::•(closure());
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
index 5ce46d8..603bbf6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
@@ -11,12 +11,12 @@
 }
 
 class B extends A {
-  int foo() => 1 + knownResult().bar(); // Should have metadata.
+  int foo() => 1 + knownResult().bar() as int; // Should have metadata.
   int bar() => 3;
 }
 
 class C implements A {
-  int foo() => 2 + knownResult().bar(); // Should be unreachable.
+  int foo() => 2 + knownResult().bar() as int; // Should be unreachable.
 }
 
 class TearOffInterfaceMethod {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
index 578e8fb..b34fce5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
@@ -1,31 +1,31 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
-    return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 3) (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.bar())){(core::num*) →* core::num*});
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  method bar() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
+    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 3) (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.bar())){(core::num) → core::num});
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  method bar() → core::int
     return 3;
 }
 class TearOffInterfaceMethod extends core::Object {
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  field dynamic bazz;
-  constructor •([@vm.inferred-type.metadata=#lib::B] self::A* arg) → self::TearOffInterfaceMethod*
-    : self::TearOffInterfaceMethod::bazz = arg.{self::A::foo}{() →* core::int*}, super core::Object::•()
+  constructor •([@vm.inferred-type.metadata=#lib::B] self::A arg) → self::TearOffInterfaceMethod
+    : self::TearOffInterfaceMethod::bazz = arg.{self::A::foo}{() → core::int}, super core::Object::•()
     ;
 }
 static method knownResult() → dynamic
   return new self::B::•();
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   [@vm.direct-call.metadata=#lib::TearOffInterfaceMethod.bazz] new self::TearOffInterfaceMethod::•(new self::B::•()).{self::TearOffInterfaceMethod::bazz}{dynamic}{dynamic}.call();
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
index ebe01db..2980835 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
@@ -11,26 +11,26 @@
 }
 
 class B extends A {
-  int foo() => 1 + knownResult().foo(); // Should have metadata.
+  int foo() => 1 + knownResult().foo() as int; // Should have metadata.
 }
 
 class C implements A {
-  int foo() => 2 + knownResult().foo(); // Should be unreachable.
+  int foo() => 2 + knownResult().foo() as int; // Should be unreachable.
 }
 
 class Base {
-  int foo() => 3 + knownResult().foo(); // Should have metadata.
-  int doCall(x) => x();
+  int foo() => 3 + knownResult().foo() as int; // Should have metadata.
+  int? doCall(x) => x();
 }
 
 class TearOffSuperMethod extends Base {
   int foo() {
     // Should be unreachable.
     aa = new C();
-    return 4 + knownResult().foo();
+    return 4 + knownResult().foo() as int;
   }
 
-  int bar() => doCall(super.foo);
+  int? bar() => doCall(super.foo);
 }
 
 main(List<String> args) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
index bc69294..0e44dd5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
@@ -1,41 +1,41 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
-    return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num*) →* core::num*});
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
+    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num) → core::num});
 }
 abstract class Base extends core::Object {
-  synthetic constructor •() → self::Base*
+  synthetic constructor •() → self::Base
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
-    return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 3.{core::num::+}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num*) →* core::num*});
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method doCall(dynamic x) → core::int*
-    return x{dynamic}.call() as{TypeError,ForDynamic} core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
+    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 3.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num) → core::num});
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method doCall(dynamic x) → core::int?
+    return x{dynamic}.call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::int?;
 }
 class TearOffSuperMethod extends self::Base {
-  synthetic constructor •() → self::TearOffSuperMethod*
+  synthetic constructor •() → self::TearOffSuperMethod
     : super self::Base::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method bar() → core::int*
-    return [@vm.direct-call.metadata=#lib::Base.doCall] [@vm.inferred-type.metadata=int? (skip check)] this.{self::Base::doCall}(super.{self::Base::foo}){(dynamic) →* core::int*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method bar() → core::int?
+    return [@vm.direct-call.metadata=#lib::Base.doCall] [@vm.inferred-type.metadata=int? (skip check)] this.{self::Base::doCall}(super.{self::Base::foo}){(dynamic) → core::int?};
 }
-[@vm.inferred-type.metadata=#lib::B?]static field self::A* aa = new self::B::•();
+[@vm.inferred-type.metadata=#lib::B?]static field self::A aa = new self::B::•();
 static method knownResult() → dynamic
   return new self::B::•();
-static method main(core::List<core::String*>* args) → dynamic {
-  [@vm.direct-call.metadata=#lib::TearOffSuperMethod.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::TearOffSuperMethod::•().{self::TearOffSuperMethod::bar}(){() →* core::int*};
-  [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=!? (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::aa.{self::A::foo}(){() →* core::int*};
+static method main(core::List<core::String> args) → dynamic {
+  [@vm.direct-call.metadata=#lib::TearOffSuperMethod.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::TearOffSuperMethod::•().{self::TearOffSuperMethod::bar}(){() → core::int?};
+  [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=!? (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::aa.{self::A::foo}(){() → core::int};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect
index 7f83b39..c5846d8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect
@@ -1,58 +1,58 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class A<T extends core::Object* = dynamic> extends core::Object {
-  synthetic constructor •() → self::A<self::A::T*>*
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
     : super core::Object::•()
     ;
 }
-class B<T extends core::Object* = dynamic> extends self::A<self::B::T*> {
-  synthetic constructor •() → self::B<self::B::T*>*
+class B<T extends core::Object? = dynamic> extends self::A<self::B::T%> {
+  synthetic constructor •() → self::B<self::B::T%>
     : super self::A::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method testT1() → dynamic
-    return _in::unsafeCast<self::B::T*>(#C1);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method testT2negative([@vm.inferred-type.metadata=#lib::A<dart.core::String*>] dynamic x) → dynamic
-    return x as self::B::T*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method testAOfT1([@vm.inferred-type.metadata=#lib::A<#lib::A<dart.core::int*>*>] dynamic x) → dynamic
-    return _in::unsafeCast<self::A<self::B::T*>*>(x);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method testAOfT2negative([@vm.inferred-type.metadata=#lib::A<#lib::A<dart.core::num*>*>] dynamic x) → dynamic
-    return x as self::A<self::B::T*>*;
+    return _in::unsafeCast<self::B::T%>(#C1);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method testT2negative([@vm.inferred-type.metadata=#lib::A<dart.core::String>] dynamic x) → dynamic
+    return x as{ForNonNullableByDefault} self::B::T%;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method testAOfT1([@vm.inferred-type.metadata=#lib::A<#lib::A<dart.core::int>>] dynamic x) → dynamic
+    return _in::unsafeCast<self::A<self::B::T%>>(x);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method testAOfT2negative([@vm.inferred-type.metadata=#lib::A<#lib::A<dart.core::num>>] dynamic x) → dynamic
+    return x as{ForNonNullableByDefault} self::A<self::B::T%>;
 }
 [@vm.unboxing-info.metadata=()->i]static method testInt1() → dynamic
-  return _in::unsafeCast<core::int*>(#C1);
+  return _in::unsafeCast<core::int>(#C1);
 static method testInt2() → dynamic
-  return _in::unsafeCast<core::int*>(#C2);
+  return _in::unsafeCast<core::int>(#C2);
 static method testDynamic() → dynamic
   return _in::unsafeCast<dynamic>(#C3);
 static method testObject() → dynamic
   return #C4;
-static method testBOfInt([@vm.inferred-type.metadata=#lib::B<dart.core::int*>] dynamic x) → dynamic
-  return _in::unsafeCast<self::B<core::int*>*>(x);
-static method testAOfInt([@vm.inferred-type.metadata=#lib::B<dart.core::int*>] dynamic x) → dynamic
-  return _in::unsafeCast<self::A<core::int*>*>(x);
-static method testAOfNum([@vm.inferred-type.metadata=#lib::B<dart.core::int*>] dynamic x) → dynamic
-  return _in::unsafeCast<self::A<core::num*>*>(x);
-static method testAOfAOfB1([@vm.inferred-type.metadata=#lib::A<#lib::A<#lib::B<dynamic>*>*>] dynamic x) → dynamic
-  return _in::unsafeCast<self::A<self::A<self::B<dynamic>*>*>*>(x);
-static method testAOfAOfB2negative([@vm.inferred-type.metadata=#lib::A<#lib::A<#lib::A<dynamic>*>*>] dynamic x) → dynamic
-  return x as self::A<self::A<self::B<dynamic>*>*>*;
+static method testBOfInt([@vm.inferred-type.metadata=#lib::B<dart.core::int>] dynamic x) → dynamic
+  return _in::unsafeCast<self::B<core::int>>(x);
+static method testAOfInt([@vm.inferred-type.metadata=#lib::B<dart.core::int>] dynamic x) → dynamic
+  return _in::unsafeCast<self::A<core::int>>(x);
+static method testAOfNum([@vm.inferred-type.metadata=#lib::B<dart.core::int>] dynamic x) → dynamic
+  return _in::unsafeCast<self::A<core::num>>(x);
+static method testAOfAOfB1([@vm.inferred-type.metadata=#lib::A<#lib::A<#lib::B<dynamic>>>] dynamic x) → dynamic
+  return _in::unsafeCast<self::A<self::A<self::B<dynamic>>>>(x);
+static method testAOfAOfB2negative([@vm.inferred-type.metadata=#lib::A<#lib::A<#lib::A<dynamic>>>] dynamic x) → dynamic
+  return x as{ForNonNullableByDefault} self::A<self::A<self::B<dynamic>>>;
 static method main() → void {
   self::testInt1();
   self::testInt2();
   self::testDynamic();
   self::testObject();
-  self::testBOfInt(new self::B::•<core::int*>());
-  self::testAOfInt(new self::B::•<core::int*>());
-  self::testAOfNum(new self::B::•<core::int*>());
-  self::testAOfAOfB1(new self::A::•<self::A<self::B<dynamic>*>*>());
-  self::testAOfAOfB2negative(new self::A::•<self::A<self::A<dynamic>*>*>());
-  [@vm.direct-call.metadata=#lib::B.testT1] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<core::int*>().{self::B::testT1}(){(dynamic) →* dynamic};
-  [@vm.direct-call.metadata=#lib::B.testT2negative] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int*>*>().{self::B::testT2negative}(new self::A::•<core::String*>()){(dynamic) →* dynamic};
-  [@vm.direct-call.metadata=#lib::B.testAOfT1] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int*>*>().{self::B::testAOfT1}(new self::A::•<self::A<core::int*>*>()){(dynamic) →* dynamic};
-  [@vm.direct-call.metadata=#lib::B.testAOfT2negative] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int*>*>().{self::B::testAOfT2negative}(new self::A::•<self::A<core::num*>*>()){(dynamic) →* dynamic};
+  self::testBOfInt(new self::B::•<core::int>());
+  self::testAOfInt(new self::B::•<core::int>());
+  self::testAOfNum(new self::B::•<core::int>());
+  self::testAOfAOfB1(new self::A::•<self::A<self::B<dynamic>>>());
+  self::testAOfAOfB2negative(new self::A::•<self::A<self::A<dynamic>>>());
+  [@vm.direct-call.metadata=#lib::B.testT1] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<core::int>().{self::B::testT1}(){(dynamic) → dynamic};
+  [@vm.direct-call.metadata=#lib::B.testT2negative] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int>>().{self::B::testT2negative}(new self::A::•<core::String>()){(dynamic) → dynamic};
+  [@vm.direct-call.metadata=#lib::B.testAOfT1] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int>>().{self::B::testAOfT1}(new self::A::•<self::A<core::int>>()){(dynamic) → dynamic};
+  [@vm.direct-call.metadata=#lib::B.testAOfT2negative] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int>>().{self::B::testAOfT2negative}(new self::A::•<self::A<core::num>>()){(dynamic) → dynamic};
 }
 constants  {
   #C1 = 42
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
index 5f0e8e8..e3a95bd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Tests elimination of type casts.
-// This test requires non-nullable experiment.
-
-// @dart = 2.10
 
 class A<T> {}
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
index c828095..337a57a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
@@ -3,9 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Tests elimination of type casts.
-// This test requires non-nullable experiment and NNBD strong mode.
-
-// @dart = 2.10
+// This test requires sound null safety.
 
 class A<T> {}
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
index 9f7ad71..7ac9fc8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
@@ -34,7 +34,7 @@
 static method testDynamic() → dynamic
   return _in::unsafeCast<dynamic>(#C3);
 static method testObjectNegative() → dynamic
-  return let dynamic #t1 = #C2 in true ?{core::Object} #t1 as{ForNonNullableByDefault} core::Object : #t1{core::Object};
+  return let dynamic #t1 = #C2 in #t1 as{ForNonNullableByDefault} core::Object;
 static method testNullableObject() → dynamic
   return #C2;
 static method testAOfNum1([@vm.inferred-type.metadata=#lib::B<dart.core::int>] dynamic x) → dynamic
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
index 726b6c9..81af9f4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
@@ -13,58 +13,58 @@
 }
 
 abstract class BI1 {
-  int get value;
+  int? get value;
 }
 
 class BI1A implements BI1 {
-  final int value;
+  final int? value;
   BI1A(this.value);
 }
 
 class BI1B implements BI1 {
-  int get value => null;
+  int? get value => null;
 }
 
 abstract class BI2 {
-  int get value;
+  int? get value;
 }
 
 class BI2A implements BI2 {
-  final int value;
+  final int? value;
   BI2A(this.value);
 }
 
 class BI2B implements BI2 {
-  int get value => smiOrMint;
+  int? get value => smiOrMint;
 }
 
 abstract class BI3 {
-  int get value;
-  set value(int value);
+  int? get value;
+  set value(int? value);
 }
 
 class BI3A implements BI3 {
-  int value;
+  int? value;
   BI3A(this.value);
 }
 
 class BI3B implements BI3 {
-  int get value => smiOrMint;
-  set value(int v) {}
+  int? get value => smiOrMint;
+  set value(int? v) {}
 }
 
 abstract class UBI {
-  int value;
+  int? value;
 }
 
 class UBIA implements UBI {
-  int value;
+  int? value;
   UBIA(this.value);
 }
 
 class UBIB implements UBI {
-  int get value => smiOrMint;
-  set value(int v) {}
+  int? get value => smiOrMint;
+  set value(int? v) {}
 }
 
 main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
index 542466c..de01101 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
@@ -1,96 +1,96 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class BI1 extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  abstract get value() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  abstract get value() → core::int?;
 }
 class BI1A extends core::Object implements self::BI1 {
-[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::int* value;
-[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::BI1A*
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::int? value;
+[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int? value) → self::BI1A
     : self::BI1A::value = value, super core::Object::•()
     ;
 }
 class BI1B extends core::Object implements self::BI1 {
-  synthetic constructor •() → self::BI1B*
+  synthetic constructor •() → self::BI1B
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get value() → core::int?
     return null;
 }
 abstract class BI2 extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  abstract get value() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  abstract get value() → core::int?;
 }
 class BI2A extends core::Object implements self::BI2 {
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  final field core::int* value;
-  constructor •() → self::BI2A*
+[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  final field core::int? value;
+  constructor •() → self::BI2A
     : self::BI2A::value = #C1, super core::Object::•()
     ;
 }
 class BI2B extends core::Object implements self::BI2 {
-  synthetic constructor •() → self::BI2B*
+  synthetic constructor •() → self::BI2B
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  get value() → core::int?
     return [@vm.inferred-type.metadata=int] self::smiOrMint;
 }
 abstract class BI3 extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  abstract get value() → core::int*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  abstract set value(core::int* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  abstract get value() → core::int?;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  abstract set value(core::int? value) → void;
 }
 class BI3A extends core::Object implements self::BI3 {
-[@vm.inferred-type.metadata=int?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field core::int* value;
-[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::BI3A*
+[@vm.inferred-type.metadata=int?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field core::int? value;
+[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int? value) → self::BI3A
     : self::BI3A::value = value, super core::Object::•()
     ;
 }
 class BI3B extends core::Object implements self::BI3 {
-  synthetic constructor •() → self::BI3B*
+  synthetic constructor •() → self::BI3B
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  get value() → core::int?
     return [@vm.inferred-type.metadata=int] self::smiOrMint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  set value([@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::int* v) → void {}
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  set value([@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::int? v) → void {}
 }
 abstract class UBI extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i]  abstract get value() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i]  abstract get /*isLegacy*/ value() → core::int?;
 }
 class UBIA extends core::Object implements self::UBI {
-[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:5] [@vm.unboxing-info.metadata=(i)->i]  field core::int* value;
-[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::UBIA*
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:5] [@vm.unboxing-info.metadata=(i)->i]  field core::int? value;
+[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int? value) → self::UBIA
     : self::UBIA::value = value, super core::Object::•()
     ;
 }
 class UBIB extends core::Object implements self::UBI {
-  synthetic constructor •() → self::UBIB*
+  synthetic constructor •() → self::UBIB
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i]  get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i]  get value() → core::int?
     return [@vm.inferred-type.metadata=int] self::smiOrMint;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
 [@vm.inferred-type.metadata=int?]static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
 static method use([@vm.inferred-type.metadata=int?] dynamic object) → void {
   [@vm.inferred-type.metadata=int?] self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
 static method main() → dynamic {
-  final self::BI1A* bi1a = new self::BI1A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
-  final self::BI1B* bi1b = new self::BI1B::•();
-  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI1*} bi1a : bi1b).{self::BI1::value}{core::int*});
-  final self::BI2A* bi2a = new self::BI2A::•();
-  final self::BI2B* bi2b = new self::BI2B::•();
-  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI2*} bi2a : bi2b).{self::BI2::value}{core::int*});
-  final self::BI3A* bi3a = new self::BI3A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
-  final self::BI3B* bi3b = new self::BI3B::•();
-  ([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3*} bi3a : bi3b).{self::BI3::value} = null;
-  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3*} bi3a : bi3b).{self::BI3::value}{core::int*});
-  final self::UBIA* ubia = new self::UBIA::•([@vm.inferred-type.metadata=int] self::smiOrMint);
-  final self::UBIB* ubib = new self::UBIB::•();
-  self::use([@vm.inferred-type.metadata=int]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::UBI*} ubia : ubib).{self::UBI::value}{core::int*});
+  final self::BI1A bi1a = new self::BI1A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
+  final self::BI1B bi1b = new self::BI1B::•();
+  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI1} bi1a : bi1b).{self::BI1::value}{core::int?});
+  final self::BI2A bi2a = new self::BI2A::•();
+  final self::BI2B bi2b = new self::BI2B::•();
+  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI2} bi2a : bi2b).{self::BI2::value}{core::int?});
+  final self::BI3A bi3a = new self::BI3A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
+  final self::BI3B bi3b = new self::BI3B::•();
+  ([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3} bi3a : bi3b).{self::BI3::value} = null;
+  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3} bi3a : bi3b).{self::BI3::value}{core::int?});
+  final self::UBIA ubia = new self::UBIA::•([@vm.inferred-type.metadata=int] self::smiOrMint);
+  final self::UBIB ubib = new self::UBIB::•();
+  self::use([@vm.inferred-type.metadata=int]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::UBI} ubia : ubib).{self::UBI::value}{core::int?});
 }
 constants  {
   #C1 = null
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect
index a3d1769b..4cddb45 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect
@@ -1,9 +1,9 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
@@ -17,30 +17,30 @@
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  field dynamic boxedNullableIntOrDouble;
 [@vm.inferred-type.metadata=#lib::X?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  field dynamic boxedNullableX;
 [@vm.inferred-type.metadata=#lib::X] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  field dynamic boxedX;
-[@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b]  constructor •([@vm.inferred-type.metadata=dart.core::_Smi] dynamic unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → self::A*
+[@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b]  constructor •([@vm.inferred-type.metadata=dart.core::_Smi] dynamic unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → self::A
     : self::A::unboxedSmi = unboxedSmi, self::A::unboxedInt = unboxedInt, self::A::unboxedDouble = unboxedDouble, self::A::boxedNullableInt = boxedNullableInt, self::A::boxedNullableDouble = boxedNullableDouble, self::A::boxedNonNullableIntOrDouble = boxedNonNullableIntOrDouble, self::A::boxedNullableIntOrDouble = boxedNullableIntOrDouble, self::A::boxedNullableX = boxedNullableX, self::A::boxedX = boxedX, super core::Object::•()
     ;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2 ?{core::bool} true : false;
 static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
 static method main() → dynamic {
-  final self::A* a = new self::A::•([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
-  [@vm.direct-call.metadata=#lib::A.unboxedSmi] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedSmi} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
-  [@vm.direct-call.metadata=#lib::A.unboxedInt] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedInt} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
-  [@vm.direct-call.metadata=#lib::A.unboxedDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2;
-  [@vm.direct-call.metadata=#lib::A.boxedNullableInt] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableInt} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
-  [@vm.direct-call.metadata=#lib::A.boxedNullableDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null;
-  [@vm.direct-call.metadata=#lib::A.boxedNonNullableIntOrDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNonNullableIntOrDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
-  [@vm.direct-call.metadata=#lib::A.boxedNullableIntOrDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableIntOrDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
-  [@vm.direct-call.metadata=#lib::A.boxedNullableX] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableX} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null;
+  final self::A a = new self::A::•([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, new self::X::•());
+  [@vm.direct-call.metadata=#lib::A.unboxedSmi] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedSmi} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
+  [@vm.direct-call.metadata=#lib::A.unboxedInt] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedInt} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
+  [@vm.direct-call.metadata=#lib::A.unboxedDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2;
+  [@vm.direct-call.metadata=#lib::A.boxedNullableInt] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableInt} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
+  [@vm.direct-call.metadata=#lib::A.boxedNullableDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null;
+  [@vm.direct-call.metadata=#lib::A.boxedNonNullableIntOrDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNonNullableIntOrDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
+  [@vm.direct-call.metadata=#lib::A.boxedNullableIntOrDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableIntOrDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
+  [@vm.direct-call.metadata=#lib::A.boxedNullableX] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableX} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null;
   [@vm.direct-call.metadata=#lib::A.boxedX] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedX} = new self::X::•();
   self::use([@vm.direct-call.metadata=#lib::A.unboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi] a.{self::A::unboxedSmi}{dynamic});
   self::use([@vm.direct-call.metadata=#lib::A.unboxedInt] [@vm.inferred-type.metadata=int] a.{self::A::unboxedInt}{dynamic});
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
index f37b67e..f367c3e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
@@ -16,7 +16,7 @@
 
 abstract class Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -26,20 +26,20 @@
       dynamic boxedNullableX,
       dynamic boxedX);
 
-  dynamic returnUnboxedSmi(X ignored);
-  dynamic returnUnboxedInt(X ignored);
-  dynamic returnUnboxedDouble(X ignored);
-  dynamic returnBoxedNullableInt(X ignored);
-  dynamic returnBoxedNullableDouble(X ignored);
-  dynamic returnBoxedIntOrDouble(X ignored);
-  dynamic returnBoxedNullableIntOrDouble(X ignored);
-  dynamic returnBoxedNullableX(X ignored);
-  dynamic returnBoxedX(X ignored);
+  dynamic returnUnboxedSmi(X? ignored);
+  dynamic returnUnboxedInt(X? ignored);
+  dynamic returnUnboxedDouble(X? ignored);
+  dynamic returnBoxedNullableInt(X? ignored);
+  dynamic returnBoxedNullableDouble(X? ignored);
+  dynamic returnBoxedIntOrDouble(X? ignored);
+  dynamic returnBoxedNullableIntOrDouble(X? ignored);
+  dynamic returnBoxedNullableX(X? ignored);
+  dynamic returnBoxedX(X? ignored);
 }
 
 class Impl1 implements Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -58,20 +58,20 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 1;
-  dynamic returnUnboxedInt(X ignored) => 1;
-  dynamic returnUnboxedDouble(X ignored) => 1.1;
-  dynamic returnBoxedNullableInt(X ignored) => null;
-  dynamic returnBoxedNullableDouble(X ignored) => null;
-  dynamic returnBoxedIntOrDouble(X ignored) => 1;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => null;
-  dynamic returnBoxedNullableX(X ignored) => null;
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 1;
+  dynamic returnUnboxedInt(X? ignored) => 1;
+  dynamic returnUnboxedDouble(X? ignored) => 1.1;
+  dynamic returnBoxedNullableInt(X? ignored) => null;
+  dynamic returnBoxedNullableDouble(X? ignored) => null;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 1;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => null;
+  dynamic returnBoxedNullableX(X? ignored) => null;
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 class BaseImpl2 {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -90,20 +90,20 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 2;
-  dynamic returnUnboxedInt(X ignored) => mint;
-  dynamic returnUnboxedDouble(X ignored) => 2.2;
-  dynamic returnBoxedNullableInt(X ignored) => 2;
-  dynamic returnBoxedNullableDouble(X ignored) => 2.2;
-  dynamic returnBoxedIntOrDouble(X ignored) => 2.2;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => 2;
-  dynamic returnBoxedNullableX(X ignored) => X();
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 2;
+  dynamic returnUnboxedInt(X? ignored) => mint;
+  dynamic returnUnboxedDouble(X? ignored) => 2.2;
+  dynamic returnBoxedNullableInt(X? ignored) => 2;
+  dynamic returnBoxedNullableDouble(X? ignored) => 2.2;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 2.2;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => 2;
+  dynamic returnBoxedNullableX(X? ignored) => X();
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 class SubImpl3 extends BaseImpl2 implements Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -122,15 +122,15 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 3;
-  dynamic returnUnboxedInt(X ignored) => mint;
-  dynamic returnUnboxedDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableInt(X ignored) => mint;
-  dynamic returnBoxedNullableDouble(X ignored) => 3.3;
-  dynamic returnBoxedIntOrDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableX(X ignored) => X();
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 3;
+  dynamic returnUnboxedInt(X? ignored) => mint;
+  dynamic returnUnboxedDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableInt(X? ignored) => mint;
+  dynamic returnBoxedNullableDouble(X? ignored) => 3.3;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableX(X? ignored) => X();
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
index 0811f05..40650ad 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
@@ -1,9 +1,9 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
@@ -20,7 +20,7 @@
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  abstract method returnBoxedX() → dynamic;
 }
 class Impl1 extends core::Object implements self::Interface {
-  synthetic constructor •() → self::Impl1*
+  synthetic constructor •() → self::Impl1
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b]  method takePositional([@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
@@ -53,7 +53,7 @@
     return new self::X::•();
 }
 class BaseImpl2 extends core::Object {
-  synthetic constructor •() → self::BaseImpl2*
+  synthetic constructor •() → self::BaseImpl2
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b]  method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
@@ -86,7 +86,7 @@
     return new self::X::•();
 }
 class SubImpl3 extends self::BaseImpl2 implements self::Interface {
-  synthetic constructor •() → self::SubImpl3*
+  synthetic constructor •() → self::SubImpl3
     : super self::BaseImpl2::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b]  method takePositional([@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=!] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
@@ -119,55 +119,55 @@
     return new self::X::•();
 }
 static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
 static method main() → dynamic {
-  final core::List<core::Object*>* values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object*>] core::_GrowableList::_literal3<core::Object*>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
-  final self::Impl1* a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int*) →* core::Object*} as self::Impl1*;
-  final self::BaseImpl2* b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int*) →* core::Object*} as self::BaseImpl2*;
-  final self::SubImpl3* c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::SubImpl3*;
-  final self::Interface* d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::Interface*;
-  [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  b.{self::BaseImpl2::takePositional}(2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  d.{self::Interface::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(){(self::X*) →* dynamic});
+  final core::List<core::Object> values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object>] core::_GrowableList::_literal3<core::Object>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
+  final self::Impl1 a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Impl1;
+  final self::BaseImpl2 b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int) → core::Object} as{ForNonNullableByDefault} self::BaseImpl2;
+  final self::SubImpl3 c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::SubImpl3;
+  final self::Interface d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Interface;
+  [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  b.{self::BaseImpl2::takePositional}(2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  d.{self::Interface::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(){(self::X?) → dynamic});
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
index ddbf2a0..f8637c8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
@@ -16,7 +16,7 @@
 
 abstract class Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -26,20 +26,20 @@
       dynamic boxedNullableX,
       dynamic boxedX);
 
-  dynamic returnUnboxedSmi(X ignored);
-  dynamic returnUnboxedInt(X ignored);
-  dynamic returnUnboxedDouble(X ignored);
-  dynamic returnBoxedNullableInt(X ignored);
-  dynamic returnBoxedNullableDouble(X ignored);
-  dynamic returnBoxedIntOrDouble(X ignored);
-  dynamic returnBoxedNullableIntOrDouble(X ignored);
-  dynamic returnBoxedNullableX(X ignored);
-  dynamic returnBoxedX(X ignored);
+  dynamic returnUnboxedSmi(X? ignored);
+  dynamic returnUnboxedInt(X? ignored);
+  dynamic returnUnboxedDouble(X? ignored);
+  dynamic returnBoxedNullableInt(X? ignored);
+  dynamic returnBoxedNullableDouble(X? ignored);
+  dynamic returnBoxedIntOrDouble(X? ignored);
+  dynamic returnBoxedNullableIntOrDouble(X? ignored);
+  dynamic returnBoxedNullableX(X? ignored);
+  dynamic returnBoxedX(X? ignored);
 }
 
 class Impl1 implements Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -58,20 +58,20 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 1;
-  dynamic returnUnboxedInt(X ignored) => 1;
-  dynamic returnUnboxedDouble(X ignored) => 1.1;
-  dynamic returnBoxedNullableInt(X ignored) => null;
-  dynamic returnBoxedNullableDouble(X ignored) => null;
-  dynamic returnBoxedIntOrDouble(X ignored) => 1;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => null;
-  dynamic returnBoxedNullableX(X ignored) => null;
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 1;
+  dynamic returnUnboxedInt(X? ignored) => 1;
+  dynamic returnUnboxedDouble(X? ignored) => 1.1;
+  dynamic returnBoxedNullableInt(X? ignored) => null;
+  dynamic returnBoxedNullableDouble(X? ignored) => null;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 1;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => null;
+  dynamic returnBoxedNullableX(X? ignored) => null;
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 class BaseImpl2 {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -90,20 +90,20 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 2;
-  dynamic returnUnboxedInt(X ignored) => mint;
-  dynamic returnUnboxedDouble(X ignored) => 2.2;
-  dynamic returnBoxedNullableInt(X ignored) => 2;
-  dynamic returnBoxedNullableDouble(X ignored) => 2.2;
-  dynamic returnBoxedIntOrDouble(X ignored) => 2.2;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => 2;
-  dynamic returnBoxedNullableX(X ignored) => X();
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 2;
+  dynamic returnUnboxedInt(X? ignored) => mint;
+  dynamic returnUnboxedDouble(X? ignored) => 2.2;
+  dynamic returnBoxedNullableInt(X? ignored) => 2;
+  dynamic returnBoxedNullableDouble(X? ignored) => 2.2;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 2.2;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => 2;
+  dynamic returnBoxedNullableX(X? ignored) => X();
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 class SubImpl3 extends BaseImpl2 implements Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -122,15 +122,15 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 3;
-  dynamic returnUnboxedInt(X ignored) => mint;
-  dynamic returnUnboxedDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableInt(X ignored) => mint;
-  dynamic returnBoxedNullableDouble(X ignored) => 3.3;
-  dynamic returnBoxedIntOrDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableX(X ignored) => X();
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 3;
+  dynamic returnUnboxedInt(X? ignored) => mint;
+  dynamic returnUnboxedDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableInt(X? ignored) => mint;
+  dynamic returnBoxedNullableDouble(X? ignored) => 3.3;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableX(X? ignored) => X();
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
index d22492c..2405a88 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
@@ -1,29 +1,29 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
 abstract class Interface extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  abstract method returnUnboxedSmi(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  abstract method returnUnboxedInt(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  abstract method returnUnboxedDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  abstract method returnBoxedNullableInt(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  abstract method returnBoxedNullableDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  abstract method returnBoxedIntOrDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  abstract method returnBoxedNullableIntOrDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  abstract method returnBoxedNullableX(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  abstract method returnBoxedX(self::X* ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  abstract method returnUnboxedSmi(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  abstract method returnUnboxedInt(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  abstract method returnUnboxedDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  abstract method returnBoxedNullableInt(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  abstract method returnBoxedNullableDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  abstract method returnBoxedIntOrDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  abstract method returnBoxedNullableIntOrDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  abstract method returnBoxedNullableX(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  abstract method returnBoxedX(self::X? ignored) → dynamic;
 }
 class Impl1 extends core::Object implements self::Interface {
-  synthetic constructor •() → self::Impl1*
+  synthetic constructor •() → self::Impl1
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
     self::use(unboxedInt);
     self::use(unboxedDouble);
     self::use(boxedNullableInt);
@@ -33,30 +33,30 @@
     self::use(boxedNullableX);
     self::use(boxedX);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi(self::X? ignored) → dynamic
     return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt(self::X? ignored) → dynamic
     return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble(self::X? ignored) → dynamic
     return 1.1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt(self::X? ignored) → dynamic
     return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble(self::X? ignored) → dynamic
     return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble(self::X? ignored) → dynamic
     return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble(self::X? ignored) → dynamic
     return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX(self::X? ignored) → dynamic
     return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX(self::X? ignored) → dynamic
     return new self::X::•();
 }
 class BaseImpl2 extends core::Object {
-  synthetic constructor •() → self::BaseImpl2*
+  synthetic constructor •() → self::BaseImpl2
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] core::int* unboxedSmi, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] core::int? unboxedSmi, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
     self::use(unboxedInt);
     self::use(unboxedDouble);
     self::use(boxedNullableInt);
@@ -66,30 +66,30 @@
     self::use(boxedNullableX);
     self::use(boxedX);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return new self::X::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return new self::X::•();
 }
 class SubImpl3 extends self::BaseImpl2 implements self::Interface {
-  synthetic constructor •() → self::SubImpl3*
+  synthetic constructor •() → self::SubImpl3
     : super self::BaseImpl2::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
     self::use(unboxedInt);
     self::use(unboxedDouble);
     self::use(boxedNullableInt);
@@ -99,85 +99,85 @@
     self::use(boxedNullableX);
     self::use(boxedX);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi(self::X? ignored) → dynamic
     return 3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt(self::X? ignored) → dynamic
     return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble(self::X? ignored) → dynamic
     return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt(self::X? ignored) → dynamic
     return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble(self::X? ignored) → dynamic
     return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble(self::X? ignored) → dynamic
     return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble(self::X? ignored) → dynamic
     return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX(self::X? ignored) → dynamic
     return new self::X::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX(self::X? ignored) → dynamic
     return new self::X::•();
 }
 static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
 static method main() → dynamic {
-  final core::List<core::Object*>* values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object*>] core::_GrowableList::_literal3<core::Object*>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
-  final self::Impl1* a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int*) →* core::Object*} as self::Impl1*;
-  final self::BaseImpl2* b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int*) →* core::Object*} as self::BaseImpl2*;
-  final self::SubImpl3* c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::SubImpl3*;
-  final self::Interface* d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::Interface*;
-  [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  b.{self::BaseImpl2::takePositional}(2, 2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  d.{self::Interface::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(null){(self::X*) →* dynamic});
-  self::use(d.{self::Interface::takePositional}{(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void});
-  self::use(d.{self::Interface::returnUnboxedSmi}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnUnboxedInt}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnUnboxedDouble}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedNullableInt}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedNullableDouble}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedIntOrDouble}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedNullableIntOrDouble}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedNullableX}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedX}{(self::X*) →* dynamic});
+  final core::List<core::Object> values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object>] core::_GrowableList::_literal3<core::Object>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
+  final self::Impl1 a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Impl1;
+  final self::BaseImpl2 b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int) → core::Object} as{ForNonNullableByDefault} self::BaseImpl2;
+  final self::SubImpl3 c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::SubImpl3;
+  final self::Interface d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Interface;
+  [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  b.{self::BaseImpl2::takePositional}(2, 2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  d.{self::Interface::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(null){(self::X?) → dynamic});
+  self::use(d.{self::Interface::takePositional}{(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void});
+  self::use(d.{self::Interface::returnUnboxedSmi}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnUnboxedInt}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnUnboxedDouble}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedNullableInt}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedNullableDouble}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedIntOrDouble}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedNullableIntOrDouble}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedNullableX}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedX}{(self::X?) → dynamic});
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
index 5151f2e..3522029 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
@@ -15,7 +15,7 @@
 class X {}
 
 void takePositional(
-    int unboxedSmi,
+    int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
@@ -35,7 +35,7 @@
 }
 
 void takeOptional(
-    [int unboxedSmi,
+    [int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
@@ -55,7 +55,7 @@
 }
 
 void takeNamed(
-    {int unboxedSmi,
+    {int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
index 2577681..3615da2 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
@@ -1,19 +1,19 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2 ?{core::bool} true : false;
 static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
@@ -48,33 +48,33 @@
   self::use(boxedX);
 }
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedSmi() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedInt() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
 [@vm.unboxing-info.metadata=()->d]static method returnUnboxedDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2;
 static method returnBoxedNullableInt() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
 static method returnBoxedNullableDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null;
 static method returnBoxedIntOrDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
 static method returnBoxedNullableIntOrDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
 static method returnBoxedNullableX() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null;
 static method returnBoxedX() → dynamic
   return new self::X::•();
 @#C3
-static method returnBoxedSmiFromEntryPoint() → core::int*
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
+static method returnBoxedSmiFromEntryPoint() → core::int
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
 @#C3
-static method takeBoxedSmiFromEntryPoint(core::int* value) → void {}
+static method takeBoxedSmiFromEntryPoint(core::int value) → void {}
 static method main() → dynamic {
-  let final core::int* #t1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t9 = new self::X::•() in self::takePositional(#t2, #t3, #t4, #t5, #t6, #t7, #t8, #t9);
-  let final core::int* #t10 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t11 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t12 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t13 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t14 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t15 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t16 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t17 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t18 = new self::X::•() in self::takeOptional(#t11, #t12, #t13, #t14, #t15, #t16, #t17, #t18);
-  let final core::int* #t19 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t20 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t21 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t22 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t23 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t24 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t25 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t26 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t27 = new self::X::•() in self::takeNamed(#t24, #t23, #t22, #t25, #t26, #t27, #t21, #t20);
-  self::takeBoxedSmiFromEntryPoint([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2);
+  let final core::int #t1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2 in let final core::int #t2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double #t3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2 in let final core::int? #t4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double? #t5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null in let final core::num #t6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num? #t7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X? #t8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null in let final self::X #t9 = new self::X::•() in self::takePositional(#t2, #t3, #t4, #t5, #t6, #t7, #t8, #t9);
+  let final core::int #t10 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2 in let final core::int #t11 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double #t12 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2 in let final core::int? #t13 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double? #t14 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null in let final core::num #t15 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num? #t16 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X? #t17 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null in let final self::X #t18 = new self::X::•() in self::takeOptional(#t11, #t12, #t13, #t14, #t15, #t16, #t17, #t18);
+  let final core::int #t19 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2 in let final core::int #t20 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double #t21 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2 in let final core::int? #t22 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double? #t23 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null in let final core::num #t24 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num? #t25 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X? #t26 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null in let final self::X #t27 = new self::X::•() in self::takeNamed(#t24, #t23, #t22, #t25, #t26, #t27, #t21, #t20);
+  self::takeBoxedSmiFromEntryPoint([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2);
   self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnUnboxedSmi());
   self::use([@vm.inferred-type.metadata=int] self::returnUnboxedInt());
   self::use([@vm.inferred-type.metadata=dart.core::_Double] self::returnUnboxedDouble());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
index f20e0ce..21788ee 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
@@ -15,7 +15,7 @@
 class X {}
 
 void takePositional(
-    int unboxedSmi,
+    int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
@@ -35,7 +35,7 @@
 }
 
 void takeOptional(
-    [int unboxedSmi,
+    [int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
@@ -55,7 +55,7 @@
 }
 
 void takeNamed(
-    {int unboxedSmi,
+    {int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
index 8296cf3..3ab3d19 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
@@ -1,23 +1,23 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2 ?{core::bool} true : false;
 static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
-static method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+static method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
   self::use(unboxedInt);
   self::use(unboxedDouble);
   self::use(boxedNullableInt);
@@ -27,7 +27,7 @@
   self::use(boxedNullableX);
   self::use(boxedX);
 }
-static method takeOptional([core::int* unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1]) → void {
+static method takeOptional([core::int? unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1]) → void {
   self::use(unboxedInt);
   self::use(unboxedDouble);
   self::use(boxedNullableInt);
@@ -37,7 +37,7 @@
   self::use(boxedNullableX);
   self::use(boxedX);
 }
-static method takeNamed({core::int* unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1}) → void {
+static method takeNamed({core::int? unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1}) → void {
   self::use(unboxedInt);
   self::use(unboxedDouble);
   self::use(boxedNullableInt);
@@ -48,27 +48,27 @@
   self::use(boxedX);
 }
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedSmi() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedInt() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
 [@vm.unboxing-info.metadata=()->d]static method returnUnboxedDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2;
 static method returnBoxedNullableInt() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
 static method returnBoxedNullableDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null;
 static method returnBoxedIntOrDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
 static method returnBoxedNullableIntOrDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
 static method returnBoxedNullableX() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null;
 static method returnBoxedX() → dynamic
   return new self::X::•();
 static method main() → dynamic {
-  self::takePositional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
-  self::takeOptional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
-  self::takeNamed(unboxedSmi: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, unboxedInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, unboxedDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, boxedNullableInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, boxedNullableDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, boxedIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, boxedNullableIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, boxedNullableX: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, boxedX: new self::X::•());
+  self::takePositional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, new self::X::•());
+  self::takeOptional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, new self::X::•());
+  self::takeNamed(unboxedSmi: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, unboxedInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, unboxedDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, boxedNullableInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, boxedNullableDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, boxedIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, boxedNullableIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, boxedNullableX: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, boxedX: new self::X::•());
   self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnUnboxedSmi());
   self::use([@vm.inferred-type.metadata=int] self::returnUnboxedInt());
   self::use([@vm.inferred-type.metadata=dart.core::_Double] self::returnUnboxedDouble());
@@ -93,16 +93,16 @@
 }
 constants  {
   #C1 = null
-  #C2 = tearoff self::takePositional
-  #C3 = tearoff self::takeOptional
-  #C4 = tearoff self::takeNamed
-  #C5 = tearoff self::returnUnboxedSmi
-  #C6 = tearoff self::returnUnboxedInt
-  #C7 = tearoff self::returnUnboxedDouble
-  #C8 = tearoff self::returnBoxedNullableInt
-  #C9 = tearoff self::returnBoxedNullableDouble
-  #C10 = tearoff self::returnBoxedIntOrDouble
-  #C11 = tearoff self::returnBoxedNullableIntOrDouble
-  #C12 = tearoff self::returnBoxedNullableX
-  #C13 = tearoff self::returnBoxedX
+  #C2 = static-tearoff self::takePositional
+  #C3 = static-tearoff self::takeOptional
+  #C4 = static-tearoff self::takeNamed
+  #C5 = static-tearoff self::returnUnboxedSmi
+  #C6 = static-tearoff self::returnUnboxedInt
+  #C7 = static-tearoff self::returnUnboxedDouble
+  #C8 = static-tearoff self::returnBoxedNullableInt
+  #C9 = static-tearoff self::returnBoxedNullableDouble
+  #C10 = static-tearoff self::returnBoxedIntOrDouble
+  #C11 = static-tearoff self::returnBoxedNullableIntOrDouble
+  #C12 = static-tearoff self::returnBoxedNullableX
+  #C13 = static-tearoff self::returnBoxedX
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unfinished_static_field_init.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unfinished_static_field_init.dart.expect
index 74d3bb3..ed5a63a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unfinished_static_field_init.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unfinished_static_field_init.dart.expect
@@ -1,9 +1,9 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 }
@@ -13,7 +13,7 @@
   return new self::A::•();
 static method bad() → dynamic
   return throw "No return!";
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   core::print([@vm.inferred-type.metadata=#lib::A?] self::static_field_good);
   core::print([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::static_field_bad);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
index 0ed46d3..6cd1f40 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
@@ -1,22 +1,18 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class I extends core::Object {
 }
-abstract class A extends core::Object implements self::I {
-}
 class B extends core::Object implements self::I {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 }
-[@vm.inferred-type.metadata=#lib::B?]static field self::I* ii = new self::B::•();
-static method bar([@vm.inferred-type.metadata=#lib::B?] self::I* i) → void {
-  if(i is self::A*) {
-    throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
-  }
+[@vm.inferred-type.metadata=#lib::B?]static field self::I ii = new self::B::•();
+static method bar([@vm.inferred-type.metadata=#lib::B?] self::I i) → void {
+  ;
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   self::bar([@vm.inferred-type.metadata=#lib::B?] self::ii);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
index 6abe2d5..d7b90d8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
@@ -11,7 +11,7 @@
   }
 }
 
-var field = A();
+A? field = A();
 
 class B {
   B() {
@@ -20,7 +20,7 @@
 }
 
 class C {
-  var instanceField = new B();
+  B? instanceField = new B();
 }
 
 void main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
index cc689dc..e544ddf 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
@@ -1,18 +1,18 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class B extends core::Object {
-  constructor •() → self::B*
+  constructor •() → self::B
     : super core::Object::•() {
     core::print("B");
   }
 }
 class C extends core::Object {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : dynamic #t1 = new self::B::•(), super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  set instanceField(self::B* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  set /*isLegacy*/ instanceField(self::B? value) → void;
 }
 static method main() → void {
   null;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
index af6a9b8..45dd11b 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
@@ -31,12 +31,12 @@
 
 class C<T> {
   // Should be replaced with setter.
-  T bar;
+  T? bar;
 }
 
 class D implements C<int> {
   // Should be replaced with setter.
-  int bar;
+  int? bar;
 }
 
 class E {
@@ -59,7 +59,7 @@
 
 class H {
   // Should be replaced with setter.
-  int unused6;
+  int? unused6;
 }
 
 class I extends H {
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 6e40a3c..057cfe3 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
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "package:expect/expect.dart" as exp;
@@ -6,45 +6,45 @@
 import "package:expect/expect.dart";
 
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : dynamic #t1 = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo(), super core::Object::•()
     ;
 }
 class B extends core::Object {
-  constructor •() → self::B*
+  constructor •() → self::B
     : dynamic #t2 = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo(), super core::Object::•()
     ;
 }
-abstract class C<T extends core::Object* = dynamic> extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  abstract set bar(generic-covariant-impl self::C::T* value) → void;
+abstract class C<T extends core::Object? = dynamic> extends core::Object {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  abstract set /*isLegacy*/ bar(generic-covariant-impl self::C::T? value) → void;
 }
-class D extends core::Object implements self::C<core::int*> {
-  synthetic constructor •() → self::D*
+class D extends core::Object implements self::C<core::int> {
+  synthetic constructor •() → self::D
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  set bar(generic-covariant-impl core::int* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  set /*isLegacy*/ bar(generic-covariant-impl core::int? value) → void;
 }
 abstract class E extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract get bar() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract get /*isLegacy*/ bar() → core::int;
 }
 class F extends core::Object implements self::E {
-  synthetic constructor •() → self::F*
+  synthetic constructor •() → self::F
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  get bar() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  get bar() → core::int
     return 42;
 }
 class G extends core::Object /*hasConstConstructor*/  {
-[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i]  final field core::int* bazz;
+[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i]  final field core::int bazz;
 }
 abstract class H extends core::Object {
-  synthetic constructor •() → self::H*
+  synthetic constructor •() → self::H
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4]  set unused6(core::int* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4]  set /*isLegacy*/ unused6(core::int? value) → void;
 }
 class I extends self::H {
-  synthetic constructor •() → self::I*
+  synthetic constructor •() → self::I
     : super self::H::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method foo() → dynamic {
@@ -55,14 +55,14 @@
 static method main() → void {
   new self::A::•();
   new self::B::•();
-  self::C<core::num*>* c = new self::D::•();
-  exp::Expect::throws<dynamic>(() → Null {
-    [@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::C<core::num> c = new self::D::•();
+  exp::Expect::throws<dynamic>(() → 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::•();
-  let final core::int* #t3 = [@vm.direct-call.metadata=#lib::F.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] e.{self::E::bar}{core::int*} in exp::Expect::equals();
+  self::E e = new self::F::•();
+  let final core::int #t3 = [@vm.direct-call.metadata=#lib::F.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] e.{self::E::bar}{core::int} in exp::Expect::equals();
   exp::Expect::isTrue(![@vm.inferred-type.metadata=dart.core::bool] core::identical(#C2, #C4));
-  [@vm.direct-call.metadata=#lib::I.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::I::•().{self::I::foo}(){() →* dynamic};
+  [@vm.direct-call.metadata=#lib::I.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::I::•().{self::I::foo}(){() → dynamic};
   5;
 }
 constants  {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart
index ea59290..a777b1b 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test for tree shaking of write-only late fields.
-// This test requires non-nullable experiment.
-
-// @dart = 2.10
 
 foo() {}
 
diff --git a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
index 6115eb3..33f4458 100644
--- a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
+++ b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
@@ -7,7 +7,7 @@
 const bool constTrue2 = !constFalse;
 const bool constFalse2 = const bool.fromEnvironment('test.define.notDefined');
 
-bool foo() => null;
+bool? foo() => null;
 
 void testSimpleConditions() {
   if (constTrue) {
@@ -25,10 +25,10 @@
 }
 
 void testAndConditions() {
-  if (constTrue && foo()) {
+  if (constTrue && foo()!) {
     print('1_yes');
   }
-  if (constFalse && foo()) {
+  if (constFalse && foo()!) {
     print('2_no');
   }
   if (constTrue && constFalse) {
@@ -40,10 +40,10 @@
 }
 
 void testOrConditions() {
-  if (constTrue || foo()) {
+  if (constTrue || foo()!) {
     print('1_yes');
   }
-  if (constFalse || foo()) {
+  if (constFalse || foo()!) {
     print('2_yes');
   }
   if (constFalse || constFalse2) {
@@ -61,54 +61,54 @@
   if (!constFalse) {
     print('2_yes');
   }
-  if (!(!(!constTrue && foo()) || foo())) {
+  if (!(!(!constTrue && foo()!) || foo()!)) {
     print('3_no');
   }
 }
 
 testConditionalExpressions() {
   print(!constFalse && constTrue ? '1_yes' : '2_no');
-  print(constFalse && foo() ? '3_no' : '4_yes ${foo()}');
+  print(constFalse && foo()! ? '3_no' : '4_yes ${foo()}');
 }
 
 void testAsserts() {
-  assert(foo());
-  assert(!foo(), "oops!");
+  assert(foo()!);
+  assert(!foo()!, "oops!");
 }
 
 class TestAssertInitializer {
-  TestAssertInitializer() : assert(foo()) {}
+  TestAssertInitializer() : assert(foo()!) {}
 }
 
 testRemovalOfStatementBodies() {
-  if (foo()) assert(foo());
-  while (foo()) assert(foo());
-  do assert(foo()); while (foo());
-  for (;;) assert(foo());
-  for (var i in [1, 2]) assert(foo());
+  if (foo()!) assert(foo()!);
+  while (foo()!) assert(foo()!);
+  do assert(foo()!); while (foo()!);
+  for (;;) assert(foo()!);
+  for (var i in [1, 2]) assert(foo()!);
   try {
-    assert(foo());
+    assert(foo()!);
   } finally {
-    assert(foo());
+    assert(foo()!);
   }
   try {
-    assert(foo());
+    assert(foo()!);
   } catch (e) {
-    assert(foo());
+    assert(foo()!);
   }
   try {
-    assert(foo());
+    assert(foo()!);
   } catch (e) {
-    assert(foo());
+    assert(foo()!);
     rethrow;
   }
   switch (42) {
     case 10:
-      assert(foo());
+      assert(foo()!);
   }
   switch (42) {
     default:
-      assert(foo());
+      assert(foo()!);
   }
 }
 
diff --git a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
index e9346d5..4bf2ed9 100644
--- a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
+++ b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
@@ -1,26 +1,16 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class TestAssertInitializer extends core::Object {
-  constructor •() → self::TestAssertInitializer*
+  constructor •() → self::TestAssertInitializer
     : super core::Object::•() {}
-  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
-  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
-  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
-  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
-  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
-  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
-  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
-  abstract member-signature method toString() → core::String*; -> core::Object::toString
-  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
-  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static const field core::bool* constTrue = #C1;
-static const field core::bool* constFalse = #C2;
-static const field core::bool* constTrue2 = #C1;
-static const field core::bool* constFalse2 = #C2;
-static method foo() → core::bool*
+static const field core::bool constTrue = #C1;
+static const field core::bool constFalse = #C2;
+static const field core::bool constTrue2 = #C1;
+static const field core::bool constFalse2 = #C2;
+static method foo() → core::bool?
   return null;
 static method testSimpleConditions() → void {
   {
@@ -31,7 +21,7 @@
   }
 }
 static method testAndConditions() → void {
-  if((#C1) && self::foo()) {
+  if((#C1) && self::foo()!) {
     core::print("1_yes");
   }
 }
@@ -39,7 +29,7 @@
   {
     core::print("1_yes");
   }
-  if((#C2) || self::foo()) {
+  if((#C2) || self::foo()!) {
     core::print("2_yes");
   }
   {
@@ -57,25 +47,25 @@
 }
 static method testAsserts() → void {}
 static method testRemovalOfStatementBodies() → dynamic {
-  if(self::foo()) {
+  if(self::foo()!) {
   }
-  while (self::foo()) {
+  while (self::foo()!) {
   }
   do {
   }
-  while (self::foo())
+  while (self::foo()!)
   for (; ; ) {
   }
   {
-    core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal2<core::int*>(1, 2).{core::Iterable::iterator}{core::Iterator<core::int*>*};
+    core::Iterator<core::int> :sync-for-iterator = core::_GrowableList::_literal2<core::int>(1, 2).{core::Iterable::iterator}{core::Iterator<core::int>};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      core::int* i = :sync-for-iterator.{core::Iterator::current}{core::int*};
+      core::int i = :sync-for-iterator.{core::Iterator::current}{core::int};
     }
   }
   {}
   try {
   }
-  on dynamic catch(final dynamic e) {
+  on core::Object catch(final core::Object e) {
   }
   {}
   switch(42) {
@@ -89,7 +79,7 @@
       {}
   }
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   self::testSimpleConditions();
   self::testAndConditions();
   self::testOrConditions();
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 4d071d5..3c1a964 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,8 +1,12 @@
 # Changelog
 
 ## 7.1.1
-- Update to version `3.47` of the spec.
+- Update to version `3.48` of the spec.
 - Added `shows` and `hides` properties to `LibraryDependency`.
+- Added `Profiler` stream, `UserTagChanged` event kind, and `updatedTag` and
+  `previousTag` properties to `Event`.
+- Fixed bug where a response without a type would cause a null type failure
+  (dart-lang/sdk#46559).
 
 ## 7.1.0
 - Update to version `3.46` of the spec.
diff --git a/pkg/vm_service/example/vm_service_assert.dart b/pkg/vm_service/example/vm_service_assert.dart
index b458ad6..0af318b 100644
--- a/pkg/vm_service/example/vm_service_assert.dart
+++ b/pkg/vm_service/example/vm_service_assert.dart
@@ -137,6 +137,7 @@
   if (obj == "BreakpointRemoved") return obj;
   if (obj == "BreakpointResolved") return obj;
   if (obj == "BreakpointUpdated") return obj;
+  if (obj == "CpuSamples") return obj;
   if (obj == "Extension") return obj;
   if (obj == "GC") return obj;
   if (obj == "Inspect") return obj;
@@ -177,6 +178,7 @@
   if (obj == "Float64List") return obj;
   if (obj == "Float64x2") return obj;
   if (obj == "Float64x2List") return obj;
+  if (obj == "FunctionType") return obj;
   if (obj == "Int") return obj;
   if (obj == "Int16List") return obj;
   if (obj == "Int32List") return obj;
@@ -577,6 +579,7 @@
   }
   assertBool(obj.isStatic!);
   assertBool(obj.isConst!);
+  assertBool(obj.implicit!);
   return obj;
 }
 
@@ -602,6 +605,8 @@
   }
   assertBool(obj.isStatic!);
   assertBool(obj.isConst!);
+  assertBool(obj.implicit!);
+  assertInstanceRef(obj.signature!);
   return obj;
 }
 
@@ -879,6 +884,13 @@
   return obj;
 }
 
+vms.Parameter assertParameter(vms.Parameter obj) {
+  assertNotNull(obj);
+  assertInstanceRef(obj.parameterType!);
+  assertBool(obj.fixed!);
+  return obj;
+}
+
 vms.PortList assertPortList(vms.PortList obj) {
   assertNotNull(obj);
   assertListOfInstanceRef(obj.ports!);
@@ -1120,6 +1132,14 @@
   return obj;
 }
 
+vms.TypeParameters assertTypeParameters(vms.TypeParameters obj) {
+  assertNotNull(obj);
+  assertListOfString(obj.names!);
+  assertTypeArgumentsRef(obj.bounds!);
+  assertTypeArgumentsRef(obj.defaults!);
+  return obj;
+}
+
 vms.UnresolvedSourceLocation assertUnresolvedSourceLocation(
     vms.UnresolvedSourceLocation obj) {
   assertNotNull(obj);
diff --git a/pkg/vm_service/java/.gitignore b/pkg/vm_service/java/.gitignore
index cdc39af..cc8a3e7 100644
--- a/pkg/vm_service/java/.gitignore
+++ b/pkg/vm_service/java/.gitignore
@@ -99,6 +99,7 @@
 src/org/dartlang/vm/service/element/NullRef.java
 src/org/dartlang/vm/service/element/Obj.java
 src/org/dartlang/vm/service/element/ObjRef.java
+src/org/dartlang/vm/service/element/Parameter.java
 src/org/dartlang/vm/service/element/PortList.java
 src/org/dartlang/vm/service/element/ProcessMemoryItem.java
 src/org/dartlang/vm/service/element/ProcessMemoryUsage.java
@@ -128,6 +129,7 @@
 src/org/dartlang/vm/service/element/Timestamp.java
 src/org/dartlang/vm/service/element/TypeArguments.java
 src/org/dartlang/vm/service/element/TypeArgumentsRef.java
+src/org/dartlang/vm/service/element/TypeParameters.java
 src/org/dartlang/vm/service/element/UnresolvedSourceLocation.java
 src/org/dartlang/vm/service/element/VM.java
 src/org/dartlang/vm/service/element/VMRef.java
diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties
index 62cbe79..5e787ed 100644
--- a/pkg/vm_service/java/version.properties
+++ b/pkg/vm_service/java/version.properties
@@ -1 +1 @@
-version=3.48
+version=3.49
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 903bb0c..77ce904 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.48.0';
+const String vmServiceVersion = '3.49.0';
 
 /// @optional
 const String optional = 'optional';
@@ -44,7 +44,7 @@
 
   if (json is List) {
     return json.map((e) => createServiceObject(e, expectedTypes)).toList();
-  } else if (json is Map) {
+  } else if (json is Map<String, dynamic>) {
     String? type = json['type'];
 
     // Not a Response type.
@@ -53,7 +53,7 @@
       if (expectedTypes.length == 1) {
         type = expectedTypes.first;
       } else {
-        return null;
+        return Response.parse(json);
       }
     } else if (_isNullInstance(json) &&
         (!expectedTypes.contains('InstanceRef'))) {
@@ -157,6 +157,7 @@
   'Null': NullVal.parse,
   '@Object': ObjRef.parse,
   'Object': Obj.parse,
+  'Parameter': Parameter.parse,
   'PortList': PortList.parse,
   'ProfileFunction': ProfileFunction.parse,
   'ProtocolList': ProtocolList.parse,
@@ -183,6 +184,7 @@
   'Timestamp': Timestamp.parse,
   '@TypeArguments': TypeArgumentsRef.parse,
   'TypeArguments': TypeArguments.parse,
+  'TypeParameters': TypeParameters.parse,
   'UnresolvedSourceLocation': UnresolvedSourceLocation.parse,
   'Version': Version.parse,
   '@VM': VMRef.parse,
@@ -824,8 +826,7 @@
   /// returned.
   Future<SourceReport> getSourceReport(
     String isolateId,
-    /*List<SourceReportKind>*/
-    List<String> reports, {
+    /*List<SourceReportKind>*/ List<String> reports, {
     String? scriptId,
     int? tokenPos,
     int? endTokenPos,
@@ -1150,7 +1151,7 @@
   /// Debug | PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted,
   /// PauseException, PausePostRequest, Resume, BreakpointAdded,
   /// BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
-  /// Profiler | UserTagChanged
+  /// Profiler | CpuSamples, UserTagChanged
   /// GC | GC
   /// Extension | Extension
   /// Timeline | TimelineEvents, TimelineStreamsSubscriptionUpdate
@@ -1691,7 +1692,7 @@
   // PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted, PauseException, PausePostRequest, Resume, BreakpointAdded, BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
   Stream<Event> get onDebugEvent => _getEventController('Debug').stream;
 
-  // UserTagChanged
+  // CpuSamples, UserTagChanged
   Stream<Event> get onProfilerEvent => _getEventController('Profiler').stream;
 
   // GC
@@ -1923,8 +1924,7 @@
   @override
   Future<SourceReport> getSourceReport(
     String isolateId,
-    /*List<SourceReportKind>*/
-    List<String> reports, {
+    /*List<SourceReportKind>*/ List<String> reports, {
     String? scriptId,
     int? tokenPos,
     int? endTokenPos,
@@ -2196,7 +2196,7 @@
       request.completeError(RPCError.parse(request.method, json['error']));
     } else {
       Map<String, dynamic> result = json['result'] as Map<String, dynamic>;
-      String type = result['type'];
+      String? type = result['type'];
       if (type == 'Sentinel') {
         request.completeError(SentinelException.parse(request.method, result));
       } else if (_typeFactories[type] == null) {
@@ -2504,6 +2504,9 @@
 
   /// Notification that the UserTag for an isolate has been changed.
   static const String kUserTagChanged = 'UserTagChanged';
+
+  /// A block of recently collected CPU samples.
+  static const String kCpuSamples = 'CpuSamples';
 }
 
 /// Adding new values to `InstanceKind` is considered a backwards compatible
@@ -2584,6 +2587,9 @@
   /// An instance of the Dart class TypeRef.
   static const String kTypeRef = 'TypeRef';
 
+  /// An instance of the Dart class FunctionType.
+  static const String kFunctionType = 'FunctionType';
+
   /// An instance of the Dart class BoundedType.
   static const String kBoundedType = 'BoundedType';
 
@@ -2929,11 +2935,18 @@
   /// The library which contains this class.
   LibraryRef? library;
 
+  /// The type parameters for the class.
+  ///
+  /// Provided if the class is generic.
+  @optional
+  List<InstanceRef>? typeParameters;
+
   ClassRef({
     required this.name,
     required this.library,
     required String id,
     this.location,
+    this.typeParameters,
   }) : super(
           id: id,
         );
@@ -2944,6 +2957,11 @@
         as SourceLocation?;
     library = createServiceObject(json['library'], const ['LibraryRef'])
         as LibraryRef?;
+    typeParameters = json['typeParameters'] == null
+        ? null
+        : List<InstanceRef>.from(
+            createServiceObject(json['typeParameters'], const ['InstanceRef'])!
+                as List);
   }
 
   @override
@@ -2958,6 +2976,8 @@
       'library': library?.toJson(),
     });
     _setIfNotNull(json, 'location', location?.toJson());
+    _setIfNotNull(json, 'typeParameters',
+        typeParameters?.map((f) => f.toJson()).toList());
     return json;
   }
 
@@ -2984,6 +3004,12 @@
   /// The library which contains this class.
   LibraryRef? library;
 
+  /// The type parameters for the class.
+  ///
+  /// Provided if the class is generic.
+  @optional
+  List<InstanceRef>? typeParameters;
+
   /// The error which occurred during class finalization, if it exists.
   @optional
   ErrorRef? error;
@@ -3040,6 +3066,7 @@
     required this.subclasses,
     required String id,
     this.location,
+    this.typeParameters,
     this.error,
     this.superClass,
     this.superType,
@@ -3054,6 +3081,11 @@
         as SourceLocation?;
     library = createServiceObject(json['library'], const ['LibraryRef'])
         as LibraryRef?;
+    typeParameters = json['typeParameters'] == null
+        ? null
+        : List<InstanceRef>.from(
+            createServiceObject(json['typeParameters'], const ['InstanceRef'])!
+                as List);
     error = createServiceObject(json['error'], const ['ErrorRef']) as ErrorRef?;
     isAbstract = json['abstract'] ?? false;
     isConst = json['const'] ?? false;
@@ -3097,6 +3129,8 @@
       'subclasses': subclasses?.map((f) => f.toJson()).toList(),
     });
     _setIfNotNull(json, 'location', location?.toJson());
+    _setIfNotNull(json, 'typeParameters',
+        typeParameters?.map((f) => f.toJson()).toList());
     _setIfNotNull(json, 'error', error?.toJson());
     _setIfNotNull(json, 'super', superClass?.toJson());
     _setIfNotNull(json, 'superType', superType?.toJson());
@@ -3901,6 +3935,10 @@
   @optional
   String? previousTag;
 
+  /// A CPU profile containing recent samples.
+  @optional
+  CpuSamples? cpuSamples;
+
   /// Binary data associated with the event.
   ///
   /// This is provided for the event kinds:
@@ -3935,6 +3973,7 @@
     this.last,
     this.updatedTag,
     this.previousTag,
+    this.cpuSamples,
     this.data,
   });
 
@@ -3979,6 +4018,8 @@
     last = json['last'];
     updatedTag = json['updatedTag'];
     previousTag = json['previousTag'];
+    cpuSamples = createServiceObject(json['cpuSamples'], const ['CpuSamples'])
+        as CpuSamples?;
     data = json['data'];
   }
 
@@ -4020,6 +4061,7 @@
     _setIfNotNull(json, 'last', last);
     _setIfNotNull(json, 'updatedTag', updatedTag);
     _setIfNotNull(json, 'previousTag', previousTag);
+    _setIfNotNull(json, 'cpuSamples', cpuSamples?.toJson());
     _setIfNotNull(json, 'data', data);
     return json;
   }
@@ -4307,8 +4349,7 @@
   List<BoundVariable>? vars;
 
   @optional
-  /*FrameKind*/
-  String? kind;
+  /*FrameKind*/ String? kind;
 
   Frame({
     required this.index,
@@ -4374,6 +4415,9 @@
   /// Is this function const?
   bool? isConst;
 
+  /// Is this function implicitly defined (e.g., implicit getter/setter)?
+  bool? implicit;
+
   /// The location of this function in the source code.
   @optional
   SourceLocation? location;
@@ -4383,6 +4427,7 @@
     required this.owner,
     required this.isStatic,
     required this.isConst,
+    required this.implicit,
     required String id,
     this.location,
   }) : super(
@@ -4395,6 +4440,7 @@
         json['owner'], const ['LibraryRef', 'ClassRef', 'FuncRef']) as dynamic;
     isStatic = json['static'] ?? false;
     isConst = json['const'] ?? false;
+    implicit = json['implicit'] ?? false;
     location = createServiceObject(json['location'], const ['SourceLocation'])
         as SourceLocation?;
   }
@@ -4411,6 +4457,7 @@
       'owner': owner?.toJson(),
       'static': isStatic,
       'const': isConst,
+      'implicit': implicit,
     });
     _setIfNotNull(json, 'location', location?.toJson());
     return json;
@@ -4422,7 +4469,7 @@
 
   String toString() => '[FuncRef ' //
       'id: ${id}, name: ${name}, owner: ${owner}, isStatic: ${isStatic}, ' //
-      'isConst: ${isConst}]';
+      'isConst: ${isConst}, implicit: ${implicit}]';
 }
 
 /// A `Func` represents a Dart language function.
@@ -4444,10 +4491,16 @@
   /// Is this function const?
   bool? isConst;
 
+  /// Is this function implicitly defined (e.g., implicit getter/setter)?
+  bool? implicit;
+
   /// The location of this function in the source code.
   @optional
   SourceLocation? location;
 
+  /// The signature of the function.
+  InstanceRef? signature;
+
   /// The compiled code associated with this function.
   @optional
   CodeRef? code;
@@ -4457,6 +4510,8 @@
     required this.owner,
     required this.isStatic,
     required this.isConst,
+    required this.implicit,
+    required this.signature,
     required String id,
     this.location,
     this.code,
@@ -4470,8 +4525,11 @@
         json['owner'], const ['LibraryRef', 'ClassRef', 'FuncRef']) as dynamic;
     isStatic = json['static'] ?? false;
     isConst = json['const'] ?? false;
+    implicit = json['implicit'] ?? false;
     location = createServiceObject(json['location'], const ['SourceLocation'])
         as SourceLocation?;
+    signature = createServiceObject(json['signature'], const ['InstanceRef'])
+        as InstanceRef?;
     code = createServiceObject(json['code'], const ['CodeRef']) as CodeRef?;
   }
 
@@ -4487,6 +4545,8 @@
       'owner': owner?.toJson(),
       'static': isStatic,
       'const': isConst,
+      'implicit': implicit,
+      'signature': signature?.toJson(),
     });
     _setIfNotNull(json, 'location', location?.toJson());
     _setIfNotNull(json, 'code', code?.toJson());
@@ -4499,7 +4559,7 @@
 
   String toString() => '[Func ' //
       'id: ${id}, name: ${name}, owner: ${owner}, isStatic: ${isStatic}, ' //
-      'isConst: ${isConst}]';
+      'isConst: ${isConst}, implicit: ${implicit}, signature: ${signature}]';
 }
 
 /// `InstanceRef` is a reference to an `Instance`.
@@ -4578,13 +4638,34 @@
   @optional
   ClassRef? typeClass;
 
-  /// The parameterized class of a type parameter:
+  /// The parameterized class of a type parameter.
   ///
   /// Provided for instance kinds:
   ///  - TypeParameter
   @optional
   ClassRef? parameterizedClass;
 
+  /// The return type of a function.
+  ///
+  /// Provided for instance kinds:
+  ///  - FunctionType
+  @optional
+  InstanceRef? returnType;
+
+  /// The list of parameter types for a function.
+  ///
+  /// Provided for instance kinds:
+  ///  - FunctionType
+  @optional
+  List<Parameter>? parameters;
+
+  /// The type parameters for a function.
+  ///
+  /// Provided for instance kinds:
+  ///  - FunctionType
+  @optional
+  List<InstanceRef>? typeParameters;
+
   /// The pattern of a RegExp instance.
   ///
   /// The pattern is always an instance of kind String.
@@ -4640,6 +4721,9 @@
     this.name,
     this.typeClass,
     this.parameterizedClass,
+    this.returnType,
+    this.parameters,
+    this.typeParameters,
     this.pattern,
     this.closureFunction,
     this.closureContext,
@@ -4664,6 +4748,18 @@
     parameterizedClass =
         createServiceObject(json['parameterizedClass'], const ['ClassRef'])
             as ClassRef?;
+    returnType = createServiceObject(json['returnType'], const ['InstanceRef'])
+        as InstanceRef?;
+    parameters = json['parameters'] == null
+        ? null
+        : List<Parameter>.from(
+            createServiceObject(json['parameters'], const ['Parameter'])!
+                as List);
+    typeParameters = json['typeParameters'] == null
+        ? null
+        : List<InstanceRef>.from(
+            createServiceObject(json['typeParameters'], const ['InstanceRef'])!
+                as List);
     pattern = createServiceObject(json['pattern'], const ['InstanceRef'])
         as InstanceRef?;
     closureFunction =
@@ -4697,6 +4793,11 @@
     _setIfNotNull(json, 'name', name);
     _setIfNotNull(json, 'typeClass', typeClass?.toJson());
     _setIfNotNull(json, 'parameterizedClass', parameterizedClass?.toJson());
+    _setIfNotNull(json, 'returnType', returnType?.toJson());
+    _setIfNotNull(
+        json, 'parameters', parameters?.map((f) => f.toJson()).toList());
+    _setIfNotNull(json, 'typeParameters',
+        typeParameters?.map((f) => f.toJson()).toList());
     _setIfNotNull(json, 'pattern', pattern?.toJson());
     _setIfNotNull(json, 'closureFunction', closureFunction?.toJson());
     _setIfNotNull(json, 'closureContext', closureContext?.toJson());
@@ -4843,6 +4944,27 @@
   @optional
   ClassRef? parameterizedClass;
 
+  /// The return type of a function.
+  ///
+  /// Provided for instance kinds:
+  ///  - FunctionType
+  @optional
+  InstanceRef? returnType;
+
+  /// The list of parameter types for a function.
+  ///
+  /// Provided for instance kinds:
+  ///  - FunctionType
+  @optional
+  List<Parameter>? parameters;
+
+  /// The type parameters for a function.
+  ///
+  /// Provided for instance kinds:
+  ///  - FunctionType
+  @optional
+  List<InstanceRef>? typeParameters;
+
   /// The fields of this Instance.
   @optional
   List<BoundField>? fields;
@@ -5010,6 +5132,9 @@
     this.name,
     this.typeClass,
     this.parameterizedClass,
+    this.returnType,
+    this.parameters,
+    this.typeParameters,
     this.fields,
     this.elements,
     this.associations,
@@ -5050,6 +5175,18 @@
     parameterizedClass =
         createServiceObject(json['parameterizedClass'], const ['ClassRef'])
             as ClassRef?;
+    returnType = createServiceObject(json['returnType'], const ['InstanceRef'])
+        as InstanceRef?;
+    parameters = json['parameters'] == null
+        ? null
+        : List<Parameter>.from(
+            createServiceObject(json['parameters'], const ['Parameter'])!
+                as List);
+    typeParameters = json['typeParameters'] == null
+        ? null
+        : List<InstanceRef>.from(
+            createServiceObject(json['typeParameters'], const ['InstanceRef'])!
+                as List);
     fields = json['fields'] == null
         ? null
         : List<BoundField>.from(
@@ -5117,6 +5254,11 @@
     _setIfNotNull(json, 'name', name);
     _setIfNotNull(json, 'typeClass', typeClass?.toJson());
     _setIfNotNull(json, 'parameterizedClass', parameterizedClass?.toJson());
+    _setIfNotNull(json, 'returnType', returnType?.toJson());
+    _setIfNotNull(
+        json, 'parameters', parameters?.map((f) => f.toJson()).toList());
+    _setIfNotNull(json, 'typeParameters',
+        typeParameters?.map((f) => f.toJson()).toList());
     _setIfNotNull(json, 'fields', fields?.map((f) => f.toJson()).toList());
     _setIfNotNull(json, 'elements', elements?.map((f) => f.toJson()).toList());
     _setIfNotNull(
@@ -5447,18 +5589,19 @@
       'id: ${id}, number: ${number}, name: ${name}, isSystemIsolateGroup: ${isSystemIsolateGroup}]';
 }
 
-/// An `Isolate` object provides information about one isolate in the VM.
+/// An `IsolateGroup` object provides information about an isolate group in the
+/// VM.
 class IsolateGroup extends Response implements IsolateGroupRef {
   static IsolateGroup? parse(Map<String, dynamic>? json) =>
       json == null ? null : IsolateGroup._fromJson(json);
 
-  /// The id which is passed to the getIsolate RPC to reload this isolate.
+  /// The id which is passed to the getIsolateGroup RPC to reload this isolate.
   String? id;
 
   /// A numeric id for this isolate, represented as a string. Unique.
   String? number;
 
-  /// A name identifying this isolate. Not guaranteed to be unique.
+  /// A name identifying this isolate group. Not guaranteed to be unique.
   String? name;
 
   /// Specifies whether the isolate group was spawned by the VM or embedder for
@@ -6328,6 +6471,58 @@
   String toString() => '[Obj id: ${id}]';
 }
 
+/// A `Parameter` is a representation of a function parameter.
+///
+/// See [Instance].
+class Parameter {
+  static Parameter? parse(Map<String, dynamic>? json) =>
+      json == null ? null : Parameter._fromJson(json);
+
+  /// The type of the parameter.
+  InstanceRef? parameterType;
+
+  /// Represents whether or not this parameter is fixed or optional.
+  bool? fixed;
+
+  /// The name of a named optional parameter.
+  @optional
+  String? name;
+
+  /// Whether or not this named optional parameter is marked as required.
+  @optional
+  bool? required;
+
+  Parameter({
+    required this.parameterType,
+    required this.fixed,
+    this.name,
+    this.required,
+  });
+
+  Parameter._fromJson(Map<String, dynamic> json) {
+    parameterType =
+        createServiceObject(json['parameterType'], const ['InstanceRef'])
+            as InstanceRef?;
+    fixed = json['fixed'] ?? false;
+    name = json['name'];
+    required = json['required'];
+  }
+
+  Map<String, dynamic> toJson() {
+    final json = <String, dynamic>{};
+    json.addAll({
+      'parameterType': parameterType?.toJson(),
+      'fixed': fixed,
+    });
+    _setIfNotNull(json, 'name', name);
+    _setIfNotNull(json, 'required', required);
+    return json;
+  }
+
+  String toString() =>
+      '[Parameter parameterType: ${parameterType}, fixed: ${fixed}]';
+}
+
 /// A `PortList` contains a list of ports associated with some isolate.
 ///
 /// See [getPort].
@@ -7553,6 +7748,49 @@
       '[TypeArguments id: ${id}, name: ${name}, types: ${types}]';
 }
 
+/// A `TypeParameters` object represents the type argument vector for some
+/// uninstantiated generic type.
+class TypeParameters {
+  static TypeParameters? parse(Map<String, dynamic>? json) =>
+      json == null ? null : TypeParameters._fromJson(json);
+
+  /// The names of the type parameters.
+  List<String>? names;
+
+  /// The bounds set on each type parameter.
+  TypeArgumentsRef? bounds;
+
+  /// The default types for each type parameter.
+  TypeArgumentsRef? defaults;
+
+  TypeParameters({
+    required this.names,
+    required this.bounds,
+    required this.defaults,
+  });
+
+  TypeParameters._fromJson(Map<String, dynamic> json) {
+    names = List<String>.from(json['names']);
+    bounds = createServiceObject(json['bounds'], const ['TypeArgumentsRef'])
+        as TypeArgumentsRef?;
+    defaults = createServiceObject(json['defaults'], const ['TypeArgumentsRef'])
+        as TypeArgumentsRef?;
+  }
+
+  Map<String, dynamic> toJson() {
+    final json = <String, dynamic>{};
+    json.addAll({
+      'names': names?.map((f) => f).toList(),
+      'bounds': bounds?.toJson(),
+      'defaults': defaults?.toJson(),
+    });
+    return json;
+  }
+
+  String toString() =>
+      '[TypeParameters names: ${names}, bounds: ${bounds}, defaults: ${defaults}]';
+}
+
 /// The `UnresolvedSourceLocation` class is used to refer to an unresolved
 /// breakpoint location. As such, it is meant to approximate the final location
 /// of the breakpoint but it is not exact.
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 9ea0b77..5aad6b6 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: 7.1.0
+version: 7.1.1
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
 
diff --git a/pkg/vm_service/test/cpu_samples_stream_test.dart b/pkg/vm_service/test/cpu_samples_stream_test.dart
new file mode 100644
index 0000000..d6846ef
--- /dev/null
+++ b/pkg/vm_service/test/cpu_samples_stream_test.dart
@@ -0,0 +1,71 @@
+// 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:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+fib(int n) {
+  if (n <= 1) {
+    return n;
+  }
+  return fib(n - 1) + fib(n - 2);
+}
+
+void testMain() async {
+  int i = 10;
+  while (true) {
+    ++i;
+    // Create progressively deeper stacks to more quickly fill the sample
+    // buffer.
+    fib(i);
+  }
+}
+
+late StreamSubscription sub;
+
+var tests = <IsolateTest>[
+  (VmService service, IsolateRef isolate) async {
+    final completer = Completer<void>();
+    int count = 0;
+    int previousOrigin = 0;
+    sub = service.onProfilerEvent.listen((event) async {
+      count++;
+      expect(event.kind, EventKind.kCpuSamples);
+      expect(event.cpuSamples, isNotNull);
+      expect(event.cpuSamples!.samples!.isNotEmpty, true);
+      if (previousOrigin != 0) {
+        expect(
+          event.cpuSamples!.timeOriginMicros! >= previousOrigin,
+          true,
+        );
+      }
+      previousOrigin = event.cpuSamples!.timeOriginMicros!;
+
+      if (count == 2) {
+        await sub.cancel();
+        completer.complete();
+      }
+    });
+    await service.streamListen(EventStreams.kProfiler);
+
+    await completer.future;
+    await service.streamCancel(EventStreams.kProfiler);
+  },
+];
+
+main([args = const <String>[]]) async => await runIsolateTests(
+      args,
+      tests,
+      'cpu_samples_stream_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: [
+        '--sample-buffer-duration=1',
+        '--profile-vm',
+      ],
+    );
diff --git a/pkg/vm_service/test/library_dependency_test.dart b/pkg/vm_service/test/library_dependency_test.dart
index 5f308ef..5745ca1 100644
--- a/pkg/vm_service/test/library_dependency_test.dart
+++ b/pkg/vm_service/test/library_dependency_test.dart
@@ -8,7 +8,6 @@
 import 'package:test/test.dart';
 import 'package:vm_service/vm_service.dart';
 
-import 'common/service_test_common.dart';
 import 'common/test_helper.dart';
 
 export 'dart:io' show Socket hide SecureSocket;
diff --git a/pkg/vm_service/test/mark_main_isolate_as_system_isolate_test.dart b/pkg/vm_service/test/mark_main_isolate_as_system_isolate_test.dart
new file mode 100644
index 0000000..c69323d
--- /dev/null
+++ b/pkg/vm_service/test/mark_main_isolate_as_system_isolate_test.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.
+
+import 'dart:isolate';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart' as service;
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+foo(void _) async {
+  print('non system isolate started');
+  while (true) {}
+}
+
+testMain() async {
+  await Isolate.spawn<void>(foo, null);
+  print('started system isolate main');
+  while (true) {}
+}
+
+var tests = <VMTest>[
+  (service.VmService service) async {
+    final vm = await service.getVM();
+    expect(vm.isolates!.length, 1);
+    expect(vm.isolates!.first.name, 'foo');
+    expect(vm.systemIsolates!.length, greaterThanOrEqualTo(1));
+    expect(vm.systemIsolates!.where((e) => e.name == 'main').isNotEmpty, true);
+  }
+];
+
+main([args = const <String>[]]) => runVMTests(
+      args,
+      tests,
+      'mark_main_isolate_as_system_isolate_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: ['--mark-main-isolate-as-system-isolate'],
+    );
diff --git a/pkg/vm_service/test/regress_46559_test.dart b/pkg/vm_service/test/regress_46559_test.dart
new file mode 100644
index 0000000..84fceae
--- /dev/null
+++ b/pkg/vm_service/test/regress_46559_test.dart
@@ -0,0 +1,45 @@
+// 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:convert';
+import 'dart:developer';
+
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+Future<ServiceExtensionResponse> echo(
+    String method, Map<String, String> args) async {
+  print('In service extension');
+  return ServiceExtensionResponse.result(json.encode(args));
+}
+
+testMain() {
+  registerExtension('ext.foo', echo);
+  debugger();
+}
+
+final tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  resumeIsolate,
+  (VmService vm, IsolateRef isolateRef) async {
+    print('waiting for response');
+    final response = await vm.callServiceExtension(
+      'ext.foo',
+      isolateId: isolateRef.id!,
+      args: {'foo': 'bar'},
+    );
+    print('got response');
+    print(response.json);
+  },
+];
+
+main([args = const <String>[]]) async => await runIsolateTests(
+      args,
+      tests,
+      'regress_46559_test.dart',
+      testeeConcurrent: testMain,
+    );
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 2cf8fd8..844b1ff 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -200,7 +200,7 @@
       request.completeError(RPCError.parse(request.method, json['error']));
     } else {
       Map<String, dynamic> result = json['result'] as Map<String, dynamic>;
-      String type = result['type'];
+      String? type = result['type'];
       if (type == 'Sentinel') {
         request.completeError(SentinelException.parse(request.method, result));
       } else if (_typeFactories[type] == null) {
@@ -517,7 +517,7 @@
 
   if (json is List) {
     return json.map((e) => createServiceObject(e, expectedTypes)).toList();
-  } else if (json is Map) {
+  } else if (json is Map<String, dynamic>) {
     String? type = json['type'];
 
     // Not a Response type.
@@ -526,7 +526,7 @@
       if (expectedTypes.length == 1) {
         type = expectedTypes.first;
       } else {
-        return null;
+        return Response.parse(json);
       }
     } else if (_isNullInstance(json) && (!expectedTypes.contains('InstanceRef'))) {
       // Replace null instances with null when we don't expect an instance to
diff --git a/runtime/bin/dart_io_api_impl.cc b/runtime/bin/dart_io_api_impl.cc
index a890132..8ec2c1d 100644
--- a/runtime/bin/dart_io_api_impl.cc
+++ b/runtime/bin/dart_io_api_impl.cc
@@ -31,6 +31,7 @@
 
 void CleanupDartIo() {
   EventHandler::Stop();
+  Process::TerminateExitCodeHandler();
 #if !defined(DART_IO_SECURE_SOCKET_DISABLED)
   SSLFilter::Cleanup();
 #endif
diff --git a/runtime/bin/elf_loader.cc b/runtime/bin/elf_loader.cc
index 92d6685..43b152d 100644
--- a/runtime/bin/elf_loader.cc
+++ b/runtime/bin/elf_loader.cc
@@ -6,7 +6,6 @@
 #include <bin/file.h>
 #include <platform/elf.h>
 #include <platform/globals.h>
-#include <vm/bss_relocs.h>
 #include <vm/cpu.h>
 #include <vm/virtual_memory.h>
 
@@ -239,8 +238,6 @@
   const char* dynamic_string_table_ = nullptr;
   const dart::elf::Symbol* dynamic_symbol_table_ = nullptr;
   uword dynamic_symbol_count_ = 0;
-  uword* vm_bss_ = nullptr;
-  uword* isolate_bss_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(LoadedElf);
 };
@@ -468,20 +465,11 @@
       dynamic_symbol_table_ = reinterpret_cast<const dart::elf::Symbol*>(
           base_->start() + header.memory_offset);
       dynamic_symbol_count_ = header.file_size / sizeof(dart::elf::Symbol);
-    } else if (strcmp(name, ".bss") == 0) {
-      auto const bss_size =
-          (BSS::kVmEntryCount + BSS::kIsolateEntryCount) * kWordSize;
-      CHECK_ERROR(header.memory_offset != 0, ".bss must be loaded.");
-      CHECK_ERROR(header.file_size >= bss_size,
-                  ".bss does not have enough space.");
-      vm_bss_ = reinterpret_cast<uword*>(base_->start() + header.memory_offset);
-      isolate_bss_ = vm_bss_ + BSS::kVmEntryCount;
     }
   }
 
   CHECK_ERROR(dynamic_string_table_ != nullptr, "Couldn't find .dynstr.");
   CHECK_ERROR(dynamic_symbol_table_ != nullptr, "Couldn't find .dynsym.");
-  CHECK_ERROR(vm_bss_ != nullptr, "Couldn't find .bss.");
   return true;
 }
 
diff --git a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
index a4ad2d5..adcdc07 100644
--- a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
@@ -1080,4 +1080,36 @@
   Dart_DeletePersistentHandle_DL(closure_to_callback_);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Functions for testing @FfiNative.
+
+DART_EXPORT Dart_Handle GetRootLibraryUrl() {
+  Dart_Handle root_lib = Dart_RootLibrary();
+  Dart_Handle lib_url = Dart_LibraryUrl(root_lib);
+  ENSURE(!Dart_IsError(lib_url));
+  return lib_url;
+}
+
+intptr_t ReturnIntPtr(intptr_t x) {
+  return x;
+}
+
+static void* FfiNativeResolver(const char* name) {
+  if (strcmp(name, "ReturnIntPtr") == 0) {
+    return reinterpret_cast<void*>(ReturnIntPtr);
+  }
+  if (strcmp(name, "IsThreadInGenerated") == 0) {
+    return reinterpret_cast<void*>(IsThreadInGenerated);
+  }
+  // This should be unreachable in tests.
+  ENSURE(false);
+}
+
+DART_EXPORT void SetFfiNativeResolverForTest(Dart_Handle url) {
+  Dart_Handle library = Dart_LookupLibrary(url);
+  ENSURE(!Dart_IsError(library));
+  Dart_Handle result = Dart_SetFfiNativeResolver(library, &FfiNativeResolver);
+  ENSURE(!Dart_IsError(result));
+}
+
 }  // namespace dart
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 9610153..a288a79 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -762,6 +762,7 @@
 
   Dart_Isolate isolate = NULL;
 
+  IsolateData* isolate_data = nullptr;
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (!isolate_run_app_snapshot && (isolate_snapshot_data == NULL)) {
     const uint8_t* platform_kernel_buffer = NULL;
@@ -783,18 +784,18 @@
     // TODO(sivachandra): When the platform program is unavailable, check if
     // application kernel binary is self contained or an incremental binary.
     // Isolate should be created only if it is a self contained kernel binary.
-    auto isolate_data = new IsolateData(isolate_group_data);
+    isolate_data = new IsolateData(isolate_group_data);
     isolate = Dart_CreateIsolateGroupFromKernel(
         script_uri, name, platform_kernel_buffer, platform_kernel_buffer_size,
         flags, isolate_group_data, isolate_data, error);
   } else {
-    auto isolate_data = new IsolateData(isolate_group_data);
+    isolate_data = new IsolateData(isolate_group_data);
     isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
                                       isolate_snapshot_instructions, flags,
                                       isolate_group_data, isolate_data, error);
   }
 #else
-  auto isolate_data = new IsolateData(isolate_group_data);
+  isolate_data = new IsolateData(isolate_group_data);
   isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
                                     isolate_snapshot_instructions, flags,
                                     isolate_group_data, isolate_data, error);
@@ -802,6 +803,7 @@
 
   Dart_Isolate created_isolate = NULL;
   if (isolate == NULL) {
+    delete isolate_data;
     delete isolate_group_data;
   } else {
     created_isolate = IsolateSetupHelper(
@@ -932,6 +934,7 @@
   int exit_code = 0;
   Dart_IsolateFlags flags;
   Dart_IsolateFlagsInitialize(&flags);
+  flags.is_system_isolate = Options::mark_main_isolate_as_system_isolate();
 
   Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper(
       /* is_main_isolate */ true, script_name, "main",
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 8f9736d..66e6fde 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -46,7 +46,8 @@
   V(disable_dart_dev, disable_dart_dev)                                        \
   V(long_ssl_cert_evaluation, long_ssl_cert_evaluation)                        \
   V(bypass_trusting_system_roots, bypass_trusting_system_roots)                \
-  V(delayed_filewatch_callback, delayed_filewatch_callback)
+  V(delayed_filewatch_callback, delayed_filewatch_callback)                    \
+  V(mark_main_isolate_as_system_isolate, mark_main_isolate_as_system_isolate)
 
 // Boolean flags that have a short form.
 #define SHORT_BOOL_OPTIONS_LIST(V)                                             \
diff --git a/runtime/bin/platform.cc b/runtime/bin/platform.cc
index 1b04cfc..3f9ff26 100644
--- a/runtime/bin/platform.cc
+++ b/runtime/bin/platform.cc
@@ -12,6 +12,8 @@
 namespace dart {
 namespace bin {
 
+AcqRelAtomic<const char*> Platform::resolved_executable_name_ = nullptr;
+
 void FUNCTION_NAME(Platform_NumberOfProcessors)(Dart_NativeArguments args) {
   Dart_SetReturnValue(args, Dart_NewInteger(Platform::NumberOfProcessors()));
 }
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index bf2d6b1..a34db67 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -6,6 +6,8 @@
 #define RUNTIME_BIN_PLATFORM_H_
 
 #include "bin/builtin.h"
+
+#include "platform/atomic.h"
 #include "platform/globals.h"
 #include "platform/utils.h"
 
@@ -83,14 +85,19 @@
   }
   static const char* GetExecutableName();
   static const char* GetResolvedExecutableName() {
-    if (resolved_executable_name_ == NULL) {
+    if (resolved_executable_name_.load() == nullptr) {
       // Try to resolve the executable path using platform specific APIs.
       const char* resolved_name = Platform::ResolveExecutablePath();
-      if (resolved_name != NULL) {
-        resolved_executable_name_ = Utils::StrDup(resolved_name);
+      if (resolved_name != nullptr) {
+        char* resolved_name_copy = Utils::StrDup(resolved_name);
+        const char* expect_old_is_null = nullptr;
+        if (!resolved_executable_name_.compare_exchange_strong(
+                expect_old_is_null, resolved_name_copy)) {
+          free(resolved_name_copy);
+        }
       }
     }
-    return resolved_executable_name_;
+    return resolved_executable_name_.load();
   }
 
   // Stores and gets the flags passed to the executable.
@@ -108,8 +115,12 @@
  private:
   // The path to the executable.
   static const char* executable_name_;
+
   // The path to the resolved executable.
-  static char* resolved_executable_name_;
+  //
+  // We use require-release semantics to ensure initializing stores to the
+  // string are visible when the string becomes visible.
+  static AcqRelAtomic<const char*> resolved_executable_name_;
 
   static int script_index_;
   static char** argv_;  // VM flags are argv_[1 ... script_index_ - 1]
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index 6e5a34a..a9a5cda 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -22,7 +22,6 @@
 namespace bin {
 
 const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
 int Platform::script_index_ = 1;
 char** Platform::argv_ = NULL;
 
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
index 5c23480..47c1907 100644
--- a/runtime/bin/platform_fuchsia.cc
+++ b/runtime/bin/platform_fuchsia.cc
@@ -23,7 +23,6 @@
 namespace bin {
 
 const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
 int Platform::script_index_ = 1;
 char** Platform::argv_ = NULL;
 
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index d9443bb..adbfac1 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -21,7 +21,6 @@
 namespace bin {
 
 const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
 int Platform::script_index_ = 1;
 char** Platform::argv_ = NULL;
 
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 0479776..8083949 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -29,7 +29,6 @@
 namespace bin {
 
 const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
 int Platform::script_index_ = 1;
 char** Platform::argv_ = NULL;
 
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 59e1b74..515a569 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -25,7 +25,6 @@
 namespace bin {
 
 const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
 int Platform::script_index_ = 1;
 char** Platform::argv_ = NULL;
 
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 874d99a..16955e9 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -1109,6 +1109,7 @@
 }
 
 void ProcessInfoList::Init() {
+  active_processes_ = NULL;
   ASSERT(ProcessInfoList::mutex_ == nullptr);
   ProcessInfoList::mutex_ = new Mutex();
 }
@@ -1120,6 +1121,9 @@
 }
 
 void ExitCodeHandler::Init() {
+  running_ = false;
+  process_count_ = 0;
+  terminate_done_ = false;
   ASSERT(ExitCodeHandler::monitor_ == nullptr);
   ExitCodeHandler::monitor_ = new Monitor();
 }
@@ -1136,6 +1140,7 @@
 
   ASSERT(signal_mutex == nullptr);
   signal_mutex = new Mutex();
+  signal_handlers = NULL;
 
   ASSERT(Process::global_exit_code_mutex_ == nullptr);
   Process::global_exit_code_mutex_ = new Mutex();
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index f87c28c..de4433c 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -826,6 +826,7 @@
 void Process::ClearSignalHandlerByFd(intptr_t fd, Dart_Port port) {}
 
 void ProcessInfoList::Init() {
+  active_processes_ = NULL;
   ASSERT(ProcessInfoList::mutex_ == nullptr);
   ProcessInfoList::mutex_ = new Mutex();
 }
@@ -837,6 +838,9 @@
 }
 
 void ExitCodeHandler::Init() {
+  port_ = ZX_HANDLE_INVALID;
+  running_ = false;
+  terminate_done_ = false;
   ASSERT(ExitCodeHandler::monitor_ == nullptr);
   ExitCodeHandler::monitor_ = new Monitor();
 }
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index c20649e..95a9c86 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -1105,6 +1105,7 @@
 }
 
 void ProcessInfoList::Init() {
+  active_processes_ = NULL;
   ASSERT(ProcessInfoList::mutex_ == nullptr);
   ProcessInfoList::mutex_ = new Mutex();
 }
@@ -1116,6 +1117,9 @@
 }
 
 void ExitCodeHandler::Init() {
+  running_ = false;
+  process_count_ = 0;
+  terminate_done_ = false;
   ASSERT(ExitCodeHandler::monitor_ == nullptr);
   ExitCodeHandler::monitor_ = new Monitor();
 }
@@ -1132,6 +1136,7 @@
 
   ASSERT(signal_mutex == nullptr);
   signal_mutex = new Mutex();
+  signal_handlers = NULL;
 
   ASSERT(Process::global_exit_code_mutex_ == nullptr);
   Process::global_exit_code_mutex_ = new Mutex();
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index f20c589..6bbbfae 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -1141,6 +1141,7 @@
 }
 
 void ProcessInfoList::Init() {
+  active_processes_ = NULL;
   ASSERT(ProcessInfoList::mutex_ == nullptr);
   ProcessInfoList::mutex_ = new Mutex();
 }
@@ -1152,6 +1153,9 @@
 }
 
 void ExitCodeHandler::Init() {
+  running_ = false;
+  process_count_ = 0;
+  terminate_done_ = false;
   ASSERT(ExitCodeHandler::monitor_ == nullptr);
   ExitCodeHandler::monitor_ = new Monitor();
 }
@@ -1168,6 +1172,7 @@
 
   ASSERT(signal_mutex == nullptr);
   signal_mutex = new Mutex();
+  signal_handlers = NULL;
 
   ASSERT(Process::global_exit_code_mutex_ == nullptr);
   Process::global_exit_code_mutex_ = new Mutex();
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 1e3a02c..c34b003 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -1096,6 +1096,7 @@
 }
 
 void ProcessInfoList::Init() {
+  active_processes_ = nullptr;
   ASSERT(ProcessInfoList::mutex_ == nullptr);
   ProcessInfoList::mutex_ = new Mutex();
 }
@@ -1109,11 +1110,13 @@
 void Process::Init() {
   ProcessInfoList::Init();
 
+  signal_handlers = NULL;
   ASSERT(signal_mutex == nullptr);
   signal_mutex = new Mutex();
 
   ASSERT(initialized_mutex == nullptr);
   initialized_mutex = new Mutex();
+  load_attempted = false;
 
   ASSERT(Process::global_exit_code_mutex_ == nullptr);
   Process::global_exit_code_mutex_ = new Mutex();
diff --git a/runtime/bin/security_context_macos.cc b/runtime/bin/security_context_macos.cc
index 410a33b..357173d 100644
--- a/runtime/bin/security_context_macos.cc
+++ b/runtime/bin/security_context_macos.cc
@@ -162,15 +162,13 @@
   ScopedCFMutableArrayRef trusted_certs(CFArrayCreateMutable(NULL, 0, NULL));
   ASSERT(store != NULL);
 
-  if (store->objs != NULL) {
-    for (uintptr_t i = 0; i < sk_X509_OBJECT_num(store->objs); ++i) {
-      X509* ca = sk_X509_OBJECT_value(store->objs, i)->data.x509;
-      ScopedSecCertificateRef cert(CreateSecCertificateFromX509(ca));
-      if (cert == NULL) {
-        return ssl_verify_invalid;
-      }
-      CFArrayAppendValue(trusted_certs.get(), cert.release());
+  for (const X509_OBJECT* obj : X509_STORE_get0_objects(store)) {
+    X509* ca = X509_OBJECT_get0_X509(obj);
+    ScopedSecCertificateRef cert(CreateSecCertificateFromX509(ca));
+    if (cert == NULL) {
+      return ssl_verify_invalid;
     }
+    CFArrayAppendValue(trusted_certs.get(), cert.release());
   }
 
   // Generate a policy for validating chains for SSL.
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index ec52dad..1f39427c 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -130,13 +130,13 @@
         // created the socket. Feed same fd and store it into native field
         // of dart socket_object. Sockets here will share same fd but contain a
         // different port() through EventHandler_SendData.
-        Socket* socketfd = new Socket(os_socket->fd);
-        os_socket->ref_count++;
+        Socket* socketfd = new Socket(os_socket_same_addr->fd);
+        os_socket_same_addr->ref_count++;
         // We set as a side-effect the file descriptor on the dart
         // socket_object.
         Socket::ReuseSocketIdNativeField(socket_object, socketfd,
                                          Socket::kFinalizerListening);
-        InsertByFd(socketfd, os_socket);
+        InsertByFd(socketfd, os_socket_same_addr);
         return Dart_True();
       }
     }
@@ -234,13 +234,13 @@
         // created the socket. Feed the same fd and store it into the native
         // field of dart socket_object. Sockets here will share same fd but
         // contain a different port() through EventHandler_SendData.
-        Socket* socketfd = new Socket(os_socket->fd);
-        os_socket->ref_count++;
+        Socket* socketfd = new Socket(os_socket_same_addr->fd);
+        os_socket_same_addr->ref_count++;
         // We set as a side-effect the file descriptor on the dart
         // socket_object.
         Socket::ReuseSocketIdNativeField(socket_object, socketfd,
                                          Socket::kFinalizerListening);
-        InsertByFd(socketfd, os_socket);
+        InsertByFd(socketfd, os_socket_same_addr);
         return Dart_True();
       }
     }
diff --git a/runtime/docs/gc.md b/runtime/docs/gc.md
index 7857b3d..1daea96 100644
--- a/runtime/docs/gc.md
+++ b/runtime/docs/gc.md
@@ -6,7 +6,7 @@
 
 Object pointers refer either to immediate objects or heap objects, distinguished by a tag in the low bits of the pointer. The Dart VM has only one kind of immediate object, Smis (small integers), whose pointers have a tag of 0. Heap objects have a pointer tag of 1. The upper bits of a Smi pointer are its value, and the upper bits of a heap object pointer are the most significant bits of its address (the least significant bit is always 0 because heap objects always have greater than 2-byte alignment).
 
-A tag of 0 allows many operations to be performed on Smis without untagging and retagging. It also allows hiding aligned addresses to the C heap from the GC.
+A tag of 0 allows many operations to be performed on Smis without untagging and retagging.
 
 A tag of 1 has no penalty on heap object access because removing the tag can be folded into the offset used by load and store instructions.
 
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index 65d35ce..7d40798 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -371,6 +371,20 @@
  */
 DART_EXPORT int64_t Dart_TimelineGetMicros();
 
+/**
+ * Returns a raw timestamp in from the monotonic clock.
+ *
+ * \return A raw timestamp from the monotonic clock.
+ */
+DART_EXPORT int64_t Dart_TimelineGetTicks();
+
+/**
+ * Returns the frequency of the monotonic clock.
+ *
+ * \return The frequency of the monotonic clock.
+ */
+DART_EXPORT int64_t Dart_TimelineGetTicksFrequency();
+
 /** Timeline stream for Dart API calls */
 #define DART_TIMELINE_STREAM_API (1 << 0)
 /** Timeline stream for compiler events */
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc
index 748e056..53ff1e6 100644
--- a/runtime/lib/function.cc
+++ b/runtime/lib/function.cc
@@ -30,42 +30,52 @@
   return result.ptr();
 }
 
+static bool ClosureEqualsHelper(Zone* zone,
+                                const Closure& receiver,
+                                const Object& other) {
+  if (receiver.ptr() == other.ptr()) {
+    return true;
+  }
+  if (!other.IsClosure()) {
+    return false;
+  }
+  const auto& other_closure = Closure::Cast(other);
+  // Check that the delayed type argument vectors match.
+  if (receiver.delayed_type_arguments() !=
+      other_closure.delayed_type_arguments()) {
+    // Mismatches should only happen when a generic function is involved.
+    ASSERT(Function::Handle(receiver.function()).IsGeneric() ||
+           Function::Handle(other_closure.function()).IsGeneric());
+    return false;
+  }
+  // Closures that are not implicit instance closures are unique.
+  const auto& func_a = Function::Handle(zone, receiver.function());
+  if (!func_a.IsImplicitInstanceClosureFunction()) {
+    return false;
+  }
+  const auto& func_b = Function::Handle(zone, other_closure.function());
+  if (!func_b.IsImplicitInstanceClosureFunction()) {
+    return false;
+  }
+  // If the closure functions are not the same, check the function's name and
+  // owner, as multiple function objects could exist for the same function due
+  // to hot reload.
+  if (func_a.ptr() != func_b.ptr() &&
+      (func_a.name() != func_b.name() || func_a.Owner() != func_b.Owner())) {
+    return false;
+  }
+  // Check that the both receiver instances are the same.
+  const Context& context_a = Context::Handle(zone, receiver.context());
+  const Context& context_b = Context::Handle(zone, other_closure.context());
+  return context_a.At(0) == context_b.At(0);
+}
+
 DEFINE_NATIVE_ENTRY(Closure_equals, 0, 2) {
   const Closure& receiver =
       Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NATIVE_ARGUMENT(Instance, other, arguments->NativeArgAt(1));
   ASSERT(!other.IsNull());
-  // For implicit instance closures compare receiver instance and function's
-  // name and owner (multiple function objects could exist for the same
-  // function due to hot reload).
-  // Objects of other closure kinds are unique, so use identity comparison.
-  if (receiver.ptr() == other.ptr()) {
-    return Bool::True().ptr();
-  }
-  if (other.IsClosure()) {
-    const Function& func_a = Function::Handle(zone, receiver.function());
-    if (func_a.IsImplicitInstanceClosureFunction()) {
-      const Closure& other_closure = Closure::Cast(other);
-      const Function& func_b = Function::Handle(zone, other_closure.function());
-      if (func_b.IsImplicitInstanceClosureFunction()) {
-        const Context& context_a = Context::Handle(zone, receiver.context());
-        const Context& context_b =
-            Context::Handle(zone, other_closure.context());
-        ObjectPtr receiver_a = context_a.At(0);
-        ObjectPtr receiver_b = context_b.At(0);
-        if ((receiver_a == receiver_b) &&
-            (!func_a.IsGeneric() ||
-             receiver.delayed_type_arguments() ==
-                 other_closure.delayed_type_arguments()) &&
-            ((func_a.ptr() == func_b.ptr()) ||
-             ((func_a.name() == func_b.name()) &&
-              (func_a.Owner() == func_b.Owner())))) {
-          return Bool::True().ptr();
-        }
-      }
-    }
-  }
-  return Bool::False().ptr();
+  return Bool::Get(ClosureEqualsHelper(zone, receiver, other)).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Closure_computeHash, 0, 1) {
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 922ad2b..0b72f7f 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -19,7 +19,9 @@
 #include "vm/lockers.h"
 #include "vm/longjump.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/object.h"
+#include "vm/object_graph_copy.h"
 #include "vm/object_store.h"
 #include "vm/port.h"
 #include "vm/resolver.h"
@@ -111,10 +113,22 @@
     PortMap::PostMessage(
         Message::New(destination_port_id, obj.ptr(), Message::kNormalPriority));
   } else {
-    MessageWriter writer(can_send_any_object);
-    // TODO(turnidge): Throw an exception when the return value is false?
-    PortMap::PostMessage(writer.WriteMessage(obj, destination_port_id,
-                                             Message::kNormalPriority));
+    const bool same_group = FLAG_enable_isolate_groups &&
+                            PortMap::IsReceiverInThisIsolateGroup(
+                                destination_port_id, isolate->group());
+    if (same_group) {
+      const auto& copy = Object::Handle(CopyMutableObjectGraph(obj));
+      auto handle = isolate->group()->api_state()->AllocatePersistentHandle();
+      handle->set_ptr(copy.ptr());
+      std::unique_ptr<Message> message(
+          new Message(destination_port_id, handle, Message::kNormalPriority));
+      PortMap::PostMessage(std::move(message));
+    } else {
+      // TODO(turnidge): Throw an exception when the return value is false?
+      PortMap::PostMessage(WriteMessage(can_send_any_object, obj,
+                                        destination_port_id,
+                                        Message::kNormalPriority));
+    }
   }
   return Object::null();
 }
@@ -559,8 +573,7 @@
   if (message->IsRaw()) {
     return Instance::RawCast(message->raw_obj());
   } else {
-    MessageSnapshotReader reader(message, thread);
-    const Object& obj = Object::Handle(zone, reader.ReadObject());
+    const Object& obj = Object::Handle(zone, ReadMessage(thread, message));
     ASSERT(!obj.IsError());
     return Instance::RawCast(obj.ptr());
   }
@@ -601,7 +614,7 @@
     ASSERT(name != nullptr);
 
     auto group = state_->isolate_group();
-    if (!IsolateGroup::AreIsolateGroupsEnabled() || group == nullptr) {
+    if (!FLAG_enable_isolate_groups || group == nullptr) {
       RunHeavyweight(name);
     } else {
       RunLightweight(name);
@@ -621,6 +634,7 @@
 
     // Make a copy of the state's isolate flags and hand it to the callback.
     Dart_IsolateFlags api_flags = *(state_->isolate_flags());
+    api_flags.is_system_isolate = false;
     Dart_Isolate isolate = (create_group_callback)(
         state_->script_url(), name, nullptr, state_->package_config(),
         &api_flags, parent_isolate_->init_callback_data(), &error);
@@ -778,10 +792,10 @@
       isolate->message_handler()->increment_paused();
     }
     {
-      MessageWriter writer(/*can_send_any_object=*/false);
       // If parent isolate died, we ignore the fact that we cannot notify it.
-      PortMap::PostMessage(writer.WriteMessage(message, state_->parent_port(),
-                                               Message::kNormalPriority));
+      PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
+                                        message, state_->parent_port(),
+                                        Message::kNormalPriority));
     }
 
     return true;
@@ -852,9 +866,9 @@
       // serializable this will throw an exception.
       SerializedObjectBuffer message_buffer;
       {
-        MessageWriter writer(/* can_send_any_object = */ true);
-        message_buffer.set_message(writer.WriteMessage(
-            message, ILLEGAL_PORT, Message::kNormalPriority));
+        message_buffer.set_message(WriteMessage(
+            /* can_send_any_object */ true, message, ILLEGAL_PORT,
+            Message::kNormalPriority));
       }
 
       const char* utf8_package_config =
@@ -937,14 +951,14 @@
   SerializedObjectBuffer arguments_buffer;
   SerializedObjectBuffer message_buffer;
   {
-    MessageWriter writer(/* can_send_any_object = */ false);
-    arguments_buffer.set_message(
-        writer.WriteMessage(args, ILLEGAL_PORT, Message::kNormalPriority));
+    arguments_buffer.set_message(WriteMessage(/* can_send_any_object */ false,
+                                              args, ILLEGAL_PORT,
+                                              Message::kNormalPriority));
   }
   {
-    MessageWriter writer(/* can_send_any_object = */ false);
-    message_buffer.set_message(
-        writer.WriteMessage(message, ILLEGAL_PORT, Message::kNormalPriority));
+    message_buffer.set_message(WriteMessage(/* can_send_any_object */ false,
+                                            message, ILLEGAL_PORT,
+                                            Message::kNormalPriority));
   }
 
   // Canonicalize the uri with respect to the current isolate.
@@ -1017,9 +1031,8 @@
   // Ensure message writer (and it's resources, e.g. forwarding tables) are
   // cleaned up before handling interrupts.
   {
-    MessageWriter writer(false);
-    PortMap::PostMessage(
-        writer.WriteMessage(msg, port.Id(), Message::kOOBPriority));
+    PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, msg,
+                                      port.Id(), Message::kOOBPriority));
   }
 
   // Drain interrupts before running so any IMMEDIATE operations on the current
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 129caeb..10fc93a 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -6,6 +6,7 @@
 
 #include "lib/invocation_mirror.h"
 #include "vm/code_patcher.h"
+#include "vm/dart_entry.h"
 #include "vm/exceptions.h"
 #include "vm/heap/heap.h"
 #include "vm/native_entry.h"
@@ -91,57 +92,56 @@
   return instance.GetType(Heap::kNew);
 }
 
-DEFINE_NATIVE_ENTRY(Object_haveSameRuntimeType, 0, 2) {
-  const Instance& left =
-      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
-  const Instance& right =
-      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
-
+static bool HaveSameRuntimeTypeHelper(Zone* zone,
+                                      const Instance& left,
+                                      const Instance& right) {
   const intptr_t left_cid = left.GetClassId();
   const intptr_t right_cid = right.GetClassId();
 
   if (left_cid != right_cid) {
     if (IsIntegerClassId(left_cid)) {
-      return Bool::Get(IsIntegerClassId(right_cid)).ptr();
-    } else if (IsStringClassId(left_cid)) {
-      return Bool::Get(IsStringClassId(right_cid)).ptr();
-    } else if (IsTypeClassId(left_cid)) {
-      return Bool::Get(IsTypeClassId(right_cid)).ptr();
-    } else {
-      return Bool::False().ptr();
+      return IsIntegerClassId(right_cid);
     }
+    if (IsStringClassId(left_cid)) {
+      return IsStringClassId(right_cid);
+    }
+    if (IsTypeClassId(left_cid)) {
+      return IsTypeClassId(right_cid);
+    }
+    return false;
   }
 
-  const Class& cls = Class::Handle(left.clazz());
-  if (cls.IsClosureClass()) {
-    const Function& left_function =
-        Function::Handle(zone, Closure::Cast(left).function());
-    const Function& right_function =
-        Function::Handle(zone, Closure::Cast(right).function());
-    if (left_function.signature() == right_function.signature() &&
-        Closure::Cast(left).function_type_arguments() ==
-            Closure::Cast(right).function_type_arguments() &&
-        Closure::Cast(left).delayed_type_arguments() ==
-            Closure::Cast(right).delayed_type_arguments() &&
-        Closure::Cast(left).instantiator_type_arguments() ==
-            Closure::Cast(right).instantiator_type_arguments()) {
-      return Bool::True().ptr();
+  if (left_cid == kClosureCid) {
+    const auto& left_closure = Closure::Cast(left);
+    const auto& right_closure = Closure::Cast(right);
+    // If all the components that make up the instantiated signature are equal,
+    // then no need to instantiate.
+    if (left_closure.function_type_arguments() ==
+            right_closure.function_type_arguments() &&
+        left_closure.delayed_type_arguments() ==
+            right_closure.delayed_type_arguments() &&
+        left_closure.instantiator_type_arguments() ==
+            right_closure.instantiator_type_arguments()) {
+      const auto& left_fun = Function::Handle(zone, left_closure.function());
+      const auto& right_fun = Function::Handle(zone, right_closure.function());
+      if (left_fun.signature() == right_fun.signature()) {
+        return true;
+      }
     }
     const AbstractType& left_type =
         AbstractType::Handle(zone, left.GetType(Heap::kNew));
     const AbstractType& right_type =
         AbstractType::Handle(zone, right.GetType(Heap::kNew));
-    return Bool::Get(
-               left_type.IsEquivalent(right_type, TypeEquality::kSyntactical))
-        .ptr();
+    return left_type.IsEquivalent(right_type, TypeEquality::kSyntactical);
   }
 
+  const Class& cls = Class::Handle(zone, left.clazz());
   if (!cls.IsGeneric()) {
-    return Bool::True().ptr();
+    return true;
   }
 
   if (left.GetTypeArguments() == right.GetTypeArguments()) {
-    return Bool::True().ptr();
+    return true;
   }
   const TypeArguments& left_type_arguments =
       TypeArguments::Handle(zone, left.GetTypeArguments());
@@ -149,10 +149,17 @@
       TypeArguments::Handle(zone, right.GetTypeArguments());
   const intptr_t num_type_args = cls.NumTypeArguments();
   const intptr_t num_type_params = cls.NumTypeParameters();
-  return Bool::Get(left_type_arguments.IsSubvectorEquivalent(
-                       right_type_arguments, num_type_args - num_type_params,
-                       num_type_params, TypeEquality::kSyntactical))
-      .ptr();
+  return left_type_arguments.IsSubvectorEquivalent(
+      right_type_arguments, num_type_args - num_type_params, num_type_params,
+      TypeEquality::kSyntactical);
+}
+
+DEFINE_NATIVE_ENTRY(Object_haveSameRuntimeType, 0, 2) {
+  const Instance& left =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const Instance& right =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
+  return Bool::Get(HaveSameRuntimeTypeHelper(zone, left, right)).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Object_instanceOf, 0, 4) {
@@ -308,6 +315,11 @@
   return Object::null();
 }
 
+DEFINE_NATIVE_ENTRY(Internal_deoptimizeFunctionsOnStack, 0, 0) {
+  DeoptimizeFunctionsOnStack();
+  return Object::null();
+}
+
 static bool ExtractInterfaceTypeArgs(Zone* zone,
                                      const Class& instance_cls,
                                      const TypeArguments& instance_type_args,
@@ -457,6 +469,7 @@
   const Closure& closure =
       Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
   const Function& target = Function::Handle(zone, closure.function());
+  ASSERT(target.IsGeneric());  // No need to check bounds for non-generics.
   const TypeParameters& type_params =
       TypeParameters::Handle(zone, target.type_parameters());
   if (type_params.IsNull() || type_params.AllDynamicBounds()) {
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 44d6148..51ff5ea 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -11,6 +11,7 @@
 #include "vm/kernel_isolate.h"
 #include "vm/message.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
 #include "vm/port.h"
@@ -59,10 +60,10 @@
                 Smi::Handle(thread->zone(), Smi::New(Message::kServiceOOBMsg)));
 
   // Serialize message.
-  MessageWriter writer(false);
   // TODO(turnidge): Throw an exception when the return value is false?
-  bool result = PortMap::PostMessage(
-      writer.WriteMessage(message, sp.Id(), Message::kOOBPriority));
+  bool result = PortMap::PostMessage(WriteMessage(
+      /* can_send_any_object */ false, message, sp.Id(),
+      Message::kOOBPriority));
   return Bool::Get(result).ptr();
 #else
   return Object::null();
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index f3a26e7..7d83c71 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -4774,8 +4774,8 @@
 
   for (var i = 0; i < list.length; i++) {
     var v = list[i];
-    if ((v is Map) && _isServiceMap(v)) {
-      list[i] = owner!.getFromMap(v);
+    if ((v is Map) && owner != null && _isServiceMap(v)) {
+      list[i] = owner.getFromMap(v);
     } else if (v is List) {
       _upgradeList(v, owner);
     } else if (v is Map) {
diff --git a/runtime/observatory/tests/service/break_on_function_child_isolate_test.dart b/runtime/observatory/tests/service/break_on_function_child_isolate_test.dart
index bd471ac..3922aa6 100644
--- a/runtime/observatory/tests/service/break_on_function_child_isolate_test.dart
+++ b/runtime/observatory/tests/service/break_on_function_child_isolate_test.dart
@@ -1,7 +1,7 @@
 // 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=--verbose_debug --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--verbose_debug --enable-isolate-groups
 
 import 'break_on_function_many_child_isolates_test.dart';
 
diff --git a/runtime/observatory/tests/service/break_on_function_many_child_isolates_test.dart b/runtime/observatory/tests/service/break_on_function_many_child_isolates_test.dart
index 916e6f9..b0e75a8 100644
--- a/runtime/observatory/tests/service/break_on_function_many_child_isolates_test.dart
+++ b/runtime/observatory/tests/service/break_on_function_many_child_isolates_test.dart
@@ -1,7 +1,7 @@
 // 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=--verbose_debug --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--verbose_debug --enable-isolate-groups
 //
 // Tests breakpoint pausing and resuming with many isolates running and pausing
 // simultaneously.
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index 9a3eab8..d553138 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -14,15 +14,20 @@
 class _DummyClass {
   static var dummyVar = 11;
   final List<String> dummyList = new List<String>.filled(20, '');
-  void dummyFunction() {}
+  void dummyFunction(int a, [bool b = false]) {}
+  void dummyGenericFunction<K, V>(K a, {required V param}) {}
 }
 
 class _DummySubClass extends _DummyClass {}
 
+class _DummyGenericSubClass<T> extends _DummyClass {}
+
 void warmup() {
   // Silence analyzer.
   new _DummySubClass();
-  new _DummyClass().dummyFunction();
+  new _DummyGenericSubClass<Object>();
+  new _DummyClass().dummyFunction(0);
+  new _DummyClass().dummyGenericFunction<Object, dynamic>(0, param: 0);
 }
 
 @pragma("vm:entry-point")
@@ -43,6 +48,9 @@
 @pragma("vm:entry-point")
 getDummyClass() => new _DummyClass();
 
+@pragma("vm:entry-point")
+getDummyGenericSubClass() => new _DummyGenericSubClass<Object>();
+
 invoke(Isolate isolate, String selector) async {
   Map params = {
     'targetId': isolate.rootLibrary.id,
@@ -766,6 +774,7 @@
     expect(result['_finalized'], equals(true));
     expect(result['_implemented'], equals(false));
     expect(result['_patch'], equals(false));
+    expect(result['typeParameters'], isNull);
     expect(result['library']['type'], equals('@Library'));
     expect(result['location']['type'], equals('SourceLocation'));
     expect(result['super']['type'], equals('@Class'));
@@ -778,6 +787,30 @@
     expect(result['subclasses'][0]['type'], equals('@Class'));
   },
 
+  // generic class
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyGenericSubClass');
+    var params = {
+      'objectId': evalResult['class']['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Class'));
+    expect(result['id'], startsWith('classes/'));
+    expect(result['name'], equals('_DummyGenericSubClass'));
+    expect(result['_vmName'], startsWith('_DummyGenericSubClass@'));
+    expect(result['abstract'], equals(false));
+    expect(result['const'], equals(false));
+    expect(result['_finalized'], equals(true));
+    expect(result['_implemented'], equals(false));
+    expect(result['_patch'], equals(false));
+    expect(result['typeParameters'].length, equals(1));
+    expect(result['library']['type'], equals('@Library'));
+    expect(result['location']['type'], equals('SourceLocation'));
+    expect(result['super']['type'], equals('@Class'));
+    expect(result['interfaces'].length, isZero);
+  },
+
   // invalid class.
   (Isolate isolate) async {
     var params = {
@@ -851,6 +884,52 @@
     expect(result['_kind'], equals('RegularFunction'));
     expect(result['static'], equals(false));
     expect(result['const'], equals(false));
+    expect(result['implicit'], equals(false));
+    expect(result['signature']['typeParameters'], isNull);
+    expect(result['signature']['returnType'], isNotNull);
+    expect(result['signature']['parameters'].length, 3);
+    expect(result['signature']['parameters'][1]['parameterType']['name'],
+        equals('int'));
+    expect(result['signature']['parameters'][1]['fixed'], isTrue);
+    expect(result['signature']['parameters'][2]['parameterType']['name'],
+        equals('bool'));
+    expect(result['signature']['parameters'][2]['fixed'], isFalse);
+    expect(result['location']['type'], equals('SourceLocation'));
+    expect(result['code']['type'], equals('@Code'));
+    expect(result['_optimizable'], equals(true));
+    expect(result['_inlinable'], equals(true));
+    expect(result['_usageCounter'], isPositive);
+    expect(result['_optimizedCallSiteCount'], isZero);
+    expect(result['_deoptimizations'], isZero);
+  },
+
+  // generic function.
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var id = "${evalResult['class']['id']}/functions/dummyGenericFunction";
+    var params = {
+      'objectId': id,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Function'));
+    expect(result['id'], equals(id));
+    expect(result['name'], equals('dummyGenericFunction'));
+    expect(result['_kind'], equals('RegularFunction'));
+    expect(result['static'], equals(false));
+    expect(result['const'], equals(false));
+    expect(result['implicit'], equals(false));
+    expect(result['signature']['typeParameters'].length, 2);
+    expect(result['signature']['returnType'], isNotNull);
+    expect(result['signature']['parameters'].length, 3);
+    expect(result['signature']['parameters'][1]['parameterType']['name'],
+        isNotNull);
+    expect(result['signature']['parameters'][1]['fixed'], isTrue);
+    expect(result['signature']['parameters'][2]['parameterType']['name'],
+        isNotNull);
+    expect(result['signature']['parameters'][2]['name'], 'param');
+    expect(result['signature']['parameters'][2]['fixed'], isFalse);
+    expect(result['signature']['parameters'][2]['required'], isTrue);
     expect(result['location']['type'], equals('SourceLocation'));
     expect(result['code']['type'], equals('@Code'));
     expect(result['_optimizable'], equals(true));
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 75d1743..6bec5f1 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'], 48);
+    expect(result['minor'], 50);
     expect(result['_privateMajor'], 0);
     expect(result['_privateMinor'], 0);
   },
diff --git a/runtime/observatory_2/lib/src/service/object.dart b/runtime/observatory_2/lib/src/service/object.dart
index 2baf6d5..14d72c2 100644
--- a/runtime/observatory_2/lib/src/service/object.dart
+++ b/runtime/observatory_2/lib/src/service/object.dart
@@ -4784,7 +4784,7 @@
 
   for (var i = 0; i < list.length; i++) {
     var v = list[i];
-    if ((v is Map) && _isServiceMap(v)) {
+    if ((v is Map) && owner != null && _isServiceMap(v)) {
       list[i] = owner.getFromMap(v);
     } else if (v is List) {
       _upgradeList(v, owner);
diff --git a/runtime/observatory_2/tests/service_2/break_on_function_child_isolate_test.dart b/runtime/observatory_2/tests/service_2/break_on_function_child_isolate_test.dart
index bd471ac..3922aa6 100644
--- a/runtime/observatory_2/tests/service_2/break_on_function_child_isolate_test.dart
+++ b/runtime/observatory_2/tests/service_2/break_on_function_child_isolate_test.dart
@@ -1,7 +1,7 @@
 // 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=--verbose_debug --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--verbose_debug --enable-isolate-groups
 
 import 'break_on_function_many_child_isolates_test.dart';
 
diff --git a/runtime/observatory_2/tests/service_2/break_on_function_many_child_isolates_test.dart b/runtime/observatory_2/tests/service_2/break_on_function_many_child_isolates_test.dart
index b527cb54..e5b6b56 100644
--- a/runtime/observatory_2/tests/service_2/break_on_function_many_child_isolates_test.dart
+++ b/runtime/observatory_2/tests/service_2/break_on_function_many_child_isolates_test.dart
@@ -1,7 +1,7 @@
 // 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=--verbose_debug --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--verbose_debug --enable-isolate-groups
 //
 // Tests breakpoint pausing and resuming with many isolates running and pausing
 // simultaneously.
diff --git a/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
index 36b9c61..44912b3 100644
--- a/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
@@ -14,15 +14,20 @@
 class _DummyClass {
   static var dummyVar = 11;
   final List<String> dummyList = new List<String>.filled(20, null);
-  void dummyFunction() {}
+  void dummyFunction(int a, [bool b = false]) {}
+  void dummyGenericFunction<K, V>(K a, {V param}) {}
 }
 
 class _DummySubClass extends _DummyClass {}
 
+class _DummyGenericSubClass<T> extends _DummyClass {}
+
 void warmup() {
   // Silence analyzer.
   new _DummySubClass();
-  new _DummyClass().dummyFunction();
+  new _DummyGenericSubClass<Object>();
+  new _DummyClass().dummyFunction(0);
+  new _DummyClass().dummyGenericFunction<Object, dynamic>(0, param: 0);
 }
 
 @pragma("vm:entry-point")
@@ -43,6 +48,9 @@
 @pragma("vm:entry-point")
 getDummyClass() => new _DummyClass();
 
+@pragma("vm:entry-point")
+getDummyGenericSubClass() => new _DummyGenericSubClass<Object>();
+
 invoke(Isolate isolate, String selector) async {
   Map params = {
     'targetId': isolate.rootLibrary.id,
@@ -778,6 +786,30 @@
     expect(result['subclasses'][0]['type'], equals('@Class'));
   },
 
+  // generic class
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyGenericSubClass');
+    var params = {
+      'objectId': evalResult['class']['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Class'));
+    expect(result['id'], startsWith('classes/'));
+    expect(result['name'], equals('_DummyGenericSubClass'));
+    expect(result['_vmName'], startsWith('_DummyGenericSubClass@'));
+    expect(result['abstract'], equals(false));
+    expect(result['const'], equals(false));
+    expect(result['_finalized'], equals(true));
+    expect(result['_implemented'], equals(false));
+    expect(result['_patch'], equals(false));
+    expect(result['typeParameters'].length, equals(1));
+    expect(result['library']['type'], equals('@Library'));
+    expect(result['location']['type'], equals('SourceLocation'));
+    expect(result['super']['type'], equals('@Class'));
+    expect(result['interfaces'].length, isZero);
+  },
+
   // invalid class.
   (Isolate isolate) async {
     var params = {
@@ -851,6 +883,52 @@
     expect(result['_kind'], equals('RegularFunction'));
     expect(result['static'], equals(false));
     expect(result['const'], equals(false));
+    expect(result['implicit'], equals(false));
+    expect(result['signature']['typeParameters'], isNull);
+    expect(result['signature']['returnType'], isNotNull);
+    expect(result['signature']['parameters'].length, 3);
+    expect(result['signature']['parameters'][1]['parameterType']['name'],
+        equals('int'));
+    expect(result['signature']['parameters'][1]['fixed'], isTrue);
+    expect(result['signature']['parameters'][2]['parameterType']['name'],
+        equals('bool'));
+    expect(result['signature']['parameters'][2]['fixed'], isFalse);
+    expect(result['location']['type'], equals('SourceLocation'));
+    expect(result['code']['type'], equals('@Code'));
+    expect(result['_optimizable'], equals(true));
+    expect(result['_inlinable'], equals(true));
+    expect(result['_usageCounter'], isPositive);
+    expect(result['_optimizedCallSiteCount'], isZero);
+    expect(result['_deoptimizations'], isZero);
+  },
+
+  // generic function.
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var id = "${evalResult['class']['id']}/functions/dummyGenericFunction";
+    var params = {
+      'objectId': id,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Function'));
+    expect(result['id'], equals(id));
+    expect(result['name'], equals('dummyGenericFunction'));
+    expect(result['_kind'], equals('RegularFunction'));
+    expect(result['static'], equals(false));
+    expect(result['const'], equals(false));
+    expect(result['implicit'], equals(false));
+    expect(result['signature']['typeParameters'].length, 2);
+    expect(result['signature']['returnType'], isNotNull);
+    expect(result['signature']['parameters'].length, 3);
+    expect(result['signature']['parameters'][1]['parameterType']['name'],
+        isNotNull);
+    expect(result['signature']['parameters'][1]['fixed'], isTrue);
+    expect(result['signature']['parameters'][2]['parameterType']['name'],
+        isNotNull);
+    expect(result['signature']['parameters'][2]['name'], 'param');
+    expect(result['signature']['parameters'][2]['fixed'], isFalse);
+    expect(result['signature']['parameters'][2]['required'], isFalse);
     expect(result['location']['type'], equals('SourceLocation'));
     expect(result['code']['type'], equals('@Code'));
     expect(result['_optimizable'], equals(true));
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 443f8bb..31490bf 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(48));
+    expect(result['minor'], equals(50));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/platform/atomic.h b/runtime/platform/atomic.h
index 98bc900..390aa62 100644
--- a/runtime/platform/atomic.h
+++ b/runtime/platform/atomic.h
@@ -21,9 +21,16 @@
   T load(std::memory_order order = std::memory_order_relaxed) const {
     return value_.load(order);
   }
+  T load(std::memory_order order = std::memory_order_relaxed) const volatile {
+    return value_.load(order);
+  }
   void store(T arg, std::memory_order order = std::memory_order_relaxed) {
     value_.store(arg, order);
   }
+  void store(T arg,
+             std::memory_order order = std::memory_order_relaxed) volatile {
+    value_.store(arg, order);
+  }
 
   T fetch_add(T arg, std::memory_order order = std::memory_order_relaxed) {
     return value_.fetch_add(arg, order);
@@ -38,12 +45,22 @@
     return value_.fetch_and(arg, order);
   }
 
+  T exchange(T arg, std::memory_order order = std::memory_order_relaxed) {
+    return value_.exchange(arg, order);
+  }
+
   bool compare_exchange_weak(
       T& expected,  // NOLINT
       T desired,
       std::memory_order order = std::memory_order_relaxed) {
     return value_.compare_exchange_weak(expected, desired, order, order);
   }
+  bool compare_exchange_weak(
+      T& expected,  // NOLINT
+      T desired,
+      std::memory_order order = std::memory_order_relaxed) volatile {
+    return value_.compare_exchange_weak(expected, desired, order, order);
+  }
   bool compare_exchange_strong(
       T& expected,  // NOLINT
       T desired,
@@ -63,6 +80,10 @@
   }
   T operator+=(T arg) { return fetch_add(arg) + arg; }
   T operator-=(T arg) { return fetch_sub(arg) - arg; }
+  T& operator++() { return fetch_add(1) + 1; }
+  T& operator--() { return fetch_sub(1) - 1; }
+  T operator++(int) { return fetch_add(1); }
+  T operator--(int) { return fetch_sub(1); }
 
  private:
   std::atomic<T> value_;
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 42edc70..ed20219 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -334,6 +334,10 @@
 #error Automatic target architecture detection failed.
 #endif
 
+#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
+#define HAS_SMI_63_BITS 1
+#endif
+
 // Verify that host and target architectures match, we cannot
 // have a 64 bit Dart VM generating 32 bit code or vice-versa.
 #if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
diff --git a/runtime/platform/growable_array.h b/runtime/platform/growable_array.h
index c568862..34ad019 100644
--- a/runtime/platform/growable_array.h
+++ b/runtime/platform/growable_array.h
@@ -188,6 +188,10 @@
   // The content is uninitialized after calling it.
   void SetLength(intptr_t new_length);
 
+  // The content (if expanded) is uninitialized after calling it.
+  // The backing store (if expanded) will grow with by a power-of-2.
+  void Resize(intptr_t new_length);
+
   // Sort the array in place.
   inline void Sort(int compare(const T*, const T*));
 
@@ -211,9 +215,6 @@
   T* data_;
   Allocator* allocator_;  // Used to (re)allocate the array.
 
-  // Used for growing the array.
-  void Resize(intptr_t new_length);
-
   DISALLOW_COPY_AND_ASSIGN(BaseGrowableArray);
 };
 
diff --git a/runtime/platform/thread_sanitizer.h b/runtime/platform/thread_sanitizer.h
index e8c4fcf..baff130 100644
--- a/runtime/platform/thread_sanitizer.h
+++ b/runtime/platform/thread_sanitizer.h
@@ -15,6 +15,8 @@
 
 #if defined(USING_THREAD_SANITIZER)
 #define NO_SANITIZE_THREAD __attribute__((no_sanitize("thread")))
+extern "C" void __tsan_acquire(void* addr);
+extern "C" void __tsan_release(void* addr);
 #else
 #define NO_SANITIZE_THREAD
 #endif
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index a1d6b1b..84366eb 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -417,34 +417,26 @@
     return ((-0x20000000000000LL <= value) && (value <= 0x20000000000000LL));
   }
 
-  static constexpr uword NBitMaskUnsafe(uint32_t n) {
-    static_assert((sizeof(uword) * kBitsPerByte) == kBitsPerWord,
-                  "Unexpected uword size");
-    return n == kBitsPerWord ? std::numeric_limits<uword>::max()
-                             : (static_cast<uword>(1) << n) - 1;
-  }
-
   // The lowest n bits are 1, the others are 0.
-  static uword NBitMask(uint32_t n) {
-    ASSERT(n <= kBitsPerWord);
-    return NBitMaskUnsafe(n);
-  }
-
-  static word SignedNBitMask(uint32_t n) {
-    uword mask = NBitMask(n);
-    return bit_cast<word>(mask);
+  template <typename T = uword>
+  static constexpr T NBitMask(size_t n) {
+    using Unsigned = typename std::make_unsigned<T>::type;
+    constexpr size_t kBitsPerT = sizeof(T) * kBitsPerByte;
+    assert(n <= sizeof(T) * kBitsPerT);
+    return static_cast<T>(n == kBitsPerT ? std::numeric_limits<Unsigned>::max()
+                                         : (static_cast<Unsigned>(1) << n) - 1);
   }
 
   template <typename T = uword>
-  static T Bit(uint32_t n) {
+  static constexpr T Bit(size_t n) {
     ASSERT(n < sizeof(T) * kBitsPerByte);
     T bit = 1;
     return bit << n;
   }
 
   template <typename T>
-  DART_FORCE_INLINE static bool TestBit(T mask, intptr_t position) {
-    ASSERT(position < static_cast<intptr_t>(sizeof(T) * kBitsPerByte));
+  static constexpr bool TestBit(T mask, size_t position) {
+    ASSERT(position < sizeof(T) * kBitsPerByte);
     return ((mask >> position) & 1) != 0;
   }
 
diff --git a/runtime/tests/concurrency/run_stress_test_shards.dart b/runtime/tests/concurrency/run_stress_test_shards.dart
index 5b3d001..2d31d15 100644
--- a/runtime/tests/concurrency/run_stress_test_shards.dart
+++ b/runtime/tests/concurrency/run_stress_test_shards.dart
@@ -78,14 +78,12 @@
     '--disable-dart-dev',
     '--no-sound-null-safety',
     '--enable-isolate-groups',
-    '--experimental-enable-isolate-groups-jit',
     'runtime/tests/concurrency/generated_stress_test.dart.jit.dill',
   ]),
   JitTestRunner('out/ReleaseX64', [
     '--disable-dart-dev',
     '--no-sound-null-safety',
     '--enable-isolate-groups',
-    '--experimental-enable-isolate-groups-jit',
     '--no-inline-alloc',
     '--use-slow-path',
     '--deoptimize-on-runtime-call-every=3',
@@ -99,7 +97,6 @@
       '-Dshards=$tsanShards',
       '--no-sound-null-safety',
       '--enable-isolate-groups',
-      '--experimental-enable-isolate-groups-jit',
       'runtime/tests/concurrency/generated_stress_test.dart.jit.dill',
     ]),
   AotTestRunner('out/ReleaseX64', [
diff --git a/runtime/tests/concurrency/stress_test_list.json b/runtime/tests/concurrency/stress_test_list.json
index b8f2ae6..7981ebb 100644
--- a/runtime/tests/concurrency/stress_test_list.json
+++ b/runtime/tests/concurrency/stress_test_list.json
@@ -3061,7 +3061,6 @@
     "../../../tests/lib/async/stream_error_test.dart",
     "../../../tests/lib/async/stream_event_transformed_test.dart",
     "../../../tests/lib/async/stream_from_futures_test.dart",
-    "../../../tests/lib/async/stream_from_iterable_test.dart",
     "../../../tests/lib/async/stream_iterator_double_cancel_test.dart",
     "../../../tests/lib/async/stream_iterator_test.dart",
     "../../../tests/lib/async/stream_join_test.dart",
@@ -3260,7 +3259,6 @@
     "../../../tests/standalone/io/file_constructor_test.dart",
     "../../../tests/standalone/io/file_copy_test.dart",
     "../../../tests/standalone/io/file_create_test.dart",
-    "../../../tests/standalone/io/file_fuzz_test.dart",
     "../../../tests/standalone/io/file_non_ascii_sync_test.dart",
     "../../../tests/standalone/io/file_non_ascii_test.dart",
     "../../../tests/standalone/io/file_output_stream_test.dart",
@@ -3274,7 +3272,6 @@
     "../../../tests/standalone/io/file_system_uri_test.dart",
     "../../../tests/standalone/io/file_typed_data_test.dart",
     "../../../tests/standalone/io/file_windows_test.dart",
-    "../../../tests/standalone/io/file_write_as_test.dart",
     "../../../tests/standalone/io/file_write_only_test.dart",
     "../../../tests/standalone/io/gzip_format_exception_test.dart",
     "../../../tests/standalone/io/http_100_continue_test.dart",
@@ -3371,7 +3368,6 @@
     "../../../tests/standalone/io/stdin_has_terminal_test.dart",
     "../../../tests/standalone/io/stdout_stderr_terminal_test.dart",
     "../../../tests/standalone/io/system_encoding_test.dart",
-    "../../../tests/standalone/io/unix_socket_test.dart",
     "../../../tests/standalone/io/unknown_host_test.dart",
     "../../../tests/standalone/io/uri_platform_test.dart",
     "../../../tests/standalone/io/web_socket_compression_test.dart",
@@ -6408,7 +6404,6 @@
     "../../../tests/lib_2/async/stream_error_test.dart",
     "../../../tests/lib_2/async/stream_event_transformed_test.dart",
     "../../../tests/lib_2/async/stream_from_futures_test.dart",
-    "../../../tests/lib_2/async/stream_from_iterable_test.dart",
     "../../../tests/lib_2/async/stream_iterator_double_cancel_test.dart",
     "../../../tests/lib_2/async/stream_iterator_test.dart",
     "../../../tests/lib_2/async/stream_join_test.dart",
@@ -6595,7 +6590,6 @@
     "../../../tests/standalone_2/io/file_copy_test.dart",
     "../../../tests/standalone_2/io/file_create_test.dart",
     "../../../tests/standalone_2/io/file_error_test.dart",
-    "../../../tests/standalone_2/io/file_fuzz_test.dart",
     "../../../tests/standalone_2/io/file_non_ascii_sync_test.dart",
     "../../../tests/standalone_2/io/file_non_ascii_test.dart",
     "../../../tests/standalone_2/io/file_output_stream_test.dart",
@@ -6609,7 +6603,6 @@
     "../../../tests/standalone_2/io/file_system_uri_test.dart",
     "../../../tests/standalone_2/io/file_typed_data_test.dart",
     "../../../tests/standalone_2/io/file_windows_test.dart",
-    "../../../tests/standalone_2/io/file_write_as_test.dart",
     "../../../tests/standalone_2/io/file_write_only_test.dart",
     "../../../tests/standalone_2/io/gzip_format_exception_test.dart",
     "../../../tests/standalone_2/io/http_100_continue_test.dart",
@@ -6705,7 +6698,6 @@
     "../../../tests/standalone_2/io/stdin_has_terminal_test.dart",
     "../../../tests/standalone_2/io/stdout_stderr_terminal_test.dart",
     "../../../tests/standalone_2/io/system_encoding_test.dart",
-    "../../../tests/standalone_2/io/unix_socket_test.dart",
     "../../../tests/standalone_2/io/unknown_host_test.dart",
     "../../../tests/standalone_2/io/uri_platform_test.dart",
     "../../../tests/standalone_2/io/web_socket_compression_test.dart",
diff --git a/runtime/tests/vm/dart/deferred_isolate_test.dart b/runtime/tests/vm/dart/deferred_isolate_test.dart
index d056b31..94be755 100644
--- a/runtime/tests/vm/dart/deferred_isolate_test.dart
+++ b/runtime/tests/vm/dart/deferred_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // Verify deferred library status is per-isolate, not per-isolate-group.
 
-// VMOptions=--enable_isolate_groups --experimental_enable_isolate_groups_jit
+// VMOptions=--enable-isolate-groups
 
 import 'dart:async';
 import 'dart:isolate';
diff --git a/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart b/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart
index 83b7cc5..2fa4962 100644
--- a/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart
+++ b/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // SharedObjects=ffi_test_functions
 // VMOptions=
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:async';
 import 'dart:ffi';
@@ -14,13 +14,14 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
+import 'test_utils.dart' show isArtificialReloadMode;
 import '../../../../../tests/ffi/dylib_utils.dart';
 
-final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
 final bool isolateGroupsEnabled =
     Platform.executableArguments.contains('--enable-isolate-groups');
-final bool isolateGroupsEnabledInJIT = Platform.executableArguments
-    .contains('--experimental-enable-isolate-groups-jit');
+final bool usesDwarfStackTraces = Platform.executableArguments
+    .any((entry) => RegExp('--dwarf[-_]stack[-_]traces').hasMatch(entry));
+final bool hasSymbolicStackTraces = !usesDwarfStackTraces;
 final sdkRoot = Platform.script.resolve('../../../../../');
 
 class Isolate extends Opaque {}
@@ -173,8 +174,10 @@
     Expect.equals(10, accumulatedErrors.length);
     for (int i = 0; i < 10; ++i) {
       Expect.equals('error-$i', accumulatedErrors[i][0]);
-      Expect.isTrue(
-          accumulatedErrors[i][1].contains('childTestMultipleErrors'));
+      if (hasSymbolicStackTraces) {
+        Expect.isTrue(
+            accumulatedErrors[i][1].contains('childTestMultipleErrors'));
+      }
     }
 
     exit.close();
@@ -204,7 +207,9 @@
     await exit.first;
     Expect.equals(1, accumulatedErrors.length);
     Expect.equals('error-0', accumulatedErrors[0][0]);
-    Expect.contains('childTestFatalError', accumulatedErrors[0][1]);
+    if (hasSymbolicStackTraces) {
+      Expect.contains('childTestFatalError', accumulatedErrors[0][1]);
+    }
 
     exit.close();
     errors.close();
@@ -212,7 +217,7 @@
   });
 }
 
-Future testAot() async {
+Future testJitOrAot() async {
   await testIsolateData();
   await testMultipleErrors();
   await testFatalError();
@@ -226,34 +231,20 @@
     exception = e;
   }
   Expect.contains(
-      'Lightweight isolates are only implemented in AOT mode and need to be '
-      'explicitly enabled by passing --enable-isolate-groups.',
+      'Lightweight isolates need to be explicitly enabled by passing '
+      '--enable-isolate-groups.',
       exception.toString());
 }
 
-Future testJit() async {
-  dynamic exception;
-  try {
-    FfiBindings.createLightweightIsolate('debug-name', Pointer.fromAddress(0));
-  } catch (e) {
-    exception = e;
-  }
-  Expect.contains(
-      'Lightweight isolates are not yet ready in JIT mode', exception);
-}
-
 Future main(args) async {
   if (!isolateGroupsEnabled) {
     await testNotSupported();
     return;
   }
-  if (isAOT) {
-    await testAot();
-  } else {
-    if (isolateGroupsEnabledInJIT) {
-      await testJit();
-    } else {
-      await testNotSupported();
-    }
-  }
+
+  // This test should not run in hot-reload because of the way it is written
+  // (embedder related code written in Dart instead of C)
+  if (isArtificialReloadMode) return;
+
+  await testJitOrAot();
 }
diff --git a/runtime/tests/vm/dart/isolates/fast_object_copy2_test.dart b/runtime/tests/vm/dart/isolates/fast_object_copy2_test.dart
new file mode 100644
index 0000000..dc684dc
--- /dev/null
+++ b/runtime/tests/vm/dart/isolates/fast_object_copy2_test.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.
+
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+
+// The tests in this file will only succeed when isolate groups are enabled
+// (hence the VMOptions above).
+
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import 'package:expect/expect.dart';
+
+import 'fast_object_copy_test.dart'
+    show UserObject, SendReceiveTestBase, notAllocatableInTLAB;
+
+// When running with isolate groups enabled, we can share all of the following
+// objects.
+final sharableObjects = [
+  1,
+  0xffffffffffffffff,
+  'foobar',
+  const UserObject(1, 1.2, ''),
+  (() {
+    final rp = ReceivePort();
+    final sp = rp.sendPort;
+    rp.close();
+    return sp;
+  })(),
+  const [1, 2, 3],
+  const {1: 1, 2: 2, 3: 2},
+  const {1, 2, 3},
+  RegExp('a'),
+  Isolate.current.pauseCapability,
+  Int32x4(1, 2, 3, 4),
+];
+
+class SendReceiveTest extends SendReceiveTestBase {
+  Future runTests() async {
+    await testSharable();
+    await testSharable2();
+  }
+
+  Future testSharable() async {
+    final sharableObjectsCopy = await sendReceive([
+      ...sharableObjects,
+    ]);
+    Expect.notIdentical(sharableObjects, sharableObjectsCopy);
+    for (int i = 0; i < sharableObjects.length; ++i) {
+      Expect.identical(sharableObjects[i], sharableObjectsCopy[i]);
+    }
+  }
+
+  Future testSharable2() async {
+    final sharableObjectsCopy = await sendReceive([
+      notAllocatableInTLAB,
+      ...sharableObjects,
+    ]);
+    Expect.notIdentical(sharableObjects, sharableObjectsCopy);
+    Expect.equals(
+        notAllocatableInTLAB[0], (sharableObjectsCopy[0] as Uint8List)[0]);
+    for (int i = 0; i < sharableObjects.length; ++i) {
+      Expect.identical(sharableObjects[i], sharableObjectsCopy[i + 1]);
+    }
+  }
+}
+
+main() async {
+  await SendReceiveTest().run();
+}
diff --git a/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart b/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart
index 00297e1..dda2b0f 100644
--- a/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart
+++ b/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart
@@ -3,7 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation --verify-store-buffer
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation --verify-store-buffer
 
 // The tests in this file are particularly for an implementation that tries to
 // allocate the entire graph in BFS order using a fast new space allocation
@@ -28,7 +31,7 @@
 final Uint8List largeInternalTypedData = Uint8List(20 * 1024 * 1024)..[0] = 42;
 
 final Uint8List smallExternalTypedData =
-    File(Platform.script.toFilePath()).readAsBytesSync();
+    File(Platform.script.toFilePath()).readAsBytesSync()..[0] = 21;
 final Uint8List smallExternalTypedDataView =
     Uint8List.view(smallExternalTypedData.buffer, 1, 1);
 
@@ -110,6 +113,17 @@
     }
     return;
   }
+  if (a is Set) {
+    final cb = b as Set;
+    Expect.equals(a.length, cb.length);
+    final aKeys = a.toList();
+    final cbKeys = cb.toList();
+    for (int i = 0; i < a.length; ++i) {
+      expectGraphsMatch(aKeys[i], cbKeys[i]);
+    }
+    return;
+  }
+
   throw 'Unexpected object encountered when matching object graphs $a / $b';
 }
 
@@ -126,6 +140,8 @@
 class HashIncrementer {
   static int counter = 1;
 
+  const HashIncrementer();
+
   int get hashCode => counter++;
   bool operator ==(other) => identical(this, other);
 }
@@ -135,21 +151,39 @@
   final double unboxedDouble;
   final dynamic slot;
 
-  UserObject(this.unboxedInt, this.unboxedDouble, this.slot);
+  const UserObject(this.unboxedInt, this.unboxedDouble, this.slot);
 }
 
-class SendReceiveTest {
+abstract class SendReceiveTestBase {
   late final ReceivePort receivePort;
   late final SendPort sendPort;
   late final StreamIterator si;
 
-  SendReceiveTest();
+  SendReceiveTestBase();
 
   Future run() async {
     receivePort = ReceivePort();
     sendPort = receivePort.sendPort;
     si = StreamIterator(receivePort);
 
+    await runTests();
+
+    si.cancel();
+    receivePort.close();
+    print('done');
+  }
+
+  Future runTests();
+
+  Future<T> sendReceive<T>(T graph) async {
+    sendPort.send(graph);
+    Expect.isTrue(await si.moveNext());
+    return si.current as T;
+  }
+}
+
+class SendReceiveTest extends SendReceiveTestBase {
+  Future runTests() async {
     await testTransferrable();
     await testTransferrable2();
     await testTransferrable3();
@@ -161,6 +195,7 @@
     await testExternalTypedData3();
     await testExternalTypedData4();
     await testExternalTypedData5();
+    await testExternalTypedData6();
 
     await testInternalTypedDataView();
     await testInternalTypedDataView2();
@@ -172,16 +207,18 @@
     await testExternalTypedDataView3();
     await testExternalTypedDataView4();
 
+    await testArray();
+
     await testMapRehash();
     await testMapRehash2();
     await testMapRehash3();
 
+    await testSetRehash();
+    await testSetRehash2();
+    await testSetRehash3();
+
     await testFastOnly();
     await testSlowOnly();
-
-    si.cancel();
-    receivePort.close();
-    print('done');
   }
 
   Future testTransferrable() async {
@@ -293,6 +330,16 @@
     }
   }
 
+  Future testExternalTypedData6() async {
+    print('testExternalTypedData6');
+    final etd = await sendReceive([
+      smallExternalTypedData,
+      largeExternalTypedData,
+    ]);
+    Expect.equals(21, etd[0][0]);
+    Expect.equals(42, etd[1][0]);
+  }
+
   Future testInternalTypedDataView() async {
     print('testInternalTypedDataView');
     final graph = [
@@ -401,6 +448,18 @@
     expectGraphsMatch(graph, copiedGraph);
   }
 
+  Future testArray() async {
+    print('testArray');
+    final oldSpace = List<dynamic>.filled(1024 * 1024, null);
+    final newSpace = UserObject(1, 1.1, 'foobar');
+    oldSpace[0] = newSpace;
+    final oldSpaceCopy = await sendReceive(oldSpace);
+    final newSpaceCopy = oldSpaceCopy[0] as UserObject;
+    Expect.equals(newSpaceCopy.unboxedInt, 1);
+    Expect.equals(newSpaceCopy.unboxedDouble, 1.1);
+    Expect.equals(newSpaceCopy.slot, 'foobar');
+  }
+
   Future testMapRehash() async {
     print('testMapRehash');
     final obj = Object();
@@ -437,7 +496,7 @@
 
   Future testMapRehash3() async {
     print('testMapRehash3');
-    final obj = HashIncrementer();
+    final obj = const HashIncrementer();
     final graph = [
       {obj: 42},
       notAllocatableInTLAB,
@@ -448,6 +507,57 @@
     Expect.equals(before + 1, after);
   }
 
+  Future testSetRehash() async {
+    print('testSetRehash');
+    final obj = Object();
+    final graph = <dynamic>[
+      <dynamic>{42, obj},
+      notAllocatableInTLAB,
+    ];
+    final result = await sendReceive(graph);
+    final setCopy = result[0] as Set<dynamic>;
+    Expect.equals(2, setCopy.length);
+    Expect.equals(42, setCopy.toList()[0]);
+    Expect.equals(obj.runtimeType, setCopy.toList()[1].runtimeType);
+    Expect.notIdentical(obj, setCopy.toList()[1]);
+    Expect.notEquals(
+        identityHashCode(obj), identityHashCode(setCopy.toList()[1]));
+    Expect.isFalse(setCopy.contains(obj));
+    Expect.isTrue(setCopy.contains(setCopy.toList()[1]));
+  }
+
+  Future testSetRehash2() async {
+    print('testSetRehash2');
+    final obj = Object();
+    final graph = <dynamic>[
+      notAllocatableInTLAB,
+      <dynamic>{42, obj},
+    ];
+    final result = await sendReceive(graph);
+    final setCopy = result[1] as Set<dynamic>;
+    Expect.equals(2, setCopy.length);
+    Expect.equals(42, setCopy.toList()[0]);
+    Expect.equals(obj.runtimeType, setCopy.toList()[1].runtimeType);
+    Expect.notIdentical(obj, setCopy.toList()[1]);
+    Expect.notEquals(
+        identityHashCode(obj), identityHashCode(setCopy.toList()[1]));
+    Expect.isFalse(setCopy.contains(obj));
+    Expect.isTrue(setCopy.contains(setCopy.toList()[1]));
+  }
+
+  Future testSetRehash3() async {
+    print('testSetRehash3');
+    final obj = const HashIncrementer();
+    final graph = [
+      {42, obj},
+      notAllocatableInTLAB,
+    ];
+    final int before = HashIncrementer.counter;
+    await sendReceive(graph);
+    final int after = HashIncrementer.counter;
+    Expect.equals(before + 1, after);
+  }
+
   Future testFastOnly() async {
     print('testFastOnly');
     for (final smallPrimitive in smallPrimitives) {
@@ -469,12 +579,6 @@
           await sendReceive([notAllocatableInTLAB, smallContainer]));
     }
   }
-
-  Future<T> sendReceive<T>(T graph) async {
-    sendPort.send(graph);
-    Expect.isTrue(await si.moveNext());
-    return si.current as T;
-  }
 }
 
 main() async {
diff --git a/runtime/tests/vm/dart/isolates/fibonacci_call_ig_test.dart b/runtime/tests/vm/dart/isolates/fibonacci_call_ig_test.dart
index 61acb3f..946cbf9 100644
--- a/runtime/tests/vm/dart/isolates/fibonacci_call_ig_test.dart
+++ b/runtime/tests/vm/dart/isolates/fibonacci_call_ig_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
@@ -12,6 +12,12 @@
 import 'test_utils.dart';
 
 main(args) async {
+  // We don't run this test in our artificial hot reload mode, because it would
+  // create too many threads during the reload (one per isolate), which can
+  // cause this test or other concurrently executing tests to Crash due to
+  // unability of `pthread_create` to create a new thread.
+  if (isArtificialReloadMode) return;
+
   final rp = ReceivePort();
   final int n = 18;
   await spawnInDetachedGroup(fibonacciRecursive, [rp.sendPort, n]);
diff --git a/runtime/tests/vm/dart/isolates/fibonacci_call_test.dart b/runtime/tests/vm/dart/isolates/fibonacci_call_test.dart
index a8ba640..daf66e0 100644
--- a/runtime/tests/vm/dart/isolates/fibonacci_call_test.dart
+++ b/runtime/tests/vm/dart/isolates/fibonacci_call_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
@@ -11,6 +11,12 @@
 import 'test_utils.dart';
 
 main(args) async {
+  // We don't run this test in our artificial hot reload mode, because it would
+  // create too many threads during the reload (one per isolate), which can
+  // cause this test or other concurrently executing tests to Crash due to
+  // unability of `pthread_create` to create a new thread.
+  if (isArtificialReloadMode) return;
+
   final rp = ReceivePort();
   final int n = 18;
   await Isolate.spawn(fibonacciRecursive, [rp.sendPort, n]);
diff --git a/runtime/tests/vm/dart/isolates/limited_active_mutator_test.dart b/runtime/tests/vm/dart/isolates/limited_active_mutator_test.dart
index 147dfdc..f56e9ee 100644
--- a/runtime/tests/vm/dart/isolates/limited_active_mutator_test.dart
+++ b/runtime/tests/vm/dart/isolates/limited_active_mutator_test.dart
@@ -2,8 +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.
 
-// SharedObjects=ffi_test_functions
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification --disable-thread-pool-limit
+// VMOptions=--enable-isolate-groups --disable-heap-verification --disable-thread-pool-limit
 
 import 'dart:async';
 import 'dart:math' as math;
diff --git a/runtime/tests/vm/dart/isolates/regress_46539_test.dart b/runtime/tests/vm/dart/isolates/regress_46539_test.dart
new file mode 100644
index 0000000..0814f0d
--- /dev/null
+++ b/runtime/tests/vm/dart/isolates/regress_46539_test.dart
@@ -0,0 +1,83 @@
+// 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=--optimization-filter=foo --enable-isolate-groups --no-use-osr --optimization-counter-threshold=1 --deterministic
+
+// Important: This is a regression test for a concurrency issue, if this test
+// is flaky it is essentially failing!
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:_internal' show VMInternalsForTesting;
+
+import 'package:expect/expect.dart';
+
+const int isolateCount = 3;
+const int deoptIsolateId = 0;
+const int polyIsolateId = 1;
+
+final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
+
+main() async {
+  // This test will cause deoptimizations (via helper in `dart:_internal`) and
+  // does therefore not run in AOT.
+  if (isAOT) return;
+
+  final onExit = ReceivePort();
+  final onError = ReceivePort()
+    ..listen((error) {
+      print('Error: $error');
+      exitCode = 250;
+    });
+  for (int i = 0; i < isolateCount; ++i) {
+    await Isolate.spawn(isolate, i,
+        onExit: onExit.sendPort, onError: onError.sendPort);
+  }
+  final onExits = StreamIterator(onExit);
+  for (int i = 0; i < isolateCount; ++i) {
+    Expect.isTrue(await onExits.moveNext());
+  }
+  onExits.cancel();
+  onError.close();
+}
+
+final globalA = A();
+final globalB = B();
+
+isolate(int isolateId) {
+  final A a = isolateId == polyIsolateId ? globalB : globalA;
+  if (isolateId == polyIsolateId) {
+    // We start deopting after 1 second.
+    sleep(500000);
+  }
+
+  // This runs in unoptimized mode and will therefore do switchable calls.
+  final sw = Stopwatch()..start();
+  while (sw.elapsedMicroseconds < 2000000) {
+    a.foo(isolateId);
+    a.foo(isolateId);
+    a.foo(isolateId);
+    a.foo(isolateId);
+  }
+}
+
+class A {
+  @pragma('vm:never-inline')
+  foo(int isolateId) {
+    if (isolateId == deoptIsolateId) {
+      VMInternalsForTesting.deoptimizeFunctionsOnStack();
+    }
+  }
+}
+
+class B implements A {
+  @pragma('vm:never-inline')
+  foo(int isolateId) {}
+}
+
+void sleep(int us) {
+  final sw = Stopwatch()..start();
+  while (sw.elapsedMicroseconds < us);
+}
diff --git a/runtime/tests/vm/dart/isolates/ring_gc_sendAndExit_test.dart b/runtime/tests/vm/dart/isolates/ring_gc_sendAndExit_test.dart
index e461273..74b6820 100644
--- a/runtime/tests/vm/dart/isolates/ring_gc_sendAndExit_test.dart
+++ b/runtime/tests/vm/dart/isolates/ring_gc_sendAndExit_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:math' as math;
 
@@ -12,6 +12,12 @@
 import 'test_utils.dart';
 
 main(args) async {
+  // We don't run this test in our artificial hot reload mode, because it would
+  // create too many threads during the reload (one per isolate), which can
+  // cause this test or other concurrently executing tests to Crash due to
+  // unability of `pthread_create` to create a new thread.
+  if (isArtificialReloadMode) return;
+
   final int numIsolates = (isDebugMode || isSimulator) ? 100 : 5000;
 
   // Spawn ring of 1k isolates.
diff --git a/runtime/tests/vm/dart/isolates/ring_gc_test.dart b/runtime/tests/vm/dart/isolates/ring_gc_test.dart
index f0ecbc1..c27cd6c 100644
--- a/runtime/tests/vm/dart/isolates/ring_gc_test.dart
+++ b/runtime/tests/vm/dart/isolates/ring_gc_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:async';
 import 'dart:math' as math;
@@ -31,6 +31,12 @@
 }
 
 main(args) async {
+  // We don't run this test in our artificial hot reload mode, because it would
+  // create too many threads during the reload (one per isolate), which can
+  // cause this test or other concurrently executing tests to Crash due to
+  // unability of `pthread_create` to create a new thread.
+  if (isArtificialReloadMode) return;
+
   final int numIsolates = (isDebugMode || isSimulator) ? 100 : 1000;
 
   // Spawn ring of 1k isolates.
diff --git a/runtime/tests/vm/dart/isolates/spawn_function_test.dart b/runtime/tests/vm/dart/isolates/spawn_function_test.dart
index bbbb2f5..f2a85ea 100644
--- a/runtime/tests/vm/dart/isolates/spawn_function_test.dart
+++ b/runtime/tests/vm/dart/isolates/spawn_function_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/runtime/tests/vm/dart/isolates/sum_recursive_call_ig_test.dart b/runtime/tests/vm/dart/isolates/sum_recursive_call_ig_test.dart
index 6b7eecb..915c102 100644
--- a/runtime/tests/vm/dart/isolates/sum_recursive_call_ig_test.dart
+++ b/runtime/tests/vm/dart/isolates/sum_recursive_call_ig_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
diff --git a/runtime/tests/vm/dart/isolates/sum_recursive_call_test.dart b/runtime/tests/vm/dart/isolates/sum_recursive_call_test.dart
index 3b18008..89bcc58 100644
--- a/runtime/tests/vm/dart/isolates/sum_recursive_call_test.dart
+++ b/runtime/tests/vm/dart/isolates/sum_recursive_call_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
diff --git a/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_ig_test.dart b/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_ig_test.dart
index bf1d165..a3fb967 100644
--- a/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_ig_test.dart
+++ b/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_ig_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
diff --git a/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_test.dart b/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_test.dart
index a98cc91..866b8f3 100644
--- a/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_test.dart
+++ b/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
diff --git a/runtime/tests/vm/dart/isolates/test_utils.dart b/runtime/tests/vm/dart/isolates/test_utils.dart
index b2ffa76..4e1d929 100644
--- a/runtime/tests/vm/dart/isolates/test_utils.dart
+++ b/runtime/tests/vm/dart/isolates/test_utils.dart
@@ -10,6 +10,10 @@
 
 final bool isDebugMode = Platform.script.path.contains('Debug');
 final bool isSimulator = Platform.script.path.contains('SIM');
+final bool isArtificialReloadMode = Platform.executableArguments.any((arg) => [
+      '--hot-reload-rollback-test-mode',
+      '--hot-reload-test-mode'
+    ].contains(arg));
 
 // Implements recursive summation:
 //   sum(n) => n == 0 ? 0
diff --git a/runtime/tests/vm/dart/isolates/thread_pool_test.dart b/runtime/tests/vm/dart/isolates/thread_pool_test.dart
index aadf1f6..3d689ca 100644
--- a/runtime/tests/vm/dart/isolates/thread_pool_test.dart
+++ b/runtime/tests/vm/dart/isolates/thread_pool_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // SharedObjects=ffi_test_functions
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:async';
 import 'dart:ffi';
diff --git a/runtime/tests/vm/dart/issue_31959_31960_test.dart b/runtime/tests/vm/dart/issue_31959_31960_test.dart
index 5cb830f..3ca1be2 100644
--- a/runtime/tests/vm/dart/issue_31959_31960_test.dart
+++ b/runtime/tests/vm/dart/issue_31959_31960_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:async';
diff --git a/runtime/tests/vm/dart/sendandexit_test.dart b/runtime/tests/vm/dart/sendandexit_test.dart
index 91d2bac..58e02c6 100644
--- a/runtime/tests/vm/dart/sendandexit_test.dart
+++ b/runtime/tests/vm/dart/sendandexit_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 //
 // Validates functionality of sendAndExit.
 
diff --git a/runtime/tests/vm/dart/spawn_infinite_loop_test.dart b/runtime/tests/vm/dart/spawn_infinite_loop_test.dart
index 79409e0..3a89e80 100644
--- a/runtime/tests/vm/dart/spawn_infinite_loop_test.dart
+++ b/runtime/tests/vm/dart/spawn_infinite_loop_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/runtime/tests/vm/dart/transferable_test.dart b/runtime/tests/vm/dart/transferable_test.dart
index 6a9c4f0..2f5155a 100644
--- a/runtime/tests/vm/dart/transferable_test.dart
+++ b/runtime/tests/vm/dart/transferable_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test that validates that transferables are faster than regular typed data.
diff --git a/runtime/tests/vm/dart/transferable_throws_test.dart b/runtime/tests/vm/dart/transferable_throws_test.dart
index 67cba0a..201c020 100644
--- a/runtime/tests/vm/dart/transferable_throws_test.dart
+++ b/runtime/tests/vm/dart/transferable_throws_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test that ensures correct exceptions are thrown when misusing
@@ -11,7 +11,6 @@
 import 'dart:async';
 import 'dart:collection';
 import 'dart:core';
-import 'dart:io';
 import 'dart:isolate';
 import 'dart:typed_data';
 import 'dart:math';
diff --git a/runtime/tests/vm/dart_2/deferred_isolate_test.dart b/runtime/tests/vm/dart_2/deferred_isolate_test.dart
index d056b31..94be755 100644
--- a/runtime/tests/vm/dart_2/deferred_isolate_test.dart
+++ b/runtime/tests/vm/dart_2/deferred_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // Verify deferred library status is per-isolate, not per-isolate-group.
 
-// VMOptions=--enable_isolate_groups --experimental_enable_isolate_groups_jit
+// VMOptions=--enable-isolate-groups
 
 import 'dart:async';
 import 'dart:isolate';
diff --git a/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart b/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart
index 4611883..8b92de1 100644
--- a/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // SharedObjects=ffi_test_functions
 // VMOptions=
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:async';
 import 'dart:ffi';
@@ -14,13 +14,14 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
+import 'test_utils.dart' show isArtificialReloadMode;
 import '../../../../../tests/ffi/dylib_utils.dart';
 
-final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
 final bool isolateGroupsEnabled =
     Platform.executableArguments.contains('--enable-isolate-groups');
-final bool isolateGroupsEnabledInJIT = Platform.executableArguments
-    .contains('--experimental-enable-isolate-groups-jit');
+final bool usesDwarfStackTraces = Platform.executableArguments
+    .any((entry) => RegExp('--dwarf[-_]stack[-_]traces').hasMatch(entry));
+final bool hasSymbolicStackTraces = !usesDwarfStackTraces;
 final sdkRoot = Platform.script.resolve('../../../../../');
 
 class Isolate extends Opaque {}
@@ -173,8 +174,10 @@
     Expect.equals(10, accumulatedErrors.length);
     for (int i = 0; i < 10; ++i) {
       Expect.equals('error-$i', accumulatedErrors[i][0]);
-      Expect.isTrue(
-          accumulatedErrors[i][1].contains('childTestMultipleErrors'));
+      if (hasSymbolicStackTraces) {
+        Expect.isTrue(
+            accumulatedErrors[i][1].contains('childTestMultipleErrors'));
+      }
     }
 
     exit.close();
@@ -204,7 +207,9 @@
     await exit.first;
     Expect.equals(1, accumulatedErrors.length);
     Expect.equals('error-0', accumulatedErrors[0][0]);
-    Expect.contains('childTestFatalError', accumulatedErrors[0][1]);
+    if (hasSymbolicStackTraces) {
+      Expect.contains('childTestFatalError', accumulatedErrors[0][1]);
+    }
 
     exit.close();
     errors.close();
@@ -212,7 +217,7 @@
   });
 }
 
-Future testAot() async {
+Future testJitOrAot() async {
   await testIsolateData();
   await testMultipleErrors();
   await testFatalError();
@@ -226,34 +231,20 @@
     exception = e;
   }
   Expect.contains(
-      'Lightweight isolates are only implemented in AOT mode and need to be '
-      'explicitly enabled by passing --enable-isolate-groups.',
+      'Lightweight isolates need to be explicitly enabled by passing '
+      '--enable-isolate-groups.',
       exception.toString());
 }
 
-Future testJit() async {
-  dynamic exception;
-  try {
-    FfiBindings.createLightweightIsolate('debug-name', Pointer.fromAddress(0));
-  } catch (e) {
-    exception = e;
-  }
-  Expect.contains(
-      'Lightweight isolates are not yet ready in JIT mode', exception);
-}
-
 Future main(args) async {
   if (!isolateGroupsEnabled) {
     await testNotSupported();
     return;
   }
-  if (isAOT) {
-    await testAot();
-  } else {
-    if (isolateGroupsEnabledInJIT) {
-      await testJit();
-    } else {
-      await testNotSupported();
-    }
-  }
+
+  // This test should not run in hot-reload because of the way it is written
+  // (embedder related code written in Dart instead of C)
+  if (isArtificialReloadMode) return;
+
+  await testJitOrAot();
 }
diff --git a/runtime/tests/vm/dart_2/isolates/fast_object_copy2_test.dart b/runtime/tests/vm/dart_2/isolates/fast_object_copy2_test.dart
new file mode 100644
index 0000000..dc684dc
--- /dev/null
+++ b/runtime/tests/vm/dart_2/isolates/fast_object_copy2_test.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.
+
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+
+// The tests in this file will only succeed when isolate groups are enabled
+// (hence the VMOptions above).
+
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import 'package:expect/expect.dart';
+
+import 'fast_object_copy_test.dart'
+    show UserObject, SendReceiveTestBase, notAllocatableInTLAB;
+
+// When running with isolate groups enabled, we can share all of the following
+// objects.
+final sharableObjects = [
+  1,
+  0xffffffffffffffff,
+  'foobar',
+  const UserObject(1, 1.2, ''),
+  (() {
+    final rp = ReceivePort();
+    final sp = rp.sendPort;
+    rp.close();
+    return sp;
+  })(),
+  const [1, 2, 3],
+  const {1: 1, 2: 2, 3: 2},
+  const {1, 2, 3},
+  RegExp('a'),
+  Isolate.current.pauseCapability,
+  Int32x4(1, 2, 3, 4),
+];
+
+class SendReceiveTest extends SendReceiveTestBase {
+  Future runTests() async {
+    await testSharable();
+    await testSharable2();
+  }
+
+  Future testSharable() async {
+    final sharableObjectsCopy = await sendReceive([
+      ...sharableObjects,
+    ]);
+    Expect.notIdentical(sharableObjects, sharableObjectsCopy);
+    for (int i = 0; i < sharableObjects.length; ++i) {
+      Expect.identical(sharableObjects[i], sharableObjectsCopy[i]);
+    }
+  }
+
+  Future testSharable2() async {
+    final sharableObjectsCopy = await sendReceive([
+      notAllocatableInTLAB,
+      ...sharableObjects,
+    ]);
+    Expect.notIdentical(sharableObjects, sharableObjectsCopy);
+    Expect.equals(
+        notAllocatableInTLAB[0], (sharableObjectsCopy[0] as Uint8List)[0]);
+    for (int i = 0; i < sharableObjects.length; ++i) {
+      Expect.identical(sharableObjects[i], sharableObjectsCopy[i + 1]);
+    }
+  }
+}
+
+main() async {
+  await SendReceiveTest().run();
+}
diff --git a/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart b/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart
index 9737462..87bbc26 100644
--- a/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart
@@ -3,7 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation --verify-store-buffer
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation --verify-store-buffer
 
 // The tests in this file are particularly for an implementation that tries to
 // allocate the entire graph in BFS order using a fast new space allocation
@@ -28,7 +31,7 @@
 final Uint8List largeInternalTypedData = Uint8List(20 * 1024 * 1024)..[0] = 42;
 
 final Uint8List smallExternalTypedData =
-    File(Platform.script.toFilePath()).readAsBytesSync();
+    File(Platform.script.toFilePath()).readAsBytesSync()..[0] = 21;
 final Uint8List smallExternalTypedDataView =
     Uint8List.view(smallExternalTypedData.buffer, 1, 1);
 
@@ -110,6 +113,17 @@
     }
     return;
   }
+  if (a is Set) {
+    final cb = b as Set;
+    Expect.equals(a.length, cb.length);
+    final aKeys = a.toList();
+    final cbKeys = cb.toList();
+    for (int i = 0; i < a.length; ++i) {
+      expectGraphsMatch(aKeys[i], cbKeys[i]);
+    }
+    return;
+  }
+
   throw 'Unexpected object encountered when matching object graphs $a / $b';
 }
 
@@ -126,6 +140,8 @@
 class HashIncrementer {
   static int counter = 1;
 
+  const HashIncrementer();
+
   int get hashCode => counter++;
   bool operator ==(other) => identical(this, other);
 }
@@ -135,21 +151,39 @@
   final double unboxedDouble;
   final dynamic slot;
 
-  UserObject(this.unboxedInt, this.unboxedDouble, this.slot);
+  const UserObject(this.unboxedInt, this.unboxedDouble, this.slot);
 }
 
-class SendReceiveTest {
+abstract class SendReceiveTestBase {
   ReceivePort receivePort;
   SendPort sendPort;
   StreamIterator si;
 
-  SendReceiveTest();
+  SendReceiveTestBase();
 
   Future run() async {
     receivePort = ReceivePort();
     sendPort = receivePort.sendPort;
     si = StreamIterator(receivePort);
 
+    await runTests();
+
+    si.cancel();
+    receivePort.close();
+    print('done');
+  }
+
+  Future runTests();
+
+  Future<T> sendReceive<T>(T graph) async {
+    sendPort.send(graph);
+    Expect.isTrue(await si.moveNext());
+    return si.current as T;
+  }
+}
+
+class SendReceiveTest extends SendReceiveTestBase {
+  Future runTests() async {
     await testTransferrable();
     await testTransferrable2();
     await testTransferrable3();
@@ -161,6 +195,7 @@
     await testExternalTypedData3();
     await testExternalTypedData4();
     await testExternalTypedData5();
+    await testExternalTypedData6();
 
     await testInternalTypedDataView();
     await testInternalTypedDataView2();
@@ -172,16 +207,18 @@
     await testExternalTypedDataView3();
     await testExternalTypedDataView4();
 
+    await testArray();
+
     await testMapRehash();
     await testMapRehash2();
     await testMapRehash3();
 
+    await testSetRehash();
+    await testSetRehash2();
+    await testSetRehash3();
+
     await testFastOnly();
     await testSlowOnly();
-
-    si.cancel();
-    receivePort.close();
-    print('done');
   }
 
   Future testTransferrable() async {
@@ -293,6 +330,16 @@
     }
   }
 
+  Future testExternalTypedData6() async {
+    print('testExternalTypedData6');
+    final etd = await sendReceive([
+      smallExternalTypedData,
+      largeExternalTypedData,
+    ]);
+    Expect.equals(21, etd[0][0]);
+    Expect.equals(42, etd[1][0]);
+  }
+
   Future testInternalTypedDataView() async {
     print('testInternalTypedDataView');
     final graph = [
@@ -401,6 +448,18 @@
     expectGraphsMatch(graph, copiedGraph);
   }
 
+  Future testArray() async {
+    print('testArray');
+    final oldSpace = List<dynamic>.filled(1024 * 1024, null);
+    final newSpace = UserObject(1, 1.1, 'foobar');
+    oldSpace[0] = newSpace;
+    final oldSpaceCopy = await sendReceive(oldSpace);
+    final newSpaceCopy = oldSpaceCopy[0] as UserObject;
+    Expect.equals(newSpaceCopy.unboxedInt, 1);
+    Expect.equals(newSpaceCopy.unboxedDouble, 1.1);
+    Expect.equals(newSpaceCopy.slot, 'foobar');
+  }
+
   Future testMapRehash() async {
     print('testMapRehash');
     final obj = Object();
@@ -437,7 +496,7 @@
 
   Future testMapRehash3() async {
     print('testMapRehash3');
-    final obj = HashIncrementer();
+    final obj = const HashIncrementer();
     final graph = [
       {obj: 42},
       notAllocatableInTLAB,
@@ -448,6 +507,57 @@
     Expect.equals(before + 1, after);
   }
 
+  Future testSetRehash() async {
+    print('testSetRehash');
+    final obj = Object();
+    final graph = <dynamic>[
+      <dynamic>{42, obj},
+      notAllocatableInTLAB,
+    ];
+    final result = await sendReceive(graph);
+    final setCopy = result[0] as Set<dynamic>;
+    Expect.equals(2, setCopy.length);
+    Expect.equals(42, setCopy.toList()[0]);
+    Expect.equals(obj.runtimeType, setCopy.toList()[1].runtimeType);
+    Expect.notIdentical(obj, setCopy.toList()[1]);
+    Expect.notEquals(
+        identityHashCode(obj), identityHashCode(setCopy.toList()[1]));
+    Expect.isFalse(setCopy.contains(obj));
+    Expect.isTrue(setCopy.contains(setCopy.toList()[1]));
+  }
+
+  Future testSetRehash2() async {
+    print('testSetRehash2');
+    final obj = Object();
+    final graph = <dynamic>[
+      notAllocatableInTLAB,
+      <dynamic>{42, obj},
+    ];
+    final result = await sendReceive(graph);
+    final setCopy = result[1] as Set<dynamic>;
+    Expect.equals(2, setCopy.length);
+    Expect.equals(42, setCopy.toList()[0]);
+    Expect.equals(obj.runtimeType, setCopy.toList()[1].runtimeType);
+    Expect.notIdentical(obj, setCopy.toList()[1]);
+    Expect.notEquals(
+        identityHashCode(obj), identityHashCode(setCopy.toList()[1]));
+    Expect.isFalse(setCopy.contains(obj));
+    Expect.isTrue(setCopy.contains(setCopy.toList()[1]));
+  }
+
+  Future testSetRehash3() async {
+    print('testSetRehash3');
+    final obj = const HashIncrementer();
+    final graph = [
+      {42, obj},
+      notAllocatableInTLAB,
+    ];
+    final int before = HashIncrementer.counter;
+    await sendReceive(graph);
+    final int after = HashIncrementer.counter;
+    Expect.equals(before + 1, after);
+  }
+
   Future testFastOnly() async {
     print('testFastOnly');
     for (final smallPrimitive in smallPrimitives) {
@@ -469,12 +579,6 @@
           await sendReceive([notAllocatableInTLAB, smallContainer]));
     }
   }
-
-  Future<T> sendReceive<T>(T graph) async {
-    sendPort.send(graph);
-    Expect.isTrue(await si.moveNext());
-    return si.current as T;
-  }
 }
 
 main() async {
diff --git a/runtime/tests/vm/dart_2/isolates/fibonacci_call_ig_test.dart b/runtime/tests/vm/dart_2/isolates/fibonacci_call_ig_test.dart
index 61acb3f..946cbf9 100644
--- a/runtime/tests/vm/dart_2/isolates/fibonacci_call_ig_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/fibonacci_call_ig_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
@@ -12,6 +12,12 @@
 import 'test_utils.dart';
 
 main(args) async {
+  // We don't run this test in our artificial hot reload mode, because it would
+  // create too many threads during the reload (one per isolate), which can
+  // cause this test or other concurrently executing tests to Crash due to
+  // unability of `pthread_create` to create a new thread.
+  if (isArtificialReloadMode) return;
+
   final rp = ReceivePort();
   final int n = 18;
   await spawnInDetachedGroup(fibonacciRecursive, [rp.sendPort, n]);
diff --git a/runtime/tests/vm/dart_2/isolates/fibonacci_call_test.dart b/runtime/tests/vm/dart_2/isolates/fibonacci_call_test.dart
index a8ba640..daf66e0 100644
--- a/runtime/tests/vm/dart_2/isolates/fibonacci_call_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/fibonacci_call_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
@@ -11,6 +11,12 @@
 import 'test_utils.dart';
 
 main(args) async {
+  // We don't run this test in our artificial hot reload mode, because it would
+  // create too many threads during the reload (one per isolate), which can
+  // cause this test or other concurrently executing tests to Crash due to
+  // unability of `pthread_create` to create a new thread.
+  if (isArtificialReloadMode) return;
+
   final rp = ReceivePort();
   final int n = 18;
   await Isolate.spawn(fibonacciRecursive, [rp.sendPort, n]);
diff --git a/runtime/tests/vm/dart_2/isolates/limited_active_mutator_test.dart b/runtime/tests/vm/dart_2/isolates/limited_active_mutator_test.dart
index 147dfdc..f56e9ee 100644
--- a/runtime/tests/vm/dart_2/isolates/limited_active_mutator_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/limited_active_mutator_test.dart
@@ -2,8 +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.
 
-// SharedObjects=ffi_test_functions
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification --disable-thread-pool-limit
+// VMOptions=--enable-isolate-groups --disable-heap-verification --disable-thread-pool-limit
 
 import 'dart:async';
 import 'dart:math' as math;
diff --git a/runtime/tests/vm/dart_2/isolates/regress_46539_test.dart b/runtime/tests/vm/dart_2/isolates/regress_46539_test.dart
new file mode 100644
index 0000000..0814f0d
--- /dev/null
+++ b/runtime/tests/vm/dart_2/isolates/regress_46539_test.dart
@@ -0,0 +1,83 @@
+// 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=--optimization-filter=foo --enable-isolate-groups --no-use-osr --optimization-counter-threshold=1 --deterministic
+
+// Important: This is a regression test for a concurrency issue, if this test
+// is flaky it is essentially failing!
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:_internal' show VMInternalsForTesting;
+
+import 'package:expect/expect.dart';
+
+const int isolateCount = 3;
+const int deoptIsolateId = 0;
+const int polyIsolateId = 1;
+
+final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
+
+main() async {
+  // This test will cause deoptimizations (via helper in `dart:_internal`) and
+  // does therefore not run in AOT.
+  if (isAOT) return;
+
+  final onExit = ReceivePort();
+  final onError = ReceivePort()
+    ..listen((error) {
+      print('Error: $error');
+      exitCode = 250;
+    });
+  for (int i = 0; i < isolateCount; ++i) {
+    await Isolate.spawn(isolate, i,
+        onExit: onExit.sendPort, onError: onError.sendPort);
+  }
+  final onExits = StreamIterator(onExit);
+  for (int i = 0; i < isolateCount; ++i) {
+    Expect.isTrue(await onExits.moveNext());
+  }
+  onExits.cancel();
+  onError.close();
+}
+
+final globalA = A();
+final globalB = B();
+
+isolate(int isolateId) {
+  final A a = isolateId == polyIsolateId ? globalB : globalA;
+  if (isolateId == polyIsolateId) {
+    // We start deopting after 1 second.
+    sleep(500000);
+  }
+
+  // This runs in unoptimized mode and will therefore do switchable calls.
+  final sw = Stopwatch()..start();
+  while (sw.elapsedMicroseconds < 2000000) {
+    a.foo(isolateId);
+    a.foo(isolateId);
+    a.foo(isolateId);
+    a.foo(isolateId);
+  }
+}
+
+class A {
+  @pragma('vm:never-inline')
+  foo(int isolateId) {
+    if (isolateId == deoptIsolateId) {
+      VMInternalsForTesting.deoptimizeFunctionsOnStack();
+    }
+  }
+}
+
+class B implements A {
+  @pragma('vm:never-inline')
+  foo(int isolateId) {}
+}
+
+void sleep(int us) {
+  final sw = Stopwatch()..start();
+  while (sw.elapsedMicroseconds < us);
+}
diff --git a/runtime/tests/vm/dart_2/isolates/reload_active_stack_test.dart b/runtime/tests/vm/dart_2/isolates/reload_active_stack_test.dart
index 22cdd91..615941f 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_active_stack_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_active_stack_test.dart
@@ -2,11 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-import 'dart:io';
-import 'dart:convert';
-
-import 'package:path/path.dart' as path;
 import 'package:expect/expect.dart';
 
 import 'reload_utils.dart';
diff --git a/runtime/tests/vm/dart_2/isolates/reload_many_isolates_live_and_die_test.dart b/runtime/tests/vm/dart_2/isolates/reload_many_isolates_live_and_die_test.dart
index 335bbb5..7cfcbf6 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_many_isolates_live_and_die_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_many_isolates_live_and_die_test.dart
@@ -3,10 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io';
-import 'dart:convert';
 
-import 'package:path/path.dart' as path;
 import 'package:expect/expect.dart';
 
 import 'reload_utils.dart';
diff --git a/runtime/tests/vm/dart_2/isolates/reload_many_isolates_test.dart b/runtime/tests/vm/dart_2/isolates/reload_many_isolates_test.dart
index 67fe65c..70ff30c 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_many_isolates_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_many_isolates_test.dart
@@ -2,11 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-import 'dart:io';
-import 'dart:convert';
-
-import 'package:path/path.dart' as path;
 import 'package:expect/expect.dart';
 
 import 'reload_utils.dart';
diff --git a/runtime/tests/vm/dart_2/isolates/reload_no_active_stack_test.dart b/runtime/tests/vm/dart_2/isolates/reload_no_active_stack_test.dart
index 93f06de2..a681d0a 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_no_active_stack_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_no_active_stack_test.dart
@@ -2,11 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-import 'dart:io';
-import 'dart:convert';
-
-import 'package:path/path.dart' as path;
 import 'package:expect/expect.dart';
 
 import 'reload_utils.dart';
diff --git a/runtime/tests/vm/dart_2/isolates/reload_utils.dart b/runtime/tests/vm/dart_2/isolates/reload_utils.dart
index f296c4c..4a664b7 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_utils.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_utils.dart
@@ -124,7 +124,6 @@
     '--disable-dart-dev',
     '--disable-service-auth-codes',
     '--enable-isolate-groups',
-    '--experimental-enable-isolate-groups-jit',
     file
   ];
   final env = Platform.environment;
diff --git a/runtime/tests/vm/dart_2/isolates/ring_gc_sendAndExit_test.dart b/runtime/tests/vm/dart_2/isolates/ring_gc_sendAndExit_test.dart
index e461273..74b6820 100644
--- a/runtime/tests/vm/dart_2/isolates/ring_gc_sendAndExit_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/ring_gc_sendAndExit_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:math' as math;
 
@@ -12,6 +12,12 @@
 import 'test_utils.dart';
 
 main(args) async {
+  // We don't run this test in our artificial hot reload mode, because it would
+  // create too many threads during the reload (one per isolate), which can
+  // cause this test or other concurrently executing tests to Crash due to
+  // unability of `pthread_create` to create a new thread.
+  if (isArtificialReloadMode) return;
+
   final int numIsolates = (isDebugMode || isSimulator) ? 100 : 5000;
 
   // Spawn ring of 1k isolates.
diff --git a/runtime/tests/vm/dart_2/isolates/ring_gc_test.dart b/runtime/tests/vm/dart_2/isolates/ring_gc_test.dart
index f0ecbc1..c27cd6c 100644
--- a/runtime/tests/vm/dart_2/isolates/ring_gc_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/ring_gc_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:async';
 import 'dart:math' as math;
@@ -31,6 +31,12 @@
 }
 
 main(args) async {
+  // We don't run this test in our artificial hot reload mode, because it would
+  // create too many threads during the reload (one per isolate), which can
+  // cause this test or other concurrently executing tests to Crash due to
+  // unability of `pthread_create` to create a new thread.
+  if (isArtificialReloadMode) return;
+
   final int numIsolates = (isDebugMode || isSimulator) ? 100 : 1000;
 
   // Spawn ring of 1k isolates.
diff --git a/runtime/tests/vm/dart_2/isolates/spawn_function_test.dart b/runtime/tests/vm/dart_2/isolates/spawn_function_test.dart
index bbbb2f5..f2a85ea 100644
--- a/runtime/tests/vm/dart_2/isolates/spawn_function_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/spawn_function_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/runtime/tests/vm/dart_2/isolates/sum_recursive_call_ig_test.dart b/runtime/tests/vm/dart_2/isolates/sum_recursive_call_ig_test.dart
index 6b7eecb..915c102 100644
--- a/runtime/tests/vm/dart_2/isolates/sum_recursive_call_ig_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/sum_recursive_call_ig_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
diff --git a/runtime/tests/vm/dart_2/isolates/sum_recursive_call_test.dart b/runtime/tests/vm/dart_2/isolates/sum_recursive_call_test.dart
index 3b18008..89bcc58 100644
--- a/runtime/tests/vm/dart_2/isolates/sum_recursive_call_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/sum_recursive_call_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
diff --git a/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_ig_test.dart b/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_ig_test.dart
index bf1d165..a3fb967 100644
--- a/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_ig_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_ig_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
diff --git a/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_test.dart b/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_test.dart
index a98cc91..866b8f3 100644
--- a/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:isolate';
 
diff --git a/runtime/tests/vm/dart_2/isolates/test_utils.dart b/runtime/tests/vm/dart_2/isolates/test_utils.dart
index 67b84d8..fdf47d7 100644
--- a/runtime/tests/vm/dart_2/isolates/test_utils.dart
+++ b/runtime/tests/vm/dart_2/isolates/test_utils.dart
@@ -10,6 +10,10 @@
 
 final bool isDebugMode = Platform.script.path.contains('Debug');
 final bool isSimulator = Platform.script.path.contains('SIM');
+final bool isArtificialReloadMode = Platform.executableArguments.any((arg) => [
+      '--hot-reload-rollback-test-mode',
+      '--hot-reload-test-mode'
+    ].contains(arg));
 
 // Implements recursive summation:
 //   sum(n) => n == 0 ? 0
diff --git a/runtime/tests/vm/dart_2/isolates/thread_pool_test.dart b/runtime/tests/vm/dart_2/isolates/thread_pool_test.dart
index b0de784..695fda2 100644
--- a/runtime/tests/vm/dart_2/isolates/thread_pool_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/thread_pool_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // SharedObjects=ffi_test_functions
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
 
 import 'dart:async';
 import 'dart:ffi';
diff --git a/runtime/tests/vm/dart_2/issue_31959_31960_test.dart b/runtime/tests/vm/dart_2/issue_31959_31960_test.dart
index b70bb0d..d63a16f 100644
--- a/runtime/tests/vm/dart_2/issue_31959_31960_test.dart
+++ b/runtime/tests/vm/dart_2/issue_31959_31960_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:async';
diff --git a/runtime/tests/vm/dart_2/sendandexit_test.dart b/runtime/tests/vm/dart_2/sendandexit_test.dart
index 91d2bac..58e02c6 100644
--- a/runtime/tests/vm/dart_2/sendandexit_test.dart
+++ b/runtime/tests/vm/dart_2/sendandexit_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 //
 // Validates functionality of sendAndExit.
 
diff --git a/runtime/tests/vm/dart_2/spawn_infinite_loop_test.dart b/runtime/tests/vm/dart_2/spawn_infinite_loop_test.dart
index 79409e0..3a89e80 100644
--- a/runtime/tests/vm/dart_2/spawn_infinite_loop_test.dart
+++ b/runtime/tests/vm/dart_2/spawn_infinite_loop_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/runtime/tests/vm/dart_2/transferable_test.dart b/runtime/tests/vm/dart_2/transferable_test.dart
index 48ea0ec..8daf5a0 100644
--- a/runtime/tests/vm/dart_2/transferable_test.dart
+++ b/runtime/tests/vm/dart_2/transferable_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test that validates that transferables are faster than regular typed data.
diff --git a/runtime/tests/vm/dart_2/transferable_throws_test.dart b/runtime/tests/vm/dart_2/transferable_throws_test.dart
index 95d1e09..fcb5bf7 100644
--- a/runtime/tests/vm/dart_2/transferable_throws_test.dart
+++ b/runtime/tests/vm/dart_2/transferable_throws_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test that ensures correct exceptions are thrown when misusing
@@ -11,7 +11,6 @@
 import 'dart:async';
 import 'dart:collection';
 import 'dart:core';
-import 'dart:io';
 import 'dart:isolate';
 import 'dart:typed_data';
 import 'dart:math';
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 2cd1ed4..41a7490 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -15,6 +15,8 @@
 dart/data_uri_import_test/none: SkipByDesign
 dart/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
 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.
 dart/minimal_kernel_test: Pass, Slow # Spawns several subprocesses
 dart/null_safety_autodetection_in_kernel_compiler_test: Pass, Slow # Spawns several subprocesses
 dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
@@ -25,6 +27,8 @@
 dart_2/data_uri_import_test/none: SkipByDesign
 dart_2/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
 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.
 dart_2/minimal_kernel_test: Pass, Slow # Spawns several subprocesses
 dart_2/null_safety_autodetection_in_kernel_compiler_test: Pass, Slow # Spawns several subprocesses
 dart_2/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
@@ -144,20 +148,6 @@
 [ $nnbd == legacy ]
 dart/*: SkipByDesign # Migrated tests are not supposed to run on non-NNBD bots.
 
-[ $runtime == vm ]
-dart/isolates/*: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart/issue_31959_31960_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart/sendandexit_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart/spawn_infinite_loop_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart/transferable_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart/transferable_throws_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/isolates/*: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/issue_31959_31960_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/sendandexit_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/spawn_infinite_loop_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/transferable_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/transferable_throws_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-
 [ $system == android ]
 dart/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # On android this test does not work due to not being able to identify library uri.
 dart/sdk_hash_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
@@ -436,34 +426,11 @@
 
 [ $runtime != dart_precompiled || $system == android ]
 dart/bare_instructions_trampolines_test: SkipByDesign # This test is for VM AOT only (android fails due to listing interfaces).
-dart/isolates/fibonacci_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests, JIT work is pending.
-dart/isolates/fibonacci_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/internal: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/limited_active_mutator_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/ring_gc_sendAndExit_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/ring_gc_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/sum_recursive_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/sum_recursive_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/sum_recursive_tail_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/sum_recursive_tail_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/thread_pool_test: Skip # Only AOT has lightweight enough isolates to run those tests.
 dart_2/bare_instructions_trampolines_test: SkipByDesign # This test is for VM AOT only (android fails due to listing interfaces).
-dart_2/isolates/fibonacci_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests, JIT work is pending.
-dart_2/isolates/fibonacci_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/internal: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/limited_active_mutator_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/ring_gc_sendAndExit_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/ring_gc_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/sum_recursive_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/sum_recursive_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/sum_recursive_tail_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/sum_recursive_tail_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/thread_pool_test: Skip # Only AOT has lightweight enough isolates to run those tests.
 
 [ $hot_reload || $hot_reload_rollback ]
 dart/appjit*: SkipByDesign # Cannot reload with URI pointing to app snapshot.
 dart/disassemble_determinism_test: SkipSlow # Runs expensive fibonacci(32) computation in 2 subprocesses
-dart/isolates/spawn_function_test: Skip # This test explicitly enables isolate groups (off-by-default atm). It will be enabled once full IG reloading is implemented.
 dart/issue_31959_31960_test: SkipSlow
 dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
 dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
@@ -475,7 +442,6 @@
 dart/stack_overflow_shared_test: SkipSlow # Too slow with --shared-slow-path-triggers-gc flag and not relevant outside precompiled.
 dart_2/appjit*: SkipByDesign # Cannot reload with URI pointing to app snapshot.
 dart_2/disassemble_determinism_test: SkipSlow # Runs expensive fibonacci(32) computation in 2 subprocesses
-dart_2/isolates/spawn_function_test: Skip # This test explicitly enables isolate groups (off-by-default atm). It will be enabled once full IG reloading is implemented.
 dart_2/issue_31959_31960_test: SkipSlow
 dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
 dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
diff --git a/runtime/tools/dartfuzz/dartfuzz_test.dart b/runtime/tools/dartfuzz/dartfuzz_test.dart
index 639935b..fb826ff 100644
--- a/runtime/tools/dartfuzz/dartfuzz_test.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_test.dart
@@ -420,7 +420,6 @@
           timeoutSeeds.add(seed);
           break;
         default:
-          reportDivergence(result1, result2);
           // Both had an error.
           numSkipped++;
           skippedSeeds.add(seed);
@@ -472,9 +471,7 @@
     var report = generateReport(result1, result2);
     print('\n$isolate: !DIVERGENCE! $version:$seed ($report)');
     if (result1.exitCode == result2.exitCode) {
-      if (result1.exitCode == 254) {
-        print('\ncompile-time error:\n${result1.output}\n${result1.stderr}\n');
-      } else if (numOutputLines > 0) {
+      if (numOutputLines > 0) {
         // Only report the actual output divergence details up to
         // numOutputLines, since this output may be lengthy and should be
         // reproducable anyway.
diff --git a/runtime/tools/dartfuzz/gen_api_table.dart b/runtime/tools/dartfuzz/gen_api_table.dart
index 869bfc3..365a50a 100644
--- a/runtime/tools/dartfuzz/gen_api_table.dart
+++ b/runtime/tools/dartfuzz/gen_api_table.dart
@@ -348,7 +348,7 @@
   final libPath = session.uriConverter.uriToPath(Uri.parse(uri));
   var result = await session.getResolvedLibrary2(libPath!);
   if (result is ResolvedLibraryResult) {
-    visitLibrary(result.element!);
+    visitLibrary(result.element);
   } else {
     throw StateError('Unable to resolve "$uri"');
   }
diff --git a/runtime/tools/dartfuzz/gen_type_table.dart b/runtime/tools/dartfuzz/gen_type_table.dart
index ea2ac48..0f2599a 100644
--- a/runtime/tools/dartfuzz/gen_type_table.dart
+++ b/runtime/tools/dartfuzz/gen_type_table.dart
@@ -1342,7 +1342,7 @@
   var libPath = session.uriConverter.uriToPath(Uri.parse(uri));
   var result = await session.getResolvedLibrary2(libPath!);
   if (result is ResolvedLibraryResult) {
-    visitLibrary(result.element!, allTypes);
+    visitLibrary(result.element, allTypes);
   } else {
     throw StateError('Unable to resolve "$uri"');
   }
diff --git a/runtime/vm/allocation.cc b/runtime/vm/allocation.cc
index aa36221..4239026 100644
--- a/runtime/vm/allocation.cc
+++ b/runtime/vm/allocation.cc
@@ -24,7 +24,6 @@
 }
 
 void* ZoneAllocated::operator new(uword size, Zone* zone) {
-  ASSERT(Thread::Current()->ZoneIsOwnedByThread(zone));
   return Allocate(size, zone);
 }
 
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index ee64cc5..2b5683b 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -18,6 +18,7 @@
 #include "vm/clustered_snapshot.h"
 #include "vm/dart_api_impl.h"
 #include "vm/datastream.h"
+#include "vm/message_snapshot.h"
 #include "vm/stack_frame.h"
 #include "vm/timer.h"
 
@@ -256,8 +257,8 @@
 // Measure compile of all kernel Service(CFE) functions.
 //
 BENCHMARK(KernelServiceCompileAll) {
-  if (FLAG_sound_null_safety == kNullSafetyOptionStrong) {
-    // TODO(bkonyi): remove this check when we build the CFE in strong mode.
+  // kernel_service.dill is built with sound null safety.
+  if (FLAG_sound_null_safety != kNullSafetyOptionStrong) {
     return;
   }
   bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
@@ -517,13 +518,12 @@
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
-    MessageWriter writer(true);
-    std::unique_ptr<Message> message = writer.WriteMessage(
-        null_object, ILLEGAL_PORT, Message::kNormalPriority);
+    std::unique_ptr<Message> message =
+        WriteMessage(/* can_send_any_object */ true, null_object, ILLEGAL_PORT,
+                     Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message.get(), thread);
-    reader.ReadObject();
+    ReadMessage(thread, message.get());
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
@@ -540,13 +540,12 @@
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
-    MessageWriter writer(true);
     std::unique_ptr<Message> message =
-        writer.WriteMessage(smi_object, ILLEGAL_PORT, Message::kNormalPriority);
+        WriteMessage(/* can_send_any_object */ true, smi_object, ILLEGAL_PORT,
+                     Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message.get(), thread);
-    reader.ReadObject();
+    ReadMessage(thread, message.get());
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
@@ -565,13 +564,12 @@
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
-    MessageWriter writer(true);
-    std::unique_ptr<Message> message = writer.WriteMessage(
-        array_object, ILLEGAL_PORT, Message::kNormalPriority);
+    std::unique_ptr<Message> message = WriteMessage(
+        /* can_send_any_object */ true, array_object, ILLEGAL_PORT,
+        Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message.get(), thread);
-    reader.ReadObject();
+    ReadMessage(thread, message.get());
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
@@ -599,13 +597,12 @@
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
-    MessageWriter writer(true);
     std::unique_ptr<Message> message =
-        writer.WriteMessage(map, ILLEGAL_PORT, Message::kNormalPriority);
+        WriteMessage(/* can_send_any_object */ true, map, ILLEGAL_PORT,
+                     Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message.get(), thread);
-    reader.ReadObject();
+    ReadMessage(thread, message.get());
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
diff --git a/runtime/vm/bitfield.h b/runtime/vm/bitfield.h
index f96a34e..d6f60c7 100644
--- a/runtime/vm/bitfield.h
+++ b/runtime/vm/bitfield.h
@@ -226,22 +226,6 @@
                    void>::type>
     : public BitField<typename S::ContainedType, T, position, size, false> {};
 
-template <typename S, typename T, int position>
-class BitField<S,
-               T,
-               position,
-               (sizeof(S) * kBitsPerByte) - position,
-               false,
-               typename std::enable_if<
-                   std::is_base_of<AtomicBitFieldContainerBase, S>::value,
-                   void>::type>
-    : public BitField<typename S::ContainedType,
-                      T,
-                      position,
-                      (sizeof(typename S::ContainedType) * kBitsPerByte) -
-                          position,
-                      false> {};
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_BITFIELD_H_
diff --git a/runtime/vm/bitmap.h b/runtime/vm/bitmap.h
index 186f1e6..74c4c5b 100644
--- a/runtime/vm/bitmap.h
+++ b/runtime/vm/bitmap.h
@@ -22,7 +22,9 @@
   }
 
   BitmapBuilder(const BitmapBuilder& other)
-      : length_(other.length_), data_size_in_bytes_(other.data_size_in_bytes_) {
+      : ZoneAllocated(),
+        length_(other.length_),
+        data_size_in_bytes_(other.data_size_in_bytes_) {
     if (data_size_in_bytes_ == kInlineCapacityInBytes) {
       memmove(data_.inline_, other.data_.inline_, kInlineCapacityInBytes);
     } else {
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 5e3ddd7..20d63d2 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -128,6 +128,8 @@
     // Finish bootstrapping, including class finalization.
     Finish(thread);
 
+    isolate_group->object_store()->InitKnownObjects();
+
     // The platform binary may contain other libraries (e.g., dart:_builtin or
     // dart:io) that will not be bundled with application.  Load them now.
     const Object& result = Object::Handle(zone, loader.LoadProgram());
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 7eb3452..e9710df6 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -344,6 +344,7 @@
   V(Internal_allocateTwoByteString, 1)                                         \
   V(Internal_writeIntoOneByteString, 3)                                        \
   V(Internal_writeIntoTwoByteString, 3)                                        \
+  V(Internal_deoptimizeFunctionsOnStack, 0)                                    \
   V(InvocationMirror_unpackTypeArguments, 2)                                   \
   V(NoSuchMethodError_existingMethodSignature, 3)                              \
   V(WeakProperty_getKey, 1)                                                    \
diff --git a/runtime/vm/canonical_tables.h b/runtime/vm/canonical_tables.h
index b0e25b5..ba9297e 100644
--- a/runtime/vm/canonical_tables.h
+++ b/runtime/vm/canonical_tables.h
@@ -131,7 +131,8 @@
     return concat.ToSymbol();
   }
 };
-typedef UnorderedHashSet<SymbolTraits> CanonicalStringSet;
+
+typedef UnorderedHashSet<SymbolTraits, AcqRelStorageTraits> CanonicalStringSet;
 
 class CanonicalTypeKey {
  public:
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index d296cc7cb..8e2fb4b 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -239,33 +239,35 @@
 #if defined(DEBUG)
   // Basic checking.
   cls = object_store->object_class();
-  ASSERT(Instance::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(Instance::InstanceSize(), cls.host_instance_size());
   cls = object_store->integer_implementation_class();
-  ASSERT(Integer::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(Integer::InstanceSize(), cls.host_instance_size());
   cls = object_store->smi_class();
-  ASSERT(Smi::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(Smi::InstanceSize(), cls.host_instance_size());
   cls = object_store->mint_class();
-  ASSERT(Mint::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(Mint::InstanceSize(), cls.host_instance_size());
   cls = object_store->one_byte_string_class();
-  ASSERT(OneByteString::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(OneByteString::InstanceSize(), cls.host_instance_size());
   cls = object_store->two_byte_string_class();
-  ASSERT(TwoByteString::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(TwoByteString::InstanceSize(), cls.host_instance_size());
   cls = object_store->external_one_byte_string_class();
-  ASSERT(ExternalOneByteString::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(ExternalOneByteString::InstanceSize(), cls.host_instance_size());
   cls = object_store->external_two_byte_string_class();
-  ASSERT(ExternalTwoByteString::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(ExternalTwoByteString::InstanceSize(), cls.host_instance_size());
   cls = object_store->double_class();
-  ASSERT(Double::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(Double::InstanceSize(), cls.host_instance_size());
   cls = object_store->bool_class();
-  ASSERT(Bool::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(Bool::InstanceSize(), cls.host_instance_size());
   cls = object_store->array_class();
-  ASSERT(Array::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(Array::InstanceSize(), cls.host_instance_size());
   cls = object_store->immutable_array_class();
-  ASSERT(ImmutableArray::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(ImmutableArray::InstanceSize(), cls.host_instance_size());
   cls = object_store->weak_property_class();
-  ASSERT(WeakProperty::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(WeakProperty::InstanceSize(), cls.host_instance_size());
   cls = object_store->linked_hash_map_class();
-  ASSERT(LinkedHashMap::InstanceSize() == cls.host_instance_size());
+  ASSERT_EQUAL(LinkedHashMap::InstanceSize(), cls.host_instance_size());
+  cls = object_store->linked_hash_set_class();
+  ASSERT_EQUAL(LinkedHashMap::InstanceSize(), cls.host_instance_size());
 #endif  // defined(DEBUG)
 
   // Remember the currently pending classes.
@@ -1455,10 +1457,6 @@
   RemapClassIds(old_to_new_cid.get());
   RehashTypes();          // Types use cid's as part of their hashes.
   IG->RehashConstants();  // Const objects use cid's as part of their hashes.
-
-  // Ensure any newly spawned isolate will apply this permutation map right
-  // after kernel loading.
-  IG->source()->cid_permutation_map = std::move(old_to_new_cid);
 }
 
 class CidRewriteVisitor : public ObjectVisitor {
@@ -1759,7 +1757,8 @@
   if (including_nonchanging_cids) {
     auto object_store = isolate_group->object_store();
     auto& null_code = Code::Handle(zone);
-    object_store->set_build_method_extractor_code(null_code);
+    object_store->set_build_generic_method_extractor_code(null_code);
+    object_store->set_build_nongeneric_method_extractor_code(null_code);
   }
 }
 
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 2fbc03f..5a41a68 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -17,7 +17,7 @@
 // Size of the class-id part of the object header. See UntaggedObject.
 typedef uint16_t ClassIdTagType;
 
-#define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V)                           \
+#define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V)                   \
   V(Class)                                                                     \
   V(PatchClass)                                                                \
   V(Function)                                                                  \
@@ -88,11 +88,16 @@
   V(RegExp)                                                                    \
   V(WeakProperty)                                                              \
   V(MirrorReference)                                                           \
-  V(LinkedHashMap)                                                             \
   V(FutureOr)                                                                  \
   V(UserTag)                                                                   \
   V(TransferableTypedData)
 
+// TODO(http://dartbug.com/45908): Add ImmutableLinkedHashMap.
+#define CLASS_LIST_MAPS(V) V(LinkedHashMap)
+
+// TODO(http://dartbug.com/45908): Add ImmutableLinkedHashSet.
+#define CLASS_LIST_SETS(V) V(LinkedHashSet)
+
 #define CLASS_LIST_ARRAYS(V)                                                   \
   V(Array)                                                                     \
   V(ImmutableArray)
@@ -163,12 +168,16 @@
   V(Float64x2)
 
 #define CLASS_LIST_FOR_HANDLES(V)                                              \
-  CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V)                                 \
+  CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V)                         \
+  V(LinkedHashMap)                                                             \
+  V(LinkedHashSet)                                                             \
   V(Array)                                                                     \
   V(String)
 
 #define CLASS_LIST_NO_OBJECT(V)                                                \
-  CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V)                                 \
+  CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V)                         \
+  CLASS_LIST_MAPS(V)                                                           \
+  CLASS_LIST_SETS(V)                                                           \
   CLASS_LIST_ARRAYS(V)                                                         \
   CLASS_LIST_STRINGS(V)
 
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index ccba236..b5491bb 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -519,10 +519,17 @@
 
   // This is called by snapshot reader and class finalizer.
   ASSERT(cid < capacity_);
+  UpdateClassSize(cid, raw_cls);
+  table_.load()[cid] = raw_cls;
+}
+
+void ClassTable::UpdateClassSize(intptr_t cid, ClassPtr raw_cls) {
+  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+  ASSERT(!IsTopLevelCid(cid));  // "top-level" classes don't get instantiated
+  ASSERT(cid < capacity_);
   const intptr_t size =
       raw_cls == nullptr ? 0 : Class::host_instance_size(raw_cls);
   shared_class_table_->SetSizeAt(cid, size);
-  table_.load()[cid] = raw_cls;
 }
 
 #ifndef PRODUCT
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 5ef0df1..e89b978 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -354,6 +354,7 @@
   }
 
   void SetAt(intptr_t index, ClassPtr raw_cls);
+  void UpdateClassSize(intptr_t cid, ClassPtr raw_cls);
 
   bool IsValidIndex(intptr_t cid) const {
     if (IsTopLevelCid(cid)) {
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 55d5b84..b3beb4d 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -16,6 +16,7 @@
 #include "vm/compiler/api/print_filter.h"
 #include "vm/compiler/assembler/disassembler.h"
 #include "vm/dart.h"
+#include "vm/dart_entry.h"
 #include "vm/dispatch_table.h"
 #include "vm/flag_list.h"
 #include "vm/growable_array.h"
@@ -114,6 +115,14 @@
   }
 
   static bool IsImmutable(const ArrayHandle& handle) { return false; }
+
+  static ObjectPtr At(ArrayHandle* array, intptr_t index) {
+    return array->At(index);
+  }
+
+  static void SetAt(ArrayHandle* array, intptr_t index, const Object& value) {
+    array->SetAt(index, value);
+  }
 };
 }  // namespace
 
@@ -3245,25 +3254,6 @@
       cache->untag()->filled_entry_count_ = d->Read<int32_t>();
     }
   }
-
-#if defined(DART_PRECOMPILED_RUNTIME)
-  void PostLoad(Deserializer* d, const Array& refs, bool primary) {
-    if (FLAG_use_bare_instructions) {
-      // By default, every megamorphic call site will load the target
-      // [Function] from the hash table and call indirectly via loading the
-      // entrypoint from the function.
-      //
-      // In --use-bare-instruction we reduce the extra indirection via the
-      // [Function] object by storing the entry point directly into the hashmap.
-      //
-      auto& cache = MegamorphicCache::Handle(d->zone());
-      for (intptr_t i = start_index_; i < stop_index_; ++i) {
-        cache ^= refs.At(i);
-        cache.SwitchToBareInstructions();
-      }
-    }
-  }
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -5600,6 +5590,10 @@
     OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
                             DECLARE_OBJECT_STORE_FIELD,
                             DECLARE_OBJECT_STORE_FIELD,
+                            DECLARE_OBJECT_STORE_FIELD,
+                            DECLARE_OBJECT_STORE_FIELD,
+                            DECLARE_OBJECT_STORE_FIELD,
+                            DECLARE_OBJECT_STORE_FIELD,
                             DECLARE_OBJECT_STORE_FIELD)
 #undef DECLARE_OBJECT_STORE_FIELD
 };
@@ -5743,7 +5737,10 @@
 
   void PostLoad(Deserializer* d, const Array& refs) {
     auto isolate_group = d->isolate_group();
-    isolate_group->class_table()->CopySizesFromClassObjects();
+    {
+      SafepointWriteRwLocker ml(d->thread(), isolate_group->program_lock());
+      isolate_group->class_table()->CopySizesFromClassObjects();
+    }
     d->heap()->old_space()->EvaluateAfterLoading();
 
     const Array& units =
@@ -6473,7 +6470,11 @@
     case kWeakPropertyCid:
       return new (Z) WeakPropertySerializationCluster();
     case kLinkedHashMapCid:
-      return new (Z) LinkedHashMapSerializationCluster();
+      // We do not have mutable hash maps in snapshots.
+      UNREACHABLE();
+    case kLinkedHashSetCid:
+      // We do not have mutable hash sets in snapshots.
+      UNREACHABLE();
     case kArrayCid:
       return new (Z) ArraySerializationCluster(is_canonical, kArrayCid);
     case kImmutableArrayCid:
@@ -7113,6 +7114,7 @@
     buffer.Printf(" %10s", "Cumulative");
     buffer.Printf(" %8s", "HeapSize");
     buffer.Printf(" %5s", "Cid");
+    buffer.Printf(" %9s", "Canonical");
     buffer.AddString("\n");
     GrowableArray<SerializationCluster*> clusters_by_size;
     for (intptr_t cid = 1; cid < num_cids_; cid++) {
@@ -7179,6 +7181,11 @@
       } else {
         buffer.Printf(" %5s", "");
       }
+      if (cluster->is_canonical()) {
+        buffer.Printf(" %9s", "canonical");
+      } else {
+        buffer.Printf(" %9s", "");
+      }
       buffer.AddString("\n");
     }
     OS::PrintErr("%s", buffer.buffer());
@@ -7380,7 +7387,11 @@
       ASSERT(!is_canonical);
       return new (Z) WeakPropertyDeserializationCluster();
     case kLinkedHashMapCid:
-      return new (Z) LinkedHashMapDeserializationCluster(is_canonical);
+      // We do not have mutable hash maps in snapshots.
+      UNREACHABLE();
+    case kLinkedHashSetCid:
+      // We do not have mutable hash sets in snapshots.
+      UNREACHABLE();
     case kArrayCid:
       return new (Z) ArrayDeserializationCluster(is_canonical, kArrayCid);
     case kImmutableArrayCid:
@@ -7805,6 +7816,7 @@
 
     {
       TIMELINE_DURATION(thread(), Isolate, "ReadFill");
+      SafepointWriteRwLocker ml(thread(), isolate_group()->program_lock());
       for (intptr_t i = 0; i < num_clusters_; i++) {
         TIMELINE_DURATION(thread(), Isolate, clusters_[i]->name());
         clusters_[i]->ReadFill(this, primary);
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index 9dab2b8..d80cb7453 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -440,7 +440,7 @@
 
   V8SnapshotProfileWriter* profile_writer() const { return profile_writer_; }
 
-  // If the given [obj] was not included into the snaposhot and have not
+  // If the given [obj] was not included into the snapshot and have not
   // yet gotten an artificial node created for it create an artificial node
   // in the profile representing this object.
   // Returns true if [obj] has an artificial profile node associated with it.
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index 0d15c38..ac29be7 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -209,7 +209,7 @@
   using ArgField = BitField<int32_t, int32_t, OpField::kNextBit>;
 
   static constexpr int32_t kMaxArgValue =
-      Utils::NBitMaskUnsafe(ArgField::bitsize() - 1);
+      Utils::NBitMask<int32_t>(ArgField::bitsize() - 1);
   static constexpr int32_t kMinArgValue = ~kMaxArgValue;
   static constexpr int32_t kSignBits = static_cast<uint32_t>(kMinArgValue) << 1;
 };
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 99d4c22..35ca895 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -522,10 +522,18 @@
 
         {
           SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
-          stub_code = StubCode::GetBuildMethodExtractorStub(
+          stub_code = StubCode::GetBuildGenericMethodExtractorStub(
               global_object_pool_builder());
         }
-        IG->object_store()->set_build_method_extractor_code(stub_code);
+        IG->object_store()->set_build_generic_method_extractor_code(stub_code);
+
+        {
+          SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
+          stub_code = StubCode::GetBuildNonGenericMethodExtractorStub(
+              global_object_pool_builder());
+        }
+        IG->object_store()->set_build_nongeneric_method_extractor_code(
+            stub_code);
       }
 
       CollectDynamicFunctionNames();
@@ -604,7 +612,6 @@
         IG->object_store()->set_pragma_name(null_field);
         IG->object_store()->set_pragma_options(null_field);
         IG->object_store()->set_completer_class(null_class);
-        IG->object_store()->set_symbol_class(null_class);
         IG->object_store()->set_compiletime_error_class(null_class);
         IG->object_store()->set_growable_list_factory(null_function);
         IG->object_store()->set_simple_instance_of_function(null_function);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 7e9299f..3502a6e 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -250,6 +250,22 @@
   label->BindTo(bound_pc, lr_state());
 }
 
+#if defined(USING_THREAD_SANITIZER)
+void Assembler::TsanLoadAcquire(Register addr) {
+  EnterCallRuntimeFrame(/*frame_size=*/0, /*is_leaf=*/true);
+  ASSERT(kTsanLoadAcquireRuntimeEntry.is_leaf());
+  CallRuntime(kTsanLoadAcquireRuntimeEntry, /*argument_count=*/1);
+  LeaveCallRuntimeFrame(/*is_leaf=*/true);
+}
+
+void Assembler::TsanStoreRelease(Register addr) {
+  EnterCallRuntimeFrame(/*frame_size=*/0, /*is_leaf=*/true);
+  ASSERT(kTsanStoreReleaseRuntimeEntry.is_leaf());
+  CallRuntime(kTsanStoreReleaseRuntimeEntry, /*argument_count=*/1);
+  LeaveCallRuntimeFrame(/*is_leaf=*/true);
+}
+#endif
+
 static int CountLeadingZeros(uint64_t value, int width) {
   if (width == 64) return Utils::CountLeadingZeros64(value);
   if (width == 32) return Utils::CountLeadingZeros32(value);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index f99eb33..596ee9d 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -557,22 +557,56 @@
   void StoreMemoryValue(Register src, Register base, int32_t offset) {
     StoreToOffset(src, base, offset, kEightBytes);
   }
+
+#if defined(USING_THREAD_SANITIZER)
+  void TsanLoadAcquire(Register addr);
+  void TsanStoreRelease(Register addr);
+#endif
+
   void LoadAcquire(Register dst, Register address, int32_t offset = 0) {
     if (offset != 0) {
       AddImmediate(TMP2, address, offset);
       ldar(dst, TMP2);
+#if defined(USING_THREAD_SANITIZER)
+      TsanLoadAcquire(TMP2);
+#endif
     } else {
       ldar(dst, address);
+#if defined(USING_THREAD_SANITIZER)
+      TsanLoadAcquire(address);
+#endif
     }
   }
+
   void LoadAcquireCompressed(Register dst,
                              Register address,
                              int32_t offset = 0) {
     if (offset != 0) {
       AddImmediate(TMP2, address, offset);
       ldar(dst, TMP2, kObjectBytes);
+#if defined(USING_THREAD_SANITIZER)
+      TsanLoadAcquire(TMP2);
+#endif
     } else {
       ldar(dst, address, kObjectBytes);
+#if defined(USING_THREAD_SANITIZER)
+      TsanLoadAcquire(address);
+#endif
+    }
+  }
+
+  void StoreRelease(Register dst, Register address, int32_t offset = 0) {
+    if (offset != 0) {
+      AddImmediate(TMP2, address, offset);
+      stlr(dst, TMP2);
+#if defined(USING_THREAD_SANITIZER)
+      TsanStoreRelease(TMP2);
+#endif
+    } else {
+      stlr(dst, address);
+#if defined(USING_THREAD_SANITIZER)
+      TsanStoreRelease(address);
+#endif
     }
   }
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm64_test.cc b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
index 53d2adf..03f8341 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
@@ -4737,8 +4737,8 @@
   __ mov(THR, R2);
   __ ldr(HEAP_BITS, Address(THR, Thread::write_barrier_mask_offset()));
   __ LslImmediate(HEAP_BITS, HEAP_BITS, 32);
-  __ StoreIntoObject(R1, FieldAddress(R1, GrowableObjectArray::data_offset()),
-                     R0);
+  __ StoreCompressedIntoObject(
+      R1, FieldAddress(R1, GrowableObjectArray::data_offset()), R0);
   RESTORES_LR_FROM_FRAME(__ Pop(LR));
   __ Pop(HEAP_BITS);
   __ Pop(THR);
@@ -4855,6 +4855,54 @@
             EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), -511));
 }
 
+#if !defined(USING_THREAD_SANITIZER)
+// can't call (tsan) runtime methods
+
+ASSEMBLER_TEST_GENERATE(StoreReleaseLoadAcquire, assembler) {
+  __ SetupDartSP();
+  __ Push(R1);
+  __ LoadImmediate(R1, 0);
+  __ Push(R1);
+  __ mov(R1, R0);
+  __ LoadImmediate(R0, 0);
+  __ StoreRelease(R1, SP, 0);
+  __ LoadAcquire(R0, SP, 0);
+  __ Pop(R1);
+  __ Pop(R1);
+  __ RestoreCSP();
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(StoreReleaseLoadAcquire, test) {
+  typedef intptr_t (*StoreReleaseLoadAcquire)(intptr_t) DART_UNUSED;
+  EXPECT_EQ(123, EXECUTE_TEST_CODE_INTPTR_INTPTR(StoreReleaseLoadAcquire,
+                                                 test->entry(), 123));
+}
+
+ASSEMBLER_TEST_GENERATE(StoreReleaseLoadAcquire1024, assembler) {
+  __ SetupDartSP();
+  __ Push(R1);
+  __ LoadImmediate(R1, 0);
+  __ Push(R1);
+  __ mov(R1, R0);
+  __ LoadImmediate(R0, 0);
+  __ sub(SP, SP, Operand(1024 * target::kWordSize));
+  __ StoreRelease(R1, SP, 1024);
+  __ LoadAcquire(R0, SP, 1024);
+  __ add(SP, SP, Operand(1024 * target::kWordSize));
+  __ Pop(R1);
+  __ Pop(R1);
+  __ RestoreCSP();
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(StoreReleaseLoadAcquire1024, test) {
+  typedef intptr_t (*StoreReleaseLoadAcquire1024)(intptr_t) DART_UNUSED;
+  EXPECT_EQ(123, EXECUTE_TEST_CODE_INTPTR_INTPTR(StoreReleaseLoadAcquire1024,
+                                                 test->entry(), 123));
+}
+#endif
+
 }  // namespace compiler
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/assembler/assembler_base.h b/runtime/vm/compiler/assembler/assembler_base.h
index 55258dc..1f22998 100644
--- a/runtime/vm/compiler/assembler/assembler_base.h
+++ b/runtime/vm/compiler/assembler/assembler_base.h
@@ -193,7 +193,7 @@
   // 64-bit ARM specific constants.
   kQWord,
 
-#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
+#if defined(HAS_SMI_63_BITS)
   kObjectBytes = kEightBytes,
 #else
   kObjectBytes = kFourBytes,
diff --git a/runtime/vm/compiler/assembler/assembler_test.cc b/runtime/vm/compiler/assembler/assembler_test.cc
index 8488eae..16342bd 100644
--- a/runtime/vm/compiler/assembler/assembler_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_test.cc
@@ -38,7 +38,8 @@
   for (int i = -128; i < 128; i++) {
     smi = Smi::New(i);
     TEST_CODE(smi.ptr(), grow_old_array.ptr(), thread);
-    EXPECT(static_cast<ArrayPtr>(smi.ptr()) == grow_old_array.data());
+    EXPECT(static_cast<CompressedObjectPtr>(smi.ptr()) ==
+           static_cast<CompressedObjectPtr>(grow_old_array.data()));
     EXPECT(!thread->StoreBufferContains(grow_old_array.ptr()));
   }
 
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 8bc3290..22b6673 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1876,6 +1876,24 @@
   entry.Call(this, argument_count);
 }
 
+#if defined(USING_THREAD_SANITIZER)
+void Assembler::TsanLoadAcquire(Address addr) {
+  PushRegisters(kVolatileRegisterSet);
+  leaq(CallingConventions::kArg1Reg, addr);
+  ASSERT(kTsanLoadAcquireRuntimeEntry.is_leaf());
+  CallRuntime(kTsanLoadAcquireRuntimeEntry, /*argument_count=*/1);
+  PopRegisters(kVolatileRegisterSet);
+}
+
+void Assembler::TsanStoreRelease(Address addr) {
+  PushRegisters(kVolatileRegisterSet);
+  leaq(CallingConventions::kArg1Reg, addr);
+  ASSERT(kTsanStoreReleaseRuntimeEntry.is_leaf());
+  CallRuntime(kTsanStoreReleaseRuntimeEntry, /*argument_count=*/1);
+  PopRegisters(kVolatileRegisterSet);
+}
+#endif
+
 void Assembler::RestoreCodePointer() {
   movq(CODE_REG,
        Address(RBP, target::frame_layout.code_from_fp * target::kWordSize));
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index c9fb518..27b45dd 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -1027,10 +1027,19 @@
   void StoreMemoryValue(Register src, Register base, int32_t offset) {
     movq(Address(base, offset), src);
   }
+
+#if defined(USING_THREAD_SANITIZER)
+  void TsanLoadAcquire(Address addr);
+  void TsanStoreRelease(Address addr);
+#endif
+
   void LoadAcquire(Register dst, Register address, int32_t offset = 0) {
     // On intel loads have load-acquire behavior (i.e. loads are not re-ordered
     // with other loads).
     movq(dst, Address(address, offset));
+#if defined(USING_THREAD_SANITIZER)
+    TsanLoadAcquire(Address(address, offset));
+#endif
   }
   void LoadAcquireCompressed(Register dst,
                              Register address,
@@ -1038,11 +1047,17 @@
     // On intel loads have load-acquire behavior (i.e. loads are not re-ordered
     // with other loads).
     LoadCompressed(dst, Address(address, offset));
+#if defined(USING_THREAD_SANITIZER)
+    TsanLoadAcquire(Address(address, offset));
+#endif
   }
   void StoreRelease(Register src, Register address, int32_t offset = 0) {
     // On intel stores have store-release behavior (i.e. stores are not
     // re-ordered with other stores).
     movq(Address(address, offset), src);
+#if defined(USING_THREAD_SANITIZER)
+    TsanStoreRelease(Address(address, offset));
+#endif
   }
 
   void CompareWithFieldValue(Register value, FieldAddress address) {
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index 00eeead..3d2deb2 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -5309,10 +5309,10 @@
   __ pushq(CODE_REG);
   __ pushq(THR);
   __ movq(THR, CallingConventions::kArg3Reg);
-  __ StoreIntoObject(CallingConventions::kArg2Reg,
-                     FieldAddress(CallingConventions::kArg2Reg,
-                                  GrowableObjectArray::data_offset()),
-                     CallingConventions::kArg1Reg);
+  __ StoreCompressedIntoObject(CallingConventions::kArg2Reg,
+                               FieldAddress(CallingConventions::kArg2Reg,
+                                            GrowableObjectArray::data_offset()),
+                               CallingConventions::kArg1Reg);
   __ popq(THR);
   __ popq(CODE_REG);
   __ ret();
@@ -6167,6 +6167,110 @@
                Address(RSP, 0),
                __ popq(RAX))
 
+ASSEMBLER_TEST_GENERATE(StoreReleaseLoadAcquire, assembler) {
+  __ pushq(RCX);
+  __ xorq(RCX, RCX);
+  __ pushq(RCX);
+
+  for (intptr_t i = 0; i < kNumberOfXmmRegisters; ++i) {
+    XmmRegister xmm_reg = static_cast<XmmRegister>(i);
+    if ((CallingConventions::kVolatileXmmRegisters & (1 << xmm_reg)) != 0) {
+      __ movq(RCX, Immediate(bit_cast<int32_t, float>(12.34f + i)));
+      __ movd(xmm_reg, RCX);
+    }
+  }
+
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    Register reg = static_cast<Register>(i);
+    if (reg == CallingConventions::kArg3Reg) {
+      continue;
+    }
+    if ((CallingConventions::kVolatileCpuRegisters & (1 << reg)) != 0) {
+      __ movq(reg, Immediate(0xAABBCCDD + i));
+    }
+  }
+  __ StoreRelease(CallingConventions::kArg3Reg, RSP, 0);
+
+  __ pushq(TMP);
+
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    Register reg = static_cast<Register>(i);
+    if (reg == CallingConventions::kArg3Reg) {
+      continue;
+    }
+    if ((CallingConventions::kVolatileCpuRegisters & (1 << reg)) != 0) {
+      Label ok;
+      if (reg == TMP) {
+        __ popq(TMP);
+        // Use kArg3Reg to validate TMP because TMP is
+        // needed for 64-bit cmpq below.
+        __ pushq(CallingConventions::kArg3Reg);
+        __ movq(CallingConventions::kArg3Reg, TMP);
+        reg = CallingConventions::kArg3Reg;
+      }
+      __ cmpq(reg, Immediate(0xAABBCCDD + i));
+      __ j(EQUAL, &ok);
+      __ int3();
+      __ Bind(&ok);
+      if (reg == CallingConventions::kArg3Reg) {
+        __ popq(CallingConventions::kArg3Reg);
+      }
+    }
+  }
+
+  for (intptr_t i = 0; i < kNumberOfXmmRegisters; ++i) {
+    XmmRegister xmm_reg = static_cast<XmmRegister>(i);
+    if ((CallingConventions::kVolatileXmmRegisters & (1 << xmm_reg)) != 0) {
+      Label ok;
+      __ movq(RCX, xmm_reg);
+      __ cmpq(RCX, Immediate(bit_cast<int32_t, float>(12.34f + i)));
+      __ j(EQUAL, &ok);
+      __ int3();
+      __ Bind(&ok);
+    }
+  }
+  __ LoadAcquire(CallingConventions::kReturnReg, RSP, 0);
+  __ popq(RCX);
+  __ popq(RCX);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(StoreReleaseLoadAcquire, test) {
+  int res = test->InvokeWithCodeAndThread<int>(123);
+  EXPECT_EQ(123, res);
+}
+
+ASSEMBLER_TEST_GENERATE(StoreReleaseLoadAcquire1024, assembler) {
+  __ pushq(RCX);
+  __ xorq(RCX, RCX);
+  __ pushq(RCX);
+  __ subq(RSP, Immediate(1024));
+  __ StoreRelease(CallingConventions::kArg3Reg, RSP, 1024);
+  __ LoadAcquire(CallingConventions::kReturnReg, RSP, 1024);
+  __ addq(RSP, Immediate(1024));
+  __ popq(RCX);
+  __ popq(RCX);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(StoreReleaseLoadAcquire1024, test) {
+  int res = test->InvokeWithCodeAndThread<int>(123);
+  EXPECT_EQ(123, res);
+#if !defined(USING_THREAD_SANITIZER)
+  EXPECT_DISASSEMBLY_NOT_WINDOWS(
+      "push rcx\n"
+      "xorq rcx,rcx\n"
+      "push rcx\n"
+      "subq rsp,0x...\n"
+      "movq [rsp+0x...],rdx\n"
+      "movq rax,[rsp+0x...]\n"
+      "addq rsp,0x...\n"
+      "pop rcx\n"
+      "pop rcx\n"
+      "ret\n");
+#endif
+}
+
 }  // namespace compiler
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index b71c702..2e5a194 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -252,8 +252,14 @@
   ASSERT(!__ constant_pool_allowed());
   ASSERT(extracted_method.IsZoneHandle());
 
-  const Code& build_method_extractor = Code::ZoneHandle(
-      isolate_group()->object_store()->build_method_extractor_code());
+  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);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 6f257d1..d7b3759 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -243,8 +243,14 @@
   ASSERT(!__ constant_pool_allowed());
   ASSERT(extracted_method.IsZoneHandle());
 
-  const Code& build_method_extractor = Code::ZoneHandle(
-      isolate_group()->object_store()->build_method_extractor_code());
+  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);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 3b5345d..6092741 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -252,8 +252,14 @@
   ASSERT(!__ constant_pool_allowed());
   ASSERT(extracted_method.IsZoneHandle());
 
-  const Code& build_method_extractor = Code::ZoneHandle(
-      isolate_group()->object_store()->build_method_extractor_code());
+  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());
   ASSERT(!build_method_extractor.IsNull());
 
   const intptr_t stub_index = __ object_pool_builder().AddObject(
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 45a70dc..527fa42 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1156,7 +1156,7 @@
 
   // Since new isolates will be spawned, the JITed code cannot depend on whether
   // global field was initialized when running with --enable-isolate-groups.
-  if (IsolateGroup::AreIsolateGroupsEnabled()) return false;
+  if (FLAG_enable_isolate_groups) return false;
 
   const Field& field = this->field();
   Isolate* only_isolate = IsolateGroup::Current()->FirstIsolate();
@@ -3736,7 +3736,7 @@
   switch (from) {
     case kUnboxedUint8:
     case kUnboxedUint16:
-#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
+#if defined(HAS_SMI_63_BITS)
     case kUnboxedInt32:
     case kUnboxedUint32:
 #endif
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 1744e17..7699857 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -24,6 +24,7 @@
 #include "vm/compiler/ffi/native_location.h"
 #include "vm/compiler/ffi/native_type.h"
 #include "vm/compiler/method_recognizer.h"
+#include "vm/dart_entry.h"
 #include "vm/flags.h"
 #include "vm/growable_array.h"
 #include "vm/native_entry.h"
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 0c07ad2..5ede916 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -779,8 +779,8 @@
   const intptr_t kCpuRegistersToPreserve =
       kDartAvailableCpuRegs & ~kNonChangeableInputRegs;
   const intptr_t kFpuRegistersToPreserve =
-      Utils::SignedNBitMask(kNumberOfFpuRegisters) &
-      ~(Utils::SignedNBitMask(kAbiPreservedFpuRegCount)
+      Utils::NBitMask<intptr_t>(kNumberOfFpuRegisters) &
+      ~(Utils::NBitMask<intptr_t>(kAbiPreservedFpuRegCount)
         << kAbiFirstPreservedFpuReg) &
       ~(1 << FpuTMP);
 
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 223b424..9484c260 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -699,7 +699,7 @@
   const intptr_t kCpuRegistersToPreserve =
       kDartAvailableCpuRegs & ~kNonChangeableInputRegs;
   const intptr_t kFpuRegistersToPreserve =
-      Utils::SignedNBitMask(kNumberOfFpuRegisters) & ~(1l << FpuTMP);
+      Utils::NBitMask<intptr_t>(kNumberOfFpuRegisters) & ~(1l << FpuTMP);
 
   const intptr_t kNumTemps = (Utils::CountOneBits64(kCpuRegistersToPreserve) +
                               Utils::CountOneBits64(kFpuRegistersToPreserve));
@@ -1496,11 +1496,12 @@
 
   // Load the code object.
   __ LoadFromOffset(R0, THR, compiler::target::Thread::callback_code_offset());
-  __ LoadFieldFromOffset(R0, R0,
-                         compiler::target::GrowableObjectArray::data_offset());
-  __ LoadFieldFromOffset(CODE_REG, R0,
-                         compiler::target::Array::data_offset() +
-                             callback_id_ * compiler::target::kWordSize);
+  __ LoadCompressedFieldFromOffset(
+      R0, R0, compiler::target::GrowableObjectArray::data_offset());
+  __ LoadCompressedFieldFromOffset(
+      CODE_REG, R0,
+      compiler::target::Array::data_offset() +
+          callback_id_ * compiler::target::kCompressedWordSize);
 
   // Put the code object in the reserved slot.
   __ StoreToOffset(CODE_REG, FPREG,
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index cb4c1be..bdde81c 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1387,11 +1387,14 @@
   // Load the code object.
   __ movq(RAX, compiler::Address(
                    THR, compiler::target::Thread::callback_code_offset()));
-  __ movq(RAX, compiler::FieldAddress(
-                   RAX, compiler::target::GrowableObjectArray::data_offset()));
-  __ movq(CODE_REG, compiler::FieldAddress(
-                        RAX, compiler::target::Array::data_offset() +
-                                 callback_id_ * compiler::target::kWordSize));
+  __ LoadCompressed(
+      RAX, compiler::FieldAddress(
+               RAX, compiler::target::GrowableObjectArray::data_offset()));
+  __ LoadCompressed(
+      CODE_REG,
+      compiler::FieldAddress(
+          RAX, compiler::target::Array::data_offset() +
+                   callback_id_ * compiler::target::kCompressedWordSize));
 
   // Put the code object in the reserved slot.
   __ movq(compiler::Address(FPREG,
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 5eec5a4..17a1c15 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2804,6 +2804,7 @@
     case Slot::Kind::kFunctionType_named_parameter_names:
     case Slot::Kind::kFunctionType_parameter_types:
     case Slot::Kind::kFunctionType_type_parameters:
+    case Slot::Kind::kInstance_native_fields_array:
     case Slot::Kind::kPointerBase_data_field:
     case Slot::Kind::kTypedDataView_data:
     case Slot::Kind::kType_arguments:
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index cd8e80c..9f84201 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -210,6 +210,7 @@
     case Slot::Kind::kArgumentsDescriptor_count:
     case Slot::Kind::kArgumentsDescriptor_size:
     case Slot::Kind::kArrayElement:
+    case Slot::Kind::kInstance_native_fields_array:
     case Slot::Kind::kTypeArguments:
     case Slot::Kind::kTypedDataView_offset_in_bytes:
     case Slot::Kind::kTypedDataView_data:
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 866e399..27adf00 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -61,6 +61,7 @@
   V(Closure, UntaggedClosure, function_type_arguments, TypeArguments, FINAL)   \
   V(FunctionType, UntaggedFunctionType, type_parameters, TypeParameters,       \
     FINAL)                                                                     \
+  V(Instance, UntaggedInstance, native_fields_array, Dynamic, VAR)             \
   V(Type, UntaggedType, arguments, TypeArguments, FINAL)                       \
   V(TypeParameters, UntaggedTypeParameters, flags, Array, FINAL)               \
   V(TypeParameters, UntaggedTypeParameters, bounds, TypeArguments, FINAL)      \
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 9aecb2c..06edf78 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -699,7 +699,7 @@
 }
 
 CompileType CompileType::Int32() {
-#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
+#if defined(HAS_SMI_63_BITS)
   return FromCid(kSmiCid);
 #else
   return Int();
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
index f2c7656..6040fb1 100644
--- a/runtime/vm/compiler/frontend/constant_reader.cc
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -353,6 +353,18 @@
       instance = function.ImplicitStaticClosure();
       break;
     }
+    case kConstructorTearOffConstant: {
+      const NameIndex index = reader.ReadCanonicalNameReference();
+      Function& function = Function::Handle(Z);
+      if (H.IsConstructor(index)) {
+        function = H.LookupConstructorByKernelConstructor(index);
+      } else {
+        function = H.LookupStaticMethodByKernelProcedure(index);
+      }
+      function = function.ImplicitClosureFunction();
+      instance = function.ImplicitStaticClosure();
+      break;
+    }
     case kTypeLiteralConstant: {
       // Build type from the raw bytes (needs temporary translator).
       // Const canonical type erasure is not applied to constant type literals.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 7a07552..257ee0e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -230,7 +230,7 @@
     bool has_field_initializers = false;
     for (intptr_t i = 0; i < list_length; ++i) {
       if (PeekTag() == kRedirectingInitializer ||
-          PeekTag() == kRedirectingFactoryConstructor) {
+          PeekTag() == kRedirectingFactory) {
         is_redirecting_constructor = true;
       } else if (PeekTag() == kFieldInitializer) {
         has_field_initializers = true;
@@ -2855,7 +2855,7 @@
 
   // read flags.
   const uint8_t flags = is_dynamic ? 0 : ReadFlags();
-  const bool is_invariant = (flags & kMethodInvocationFlagInvariant) != 0;
+  const bool is_invariant = (flags & kInstanceInvocationFlagInvariant) != 0;
 
   const TokenPosition position = ReadPosition();  // read position.
   if (p != NULL) *p = position;
@@ -5299,7 +5299,9 @@
         if (!closure_owner_.IsNull()) {
           function = Function::NewClosureFunctionWithKind(
               UntaggedFunction::kClosureFunction, *name,
-              parsed_function()->function(), position, closure_owner_);
+              parsed_function()->function(),
+              parsed_function()->function().is_static(), position,
+              closure_owner_);
         } else {
           function = Function::NewClosureFunction(
               *name, parsed_function()->function(), position);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 6968ff1..68cdb57 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -854,6 +854,7 @@
     case MethodRecognizer::kFfiStorePointer:
     case MethodRecognizer::kFfiFromAddress:
     case MethodRecognizer::kFfiGetAddress:
+    case MethodRecognizer::kGetNativeField:
     case MethodRecognizer::kObjectEquals:
     case MethodRecognizer::kStringBaseLength:
     case MethodRecognizer::kStringBaseIsEmpty:
@@ -1485,12 +1486,26 @@
       body += Box(kUnboxedFfiIntPtr);
     } break;
     case MethodRecognizer::kHas63BitSmis: {
-#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
+#if defined(HAS_SMI_63_BITS)
       body += Constant(Bool::True());
 #else
       body += Constant(Bool::False());
 #endif  // defined(ARCH_IS_64_BIT)
     } break;
+    case MethodRecognizer::kGetNativeField: {
+      auto& name = String::ZoneHandle(Z, function.name());
+      // Note: This method is force optimized so we can push untagged, etc.
+      // Load TypedDataArray from Instance Handle implementing
+      // NativeFieldWrapper.
+      body += LoadLocal(parsed_function_->RawParameterVariable(0));  // Object.
+      body += CheckNullOptimized(TokenPosition::kNoSource, name);
+      body += LoadNativeField(Slot::Instance_native_fields_array());  // Fields.
+      body += CheckNullOptimized(TokenPosition::kNoSource, name);
+      // Load the native field at index.
+      body += IntConstant(0);  // Index.
+      body += LoadIndexed(kIntPtrCid);
+      body += Box(kUnboxedIntPtr);
+    } break;
     default: {
       UNREACHABLE();
       break;
@@ -3410,13 +3425,45 @@
 
   intptr_t type_args_len = 0;
   if (function.IsGeneric()) {
-    type_args_len = function.NumTypeParameters();
-    ASSERT(parsed_function_->function_type_arguments() != NULL);
-    closure += LoadLocal(parsed_function_->function_type_arguments());
+    if (target.IsConstructor()) {
+      const auto& result_type = AbstractType::Handle(Z, function.result_type());
+      ASSERT(result_type.IsFinalized());
+      // Instantiate a flattened type arguments vector which
+      // includes type arguments corresponding to superclasses.
+      // TranslateInstantiatedTypeArguments is smart enough to
+      // avoid instantiation and resuse passed function type arguments
+      // if there are no extra type arguments in the flattened vector.
+      const auto& instantiated_type_arguments =
+          TypeArguments::ZoneHandle(Z, result_type.arguments());
+      closure +=
+          TranslateInstantiatedTypeArguments(instantiated_type_arguments);
+    } else {
+      type_args_len = function.NumTypeParameters();
+      ASSERT(parsed_function_->function_type_arguments() != NULL);
+      closure += LoadLocal(parsed_function_->function_type_arguments());
+    }
+  } else if (target.IsFactory()) {
+    // Factories always take an extra implicit argument for
+    // type arguments even if their classes don't have type parameters.
+    closure += NullConstant();
   }
 
   // Push receiver.
-  if (!target.is_static()) {
+  if (target.IsGenerativeConstructor()) {
+    const Class& cls = Class::Handle(Z, target.Owner());
+    if (cls.NumTypeArguments() > 0) {
+      if (!function.IsGeneric()) {
+        Type& cls_type = Type::Handle(Z, cls.DeclarationType());
+        closure += Constant(TypeArguments::ZoneHandle(Z, cls_type.arguments()));
+      }
+      closure += AllocateObject(function.token_pos(), cls, 1);
+    } else {
+      ASSERT(!function.IsGeneric());
+      closure += AllocateObject(function.token_pos(), cls, 0);
+    }
+    LocalVariable* receiver = MakeTemporary();
+    closure += LoadLocal(receiver);
+  } else if (!target.is_static()) {
     // The context has a fixed shape: a single variable which is the
     // closed-over receiver.
     closure += LoadLocal(parsed_function_->ParameterVariable(0));
@@ -3430,7 +3477,7 @@
   // Forward parameters to the target.
   intptr_t argument_count = function.NumParameters() -
                             function.NumImplicitParameters() +
-                            (target.is_static() ? 0 : 1);
+                            target.NumImplicitParameters();
   ASSERT(argument_count == target.NumParameters());
 
   Array& argument_names =
@@ -3440,6 +3487,12 @@
                         argument_names, ICData::kNoRebind,
                         /* result_type = */ NULL, type_args_len);
 
+  if (target.IsGenerativeConstructor()) {
+    // Drop result of constructor invocation, leave receiver
+    // instance on the stack.
+    closure += Drop();
+  }
+
   // Return the result.
   closure += Return(function.end_token_pos());
 
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 11b2fea..99a51ea 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -3389,6 +3389,10 @@
   ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());
   ASSERT(type_parameter_count >= 0);
   if (type_parameter_count == 0) {
+    ASSERT(parameterized_class.IsNull() ||
+           parameterized_class.type_parameters() == TypeParameters::null());
+    ASSERT(parameterized_signature.IsNull() ||
+           parameterized_signature.type_parameters() == TypeParameters::null());
     return;
   }
 
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index c8e3ca3..e9a4807 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -554,7 +554,7 @@
     kConst = 1 << 3,  // Only for external const factories.
 
     // TODO(29841): Remove this line after the issue is resolved.
-    kRedirectingFactoryConstructor = 1 << 4,
+    kRedirectingFactory = 1 << 4,
     kExtensionMember = 1 << 5,
     kSyntheticProcedure = 1 << 7,
   };
@@ -579,8 +579,8 @@
     return stub_kind_ == kAbstractForwardingStubKind ||
            stub_kind_ == kConcreteForwardingStubKind;
   }
-  bool IsRedirectingFactoryConstructor() const {
-    return (flags_ & kRedirectingFactoryConstructor) != 0;
+  bool IsRedirectingFactory() const {
+    return (flags_ & kRedirectingFactory) != 0;
   }
   bool IsNoSuchMethodForwarder() const {
     return stub_kind_ == kNoSuchMethodForwarderStubKind;
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index 035bf63..635b3d9 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -68,6 +68,11 @@
   if (expect_type_args) {
     Fragment f = BuildTypeArgumentsHandling();
     if (link) prologue += f;
+
+    if (function_.IsClosureFunction()) {
+      Fragment f = BuildClosureDelayedTypeArgumentsHandling();
+      if (!compiling_for_osr_) prologue += f;
+    }
   }
 
   const bool is_empty_prologue = prologue.entry == prologue.current;
@@ -372,29 +377,33 @@
 
   handling += TestTypeArgsLen(store_null, store_type_args, 0);
 
-  const auto& function = parsed_function_->function();
-  if (function.IsClosureFunction()) {
-    LocalVariable* closure = parsed_function_->ParameterVariable(0);
-
-    // Currently, delayed type arguments can only be introduced through type
-    // inference in the FE. So if they are present, we can assume they are
-    // correct in number and bound.
-    Fragment use_delayed_type_args;
-    use_delayed_type_args += LoadLocal(closure);
-    use_delayed_type_args +=
-        LoadNativeField(Slot::Closure_delayed_type_arguments());
-    use_delayed_type_args +=
-        StoreLocal(TokenPosition::kNoSource, type_args_var);
-    use_delayed_type_args += Drop();
-
-    handling += TestDelayedTypeArgs(closure,
-                                    /*present=*/use_delayed_type_args,
-                                    /*absent=*/Fragment());
-  }
-
   return handling;
 }
 
+Fragment PrologueBuilder::BuildClosureDelayedTypeArgumentsHandling() {
+  const auto& function = parsed_function_->function();
+  ASSERT(function.IsClosureFunction());
+  LocalVariable* const type_args_var =
+      parsed_function_->RawTypeArgumentsVariable();
+  ASSERT(type_args_var != nullptr);
+
+  LocalVariable* const closure = parsed_function_->ParameterVariable(0);
+
+  // Currently, delayed type arguments can only be introduced through type
+  // inference in the FE. So if they are present, we can assume they are
+  // correct in number and bound.
+  Fragment use_delayed_type_args;
+  use_delayed_type_args += LoadLocal(closure);
+  use_delayed_type_args +=
+      LoadNativeField(Slot::Closure_delayed_type_arguments());
+  use_delayed_type_args += StoreLocal(TokenPosition::kNoSource, type_args_var);
+  use_delayed_type_args += Drop();
+
+  return TestDelayedTypeArgs(closure,
+                             /*present=*/use_delayed_type_args,
+                             /*absent=*/Fragment());
+}
+
 void PrologueBuilder::SortOptionalNamedParametersInto(int* opt_param_position,
                                                       int num_fixed_params,
                                                       int num_params) {
diff --git a/runtime/vm/compiler/frontend/prologue_builder.h b/runtime/vm/compiler/frontend/prologue_builder.h
index c8d629d..d474d72 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.h
+++ b/runtime/vm/compiler/frontend/prologue_builder.h
@@ -61,6 +61,8 @@
 
   Fragment BuildTypeArgumentsHandling();
 
+  Fragment BuildClosureDelayedTypeArgumentsHandling();
+
   LocalVariable* ParameterVariable(intptr_t index) {
     return parsed_function_->RawParameterVariable(index);
   }
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index b2a6031..0205fe4 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -604,13 +604,11 @@
     LocalVariable* future = scope_->LookupVariable(Symbols::_future(), true);
     ASSERT(future != nullptr);
     future->set_is_chained_future();
-    future->set_expected_context_index(Context::kFutureTimeoutFutureIndex);
   } else if (function.recognized_kind() == MethodRecognizer::kFutureWait &&
              depth_.function_ == 1) {
     LocalVariable* future = scope_->LookupVariable(Symbols::_future(), true);
     ASSERT(future != nullptr);
     future->set_is_chained_future();
-    future->set_expected_context_index(Context::kFutureWaitFutureIndex);
   }
 }
 
@@ -1454,9 +1452,6 @@
 
 void ScopeBuilder::VisitTypeParameterType() {
   Function& function = Function::Handle(Z, parsed_function_->function().ptr());
-  while (function.IsClosureFunction()) {
-    function = function.parent_function();
-  }
 
   helper_.ReadNullability();  // read nullability.
 
@@ -1467,19 +1462,25 @@
 
   intptr_t index = helper_.ReadUInt();  // read index for parameter.
 
-  if (function.IsFactory()) {
-    // The type argument vector is passed as the very first argument to the
-    // factory constructor function.
-    HandleSpecialLoad(&result_->type_arguments_variable,
-                      Symbols::TypeArgumentsParameter());
-  } else {
-    // If the type parameter is a parameter to this or an enclosing function, we
-    // can read it directly from the function type arguments vector later.
-    // Otherwise, the type arguments vector we need is stored on the instance
-    // object, so we need to capture 'this'.
-    Class& parent_class = Class::Handle(Z, function.Owner());
-    if (index < parent_class.NumTypeParameters()) {
-      HandleLoadReceiver();
+  if (!function.IsImplicitStaticClosureFunction()) {
+    while (function.IsClosureFunction()) {
+      function = function.parent_function();
+    }
+
+    if (function.IsFactory()) {
+      // The type argument vector is passed as the very first argument to the
+      // factory constructor function.
+      HandleSpecialLoad(&result_->type_arguments_variable,
+                        Symbols::TypeArgumentsParameter());
+    } else {
+      // If the type parameter is a parameter to this or an enclosing function,
+      // we can read it directly from the function type arguments vector later.
+      // Otherwise, the type arguments vector we need is stored on the instance
+      // object, so we need to capture 'this'.
+      Class& parent_class = Class::Handle(Z, function.Owner());
+      if (index < parent_class.NumTypeParameters()) {
+        HandleLoadReceiver();
+      }
     }
   }
 
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 0104e80..c9f4f86 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -212,7 +212,7 @@
   ASSERT(thread->IsMutatorThread());
   const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
 
-  if (IsolateGroup::AreIsolateGroupsEnabled()) {
+  if (FLAG_enable_isolate_groups) {
     // Another isolate's mutator thread may have created [function] and
     // published it via an ICData, MegamorphicCache etc. Entering the lock below
     // is an acquire operation that pairs with the release operation when the
@@ -225,7 +225,7 @@
   // there's no existing code. In multi-isolate scenarios with shared JITed code
   // we can end up in the lazy compile runtime entry here with code being
   // installed.
-  ASSERT(!function.HasCode() || IsolateGroup::AreIsolateGroupsEnabled());
+  ASSERT(!function.HasCode() || FLAG_enable_isolate_groups);
 
   // Will throw if compilation failed (e.g. with compile-time error).
   function.EnsureHasCode();
@@ -514,14 +514,6 @@
                                    CompilerState::ShouldTrace(function));
 
       {
-        if (optimized()) {
-          // In background compilation the deoptimization counter may have
-          // already reached the limit.
-          ASSERT(Compiler::IsBackgroundCompilation() ||
-                 (function.deoptimization_counter() <
-                  FLAG_max_deoptimization_counter_threshold));
-        }
-
         // Extract type feedback before the graph is built, as the graph
         // builder uses it to attach it to nodes.
         ic_data_array = new (zone) ZoneGrowableArray<const ICData*>();
diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc
index 0c5a85a..af01254 100644
--- a/runtime/vm/compiler/method_recognizer.cc
+++ b/runtime/vm/compiler/method_recognizer.cc
@@ -290,6 +290,7 @@
   libs->Add(&Library::ZoneHandle(Library::DeveloperLibrary()));
   libs->Add(&Library::ZoneHandle(Library::AsyncLibrary()));
   libs->Add(&Library::ZoneHandle(Library::FfiLibrary()));
+  libs->Add(&Library::ZoneHandle(Library::NativeWrappersLibrary()));
 }
 
 static Token::Kind RecognizeTokenKindHelper(const String& name) {
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index f45e224..9680f0b 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -197,6 +197,7 @@
   V(::, _storePointer, FfiStorePointer, 0xea6b7751)                            \
   V(::, _fromAddress, FfiFromAddress, 0xfd8cb1cc)                              \
   V(Pointer, get:address, FfiGetAddress, 0x7cde87be)                           \
+  V(::, getNativeField, GetNativeField, 0x95b4ec94)                            \
   V(::, reachabilityFence, ReachabilityFence, 0x619235c1)                      \
   V(_Utf8Decoder, _scan, Utf8DecoderScan, 0x1dcaf73d)                          \
   V(_Future, timeout, FutureTimeout, 0x73041520)                               \
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index c289e46..c8e499b 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -315,8 +315,8 @@
 const word kOldPageMask = dart::kOldPageMask;
 
 static word TranslateOffsetInWordsToHost(word offset) {
-  RELEASE_ASSERT((offset % kWordSize) == 0);
-  return (offset / kWordSize) * dart::kWordSize;
+  RELEASE_ASSERT((offset % kCompressedWordSize) == 0);
+  return (offset / kCompressedWordSize) * dart::kCompressedWordSize;
 }
 
 bool SizeFitsInSizeTag(uword instance_size) {
@@ -410,6 +410,8 @@
       return TypedDataBase::InstanceSize();
     case kLinkedHashMapCid:
       return LinkedHashMap::InstanceSize();
+    case kLinkedHashSetCid:
+      return LinkedHashSet::InstanceSize();
     case kUnhandledExceptionCid:
       return UnhandledException::InstanceSize();
     case kWeakPropertyCid:
@@ -475,6 +477,10 @@
   return TranslateOffsetInWords(dart::Instance::NextFieldOffset());
 }
 
+word Instance::native_fields_array_offset() {
+  return TranslateOffsetInWords(dart::Instance::NativeFieldsOffset());
+}
+
 word Instance::DataOffsetFor(intptr_t cid) {
   if (dart::IsExternalTypedDataClassId(cid) ||
       dart::IsExternalStringClassId(cid)) {
@@ -960,243 +966,19 @@
   return TranslateOffsetInWords(dart::Instance::NextFieldOffset());
 }
 
-word Pointer::NextFieldOffset() {
-  return TranslateOffsetInWords(dart::Pointer::NextFieldOffset());
-}
-
-word WeakSerializationReference::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ObjectPool::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Class::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Function::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ICData::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word MegamorphicCache::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word SingleTargetCache::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Array::NextFieldOffset() {
-  return -kWordSize;
-}
-
 intptr_t Array::index_at_offset(intptr_t offset_in_bytes) {
   return dart::Array::index_at_offset(
       TranslateOffsetInWordsToHost(offset_in_bytes));
 }
 
-word GrowableObjectArray::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word TypedDataBase::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word TypedData::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ExternalTypedData::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word TypedDataView::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word LinkedHashMap::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word AbstractType::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Type::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word FunctionType::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word TypeRef::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Double::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Mint::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word String::NextFieldOffset() {
-  return -kWordSize;
-}
-
 word String::InstanceSize(word payload_size) {
   return RoundedAllocationSize(String::InstanceSize() + payload_size);
 }
 
-word OneByteString::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word TwoByteString::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ExternalOneByteString::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ExternalTwoByteString::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Int32x4::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Float32x4::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Float64x2::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word DynamicLibrary::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word PatchClass::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word FfiTrampolineData::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Script::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Library::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Namespace::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word KernelProgramInfo::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word PcDescriptors::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word CodeSourceMap::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word CompressedStackMaps::NextFieldOffset() {
-  return -kWordSize;
-}
-
 word LocalVarDescriptors::InstanceSize() {
   return 0;
 }
 
-word LocalVarDescriptors::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ExceptionHandlers::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ContextScope::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Sentinel::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word UnlinkedCall::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ApiError::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word LanguageError::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word UnhandledException::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word UnwindError::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Bool::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word TypeParameter::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word LibraryPrefix::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Capability::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ReceivePort::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word SendPort::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word TransferableTypedData::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word StackTrace::NextFieldOffset() {
-  return -kWordSize;
-}
-
 word Integer::NextFieldOffset() {
   return TranslateOffsetInWords(dart::Integer::NextFieldOffset());
 }
@@ -1205,94 +987,10 @@
   return 0;
 }
 
-word Smi::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word WeakProperty::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word MirrorReference::NextFieldOffset() {
-  return -kWordSize;
-}
-
 word Number::NextFieldOffset() {
   return TranslateOffsetInWords(dart::Number::NextFieldOffset());
 }
 
-word MonomorphicSmiableCall::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word InstructionsSection::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word InstructionsTable::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Instructions::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Code::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word SubtypeTestCache::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word LoadingUnit::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Context::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Closure::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ClosureData::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word RegExp::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word UserTag::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word FutureOr::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word Field::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word TypeParameters::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word TypeArguments::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word FreeListElement::FakeInstance::NextFieldOffset() {
-  return -kWordSize;
-}
-
-word ForwardingCorpse::FakeInstance::NextFieldOffset() {
-  return -kWordSize;
-}
-
 }  // namespace target
 }  // namespace compiler
 }  // namespace dart
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index fb22d3b..52642b1 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -419,6 +419,9 @@
 
 bool WillAllocateNewOrRememberedArray(intptr_t length);
 
+#define FINAL_CLASS()                                                          \
+  static word NextFieldOffset() { return -kWordSize; }
+
 //
 // Target specific offsets and constants.
 //
@@ -461,7 +464,7 @@
   static word element_offset(intptr_t index);
   static word InstanceSize(intptr_t length);
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Class : public AllStatic {
@@ -480,7 +483,7 @@
 
   static word InstanceSize();
 
-  static word NextFieldOffset();
+  FINAL_CLASS();
 
   // Return class id of the given class on the target.
   static classid_t GetId(const dart::Class& handle);
@@ -508,8 +511,8 @@
 class Instance : public AllStatic {
  public:
   // Returns the offset to the first field of [UntaggedInstance].
-  // Returns the offset to the first field of [UntaggedInstance].
   static word first_field_offset();
+  static word native_fields_array_offset();
   static word DataOffsetFor(intptr_t cid);
   static word ElementSizeFor(intptr_t cid);
   static word InstanceSize();
@@ -526,7 +529,7 @@
   static word signature_offset();
   static word usage_counter_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class CallSiteData : public AllStatic {
@@ -550,7 +553,7 @@
   static word NumArgsTestedShift();
   static word NumArgsTestedMask();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class MegamorphicCache : public AllStatic {
@@ -559,7 +562,7 @@
   static word mask_offset();
   static word buckets_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class SingleTargetCache : public AllStatic {
@@ -569,7 +572,7 @@
   static word entry_point_offset();
   static word target_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Array : public AllStatic {
@@ -583,7 +586,7 @@
   static intptr_t index_at_offset(intptr_t offset_in_bytes);
   static word InstanceSize(intptr_t length);
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 
   static const word kMaxElements;
   static const word kMaxNewSpaceElements;
@@ -595,7 +598,7 @@
   static word type_arguments_offset();
   static word length_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class PointerBase : public AllStatic {
@@ -607,7 +610,7 @@
  public:
   static word length_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class TypedData : public AllStatic {
@@ -616,14 +619,14 @@
   static word HeaderSize();
   static word InstanceSize();
   static word InstanceSize(word lengthInBytes);
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class ExternalTypedData : public AllStatic {
  public:
   static word data_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class TypedDataView : public AllStatic {
@@ -631,7 +634,7 @@
   static word offset_in_bytes_offset();
   static word data_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class LinkedHashBase : public AllStatic {
@@ -647,14 +650,19 @@
 
 class LinkedHashMap : public LinkedHashBase {
  public:
-  static word NextFieldOffset();
+  FINAL_CLASS();
+};
+
+class LinkedHashSet : public LinkedHashBase {
+ public:
+  FINAL_CLASS();
 };
 
 class FutureOr : public AllStatic {
  public:
   static word type_arguments_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class ArgumentsDescriptor : public AllStatic {
@@ -678,14 +686,14 @@
  public:
   static word type_arguments_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class AbstractType : public AllStatic {
  public:
   static word type_test_stub_entry_point_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Type : public AllStatic {
@@ -696,7 +704,7 @@
   static word type_class_id_offset();
   static word nullability_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class FunctionType : public AllStatic {
@@ -710,14 +718,14 @@
   static word type_parameters_offset();
   static word nullability_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class TypeRef : public AllStatic {
  public:
   static word type_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Nullability : public AllStatic {
@@ -731,14 +739,14 @@
  public:
   static word value_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Mint : public AllStatic {
  public:
   static word value_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class String : public AllStatic {
@@ -748,8 +756,8 @@
   static word hash_offset();
   static word length_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
   static word InstanceSize(word payload_size);
+  FINAL_CLASS();
 };
 
 class OneByteString : public AllStatic {
@@ -757,7 +765,7 @@
   static word data_offset();
   static word InstanceSize(intptr_t length);
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 
  private:
   static word element_offset(intptr_t index);
@@ -768,7 +776,7 @@
   static word data_offset();
   static word InstanceSize(intptr_t length);
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 
  private:
   static word element_offset(intptr_t index);
@@ -778,77 +786,77 @@
  public:
   static word external_data_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class ExternalTwoByteString : public AllStatic {
  public:
   static word external_data_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Int32x4 : public AllStatic {
  public:
   static word value_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Float32x4 : public AllStatic {
  public:
   static word value_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Float64x2 : public AllStatic {
  public:
   static word value_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class DynamicLibrary : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class PatchClass : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class FfiTrampolineData : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Script : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Library : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Namespace : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class KernelProgramInfo : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class PcDescriptors : public AllStatic {
@@ -856,7 +864,7 @@
   static word HeaderSize();
   static word InstanceSize();
   static word InstanceSize(word payload_size);
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class CodeSourceMap : public AllStatic {
@@ -864,7 +872,7 @@
   static word HeaderSize();
   static word InstanceSize();
   static word InstanceSize(word payload_size);
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class CompressedStackMaps : public AllStatic {
@@ -872,13 +880,13 @@
   static word HeaderSize();
   static word InstanceSize();
   static word InstanceSize(word payload_size);
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class LocalVarDescriptors : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class ExceptionHandlers : public AllStatic {
@@ -886,7 +894,7 @@
   static word element_offset(intptr_t index);
   static word InstanceSize(intptr_t length);
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class ContextScope : public AllStatic {
@@ -894,31 +902,31 @@
   static word element_offset(intptr_t index);
   static word InstanceSize(intptr_t length);
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Sentinel : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class UnlinkedCall : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class ApiError : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class LanguageError : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class UnhandledException : public AllStatic {
@@ -926,19 +934,19 @@
   static word exception_offset();
   static word stacktrace_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class UnwindError : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Bool : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class TypeParameter : public AllStatic {
@@ -946,7 +954,7 @@
   static word bound_offset();
   static word flags_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
   static word parameterized_class_id_offset();
   static word index_offset();
   static word nullability_offset();
@@ -955,37 +963,37 @@
 class LibraryPrefix : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Capability : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class ReceivePort : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class SendPort : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class TransferableTypedData : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class StackTrace : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Integer : public AllStatic {
@@ -997,7 +1005,7 @@
 class Smi : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class WeakProperty : public AllStatic {
@@ -1005,13 +1013,13 @@
   static word key_offset();
   static word value_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class MirrorReference : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Number : public AllStatic {
@@ -1036,7 +1044,7 @@
   static word entrypoint_offset();
   static word target_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Thread : public AllStatic {
@@ -1222,7 +1230,7 @@
   static word HeaderSize();
   static word InstanceSize();
   static word InstanceSize(word payload_size);
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class InstructionsTable : public AllStatic {
@@ -1230,7 +1238,7 @@
   static word HeaderSize();
   static word InstanceSize();
   static word InstanceSize(intptr_t length);
-  static word NextFieldOffset();
+  FINAL_CLASS();
 
  private:
   static word element_offset(intptr_t index);
@@ -1248,7 +1256,7 @@
   static word HeaderSize();
   static word InstanceSize();
   static word InstanceSize(word payload_size);
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Code : public AllStatic {
@@ -1264,7 +1272,7 @@
   static word HeaderSize();
   static word InstanceSize();
   static word InstanceSize(intptr_t length);
-  static word NextFieldOffset();
+  FINAL_CLASS();
 
  private:
   static word element_offset(intptr_t index);
@@ -1273,7 +1281,7 @@
 class WeakSerializationReference : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class SubtypeTestCache : public AllStatic {
@@ -1290,13 +1298,13 @@
   static const word kInstanceDelayedFunctionTypeArguments;
   static const word kTestResult;
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class LoadingUnit : public AllStatic {
  public:
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Context : public AllStatic {
@@ -1307,7 +1315,7 @@
   static word variable_offset(intptr_t index);
   static word InstanceSize(intptr_t length);
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Closure : public AllStatic {
@@ -1320,14 +1328,14 @@
   static word instantiator_type_arguments_offset();
   static word hash_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class ClosureData : public AllStatic {
  public:
   static word default_type_arguments_kind_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class OldPage : public AllStatic {
@@ -1363,14 +1371,14 @@
  public:
   static word function_offset(classid_t cid, bool sticky);
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class UserTag : public AllStatic {
  public:
   static word tag_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class Symbols : public AllStatic {
@@ -1391,7 +1399,7 @@
   static word initializer_function_offset();
   static word host_offset_or_field_id_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class TypeParameters : public AllStatic {
@@ -1401,7 +1409,7 @@
   static word bounds_offset();
   static word defaults_offset();
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 };
 
 class TypeArguments : public AllStatic {
@@ -1413,7 +1421,7 @@
   static word types_offset();
   static word InstanceSize(intptr_t length);
   static word InstanceSize();
-  static word NextFieldOffset();
+  FINAL_CLASS();
 
   static const word kMaxElements;
 };
@@ -1423,7 +1431,7 @@
   class FakeInstance : public AllStatic {
    public:
     static word InstanceSize();
-    static word NextFieldOffset();
+    FINAL_CLASS();
   };
 };
 
@@ -1432,7 +1440,7 @@
   class FakeInstance : public AllStatic {
    public:
     static word InstanceSize();
-    static word NextFieldOffset();
+    FINAL_CLASS();
   };
 };
 
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index b57c17d..99f76c0 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -195,16 +195,16 @@
     IsolateGroup_cached_class_table_table_offset = 16;
 static constexpr dart::compiler::target::word Isolate_single_step_offset = 36;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 24;
+    LinkedHashBase_deleted_keys_offset = 20;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    12;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 8;
+    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 =
-    20;
+    16;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
@@ -220,11 +220,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    128;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
+    184;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 124;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    156;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
+    212;
+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;
@@ -245,9 +246,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    724;
+    732;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    728;
+    736;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -272,7 +273,7 @@
     Thread_allocate_object_slow_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 764;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 772;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -283,7 +284,7 @@
     Thread_call_to_runtime_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 772;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 780;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -301,7 +302,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    744;
+    752;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -321,13 +322,13 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    732;
+    740;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    760;
+    768;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 776;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 784;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
@@ -369,11 +370,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 736;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 744;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 740;
+    Thread_saved_shadow_call_stack_offset = 748;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    748;
+    756;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -407,9 +408,9 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 752;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 760;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 756;
+    Thread_callback_stack_return_offset = 764;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -469,7 +470,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
+        700, 704, 708, 712, 716, -1, 720, -1, 724, 728, -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;
@@ -737,16 +738,16 @@
     IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word Isolate_single_step_offset = 72;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 32;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 48;
+    LinkedHashBase_deleted_keys_offset = 40;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    24;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 16;
+    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 =
-    40;
+    32;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
@@ -762,11 +763,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+    368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    424;
+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 =
@@ -788,9 +790,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1464;
+    1480;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1472;
+    1488;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -816,7 +818,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -827,7 +829,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1576;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -845,7 +847,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1504;
+    1520;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -865,14 +867,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1480;
+    1496;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1536;
+    1552;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -914,11 +916,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1504;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1496;
+    Thread_saved_shadow_call_stack_offset = 1512;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1512;
+    1528;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -953,9 +955,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1528;
+    Thread_callback_stack_return_offset = 1544;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -1016,8 +1018,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
-        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
+        1392, 1400, 1408, 1416, -1,   -1,   1424, 1432,
+        1440, 1448, 1456, -1,   1464, 1472, -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;
@@ -1284,16 +1286,16 @@
     IsolateGroup_cached_class_table_table_offset = 16;
 static constexpr dart::compiler::target::word Isolate_single_step_offset = 36;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 24;
+    LinkedHashBase_deleted_keys_offset = 20;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    12;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 8;
+    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 =
-    20;
+    16;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
@@ -1309,11 +1311,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    128;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
+    184;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 124;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    156;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
+    212;
+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;
@@ -1334,9 +1337,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    692;
+    700;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    696;
+    704;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -1361,7 +1364,7 @@
     Thread_allocate_object_slow_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 732;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 740;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -1372,7 +1375,7 @@
     Thread_call_to_runtime_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 740;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 748;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -1390,7 +1393,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    712;
+    720;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -1410,13 +1413,13 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    700;
+    708;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    728;
+    736;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 744;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 752;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
@@ -1458,11 +1461,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 704;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 712;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 708;
+    Thread_saved_shadow_call_stack_offset = 716;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    716;
+    724;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -1496,9 +1499,9 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 720;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 728;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 724;
+    Thread_callback_stack_return_offset = 732;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -1823,16 +1826,16 @@
     IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word Isolate_single_step_offset = 72;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 32;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 48;
+    LinkedHashBase_deleted_keys_offset = 40;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    24;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 16;
+    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 =
-    40;
+    32;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
@@ -1848,11 +1851,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+    368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    424;
+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 =
@@ -1874,9 +1878,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1528;
+    1544;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1536;
+    1552;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -1902,7 +1906,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -1913,7 +1917,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 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 = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -1931,7 +1935,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -1951,14 +1955,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1600;
+    1616;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -2000,11 +2004,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1568;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1560;
+    Thread_saved_shadow_call_stack_offset = 1576;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -2039,9 +2043,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1592;
+    Thread_callback_stack_return_offset = 1608;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -2102,9 +2106,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
-        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
-        -1,   1512, 1520, 1528, -1,   -1,   -1,   -1,   -1,   -1};
+        1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+        1480, 1488, 1496, 1504, -1,   -1,   -1,   -1,   1512, 1520, -1,
+        -1,   1528, 1536, 1544, -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;
@@ -2371,16 +2375,16 @@
     IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word Isolate_single_step_offset = 72;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 28;
+    LinkedHashBase_deleted_keys_offset = 24;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    16;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 12;
+    12;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 28;
 static constexpr dart::compiler::target::word
     LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
-    24;
+    20;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
@@ -2396,11 +2400,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+    368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    424;
+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 =
@@ -2422,9 +2427,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1464;
+    1480;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1472;
+    1488;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -2450,7 +2455,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -2461,7 +2466,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1576;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -2479,7 +2484,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1504;
+    1520;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -2499,14 +2504,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1480;
+    1496;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1536;
+    1552;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -2548,11 +2553,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1504;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1496;
+    Thread_saved_shadow_call_stack_offset = 1512;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1512;
+    1528;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -2587,33 +2592,33 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1528;
+    Thread_callback_stack_return_offset = 1544;
 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 = 28;
-static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
-static constexpr dart::compiler::target::word Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word FunctionType_hash_offset = 36;
+static constexpr dart::compiler::target::word Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word Type_hash_offset = 32;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
-    FunctionType_packed_parameter_counts_offset = 40;
+    FunctionType_packed_parameter_counts_offset = 44;
 static constexpr dart::compiler::target::word
-    FunctionType_packed_type_parameter_counts_offset = 44;
+    FunctionType_packed_type_parameter_counts_offset = 48;
 static constexpr dart::compiler::target::word
-    FunctionType_parameter_types_offset = 28;
+    FunctionType_parameter_types_offset = 32;
 static constexpr dart::compiler::target::word
-    FunctionType_named_parameter_names_offset = 32;
+    FunctionType_named_parameter_names_offset = 36;
 static constexpr dart::compiler::target::word
-    FunctionType_type_parameters_offset = 20;
+    FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
+    TypeParameter_parameterized_class_id_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 35;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    33;
+    37;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
@@ -2625,13 +2630,13 @@
 static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 16;
 static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
     20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 32;
-static constexpr dart::compiler::target::word TypeRef_type_offset = 20;
-static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
 static constexpr dart::compiler::target::word
-    TypedDataView_offset_in_bytes_offset = 24;
+    TypedDataView_offset_in_bytes_offset = 28;
 static constexpr dart::compiler::target::word TypedData_data_offset = 24;
 static constexpr dart::compiler::target::word
     UnhandledException_exception_offset = 8;
@@ -2650,8 +2655,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
-        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
+        1392, 1400, 1408, 1416, -1,   -1,   1424, 1432,
+        1440, 1448, 1456, -1,   1464, 1472, -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;
@@ -2678,7 +2683,7 @@
 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 = 96;
-static constexpr dart::compiler::target::word FunctionType_InstanceSize = 48;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 56;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     24;
@@ -2726,7 +2731,7 @@
 static constexpr dart::compiler::target::word Type_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 24;
-static constexpr dart::compiler::target::word TypeRef_InstanceSize = 24;
+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 = 32;
@@ -2918,16 +2923,16 @@
     IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word Isolate_single_step_offset = 72;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 28;
+    LinkedHashBase_deleted_keys_offset = 24;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    16;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 12;
+    12;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 28;
 static constexpr dart::compiler::target::word
     LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
-    24;
+    20;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
@@ -2943,11 +2948,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+    368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    424;
+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 =
@@ -2969,9 +2975,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1528;
+    1544;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1536;
+    1552;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -2997,7 +3003,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -3008,7 +3014,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 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 = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -3026,7 +3032,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -3046,14 +3052,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1600;
+    1616;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -3095,11 +3101,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1568;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1560;
+    Thread_saved_shadow_call_stack_offset = 1576;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -3134,33 +3140,33 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1592;
+    Thread_callback_stack_return_offset = 1608;
 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 = 28;
-static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
-static constexpr dart::compiler::target::word Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word FunctionType_hash_offset = 36;
+static constexpr dart::compiler::target::word Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word Type_hash_offset = 32;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
-    FunctionType_packed_parameter_counts_offset = 40;
+    FunctionType_packed_parameter_counts_offset = 44;
 static constexpr dart::compiler::target::word
-    FunctionType_packed_type_parameter_counts_offset = 44;
+    FunctionType_packed_type_parameter_counts_offset = 48;
 static constexpr dart::compiler::target::word
-    FunctionType_parameter_types_offset = 28;
+    FunctionType_parameter_types_offset = 32;
 static constexpr dart::compiler::target::word
-    FunctionType_named_parameter_names_offset = 32;
+    FunctionType_named_parameter_names_offset = 36;
 static constexpr dart::compiler::target::word
-    FunctionType_type_parameters_offset = 20;
+    FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
+    TypeParameter_parameterized_class_id_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 35;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    33;
+    37;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
@@ -3172,13 +3178,13 @@
 static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 16;
 static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
     20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 32;
-static constexpr dart::compiler::target::word TypeRef_type_offset = 20;
-static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
 static constexpr dart::compiler::target::word
-    TypedDataView_offset_in_bytes_offset = 24;
+    TypedDataView_offset_in_bytes_offset = 28;
 static constexpr dart::compiler::target::word TypedData_data_offset = 24;
 static constexpr dart::compiler::target::word
     UnhandledException_exception_offset = 8;
@@ -3197,9 +3203,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
-        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
-        -1,   1512, 1520, 1528, -1,   -1,   -1,   -1,   -1,   -1};
+        1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+        1480, 1488, 1496, 1504, -1,   -1,   -1,   -1,   1512, 1520, -1,
+        -1,   1528, 1536, 1544, -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;
@@ -3226,7 +3232,7 @@
 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 = 96;
-static constexpr dart::compiler::target::word FunctionType_InstanceSize = 48;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 56;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     24;
@@ -3274,7 +3280,7 @@
 static constexpr dart::compiler::target::word Type_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 24;
-static constexpr dart::compiler::target::word TypeRef_InstanceSize = 24;
+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 = 32;
@@ -3462,16 +3468,16 @@
 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 = 16;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 24;
+    LinkedHashBase_deleted_keys_offset = 20;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    12;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 8;
+    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 =
-    20;
+    16;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
@@ -3487,11 +3493,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    128;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
+    184;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 124;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    156;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
+    212;
+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;
@@ -3512,9 +3519,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    724;
+    732;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    728;
+    736;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -3539,7 +3546,7 @@
     Thread_allocate_object_slow_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 764;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 772;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -3550,7 +3557,7 @@
     Thread_call_to_runtime_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 772;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 780;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -3568,7 +3575,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    744;
+    752;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -3588,13 +3595,13 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    732;
+    740;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    760;
+    768;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 776;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 784;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
@@ -3636,11 +3643,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 736;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 744;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 740;
+    Thread_saved_shadow_call_stack_offset = 748;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    748;
+    756;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -3674,9 +3681,9 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 752;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 760;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 756;
+    Thread_callback_stack_return_offset = 764;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -3736,7 +3743,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
+        700, 704, 708, 712, 716, -1, 720, -1, 724, 728, -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;
@@ -3998,16 +4005,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 = 32;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 48;
+    LinkedHashBase_deleted_keys_offset = 40;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    24;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 16;
+    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 =
-    40;
+    32;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
@@ -4023,11 +4030,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+    368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    424;
+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 =
@@ -4049,9 +4057,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1464;
+    1480;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1472;
+    1488;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -4077,7 +4085,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -4088,7 +4096,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1576;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -4106,7 +4114,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1504;
+    1520;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -4126,14 +4134,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1480;
+    1496;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1536;
+    1552;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -4175,11 +4183,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1504;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1496;
+    Thread_saved_shadow_call_stack_offset = 1512;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1512;
+    1528;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -4214,9 +4222,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1528;
+    Thread_callback_stack_return_offset = 1544;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -4277,8 +4285,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
-        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
+        1392, 1400, 1408, 1416, -1,   -1,   1424, 1432,
+        1440, 1448, 1456, -1,   1464, 1472, -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;
@@ -4539,16 +4547,16 @@
 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 = 16;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 24;
+    LinkedHashBase_deleted_keys_offset = 20;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    12;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 8;
+    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 =
-    20;
+    16;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
@@ -4564,11 +4572,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    128;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
+    184;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 124;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    156;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
+    212;
+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;
@@ -4589,9 +4598,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    692;
+    700;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    696;
+    704;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -4616,7 +4625,7 @@
     Thread_allocate_object_slow_entry_point_offset = 288;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 732;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 740;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -4627,7 +4636,7 @@
     Thread_call_to_runtime_entry_point_offset = 268;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 740;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 748;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -4645,7 +4654,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    712;
+    720;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -4665,13 +4674,13 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    700;
+    708;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    728;
+    736;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 744;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 752;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
 static constexpr dart::compiler::target::word
@@ -4713,11 +4722,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 704;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 712;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 708;
+    Thread_saved_shadow_call_stack_offset = 716;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    716;
+    724;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -4751,9 +4760,9 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 720;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 728;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 724;
+    Thread_callback_stack_return_offset = 732;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -5072,16 +5081,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 = 32;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 48;
+    LinkedHashBase_deleted_keys_offset = 40;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    24;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 16;
+    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 =
-    40;
+    32;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
@@ -5097,11 +5106,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+    368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    424;
+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 =
@@ -5123,9 +5133,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1528;
+    1544;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1536;
+    1552;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -5151,7 +5161,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -5162,7 +5172,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 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 = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -5180,7 +5190,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -5200,14 +5210,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1600;
+    1616;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -5249,11 +5259,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1568;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1560;
+    Thread_saved_shadow_call_stack_offset = 1576;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -5288,9 +5298,9 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1592;
+    Thread_callback_stack_return_offset = 1608;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -5351,9 +5361,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
-        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
-        -1,   1512, 1520, 1528, -1,   -1,   -1,   -1,   -1,   -1};
+        1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+        1480, 1488, 1496, 1504, -1,   -1,   -1,   -1,   1512, 1520, -1,
+        -1,   1528, 1536, 1544, -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;
@@ -5614,16 +5624,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 = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 28;
+    LinkedHashBase_deleted_keys_offset = 24;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    16;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 12;
+    12;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 28;
 static constexpr dart::compiler::target::word
     LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
-    24;
+    20;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
@@ -5639,11 +5649,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+    368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    424;
+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 =
@@ -5665,9 +5676,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1464;
+    1480;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1472;
+    1488;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -5693,7 +5704,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -5704,7 +5715,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1576;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -5722,7 +5733,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1504;
+    1520;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -5742,14 +5753,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1480;
+    1496;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1536;
+    1552;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -5791,11 +5802,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1504;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1496;
+    Thread_saved_shadow_call_stack_offset = 1512;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1512;
+    1528;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -5830,33 +5841,33 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1528;
+    Thread_callback_stack_return_offset = 1544;
 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 = 28;
-static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
-static constexpr dart::compiler::target::word Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word FunctionType_hash_offset = 36;
+static constexpr dart::compiler::target::word Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word Type_hash_offset = 32;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
-    FunctionType_packed_parameter_counts_offset = 40;
+    FunctionType_packed_parameter_counts_offset = 44;
 static constexpr dart::compiler::target::word
-    FunctionType_packed_type_parameter_counts_offset = 44;
+    FunctionType_packed_type_parameter_counts_offset = 48;
 static constexpr dart::compiler::target::word
-    FunctionType_parameter_types_offset = 28;
+    FunctionType_parameter_types_offset = 32;
 static constexpr dart::compiler::target::word
-    FunctionType_named_parameter_names_offset = 32;
+    FunctionType_named_parameter_names_offset = 36;
 static constexpr dart::compiler::target::word
-    FunctionType_type_parameters_offset = 20;
+    FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
+    TypeParameter_parameterized_class_id_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 35;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    33;
+    37;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
@@ -5868,13 +5879,13 @@
 static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 16;
 static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
     20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 32;
-static constexpr dart::compiler::target::word TypeRef_type_offset = 20;
-static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
 static constexpr dart::compiler::target::word
-    TypedDataView_offset_in_bytes_offset = 24;
+    TypedDataView_offset_in_bytes_offset = 28;
 static constexpr dart::compiler::target::word TypedData_data_offset = 24;
 static constexpr dart::compiler::target::word
     UnhandledException_exception_offset = 8;
@@ -5893,8 +5904,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
-        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
+        1392, 1400, 1408, 1416, -1,   -1,   1424, 1432,
+        1440, 1448, 1456, -1,   1464, 1472, -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;
@@ -5921,7 +5932,7 @@
 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 = 96;
-static constexpr dart::compiler::target::word FunctionType_InstanceSize = 48;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 56;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     24;
@@ -5969,7 +5980,7 @@
 static constexpr dart::compiler::target::word Type_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 24;
-static constexpr dart::compiler::target::word TypeRef_InstanceSize = 24;
+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 = 32;
@@ -6155,16 +6166,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 = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
 static constexpr dart::compiler::target::word
-    LinkedHashBase_deleted_keys_offset = 28;
+    LinkedHashBase_deleted_keys_offset = 24;
 static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
-    16;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 12;
+    12;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 28;
 static constexpr dart::compiler::target::word
     LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
-    24;
+    20;
 static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
@@ -6180,11 +6191,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+    368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+    424;
+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 =
@@ -6206,9 +6218,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1528;
+    1544;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1536;
+    1552;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -6234,7 +6246,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -6245,7 +6257,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 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 = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -6263,7 +6275,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -6283,14 +6295,14 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 256;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1600;
+    1616;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_isolate_group_offset =
-    1632;
+    1648;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
 static constexpr dart::compiler::target::word
@@ -6332,11 +6344,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1568;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1560;
+    Thread_saved_shadow_call_stack_offset = 1576;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1576;
+    1592;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -6371,33 +6383,33 @@
     72;
 static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    Thread_callback_stack_return_offset = 1592;
+    Thread_callback_stack_return_offset = 1608;
 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 = 28;
-static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
-static constexpr dart::compiler::target::word Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word FunctionType_hash_offset = 36;
+static constexpr dart::compiler::target::word Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word Type_hash_offset = 32;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
-    FunctionType_packed_parameter_counts_offset = 40;
+    FunctionType_packed_parameter_counts_offset = 44;
 static constexpr dart::compiler::target::word
-    FunctionType_packed_type_parameter_counts_offset = 44;
+    FunctionType_packed_type_parameter_counts_offset = 48;
 static constexpr dart::compiler::target::word
-    FunctionType_parameter_types_offset = 28;
+    FunctionType_parameter_types_offset = 32;
 static constexpr dart::compiler::target::word
-    FunctionType_named_parameter_names_offset = 32;
+    FunctionType_named_parameter_names_offset = 36;
 static constexpr dart::compiler::target::word
-    FunctionType_type_parameters_offset = 20;
+    FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
+    TypeParameter_parameterized_class_id_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 35;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    33;
+    37;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
@@ -6409,13 +6421,13 @@
 static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 16;
 static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
     20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 32;
-static constexpr dart::compiler::target::word TypeRef_type_offset = 20;
-static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
 static constexpr dart::compiler::target::word
-    TypedDataView_offset_in_bytes_offset = 24;
+    TypedDataView_offset_in_bytes_offset = 28;
 static constexpr dart::compiler::target::word TypedData_data_offset = 24;
 static constexpr dart::compiler::target::word
     UnhandledException_exception_offset = 8;
@@ -6434,9 +6446,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
-        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
-        -1,   1512, 1520, 1528, -1,   -1,   -1,   -1,   -1,   -1};
+        1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+        1480, 1488, 1496, 1504, -1,   -1,   -1,   -1,   1512, 1520, -1,
+        -1,   1528, 1536, 1544, -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;
@@ -6463,7 +6475,7 @@
 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 = 96;
-static constexpr dart::compiler::target::word FunctionType_InstanceSize = 48;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 56;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     24;
@@ -6511,7 +6523,7 @@
 static constexpr dart::compiler::target::word Type_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 24;
-static constexpr dart::compiler::target::word TypeRef_InstanceSize = 24;
+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 = 32;
@@ -6723,17 +6735,17 @@
     36;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 16;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
-    16;
+    12;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_deleted_keys_offset = 24;
+    AOT_LinkedHashBase_deleted_keys_offset = 20;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_hash_mask_offset = 12;
+    AOT_LinkedHashBase_hash_mask_offset = 8;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
-    8;
+    24;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashBase_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_used_data_offset = 20;
+    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;
@@ -6753,13 +6765,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 128;
+    AOT_ObjectStore_double_type_offset = 184;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    68;
+    124;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 156;
+    AOT_ObjectStore_string_type_offset = 212;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    48;
+    104;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word
@@ -6785,9 +6797,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 724;
+    AOT_Thread_active_exception_offset = 732;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 728;
+    AOT_Thread_active_stacktrace_offset = 736;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -6813,7 +6825,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 196;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    764;
+    772;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -6826,7 +6838,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 136;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    772;
+    780;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -6845,7 +6857,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 744;
+    AOT_Thread_execution_state_offset = 752;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -6865,14 +6877,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 732;
+    AOT_Thread_global_object_pool_offset = 740;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 760;
+    AOT_Thread_exit_through_ffi_offset = 768;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 44;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    776;
+    784;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 68;
 static constexpr dart::compiler::target::word
@@ -6916,11 +6928,11 @@
     104;
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 736;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 744;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 740;
+    AOT_Thread_saved_shadow_call_stack_offset = 748;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 748;
+    AOT_Thread_safepoint_state_offset = 756;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -6957,9 +6969,9 @@
     AOT_Thread_write_barrier_mask_offset = 36;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 40;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    752;
+    760;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 756;
+    AOT_Thread_callback_stack_return_offset = 764;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -7032,7 +7044,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
+        700, 704, 708, 712, 716, -1, 720, -1, 724, 728, -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;
@@ -7330,17 +7342,17 @@
     72;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
-    32;
+    24;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_deleted_keys_offset = 48;
+    AOT_LinkedHashBase_deleted_keys_offset = 40;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_hash_mask_offset = 24;
+    AOT_LinkedHashBase_hash_mask_offset = 16;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
-    16;
+    48;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_used_data_offset = 40;
+    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;
@@ -7360,13 +7372,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 256;
+    AOT_ObjectStore_double_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    136;
+    248;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 312;
+    AOT_ObjectStore_string_type_offset = 424;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    96;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -7392,9 +7404,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1464;
+    AOT_Thread_active_exception_offset = 1480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1472;
+    AOT_Thread_active_stacktrace_offset = 1488;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -7420,7 +7432,7 @@
 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 =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -7433,7 +7445,7 @@
 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 =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -7452,7 +7464,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1504;
+    AOT_Thread_execution_state_offset = 1520;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -7472,14 +7484,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1480;
+    AOT_Thread_global_object_pool_offset = 1496;
 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 = 1536;
+    AOT_Thread_exit_through_ffi_offset = 1552;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -7524,11 +7536,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1488;
+    1504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1496;
+    AOT_Thread_saved_shadow_call_stack_offset = 1512;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1512;
+    AOT_Thread_safepoint_state_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -7565,9 +7577,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1528;
+    AOT_Thread_callback_stack_return_offset = 1544;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -7641,8 +7653,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
-        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
+        1392, 1400, 1408, 1416, -1,   -1,   1424, 1432,
+        1440, 1448, 1456, -1,   1464, 1472, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -7943,17 +7955,17 @@
     72;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
-    32;
+    24;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_deleted_keys_offset = 48;
+    AOT_LinkedHashBase_deleted_keys_offset = 40;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_hash_mask_offset = 24;
+    AOT_LinkedHashBase_hash_mask_offset = 16;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
-    16;
+    48;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_used_data_offset = 40;
+    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;
@@ -7973,13 +7985,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 256;
+    AOT_ObjectStore_double_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    136;
+    248;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 312;
+    AOT_ObjectStore_string_type_offset = 424;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    96;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -8005,9 +8017,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1528;
+    AOT_Thread_active_exception_offset = 1544;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1536;
+    AOT_Thread_active_stacktrace_offset = 1552;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -8033,7 +8045,7 @@
 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 =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -8046,7 +8058,7 @@
 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 = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -8065,7 +8077,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1568;
+    AOT_Thread_execution_state_offset = 1584;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -8085,14 +8097,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1544;
+    AOT_Thread_global_object_pool_offset = 1560;
 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 = 1600;
+    AOT_Thread_exit_through_ffi_offset = 1616;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 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 = 136;
 static constexpr dart::compiler::target::word
@@ -8137,11 +8149,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1552;
+    1568;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1560;
+    AOT_Thread_saved_shadow_call_stack_offset = 1576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1576;
+    AOT_Thread_safepoint_state_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -8178,9 +8190,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1592;
+    AOT_Thread_callback_stack_return_offset = 1608;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -8254,9 +8266,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
-        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
-        -1,   1512, 1520, 1528, -1,   -1,   -1,   -1,   -1,   -1};
+        1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+        1480, 1488, 1496, 1504, -1,   -1,   -1,   -1,   1512, 1520, -1,
+        -1,   1528, 1536, 1544, -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;
@@ -8553,17 +8565,17 @@
     72;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
-    20;
+    16;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_deleted_keys_offset = 28;
+    AOT_LinkedHashBase_deleted_keys_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_hash_mask_offset = 16;
+    AOT_LinkedHashBase_hash_mask_offset = 12;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
-    12;
+    28;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_used_data_offset = 24;
+    AOT_LinkedHashBase_used_data_offset = 20;
 static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     AOT_MarkingStackBlock_pointers_offset = 16;
@@ -8583,13 +8595,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 256;
+    AOT_ObjectStore_double_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    136;
+    248;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 312;
+    AOT_ObjectStore_string_type_offset = 424;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    96;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -8615,9 +8627,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1464;
+    AOT_Thread_active_exception_offset = 1480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1472;
+    AOT_Thread_active_stacktrace_offset = 1488;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -8643,7 +8655,7 @@
 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 =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -8656,7 +8668,7 @@
 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 =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -8675,7 +8687,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1504;
+    AOT_Thread_execution_state_offset = 1520;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -8695,14 +8707,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1480;
+    AOT_Thread_global_object_pool_offset = 1496;
 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 = 1536;
+    AOT_Thread_exit_through_ffi_offset = 1552;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -8747,11 +8759,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1488;
+    1504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1496;
+    AOT_Thread_saved_shadow_call_stack_offset = 1512;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1512;
+    AOT_Thread_safepoint_state_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -8788,36 +8800,36 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1528;
+    AOT_Thread_callback_stack_return_offset = 1544;
 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 = 28;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 32;
 static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
-    20;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 36;
+    24;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_packed_parameter_counts_offset = 40;
+    AOT_FunctionType_packed_parameter_counts_offset = 44;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_packed_type_parameter_counts_offset = 44;
+    AOT_FunctionType_packed_type_parameter_counts_offset = 48;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_parameter_types_offset = 28;
+    AOT_FunctionType_parameter_types_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_named_parameter_names_offset = 32;
+    AOT_FunctionType_named_parameter_names_offset = 36;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_type_parameters_offset = 20;
+    AOT_FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 28;
+    AOT_TypeParameter_parameterized_class_id_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    31;
+    35;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 33;
+    AOT_TypeParameter_nullability_offset = 37;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -8835,16 +8847,16 @@
 static constexpr dart::compiler::target::word
     AOT_TypeParameters_defaults_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    24;
+    28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    32;
-static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
+    36;
+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 =
     20;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+    24;
 static constexpr dart::compiler::target::word
-    AOT_TypedDataView_offset_in_bytes_offset = 24;
+    AOT_TypedDataView_offset_in_bytes_offset = 28;
 static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
 static constexpr dart::compiler::target::word
     AOT_UnhandledException_exception_offset = 8;
@@ -8864,8 +8876,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
-        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
+        1392, 1400, 1408, 1416, -1,   -1,   1424, 1432,
+        1440, 1448, 1456, -1,   1464, 1472, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -8895,7 +8907,7 @@
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
-    48;
+    56;
 static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word
     AOT_GrowableObjectArray_InstanceSize = 24;
@@ -8950,7 +8962,7 @@
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
     24;
-static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 24;
+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;
@@ -9162,17 +9174,17 @@
     72;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
-    20;
+    16;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_deleted_keys_offset = 28;
+    AOT_LinkedHashBase_deleted_keys_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_hash_mask_offset = 16;
+    AOT_LinkedHashBase_hash_mask_offset = 12;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
-    12;
+    28;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_used_data_offset = 24;
+    AOT_LinkedHashBase_used_data_offset = 20;
 static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     AOT_MarkingStackBlock_pointers_offset = 16;
@@ -9192,13 +9204,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 256;
+    AOT_ObjectStore_double_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    136;
+    248;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 312;
+    AOT_ObjectStore_string_type_offset = 424;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    96;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -9224,9 +9236,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1528;
+    AOT_Thread_active_exception_offset = 1544;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1536;
+    AOT_Thread_active_stacktrace_offset = 1552;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -9252,7 +9264,7 @@
 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 =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -9265,7 +9277,7 @@
 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 = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -9284,7 +9296,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1568;
+    AOT_Thread_execution_state_offset = 1584;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -9304,14 +9316,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1544;
+    AOT_Thread_global_object_pool_offset = 1560;
 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 = 1600;
+    AOT_Thread_exit_through_ffi_offset = 1616;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 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 = 136;
 static constexpr dart::compiler::target::word
@@ -9356,11 +9368,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1552;
+    1568;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1560;
+    AOT_Thread_saved_shadow_call_stack_offset = 1576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1576;
+    AOT_Thread_safepoint_state_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -9397,36 +9409,36 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1592;
+    AOT_Thread_callback_stack_return_offset = 1608;
 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 = 28;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 32;
 static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
-    20;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 36;
+    24;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_packed_parameter_counts_offset = 40;
+    AOT_FunctionType_packed_parameter_counts_offset = 44;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_packed_type_parameter_counts_offset = 44;
+    AOT_FunctionType_packed_type_parameter_counts_offset = 48;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_parameter_types_offset = 28;
+    AOT_FunctionType_parameter_types_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_named_parameter_names_offset = 32;
+    AOT_FunctionType_named_parameter_names_offset = 36;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_type_parameters_offset = 20;
+    AOT_FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 28;
+    AOT_TypeParameter_parameterized_class_id_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    31;
+    35;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 33;
+    AOT_TypeParameter_nullability_offset = 37;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -9444,16 +9456,16 @@
 static constexpr dart::compiler::target::word
     AOT_TypeParameters_defaults_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    24;
+    28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    32;
-static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
+    36;
+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 =
     20;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+    24;
 static constexpr dart::compiler::target::word
-    AOT_TypedDataView_offset_in_bytes_offset = 24;
+    AOT_TypedDataView_offset_in_bytes_offset = 28;
 static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
 static constexpr dart::compiler::target::word
     AOT_UnhandledException_exception_offset = 8;
@@ -9473,9 +9485,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
-        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
-        -1,   1512, 1520, 1528, -1,   -1,   -1,   -1,   -1,   -1};
+        1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+        1480, 1488, 1496, 1504, -1,   -1,   -1,   -1,   1512, 1520, -1,
+        -1,   1528, 1536, 1544, -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;
@@ -9505,7 +9517,7 @@
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
-    48;
+    56;
 static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word
     AOT_GrowableObjectArray_InstanceSize = 24;
@@ -9560,7 +9572,7 @@
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
     24;
-static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 24;
+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;
@@ -9767,17 +9779,17 @@
     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 =
-    16;
+    12;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_deleted_keys_offset = 24;
+    AOT_LinkedHashBase_deleted_keys_offset = 20;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_hash_mask_offset = 12;
+    AOT_LinkedHashBase_hash_mask_offset = 8;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
-    8;
+    24;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashBase_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_used_data_offset = 20;
+    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;
@@ -9797,13 +9809,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 128;
+    AOT_ObjectStore_double_type_offset = 184;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    68;
+    124;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 156;
+    AOT_ObjectStore_string_type_offset = 212;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    48;
+    104;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word
@@ -9829,9 +9841,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 368;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 724;
+    AOT_Thread_active_exception_offset = 732;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 728;
+    AOT_Thread_active_stacktrace_offset = 736;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
@@ -9857,7 +9869,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 196;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    764;
+    772;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 332;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -9870,7 +9882,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 136;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    772;
+    780;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -9889,7 +9901,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 744;
+    AOT_Thread_execution_state_offset = 752;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
@@ -9909,14 +9921,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 364;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 732;
+    AOT_Thread_global_object_pool_offset = 740;
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 760;
+    AOT_Thread_exit_through_ffi_offset = 768;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 44;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    776;
+    784;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 68;
 static constexpr dart::compiler::target::word
@@ -9960,11 +9972,11 @@
     104;
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 736;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 744;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 740;
+    AOT_Thread_saved_shadow_call_stack_offset = 748;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 748;
+    AOT_Thread_safepoint_state_offset = 756;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 240;
 static constexpr dart::compiler::target::word
@@ -10001,9 +10013,9 @@
     AOT_Thread_write_barrier_mask_offset = 36;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 40;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    752;
+    760;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 756;
+    AOT_Thread_callback_stack_return_offset = 764;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -10076,7 +10088,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
+        700, 704, 708, 712, 716, -1, 720, -1, 724, 728, -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;
@@ -10367,17 +10379,17 @@
     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 =
-    32;
+    24;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_deleted_keys_offset = 48;
+    AOT_LinkedHashBase_deleted_keys_offset = 40;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_hash_mask_offset = 24;
+    AOT_LinkedHashBase_hash_mask_offset = 16;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
-    16;
+    48;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_used_data_offset = 40;
+    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;
@@ -10397,13 +10409,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 256;
+    AOT_ObjectStore_double_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    136;
+    248;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 312;
+    AOT_ObjectStore_string_type_offset = 424;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    96;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -10429,9 +10441,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1464;
+    AOT_Thread_active_exception_offset = 1480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1472;
+    AOT_Thread_active_stacktrace_offset = 1488;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -10457,7 +10469,7 @@
 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 =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -10470,7 +10482,7 @@
 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 =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -10489,7 +10501,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1504;
+    AOT_Thread_execution_state_offset = 1520;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -10509,14 +10521,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1480;
+    AOT_Thread_global_object_pool_offset = 1496;
 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 = 1536;
+    AOT_Thread_exit_through_ffi_offset = 1552;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -10561,11 +10573,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1488;
+    1504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1496;
+    AOT_Thread_saved_shadow_call_stack_offset = 1512;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1512;
+    AOT_Thread_safepoint_state_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -10602,9 +10614,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1528;
+    AOT_Thread_callback_stack_return_offset = 1544;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -10678,8 +10690,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
-        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
+        1392, 1400, 1408, 1416, -1,   -1,   1424, 1432,
+        1440, 1448, 1456, -1,   1464, 1472, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -10973,17 +10985,17 @@
     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 =
-    32;
+    24;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_deleted_keys_offset = 48;
+    AOT_LinkedHashBase_deleted_keys_offset = 40;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_hash_mask_offset = 24;
+    AOT_LinkedHashBase_hash_mask_offset = 16;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
-    16;
+    48;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_used_data_offset = 40;
+    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;
@@ -11003,13 +11015,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 256;
+    AOT_ObjectStore_double_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    136;
+    248;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 312;
+    AOT_ObjectStore_string_type_offset = 424;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    96;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -11035,9 +11047,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1528;
+    AOT_Thread_active_exception_offset = 1544;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1536;
+    AOT_Thread_active_stacktrace_offset = 1552;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -11063,7 +11075,7 @@
 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 =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -11076,7 +11088,7 @@
 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 = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -11095,7 +11107,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1568;
+    AOT_Thread_execution_state_offset = 1584;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -11115,14 +11127,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1544;
+    AOT_Thread_global_object_pool_offset = 1560;
 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 = 1600;
+    AOT_Thread_exit_through_ffi_offset = 1616;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 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 = 136;
 static constexpr dart::compiler::target::word
@@ -11167,11 +11179,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1552;
+    1568;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1560;
+    AOT_Thread_saved_shadow_call_stack_offset = 1576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1576;
+    AOT_Thread_safepoint_state_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -11208,9 +11220,9 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1592;
+    AOT_Thread_callback_stack_return_offset = 1608;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -11284,9 +11296,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
-        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
-        -1,   1512, 1520, 1528, -1,   -1,   -1,   -1,   -1,   -1};
+        1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+        1480, 1488, 1496, 1504, -1,   -1,   -1,   -1,   1512, 1520, -1,
+        -1,   1528, 1536, 1544, -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;
@@ -11576,17 +11588,17 @@
     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 =
-    20;
+    16;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_deleted_keys_offset = 28;
+    AOT_LinkedHashBase_deleted_keys_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_hash_mask_offset = 16;
+    AOT_LinkedHashBase_hash_mask_offset = 12;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
-    12;
+    28;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_used_data_offset = 24;
+    AOT_LinkedHashBase_used_data_offset = 20;
 static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     AOT_MarkingStackBlock_pointers_offset = 16;
@@ -11606,13 +11618,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 256;
+    AOT_ObjectStore_double_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    136;
+    248;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 312;
+    AOT_ObjectStore_string_type_offset = 424;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    96;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -11638,9 +11650,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1464;
+    AOT_Thread_active_exception_offset = 1480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1472;
+    AOT_Thread_active_stacktrace_offset = 1488;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -11666,7 +11678,7 @@
 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 =
-    1544;
+    1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -11679,7 +11691,7 @@
 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 =
-    1560;
+    1576;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -11698,7 +11710,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1504;
+    AOT_Thread_execution_state_offset = 1520;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -11718,14 +11730,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1480;
+    AOT_Thread_global_object_pool_offset = 1496;
 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 = 1536;
+    AOT_Thread_exit_through_ffi_offset = 1552;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
-    1568;
+    1584;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
 static constexpr dart::compiler::target::word
@@ -11770,11 +11782,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1488;
+    1504;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1496;
+    AOT_Thread_saved_shadow_call_stack_offset = 1512;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1512;
+    AOT_Thread_safepoint_state_offset = 1528;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -11811,36 +11823,36 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1520;
+    1536;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1528;
+    AOT_Thread_callback_stack_return_offset = 1544;
 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 = 28;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 32;
 static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
-    20;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 36;
+    24;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_packed_parameter_counts_offset = 40;
+    AOT_FunctionType_packed_parameter_counts_offset = 44;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_packed_type_parameter_counts_offset = 44;
+    AOT_FunctionType_packed_type_parameter_counts_offset = 48;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_parameter_types_offset = 28;
+    AOT_FunctionType_parameter_types_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_named_parameter_names_offset = 32;
+    AOT_FunctionType_named_parameter_names_offset = 36;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_type_parameters_offset = 20;
+    AOT_FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 28;
+    AOT_TypeParameter_parameterized_class_id_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    31;
+    35;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 33;
+    AOT_TypeParameter_nullability_offset = 37;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -11858,16 +11870,16 @@
 static constexpr dart::compiler::target::word
     AOT_TypeParameters_defaults_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    24;
+    28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    32;
-static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
+    36;
+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 =
     20;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+    24;
 static constexpr dart::compiler::target::word
-    AOT_TypedDataView_offset_in_bytes_offset = 24;
+    AOT_TypedDataView_offset_in_bytes_offset = 28;
 static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
 static constexpr dart::compiler::target::word
     AOT_UnhandledException_exception_offset = 8;
@@ -11887,8 +11899,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, -1,   -1,   1408, 1416,
-        1424, 1432, 1440, -1,   1448, 1456, -1,   -1};
+        1392, 1400, 1408, 1416, -1,   -1,   1424, 1432,
+        1440, 1448, 1456, -1,   1464, 1472, -1,   -1};
 static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -11918,7 +11930,7 @@
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
-    48;
+    56;
 static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word
     AOT_GrowableObjectArray_InstanceSize = 24;
@@ -11973,7 +11985,7 @@
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
     24;
-static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 24;
+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;
@@ -12178,17 +12190,17 @@
     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 =
-    20;
+    16;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_deleted_keys_offset = 28;
+    AOT_LinkedHashBase_deleted_keys_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_hash_mask_offset = 16;
+    AOT_LinkedHashBase_hash_mask_offset = 12;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
-    12;
+    28;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashBase_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_LinkedHashBase_used_data_offset = 24;
+    AOT_LinkedHashBase_used_data_offset = 20;
 static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     AOT_MarkingStackBlock_pointers_offset = 16;
@@ -12208,13 +12220,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 256;
+    AOT_ObjectStore_double_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    136;
+    248;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 312;
+    AOT_ObjectStore_string_type_offset = 424;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    96;
+    208;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -12240,9 +12252,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1528;
+    AOT_Thread_active_exception_offset = 1544;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1536;
+    AOT_Thread_active_stacktrace_offset = 1552;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 232;
 static constexpr dart::compiler::target::word
@@ -12268,7 +12280,7 @@
 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 =
-    1608;
+    1624;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -12281,7 +12293,7 @@
 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 = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -12300,7 +12312,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1568;
+    AOT_Thread_execution_state_offset = 1584;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -12320,14 +12332,14 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 720;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1544;
+    AOT_Thread_global_object_pool_offset = 1560;
 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 = 1600;
+    AOT_Thread_exit_through_ffi_offset = 1616;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 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 = 136;
 static constexpr dart::compiler::target::word
@@ -12372,11 +12384,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 664;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1552;
+    1568;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1560;
+    AOT_Thread_saved_shadow_call_stack_offset = 1576;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1576;
+    AOT_Thread_safepoint_state_offset = 1592;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -12413,36 +12425,36 @@
     AOT_Thread_write_barrier_mask_offset = 72;
 static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1584;
+    1600;
 static constexpr dart::compiler::target::word
-    AOT_Thread_callback_stack_return_offset = 1592;
+    AOT_Thread_callback_stack_return_offset = 1608;
 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 = 28;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 32;
 static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
-    20;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 36;
+    24;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_packed_parameter_counts_offset = 40;
+    AOT_FunctionType_packed_parameter_counts_offset = 44;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_packed_type_parameter_counts_offset = 44;
+    AOT_FunctionType_packed_type_parameter_counts_offset = 48;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_parameter_types_offset = 28;
+    AOT_FunctionType_parameter_types_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_named_parameter_names_offset = 32;
+    AOT_FunctionType_named_parameter_names_offset = 36;
 static constexpr dart::compiler::target::word
-    AOT_FunctionType_type_parameters_offset = 20;
+    AOT_FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 28;
+    AOT_TypeParameter_parameterized_class_id_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    31;
+    35;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 33;
+    AOT_TypeParameter_nullability_offset = 37;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -12460,16 +12472,16 @@
 static constexpr dart::compiler::target::word
     AOT_TypeParameters_defaults_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    24;
+    28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    32;
-static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
+    36;
+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 =
     20;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+    24;
 static constexpr dart::compiler::target::word
-    AOT_TypedDataView_offset_in_bytes_offset = 24;
+    AOT_TypedDataView_offset_in_bytes_offset = 28;
 static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
 static constexpr dart::compiler::target::word
     AOT_UnhandledException_exception_offset = 8;
@@ -12489,9 +12501,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
-        1464, 1472, 1480, 1488, -1,   -1,   -1,   -1,   1496, 1504, -1,
-        -1,   1512, 1520, 1528, -1,   -1,   -1,   -1,   -1,   -1};
+        1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+        1480, 1488, 1496, 1504, -1,   -1,   -1,   -1,   1512, 1520, -1,
+        -1,   1528, 1536, 1544, -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;
@@ -12521,7 +12533,7 @@
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
-    48;
+    56;
 static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word
     AOT_GrowableObjectArray_InstanceSize = 24;
@@ -12576,7 +12588,7 @@
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
     24;
-static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 24;
+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;
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index 7b7eb71..a425e97 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -54,7 +54,8 @@
   static void GenerateBuildMethodExtractorStub(
       Assembler* assembler,
       const Code& closure_allocation_stub,
-      const Code& context_allocation_stub);
+      const Code& context_allocation_stub,
+      bool generic);
 #endif
 
   static void EnsureIsNewOrRemembered(Assembler* assembler,
@@ -110,7 +111,11 @@
 
 #if defined(TARGET_ARCH_X64)
   static constexpr intptr_t kNativeCallbackTrampolineSize = 10;
+#if defined(DART_COMPRESSED_POINTERS)
+  static constexpr intptr_t kNativeCallbackSharedStubSize = 225;
+#else
   static constexpr intptr_t kNativeCallbackSharedStubSize = 217;
+#endif
   static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
 #elif defined(TARGET_ARCH_IA32)
   static constexpr intptr_t kNativeCallbackTrampolineSize = 10;
@@ -122,7 +127,11 @@
   static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 4;
 #elif defined(TARGET_ARCH_ARM64)
   static constexpr intptr_t kNativeCallbackTrampolineSize = 12;
+#if defined(DART_COMPRESSED_POINTERS)
+  static constexpr intptr_t kNativeCallbackSharedStubSize = 276;
+#else
   static constexpr intptr_t kNativeCallbackSharedStubSize = 268;
+#endif
   static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
 #endif
 
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 50f9b49..7a139c4 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -224,7 +224,8 @@
 void StubCodeCompiler::GenerateBuildMethodExtractorStub(
     Assembler* assembler,
     const Code& closure_allocation_stub,
-    const Code& context_allocation_stub) {
+    const Code& context_allocation_stub,
+    bool generic) {
   const intptr_t kReceiverOffset = target::frame_layout.param_end_from_fp + 1;
 
   __ EnterStubFrame();
@@ -291,12 +292,15 @@
       FieldAddress(AllocateClosureABI::kResultReg,
                    target::Closure::instantiator_type_arguments_offset()),
       AllocateClosureABI::kScratchReg);
-  __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
-  __ StoreIntoObjectNoBarrier(
-      AllocateClosureABI::kResultReg,
-      FieldAddress(AllocateClosureABI::kResultReg,
-                   target::Closure::delayed_type_arguments_offset()),
-      AllocateClosureABI::kScratchReg);
+  // Keep delayed_type_arguments as null if non-generic (see Closure::New).
+  if (generic) {
+    __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
+    __ StoreIntoObjectNoBarrier(
+        AllocateClosureABI::kResultReg,
+        FieldAddress(AllocateClosureABI::kResultReg,
+                     target::Closure::delayed_type_arguments_offset()),
+        AllocateClosureABI::kScratchReg);
+  }
 
   __ LeaveStubFrame();
   // No-op if the two are the same.
@@ -689,13 +693,13 @@
   // calling into the runtime.
   __ EnterStubFrame();
   __ LoadImmediate(R1, 0);
-  __ Push(R9);  // Preserve cache (guarded CID as Smi).
+  __ Push(R1);  // Result slot.
   __ Push(R0);  // Preserve receiver.
-  __ Push(R1);
-  __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 0);
-  __ Pop(CODE_REG);
+  __ Push(R9);  // Old cache value (also 2nd return value).
+  __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
+  __ Pop(R9);  // Get target cache object.
   __ Pop(R0);  // Restore receiver.
-  __ Pop(R9);  // Restore cache (guarded CID as Smi).
+  __ Pop(CODE_REG);  // Get target Code object.
   // Remove the stub frame.
   __ LeaveStubFrame();
   // Jump to the dart function.
@@ -3140,20 +3144,13 @@
   // proper target for the given name and arguments descriptor.  If the
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
-  const auto target_address = FieldAddress(IP, base + target::kWordSize);
-  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ ldr(
-        ARGS_DESC_REG,
-        FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
-    __ Branch(target_address);
-  } else {
-    __ ldr(R0, target_address);
+  __ ldr(R0, FieldAddress(IP, base + target::kWordSize));
+  if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
     __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
-    __ ldr(
-        ARGS_DESC_REG,
-        FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
-    __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
   }
+  __ ldr(ARGS_DESC_REG,
+         FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
+  __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
 
   // Probe failed, check if it is a miss.
   __ Bind(&probe_failed);
@@ -3194,14 +3191,17 @@
   __ b(&loop);
 
   __ Bind(&found);
-  const intptr_t code_offset =
-      target::ICData::CodeIndexFor(1) * target::kWordSize;
-  const intptr_t entry_offset =
-      target::ICData::EntryPointIndexFor(1) * target::kWordSize;
-  if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
-    __ ldr(CODE_REG, Address(R8, code_offset));
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    const intptr_t entry_offset =
+        target::ICData::EntryPointIndexFor(1) * target::kWordSize;
+    __ LoadCompressed(R0, Address(R8, entry_offset));
+    __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
+  } else {
+    const intptr_t code_offset =
+        target::ICData::CodeIndexFor(1) * target::kWordSize;
+    __ LoadCompressed(CODE_REG, Address(R8, code_offset));
+    __ Branch(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   }
-  __ Branch(Address(R8, entry_offset));
 
   __ Bind(&miss);
   __ LoadIsolate(R2);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 1e36ee5..2c1288d 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -415,8 +415,8 @@
 
   // Load the code object.
   __ LoadFromOffset(R10, THR, compiler::target::Thread::callback_code_offset());
-  __ LoadFieldFromOffset(R10, R10,
-                         compiler::target::GrowableObjectArray::data_offset());
+  __ LoadCompressedFieldFromOffset(
+      R10, R10, compiler::target::GrowableObjectArray::data_offset());
   __ LoadCompressed(
       R10,
       __ ElementAddressForRegIndex(
@@ -460,7 +460,8 @@
 void StubCodeCompiler::GenerateBuildMethodExtractorStub(
     Assembler* assembler,
     const Code& closure_allocation_stub,
-    const Code& context_allocation_stub) {
+    const Code& context_allocation_stub,
+    bool generic) {
   const intptr_t kReceiverOffset = target::frame_layout.param_end_from_fp + 1;
 
   __ EnterStubFrame();
@@ -530,12 +531,15 @@
       FieldAddress(AllocateClosureABI::kResultReg,
                    target::Closure::instantiator_type_arguments_offset()),
       AllocateClosureABI::kScratchReg);
-  __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
-  __ StoreCompressedIntoObjectNoBarrier(
-      AllocateClosureABI::kResultReg,
-      FieldAddress(AllocateClosureABI::kResultReg,
-                   target::Closure::delayed_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.
@@ -804,13 +808,13 @@
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
-  __ Push(R5);  // Preserve cache (guarded CID as Smi).
+  __ Push(ZR);  // Result slot.
   __ Push(R0);  // Preserve receiver.
-  __ Push(ZR);
-  __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 0);
-  __ Pop(CODE_REG);
-  __ Pop(R0);  // Restore receiver.
-  __ Pop(R5);  // Restore cache (guarded CID as Smi).
+  __ Push(R5);  // Old cache value (also 2nd return value).
+  __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
+  __ Pop(R5);        // Get target cache object.
+  __ Pop(R0);        // Restore receiver.
+  __ Pop(CODE_REG);  // Get target Code object.
   // Remove the stub frame.
   __ LeaveStubFrame();
   // Jump to the dart function.
@@ -3309,19 +3313,12 @@
   // proper target for the given name and arguments descriptor.  If the
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
-  const auto target_address =
-      FieldAddress(TMP, base + target::kCompressedWordSize, kObjectBytes);
-  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ ldr(R1, target_address);
-    __ ldr(
-        ARGS_DESC_REG,
-        FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
-  } else {
-    __ LoadCompressed(R0, target_address);
-    __ ldr(R1, FieldAddress(R0, target::Function::entry_point_offset()));
-    __ ldr(
-        ARGS_DESC_REG,
-        FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
+  __ LoadCompressed(
+      R0, FieldAddress(TMP, base + target::kCompressedWordSize, kObjectBytes));
+  __ ldr(R1, FieldAddress(R0, target::Function::entry_point_offset()));
+  __ ldr(ARGS_DESC_REG,
+         FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
+  if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
     __ LoadCompressed(CODE_REG,
                       FieldAddress(R0, target::Function::code_offset()));
   }
@@ -3374,22 +3371,20 @@
   __ b(&loop);
 
   __ Bind(&found);
-  const intptr_t code_offset =
-      target::ICData::CodeIndexFor(1) * target::kCompressedWordSize;
-#if defined(DART_COMPRESSED_POINTERS)
-  __ LoadCompressed(CODE_REG,
-                    Address(R8, code_offset, Address::Offset, kObjectBytes));
-  __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
-  __ br(R1);
-#else
-  const intptr_t entry_offset =
-      target::ICData::EntryPointIndexFor(1) * target::kCompressedWordSize;
-  __ ldr(R1, Address(R8, entry_offset));
-  if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
-    __ ldr(CODE_REG, Address(R8, code_offset));
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    const intptr_t entry_offset =
+        target::ICData::EntryPointIndexFor(1) * target::kCompressedWordSize;
+    __ LoadCompressed(R1,
+                      Address(R8, entry_offset, Address::Offset, kObjectBytes));
+    __ ldr(R1, FieldAddress(R1, target::Function::entry_point_offset()));
+  } else {
+    const intptr_t code_offset =
+        target::ICData::CodeIndexFor(1) * target::kCompressedWordSize;
+    __ LoadCompressed(CODE_REG,
+                      Address(R8, code_offset, Address::Offset, kObjectBytes));
+    __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   }
   __ br(R1);
-#endif
 
   __ Bind(&miss);
   __ LoadIsolate(R2);
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 16ef27a..ea1b6a4 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -515,13 +515,13 @@
   __ Bind(&monomorphic);
   // This was a switchable call.
   __ EnterStubFrame();
-  __ pushl(ECX);           // Preserve cache (guarded CID as Smi).
-  __ pushl(EBX);           // Preserve receiver.
   __ pushl(Immediate(0));  // Result slot.
-  __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 0);
-  __ popl(CODE_REG);  // Get Code object.
+  __ pushl(EBX);           // Preserve receiver.
+  __ pushl(ECX);           // Old cache value (also 2nd return value).
+  __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
+  __ popl(ECX);       // Get target cache object.
   __ popl(EBX);       // Restore receiver.
-  __ popl(ECX);       // Restore cache (guarded CID as Smi).
+  __ popl(CODE_REG);  // Get target Code object.
   __ movl(EAX, FieldAddress(CODE_REG, target::Code::entry_point_offset(
                                           CodeEntryKind::kMonomorphic)));
   __ LeaveFrame();
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index e776269..74405e0 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -359,9 +359,10 @@
   // Load the target from the thread.
   __ movq(TMP, compiler::Address(
                    THR, compiler::target::Thread::callback_code_offset()));
-  __ movq(TMP, compiler::FieldAddress(
-                   TMP, compiler::target::GrowableObjectArray::data_offset()));
-  __ movq(
+  __ LoadCompressed(
+      TMP, compiler::FieldAddress(
+               TMP, compiler::target::GrowableObjectArray::data_offset()));
+  __ LoadCompressed(
       TMP,
       __ ElementAddressForRegIndex(
           /*external=*/false,
@@ -403,7 +404,8 @@
 void StubCodeCompiler::GenerateBuildMethodExtractorStub(
     Assembler* assembler,
     const Code& closure_allocation_stub,
-    const Code& context_allocation_stub) {
+    const Code& context_allocation_stub,
+    bool generic) {
   const intptr_t kReceiverOffsetInWords =
       target::frame_layout.param_end_from_fp + 1;
 
@@ -471,12 +473,15 @@
       FieldAddress(AllocateClosureABI::kResultReg,
                    target::Closure::instantiator_type_arguments_offset()),
       AllocateClosureABI::kScratchReg);
-  __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
-  __ StoreCompressedIntoObjectNoBarrier(
-      AllocateClosureABI::kResultReg,
-      FieldAddress(AllocateClosureABI::kResultReg,
-                   target::Closure::delayed_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.
@@ -721,13 +726,13 @@
   __ movq(CODE_REG,
           Address(THR, target::Thread::fix_callers_target_code_offset()));
   __ EnterStubFrame();
-  __ pushq(RBX);           // Preserve cache (guarded CID as Smi).
-  __ pushq(RDX);           // Preserve receiver.
   __ pushq(Immediate(0));  // Result slot.
-  __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 0);
-  __ popq(CODE_REG);  // Get Code object.
+  __ pushq(RDX);           // Preserve receiver.
+  __ pushq(RBX);           // Old cache value (also 2nd return value).
+  __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
+  __ popq(RBX);       // Get target cache object.
   __ popq(RDX);       // Restore receiver.
-  __ popq(RBX);       // Restore cache (guarded CID as Smi).
+  __ popq(CODE_REG);  // Get target Code object.
   __ movq(RAX, FieldAddress(CODE_REG, target::Code::entry_point_offset(
                                           CodeEntryKind::kMonomorphic)));
   __ LeaveStubFrame();
@@ -3251,21 +3256,16 @@
   // proper target for the given name and arguments descriptor.  If the
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
-  const auto target_address = FieldAddress(RDI, RCX, TIMES_COMPRESSED_WORD_SIZE,
-                                           base + target::kCompressedWordSize);
-  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ movq(R10, FieldAddress(
-                     RBX, target::CallSiteData::arguments_descriptor_offset()));
-    __ jmp(target_address);
-  } else {
-    __ LoadCompressed(RAX, target_address);
-    __ movq(R10, FieldAddress(
-                     RBX, target::CallSiteData::arguments_descriptor_offset()));
-    __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
+  __ LoadCompressed(RAX, FieldAddress(RDI, RCX, TIMES_COMPRESSED_WORD_SIZE,
+                                      base + target::kCompressedWordSize));
+  __ movq(R10, FieldAddress(
+                   RBX, target::CallSiteData::arguments_descriptor_offset()));
+  __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
+  if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
     __ LoadCompressed(CODE_REG,
                       FieldAddress(RAX, target::Function::code_offset()));
-    __ jmp(RCX);
   }
+  __ jmp(RCX);
 
   // Probe failed, check if it is a miss.
   __ Bind(&probe_failed);
@@ -3316,19 +3316,17 @@
   __ jmp(&loop);
 
   __ Bind(&found);
-  const intptr_t code_offset =
-      target::ICData::CodeIndexFor(1) * target::kCompressedWordSize;
-#if defined(DART_COMPRESSED_POINTERS)
-  __ LoadCompressed(CODE_REG, Address(R13, code_offset));
-  __ jmp(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
-#else
-  const intptr_t entry_offset =
-      target::ICData::EntryPointIndexFor(1) * target::kCompressedWordSize;
-  if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
-    __ movq(CODE_REG, Address(R13, code_offset));
+  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+    const intptr_t entry_offset =
+        target::ICData::EntryPointIndexFor(1) * target::kCompressedWordSize;
+    __ LoadCompressed(RCX, Address(R13, entry_offset));
+    __ jmp(FieldAddress(RCX, target::Function::entry_point_offset()));
+  } else {
+    const intptr_t code_offset =
+        target::ICData::CodeIndexFor(1) * target::kCompressedWordSize;
+    __ LoadCompressed(CODE_REG, Address(R13, code_offset));
+    __ jmp(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   }
-  __ jmp(Address(R13, entry_offset));
-#endif
 
   __ Bind(&miss);
   __ LoadIsolate(RAX);
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 2fbb323..a3e59b2 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -301,6 +301,7 @@
     vm_isolate_->isolate_object_store()->Init();
     TargetCPUFeatures::Init();
     Object::Init(vm_isolate_->group());
+    OffsetsTable::Init();
     ArgumentsDescriptor::Init();
     ICData::Init();
     SubtypeTestCache::Init();
@@ -635,6 +636,7 @@
   ICData::Cleanup();
   SubtypeTestCache::Cleanup();
   ArgumentsDescriptor::Cleanup();
+  OffsetsTable::Cleanup();
   TargetCPUFeatures::Cleanup();
   MarkingStack::Cleanup();
   StoreBuffer::Cleanup();
@@ -869,16 +871,32 @@
 
   if (kIsAotRuntime || was_child_cloned_into_existing_isolate) {
 #if !defined(TARGET_ARCH_IA32)
-    ASSERT(IG->object_store()->build_method_extractor_code() != Code::null());
+    ASSERT(IG->object_store()->build_generic_method_extractor_code() !=
+           Code::null());
+    ASSERT(IG->object_store()->build_nongeneric_method_extractor_code() !=
+           Code::null());
 #endif
   } else {
 #if !defined(TARGET_ARCH_IA32)
     if (I != Dart::vm_isolate()) {
-      if (IG->object_store()->build_method_extractor_code() != nullptr) {
+      if (IG->object_store()->build_generic_method_extractor_code() !=
+          nullptr) {
         SafepointWriteRwLocker ml(T, IG->program_lock());
-        if (IG->object_store()->build_method_extractor_code() != nullptr) {
-          IG->object_store()->set_build_method_extractor_code(
-              Code::Handle(StubCode::GetBuildMethodExtractorStub(nullptr)));
+        if (IG->object_store()->build_generic_method_extractor_code() !=
+            nullptr) {
+          IG->object_store()->set_build_generic_method_extractor_code(
+              Code::Handle(
+                  StubCode::GetBuildGenericMethodExtractorStub(nullptr)));
+        }
+      }
+      if (IG->object_store()->build_nongeneric_method_extractor_code() !=
+          nullptr) {
+        SafepointWriteRwLocker ml(T, IG->program_lock());
+        if (IG->object_store()->build_nongeneric_method_extractor_code() !=
+            nullptr) {
+          IG->object_store()->set_build_nongeneric_method_extractor_code(
+              Code::Handle(
+                  StubCode::GetBuildNonGenericMethodExtractorStub(nullptr)));
         }
       }
     }
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index fa95787..b0776be 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -8,6 +8,7 @@
 #include "include/dart_api.h"
 #include "include/dart_tools_api.h"
 #include "vm/allocation.h"
+#include "vm/isolate.h"
 #include "vm/snapshot.h"
 
 namespace dart {
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 4b03928..86cd097 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -32,6 +32,7 @@
 #include "vm/lockers.h"
 #include "vm/message.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/native_entry.h"
 #include "vm/native_symbol.h"
 #include "vm/object.h"
@@ -1453,16 +1454,14 @@
 
   *error = nullptr;
 
-  if (!IsolateGroup::AreIsolateGroupsEnabled()) {
+  if (!FLAG_enable_isolate_groups) {
     *error = Utils::StrDup(
-        "Lightweight isolates are only implemented in AOT "
-        "mode and need to be explicitly enabled by passing "
+        "Lightweight isolates need to be explicitly enabled by passing "
         "--enable-isolate-groups.");
     return nullptr;
   }
 
   Isolate* isolate;
-#if defined(DART_PRECOMPILED_RUNTIME)
   isolate = CreateWithinExistingIsolateGroup(member->group(), name, error);
   if (isolate != nullptr) {
     isolate->set_origin_id(member->origin_id());
@@ -1470,10 +1469,6 @@
     isolate->set_on_shutdown_callback(shutdown_callback);
     isolate->set_on_cleanup_callback(cleanup_callback);
   }
-#else
-  *error = Utils::StrDup("Lightweight isolates are not yet ready in JIT mode.");
-  isolate = nullptr;
-#endif
 
   return Api::CastIsolate(isolate);
 }
@@ -2167,17 +2162,10 @@
     return false;
   }
 
-  // Smis and null can be sent without serialization.
-  ObjectPtr raw_obj = Api::UnwrapHandle(handle);
-  if (ApiObjectConverter::CanConvert(raw_obj)) {
-    return PortMap::PostMessage(
-        Message::New(port_id, raw_obj, Message::kNormalPriority));
-  }
-
-  const Object& object = Object::Handle(Z, raw_obj);
-  MessageWriter writer(false);
-  return PortMap::PostMessage(
-      writer.WriteMessage(object, port_id, Message::kNormalPriority));
+  const Object& object = Object::Handle(Z, Api::UnwrapHandle(handle));
+  return PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
+                                           object, port_id,
+                                           Message::kNormalPriority));
 }
 
 DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id) {
@@ -6169,10 +6157,6 @@
   return ServiceIsolate::IsServiceIsolate(iso);
 }
 
-DART_EXPORT int64_t Dart_TimelineGetMicros() {
-  return OS::GetCurrentMonotonicMicros();
-}
-
 DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
     const char* name,
     Dart_ServiceRequestCallback callback,
@@ -6314,6 +6298,18 @@
 #endif
 }
 
+DART_EXPORT int64_t Dart_TimelineGetMicros() {
+  return OS::GetCurrentMonotonicMicros();
+}
+
+DART_EXPORT int64_t Dart_TimelineGetTicks() {
+  return OS::GetCurrentMonotonicTicks();
+}
+
+DART_EXPORT int64_t Dart_TimelineGetTicksFrequency() {
+  return OS::GetCurrentMonotonicFrequency();
+}
+
 DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
 #if defined(SUPPORT_TIMELINE)
   const bool api_enabled = (stream_mask & DART_TIMELINE_STREAM_API) != 0;
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 6f116a0..b61e6c2 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -4166,6 +4166,61 @@
   EXPECT_VALID(Dart_Invoke(lib, NewString("main"), 0, NULL));
 }
 
+void FUNCTION_NAME(SecretKeeper_KeepSecret)(Dart_NativeArguments native_args) {
+  Dart_Handle receiver = Dart_GetNativeArgument(native_args, 0);
+  int64_t secret = 0;
+  Dart_GetNativeIntegerArgument(native_args, 1, &secret);
+  EXPECT_VALID(Dart_SetNativeInstanceField(receiver, 0, secret));
+}
+
+static Dart_NativeFunction SecretKeeperNativeResolver(Dart_Handle name,
+                                                      int argument_count,
+                                                      bool* auto_setup_scope) {
+  return reinterpret_cast<Dart_NativeFunction>(Builtin_SecretKeeper_KeepSecret);
+}
+
+TEST_CASE(DartAPI_NativeFieldAccess) {
+  const char* kScriptChars = R"(
+    import 'dart:nativewrappers';
+    class SecretKeeper extends NativeFieldWrapperClass1 {
+      SecretKeeper(int secret) { _keepSecret(secret); }
+      void _keepSecret(int secret) native "SecretKeeper_KeepSecret";
+    }
+    main() => getNativeField(SecretKeeper(321));
+  )";
+
+  Dart_Handle result;
+  Dart_Handle lib =
+      TestCase::LoadTestScript(kScriptChars, SecretKeeperNativeResolver);
+  result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
+
+  EXPECT_VALID(result);
+  EXPECT(Dart_IsInteger(result));
+  int64_t value = 0;
+  result = Dart_IntegerToInt64(result, &value);
+  EXPECT_VALID(result);
+  EXPECT_EQ(321, value);
+}
+
+TEST_CASE(DartAPI_NativeFieldAccess_Throws) {
+  const char* kScriptChars = R"(
+    import 'dart:nativewrappers';
+    class ForgetfulSecretKeeper extends NativeFieldWrapperClass1 {
+      ForgetfulSecretKeeper(int secret) { /* Forget to init. native field. */ }
+    }
+    main() => getNativeField(ForgetfulSecretKeeper(321));
+  )";
+
+  Dart_Handle result;
+  Dart_Handle lib =
+      TestCase::LoadTestScript(kScriptChars, SecretKeeperNativeResolver);
+
+  result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
+
+  EXPECT(Dart_IsError(result));
+  EXPECT(Dart_IsUnhandledExceptionError(result));
+}
+
 static Dart_WeakPersistentHandle weak1 = NULL;
 static Dart_WeakPersistentHandle weak2 = NULL;
 static Dart_WeakPersistentHandle weak3 = NULL;
@@ -9082,6 +9137,19 @@
   EXPECT_SUBSTRING("testAsyncEvent", js.ToCString());
 }
 
+TEST_CASE(DartAPI_TimelineClock) {
+  int64_t micros1 = Dart_TimelineGetMicros();
+  int64_t ticks1 = Dart_TimelineGetTicks();
+  int64_t frequency1 = Dart_TimelineGetTicksFrequency();
+  OS::Sleep(1);
+  int64_t micros2 = Dart_TimelineGetMicros();
+  int64_t ticks2 = Dart_TimelineGetTicks();
+  int64_t frequency2 = Dart_TimelineGetTicksFrequency();
+  EXPECT_NE(micros1, micros2);
+  EXPECT_NE(ticks1, ticks2);
+  EXPECT_EQ(frequency1, frequency2);
+}
+
 static void HintFreedNative(Dart_NativeArguments args) {
   int64_t size = 0;
   EXPECT_VALID(Dart_GetNativeIntegerArgument(args, 0, &size));
@@ -9305,7 +9373,7 @@
 TEST_CASE(Dart_SetFfiNativeResolver) {
   const char* kScriptChars = R"(
     import 'dart:ffi';
-    @FfiNative<IntPtr Function(Double)>('EchoInt')
+    @FfiNative<IntPtr Function(Double)>('EchoInt', isLeaf:true)
     external int echoInt(double x);
     main() => echoInt(7.0);
     )";
@@ -9327,7 +9395,7 @@
 TEST_CASE(Dart_SetFfiNativeResolver_MissingResolver) {
   const char* kScriptChars = R"(
     import 'dart:ffi';
-    @FfiNative<IntPtr Function(Double)>('EchoInt')
+    @FfiNative<IntPtr Function(Double)>('EchoInt', isLeaf:true)
     external int echoInt(double x);
     main() => echoInt(7.0);
     )";
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
deleted file mode 100644
index 73df245..0000000
--- a/runtime/vm/dart_api_message.cc
+++ /dev/null
@@ -1,1192 +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 <memory>
-
-#include "vm/dart_api_message.h"
-
-#include "platform/undefined_behavior_sanitizer.h"
-#include "platform/unicode.h"
-#include "vm/object.h"
-#include "vm/snapshot_ids.h"
-#include "vm/symbols.h"
-
-namespace dart {
-
-static const int kNumInitialReferences = 4;
-
-ApiMessageReader::ApiMessageReader(Message* msg)
-    : BaseReader(msg->IsRaw() ? reinterpret_cast<uint8_t*>(
-                                    static_cast<uword>(msg->raw_obj()))
-                              : msg->snapshot(),
-                 msg->snapshot_length()),
-      zone_(NULL),
-      backward_references_(kNumInitialReferences),
-      vm_isolate_references_(kNumInitialReferences),
-      vm_symbol_references_(NULL),
-      finalizable_data_(msg->finalizable_data()) {}
-
-ApiMessageReader::~ApiMessageReader() {}
-
-void ApiMessageReader::Init() {
-  // We need to have an enclosing ApiNativeScope.
-  ASSERT(ApiNativeScope::Current() != NULL);
-  zone_ = ApiNativeScope::Current()->zone();
-  ASSERT(zone_ != NULL);
-
-  // Initialize marker objects used to handle Lists.
-  // TODO(sjesse): Remove this when message serialization format is
-  // updated.
-  memset(&type_arguments_marker, 0, sizeof(type_arguments_marker));
-  memset(&dynamic_type_marker, 0, sizeof(dynamic_type_marker));
-  type_arguments_marker.type =
-      static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kTypeArguments);
-  dynamic_type_marker.type =
-      static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kDynamicType);
-}
-
-Dart_CObject* ApiMessageReader::ReadMessage() {
-  Init();
-  if (PendingBytes() > 0) {
-    // Read the object out of the message.
-    return ReadObject();
-  } else {
-    const ObjectPtr raw_obj = static_cast<const ObjectPtr>(
-        reinterpret_cast<uword>(CurrentBufferAddress()));
-    ASSERT(ApiObjectConverter::CanConvert(raw_obj));
-    Dart_CObject* cobj =
-        reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));
-    ApiObjectConverter::Convert(raw_obj, cobj);
-    return cobj;
-  }
-}
-
-intptr_t ApiMessageReader::LookupInternalClass(intptr_t class_header) {
-  if (IsVMIsolateObject(class_header)) {
-    return GetVMIsolateObjectId(class_header);
-  }
-  ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
-  return SerializedHeaderData::decode(class_header);
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObject(Dart_CObject_Type type) {
-  Dart_CObject* value =
-      reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));
-  ASSERT(value != NULL);
-  value->type = type;
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectUnsupported() {
-  return AllocateDartCObject(Dart_CObject_kUnsupported);
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectNull() {
-  return AllocateDartCObject(Dart_CObject_kNull);
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectBool(bool val) {
-  Dart_CObject* value = AllocateDartCObject(Dart_CObject_kBool);
-  value->value.as_bool = val;
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectInt32(int32_t val) {
-  Dart_CObject* value = AllocateDartCObject(Dart_CObject_kInt32);
-  value->value.as_int32 = val;
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectInt64(int64_t val) {
-  Dart_CObject* value = AllocateDartCObject(Dart_CObject_kInt64);
-  value->value.as_int64 = val;
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectDouble(double val) {
-  Dart_CObject* value = AllocateDartCObject(Dart_CObject_kDouble);
-  value->value.as_double = val;
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectString(intptr_t length) {
-  // Allocate a Dart_CObject structure followed by an array of chars
-  // for the string content. The pointer to the string content is set
-  // up to this area.
-  Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
-      allocator(sizeof(Dart_CObject) + length + 1));
-  ASSERT(value != NULL);
-  value->value.as_string = reinterpret_cast<char*>(value) + sizeof(*value);
-  value->type = Dart_CObject_kString;
-  return value;
-}
-
-static int GetTypedDataSizeInBytes(Dart_TypedData_Type type) {
-  switch (type) {
-    case Dart_TypedData_kInt8:
-    case Dart_TypedData_kUint8:
-    case Dart_TypedData_kUint8Clamped:
-      return 1;
-    case Dart_TypedData_kInt16:
-    case Dart_TypedData_kUint16:
-      return 2;
-    case Dart_TypedData_kInt32:
-    case Dart_TypedData_kUint32:
-    case Dart_TypedData_kFloat32:
-      return 4;
-    case Dart_TypedData_kInt64:
-    case Dart_TypedData_kUint64:
-    case Dart_TypedData_kFloat64:
-      return 8;
-    case Dart_TypedData_kInt32x4:
-    case Dart_TypedData_kFloat32x4:
-    case Dart_TypedData_kFloat64x2:
-      return 16;
-    default:
-      break;
-  }
-  UNREACHABLE();
-  return -1;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectTypedData(
-    Dart_TypedData_Type type,
-    intptr_t length) {
-  // Allocate a Dart_CObject structure followed by an array of bytes
-  // for the byte array content. The pointer to the byte array content
-  // is set up to this area.
-  intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * length;
-  Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
-      allocator(sizeof(Dart_CObject) + length_in_bytes));
-  ASSERT(value != NULL);
-  value->type = Dart_CObject_kTypedData;
-  value->value.as_typed_data.type = type;
-  value->value.as_typed_data.length = length_in_bytes;
-  if (length > 0) {
-    value->value.as_typed_data.values =
-        reinterpret_cast<uint8_t*>(value) + sizeof(*value);
-  } else {
-    value->value.as_typed_data.values = NULL;
-  }
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectArray(intptr_t length) {
-  // Allocate a Dart_CObject structure followed by an array of
-  // pointers to Dart_CObject structures. The pointer to the array
-  // content is set up to this area.
-  Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
-      allocator(sizeof(Dart_CObject) + length * sizeof(value)));
-  ASSERT(value != NULL);
-  value->type = Dart_CObject_kArray;
-  value->value.as_array.length = length;
-  if (length > 0) {
-    value->value.as_array.values = reinterpret_cast<Dart_CObject**>(value + 1);
-  } else {
-    value->value.as_array.values = NULL;
-  }
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectVmIsolateObj(intptr_t id) {
-  ObjectPtr raw = VmIsolateSnapshotObject(id);
-  intptr_t cid = raw->GetClassId();
-  switch (cid) {
-    case kOneByteStringCid: {
-      OneByteStringPtr raw_str = static_cast<OneByteStringPtr>(raw);
-      const char* str = reinterpret_cast<const char*>(raw_str->untag()->data());
-      ASSERT(str != NULL);
-      Dart_CObject* object = NULL;
-      for (intptr_t i = 0; i < vm_isolate_references_.length(); i++) {
-        object = vm_isolate_references_.At(i);
-        if (object->type == Dart_CObject_kString) {
-          if (strcmp(str, object->value.as_string) == 0) {
-            return object;
-          }
-        }
-      }
-      object = CreateDartCObjectString(raw);
-      vm_isolate_references_.Add(object);
-      return object;
-    }
-
-    case kMintCid: {
-      const Mint& obj = Mint::Handle(static_cast<MintPtr>(raw));
-      int64_t value64 = obj.value();
-      if ((kMinInt32 <= value64) && (value64 <= kMaxInt32)) {
-        return GetCanonicalMintObject(Dart_CObject_kInt32, value64);
-      } else {
-        return GetCanonicalMintObject(Dart_CObject_kInt64, value64);
-      }
-    }
-
-    default:
-      UNREACHABLE();
-      return NULL;
-  }
-}
-
-Dart_CObject_Internal* ApiMessageReader::AllocateDartCObjectInternal(
-    Dart_CObject_Internal::Type type) {
-  Dart_CObject_Internal* value = reinterpret_cast<Dart_CObject_Internal*>(
-      allocator(sizeof(Dart_CObject_Internal)));
-  ASSERT(value != NULL);
-  value->type = static_cast<Dart_CObject_Type>(type);
-  return value;
-}
-
-Dart_CObject_Internal* ApiMessageReader::AllocateDartCObjectClass() {
-  return AllocateDartCObjectInternal(Dart_CObject_Internal::kClass);
-}
-
-ApiMessageReader::BackRefNode* ApiMessageReader::AllocateBackRefNode(
-    Dart_CObject* reference,
-    DeserializeState state) {
-  BackRefNode* value =
-      reinterpret_cast<BackRefNode*>(allocator(sizeof(BackRefNode)));
-  value->set_reference(reference);
-  value->set_state(state);
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
-  // Read the class header information and lookup the class.
-  intptr_t class_header = Read<int32_t>();
-  intptr_t tags = ReadTags();
-  USE(tags);
-  intptr_t class_id;
-
-  // There is limited support for reading regular dart instances. Only
-  // typed data views are currently handled.
-  if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
-    Dart_CObject_Internal* object =
-        reinterpret_cast<Dart_CObject_Internal*>(GetBackRef(object_id));
-    if (object == NULL) {
-      object =
-          AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);
-      AddBackRef(object_id, object, kIsDeserialized);
-      // Read class of object.
-      object->cls = reinterpret_cast<Dart_CObject_Internal*>(ReadObjectImpl());
-      ASSERT(object->cls->type ==
-             static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kClass));
-    }
-    ASSERT(object->type == static_cast<Dart_CObject_Type>(
-                               Dart_CObject_Internal::kUninitialized));
-    return object;
-  }
-
-  ASSERT((class_header & kSmiTagMask) != 0);
-  class_id = LookupInternalClass(class_header);
-  if ((class_id == kArrayCid) || (class_id == kImmutableArrayCid)) {
-    intptr_t len = ReadSmiValue();
-    Dart_CObject* value = GetBackRef(object_id);
-    if (value == NULL) {
-      value = AllocateDartCObjectArray(len);
-      AddBackRef(object_id, value, kIsDeserialized);
-    }
-    // Skip type arguments.
-    // TODO(sjesse): Remove this when message serialization format is
-    // updated (currently type_arguments is leaked).
-    Dart_CObject* type_arguments = ReadObjectImpl();
-    if (type_arguments != &type_arguments_marker &&
-        type_arguments->type != Dart_CObject_kNull) {
-      return AllocateDartCObjectUnsupported();
-    }
-    for (int i = 0; i < len; i++) {
-      value->value.as_array.values[i] = ReadObjectRef();
-    }
-    return value;
-  }
-
-  return ReadInternalVMObject(class_id, object_id);
-}
-
-Dart_CObject* ApiMessageReader::ReadPredefinedSymbol(intptr_t object_id) {
-  ASSERT(Symbols::IsPredefinedSymbolId(object_id));
-  intptr_t symbol_id = object_id - kMaxPredefinedObjectIds;
-  Dart_CObject* object;
-  if (vm_symbol_references_ != NULL &&
-      (object = vm_symbol_references_[symbol_id]) != NULL) {
-    return object;
-  }
-
-  if (vm_symbol_references_ == NULL) {
-    intptr_t size =
-        (sizeof(*vm_symbol_references_) * Symbols::kMaxPredefinedId);
-    vm_symbol_references_ = reinterpret_cast<Dart_CObject**>(allocator(size));
-    memset(vm_symbol_references_, 0, size);
-  }
-
-  object = CreateDartCObjectString(Symbols::GetPredefinedSymbol(object_id));
-  ASSERT(vm_symbol_references_[symbol_id] == NULL);
-  vm_symbol_references_[symbol_id] = object;
-  return object;
-}
-
-intptr_t ApiMessageReader::NextAvailableObjectId() const {
-  return backward_references_.length() + kMaxPredefinedObjectIds;
-}
-
-Dart_CObject* ApiMessageReader::CreateDartCObjectString(ObjectPtr raw) {
-  ASSERT(IsOneByteStringClassId(raw->GetClassId()));
-  OneByteStringPtr raw_str = static_cast<OneByteStringPtr>(raw);
-  intptr_t len = Smi::Value(raw_str->untag()->length());
-  Dart_CObject* object = AllocateDartCObjectString(len);
-  char* p = object->value.as_string;
-  memmove(p, raw_str->untag()->data(), len);
-  p[len] = '\0';
-  return object;
-}
-
-Dart_CObject* ApiMessageReader::GetCanonicalMintObject(Dart_CObject_Type type,
-                                                       int64_t value64) {
-  Dart_CObject* object = NULL;
-  for (intptr_t i = 0; i < vm_isolate_references_.length(); i++) {
-    object = vm_isolate_references_.At(i);
-    if (object->type == type) {
-      if (value64 == object->value.as_int64) {
-        return object;
-      }
-    }
-  }
-  if (type == Dart_CObject_kInt32) {
-    object = AllocateDartCObjectInt32(static_cast<int32_t>(value64));
-  } else {
-    object = AllocateDartCObjectInt64(value64);
-  }
-  vm_isolate_references_.Add(object);
-  return object;
-}
-
-Dart_CObject* ApiMessageReader::ReadObjectRef() {
-  int64_t value64 = Read<int64_t>();
-  if ((value64 & kSmiTagMask) == 0) {
-    int64_t untagged_value = value64 >> kSmiTagShift;
-    if ((kMinInt32 <= untagged_value) && (untagged_value <= kMaxInt32)) {
-      return AllocateDartCObjectInt32(static_cast<int32_t>(untagged_value));
-    } else {
-      return AllocateDartCObjectInt64(untagged_value);
-    }
-  }
-  ASSERT((value64 <= kIntptrMax) && (value64 >= kIntptrMin));
-  intptr_t value = static_cast<intptr_t>(value64);
-  if (IsVMIsolateObject(value)) {
-    return ReadVMIsolateObject(value);
-  }
-  if (SerializedHeaderTag::decode(value) == kObjectId) {
-    return ReadIndexedObject(SerializedHeaderData::decode(value));
-  }
-  ASSERT(SerializedHeaderTag::decode(value) == kInlined);
-  // Read the class header information and lookup the class.
-  intptr_t class_header = Read<int32_t>();
-
-  intptr_t object_id = SerializedHeaderData::decode(value);
-  if (object_id == kOmittedObjectId) {
-    object_id = NextAvailableObjectId();
-  }
-
-  intptr_t tags = ReadTags();
-  USE(tags);
-
-  // Reading of regular dart instances has limited support in order to
-  // read typed data views.
-  if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
-    Dart_CObject_Internal* object =
-        AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);
-    AddBackRef(object_id, object, kIsNotDeserialized);
-    // Read class of object.
-    object->cls = reinterpret_cast<Dart_CObject_Internal*>(ReadObjectImpl());
-    ASSERT(object->cls->type ==
-           static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kClass));
-    return object;
-  }
-  ASSERT((class_header & kSmiTagMask) != 0);
-  intptr_t class_id = LookupInternalClass(class_header);
-  if ((class_id == kArrayCid) || (class_id == kImmutableArrayCid)) {
-    ASSERT(GetBackRef(object_id) == NULL);
-    intptr_t len = ReadSmiValue();
-    Dart_CObject* value = AllocateDartCObjectArray(len);
-    AddBackRef(object_id, value, kIsNotDeserialized);
-    return value;
-  }
-  return ReadInternalVMObject(class_id, object_id);
-}
-
-Dart_CObject* ApiMessageReader::ReadVMIsolateObject(intptr_t value) {
-  intptr_t object_id = GetVMIsolateObjectId(value);
-  if (object_id == kNullObject) {
-    return AllocateDartCObjectNull();
-  }
-  if (object_id == kTrueValue) {
-    return AllocateDartCObjectBool(true);
-  }
-  if (object_id == kFalseValue) {
-    return AllocateDartCObjectBool(false);
-  }
-  if (object_id == kDoubleObject) {
-    return AllocateDartCObjectDouble(ReadDouble());
-  }
-  if (Symbols::IsPredefinedSymbolId(object_id)) {
-    return ReadPredefinedSymbol(object_id);
-  }
-  // No other VM isolate objects are supported.
-  return AllocateDartCObjectNull();
-}
-
-Dart_CObject* ApiMessageReader::ReadInternalVMObject(intptr_t class_id,
-                                                     intptr_t object_id) {
-  switch (class_id) {
-    case kClassCid: {
-      Dart_CObject_Internal* object = AllocateDartCObjectClass();
-      AddBackRef(object_id, object, kIsDeserialized);
-      object->internal.as_class.library_url = ReadObjectImpl();
-      ASSERT(object->internal.as_class.library_url->type ==
-             Dart_CObject_kString);
-      object->internal.as_class.class_name = ReadObjectImpl();
-      ASSERT(object->internal.as_class.class_name->type ==
-             Dart_CObject_kString);
-      return object;
-    }
-    case kTypeArgumentsCid: {
-      // TODO(sjesse): Remove this when message serialization format is
-      // updated (currently length is leaked).
-      Dart_CObject* value = &type_arguments_marker;
-      AddBackRef(object_id, value, kIsDeserialized);
-      Dart_CObject* length = ReadObjectImpl();
-      ASSERT(length->type == Dart_CObject_kInt32);
-      // The instantiations_ field is only written to a full snapshot.
-      for (int i = 0; i < length->value.as_int32; i++) {
-        Dart_CObject* type = ReadObjectImpl();
-        if (type != &dynamic_type_marker) {
-          return AllocateDartCObjectUnsupported();
-        }
-      }
-      return value;
-    }
-    case kTypeParameterCid: {
-      Dart_CObject* value = &dynamic_type_marker;
-      AddBackRef(object_id, value, kIsDeserialized);
-      intptr_t index = Read<int32_t>();
-      USE(index);
-      intptr_t token_index = Read<int32_t>();
-      USE(token_index);
-      int8_t type_state = Read<int8_t>();
-      USE(type_state);
-      Dart_CObject* parameterized_class = ReadObjectImpl();
-      // The type parameter is finalized, therefore parameterized_class is null.
-      ASSERT(parameterized_class->type == Dart_CObject_kNull);
-      Dart_CObject* name = ReadObjectImpl();
-      ASSERT(name->type == Dart_CObject_kString);
-      return value;
-    }
-    case kMintCid: {
-      int64_t value64 = Read<int64_t>();
-      Dart_CObject* object;
-      if ((kMinInt32 <= value64) && (value64 <= kMaxInt32)) {
-        object = AllocateDartCObjectInt32(static_cast<int32_t>(value64));
-      } else {
-        object = AllocateDartCObjectInt64(value64);
-      }
-      AddBackRef(object_id, object, kIsDeserialized);
-      return object;
-    }
-    case kDoubleCid: {
-      // Doubles are handled specially when being sent as part of message
-      // snapshots.
-      UNREACHABLE();
-    }
-    case kOneByteStringCid: {
-      intptr_t len = ReadSmiValue();
-      uint8_t* latin1 =
-          reinterpret_cast<uint8_t*>(allocator(len * sizeof(uint8_t)));
-      intptr_t utf8_len = 0;
-      for (intptr_t i = 0; i < len; i++) {
-        latin1[i] = Read<uint8_t>();
-        utf8_len += Utf8::Length(latin1[i]);
-      }
-      Dart_CObject* object = AllocateDartCObjectString(utf8_len);
-      AddBackRef(object_id, object, kIsDeserialized);
-      char* p = object->value.as_string;
-      for (intptr_t i = 0; i < len; i++) {
-        p += Utf8::Encode(latin1[i], p);
-      }
-      *p = '\0';
-      ASSERT(p == (object->value.as_string + utf8_len));
-      return object;
-    }
-    case kTwoByteStringCid: {
-      intptr_t len = ReadSmiValue();
-      uint16_t* utf16 =
-          reinterpret_cast<uint16_t*>(allocator(len * sizeof(uint16_t)));
-      intptr_t utf8_len = 0;
-      // Read all the UTF-16 code units.
-      for (intptr_t i = 0; i < len; i++) {
-        utf16[i] = Read<uint16_t>();
-      }
-      // Calculate the UTF-8 length and check if the string can be
-      // UTF-8 encoded.
-      bool valid = true;
-      intptr_t i = 0;
-      while (i < len && valid) {
-        int32_t ch = Utf16::Next(utf16, &i, len);
-        utf8_len += Utf8::Length(ch);
-        valid = !Utf16::IsSurrogate(ch);
-      }
-      if (!valid) {
-        return AllocateDartCObjectUnsupported();
-      }
-      Dart_CObject* object = AllocateDartCObjectString(utf8_len);
-      AddBackRef(object_id, object, kIsDeserialized);
-      char* p = object->value.as_string;
-      i = 0;
-      while (i < len) {
-        p += Utf8::Encode(Utf16::Next(utf16, &i, len), p);
-      }
-      *p = '\0';
-      ASSERT(p == (object->value.as_string + utf8_len));
-      return object;
-    }
-    case kSendPortCid: {
-      int64_t value64 = Read<int64_t>();
-      int64_t originId = Read<uint64_t>();
-      Dart_CObject* object = AllocateDartCObject(Dart_CObject_kSendPort);
-      object->value.as_send_port.id = value64;
-      object->value.as_send_port.origin_id = originId;
-      AddBackRef(object_id, object, kIsDeserialized);
-      return object;
-    }
-    case kCapabilityCid: {
-      int64_t id = Read<int64_t>();
-      Dart_CObject* object = AllocateDartCObject(Dart_CObject_kCapability);
-      object->value.as_capability.id = id;
-      AddBackRef(object_id, object, kIsDeserialized);
-      return object;
-    }
-
-#define READ_TYPED_DATA(tname, ctype)                                          \
-  {                                                                            \
-    intptr_t len = ReadSmiValue();                                             \
-    auto type = Dart_TypedData_k##tname;                                       \
-    intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * len;            \
-    Dart_CObject* object =                                                     \
-        reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));      \
-    ASSERT(object != NULL);                                                    \
-    object->type = Dart_CObject_kTypedData;                                    \
-    object->value.as_typed_data.type = type;                                   \
-    object->value.as_typed_data.length = length_in_bytes;                      \
-    if (len > 0) {                                                             \
-      Align(Zone::kAlignment);                                                 \
-      object->value.as_typed_data.values =                                     \
-          const_cast<uint8_t*>(CurrentBufferAddress());                        \
-      Advance(length_in_bytes);                                                \
-    } else {                                                                   \
-      object->value.as_typed_data.values = NULL;                               \
-    }                                                                          \
-    AddBackRef(object_id, object, kIsDeserialized);                            \
-    return object;                                                             \
-  }
-
-#define READ_EXTERNAL_TYPED_DATA(tname, ctype)                                 \
-  {                                                                            \
-    intptr_t len = ReadSmiValue();                                             \
-    auto type = Dart_TypedData_k##tname;                                       \
-    intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * len;            \
-    Dart_CObject* object =                                                     \
-        reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));      \
-    ASSERT(object != NULL);                                                    \
-    object->type = Dart_CObject_kTypedData;                                    \
-    object->value.as_typed_data.type = type;                                   \
-    object->value.as_typed_data.length = length_in_bytes;                      \
-    object->value.as_typed_data.values =                                       \
-        reinterpret_cast<uint8_t*>(finalizable_data_->Get().data);             \
-    AddBackRef(object_id, object, kIsDeserialized);                            \
-    return object;                                                             \
-  }
-
-#define READ_TYPED_DATA_VIEW(tname, ctype)                                     \
-  {                                                                            \
-    Dart_CObject_Internal* object =                                            \
-        AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);    \
-    AddBackRef(object_id, object, kIsDeserialized);                            \
-    object->type =                                                             \
-        static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView);          \
-    object->internal.as_view.offset_in_bytes = ReadSmiValue();                 \
-    object->internal.as_view.length = ReadSmiValue();                          \
-    object->internal.as_view.buffer = ReadObjectImpl();                        \
-    Dart_CObject* buffer = object->internal.as_view.buffer;                    \
-    RELEASE_ASSERT(buffer->type == Dart_CObject_kTypedData);                   \
-                                                                               \
-    /* Now turn the view into a byte array.*/                                  \
-    const Dart_TypedData_Type type = Dart_TypedData_k##tname;                  \
-    object->type = Dart_CObject_kTypedData;                                    \
-    object->value.as_typed_data.type = type;                                   \
-    object->value.as_typed_data.length =                                       \
-        object->internal.as_view.length * GetTypedDataSizeInBytes(type);       \
-    object->value.as_typed_data.values =                                       \
-        buffer->value.as_typed_data.values +                                   \
-        object->internal.as_view.offset_in_bytes;                              \
-    return object;                                                             \
-  }
-
-#define TYPED_DATA_LIST(V)                                                     \
-  V(Int8, int8_t)                                                              \
-  V(Uint8, uint8_t)                                                            \
-  V(Uint8Clamped, uint8_t)                                                     \
-  V(Int16, int16_t)                                                            \
-  V(Uint16, uint16_t)                                                          \
-  V(Int32, int32_t)                                                            \
-  V(Uint32, uint32_t)                                                          \
-  V(Int64, int64_t)                                                            \
-  V(Uint64, uint64_t)                                                          \
-  V(Float32, float)                                                            \
-  V(Float64, double)                                                           \
-  V(Int32x4, simd128_value_t)                                                  \
-  V(Float32x4, simd128_value_t)                                                \
-  V(Float64x2, simd128_value_t)
-
-#define EMIT_TYPED_DATA_CASES(type, c_type)                                    \
-  case kTypedData##type##ArrayCid:                                             \
-    READ_TYPED_DATA(type, c_type);                                             \
-  case kExternalTypedData##type##ArrayCid:                                     \
-    READ_EXTERNAL_TYPED_DATA(type, c_type);                                    \
-  case kTypedData##type##ArrayViewCid:                                         \
-    READ_TYPED_DATA_VIEW(type, c_type);
-
-      TYPED_DATA_LIST(EMIT_TYPED_DATA_CASES)
-#undef EMIT_TYPED_DATA_CASES
-#undef TYPED_DATA_LIST
-#undef READ_TYPED_DATA
-#undef READ_EXTERNAL_TYPED_DATA
-#undef READ_TYPED_DATA_VIEW
-
-    case kGrowableObjectArrayCid: {
-      // A GrowableObjectArray is serialized as its type arguments and
-      // length followed by its backing store. The backing store is an
-      // array with a length which might be longer than the length of
-      // the GrowableObjectArray.
-      Dart_CObject* value = GetBackRef(object_id);
-      ASSERT(value == NULL);
-      // Allocate an empty array for the GrowableObjectArray which
-      // will be updated to point to the content when the backing
-      // store has been deserialized.
-      value = AllocateDartCObjectArray(0);
-      AddBackRef(object_id, value, kIsDeserialized);
-
-      // Read and skip the type arguments field.
-      // TODO(sjesse): Remove this when message serialization format is
-      // updated (currently type_arguments is leaked).
-      Dart_CObject* type_arguments = ReadObjectImpl();
-      if (type_arguments != &type_arguments_marker &&
-          type_arguments->type != Dart_CObject_kNull) {
-        return AllocateDartCObjectUnsupported();
-      }
-
-      // Read the length field.
-      intptr_t len = ReadSmiValue();
-
-      // Read the content of the GrowableObjectArray.
-      Dart_CObject* content = ReadObjectRef();
-      ASSERT(content->type == Dart_CObject_kArray);
-      // Make the empty array allocated point to the backing store content.
-      value->value.as_array.length = len;
-      value->value.as_array.values = content->value.as_array.values;
-      return value;
-    }
-    default:
-      // Everything else not supported.
-      Dart_CObject* value = AllocateDartCObjectUnsupported();
-      AddBackRef(object_id, value, kIsDeserialized);
-      return value;
-  }
-}
-
-Dart_CObject* ApiMessageReader::ReadIndexedObject(intptr_t object_id) {
-  if (object_id >= kFirstTypeSnapshotId && object_id <= kLastTypeSnapshotId) {
-    // Always return dynamic type (this is only a marker).
-    return &dynamic_type_marker;
-  }
-  if (object_id >= kFirstTypeArgumentsSnapshotId &&
-      object_id <= kLastTypeArgumentsSnapshotId) {
-    return &type_arguments_marker;
-  }
-
-  intptr_t index = object_id - kMaxPredefinedObjectIds;
-  ASSERT((0 <= index) && (index < backward_references_.length()));
-  ASSERT(backward_references_[index]->reference() != NULL);
-  return backward_references_[index]->reference();
-}
-
-Dart_CObject* ApiMessageReader::ReadObject() {
-  Dart_CObject* value = ReadObjectImpl();
-  for (intptr_t i = 0; i < backward_references_.length(); i++) {
-    if (!backward_references_[i]->is_deserialized()) {
-      ReadObjectImpl();
-      backward_references_[i]->set_state(kIsDeserialized);
-    }
-  }
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::ReadObjectImpl() {
-  int64_t value64 = Read<int64_t>();
-  if ((value64 & kSmiTagMask) == 0) {
-    int64_t untagged_value = value64 >> kSmiTagShift;
-    if ((kMinInt32 <= untagged_value) && (untagged_value <= kMaxInt32)) {
-      return AllocateDartCObjectInt32(static_cast<int32_t>(untagged_value));
-    } else {
-      return AllocateDartCObjectInt64(untagged_value);
-    }
-  }
-  ASSERT((value64 <= kIntptrMax) && (value64 >= kIntptrMin));
-  intptr_t value = static_cast<intptr_t>(value64);
-  if (IsVMIsolateObject(value)) {
-    return ReadVMIsolateObject(value);
-  }
-  if (SerializedHeaderTag::decode(value) == kObjectId) {
-    return ReadIndexedObject(SerializedHeaderData::decode(value));
-  }
-  ASSERT(SerializedHeaderTag::decode(value) == kInlined);
-
-  intptr_t object_id = SerializedHeaderData::decode(value);
-  if (object_id == kOmittedObjectId) {
-    object_id = NextAvailableObjectId();
-  }
-  return ReadInlinedObject(object_id);
-}
-
-void ApiMessageReader::AddBackRef(intptr_t id,
-                                  Dart_CObject* obj,
-                                  DeserializeState state) {
-  intptr_t index = (id - kMaxPredefinedObjectIds);
-  ASSERT(index == backward_references_.length());
-  BackRefNode* node = AllocateBackRefNode(obj, state);
-  ASSERT(node != NULL);
-  backward_references_.Add(node);
-}
-
-Dart_CObject* ApiMessageReader::GetBackRef(intptr_t id) {
-  ASSERT(id >= kMaxPredefinedObjectIds);
-  intptr_t index = (id - kMaxPredefinedObjectIds);
-  if (index < backward_references_.length()) {
-    return backward_references_[index]->reference();
-  }
-  return NULL;
-}
-
-ApiMessageWriter::ApiMessageWriter()
-    : BaseWriter(kInitialSize),
-      object_id_(0),
-      forward_list_(NULL),
-      forward_list_length_(0),
-      forward_id_(0),
-      finalizable_data_(new MessageFinalizableData()) {
-  ASSERT(kDartCObjectTypeMask >= Dart_CObject_kNumberOfTypes - 1);
-}
-
-ApiMessageWriter::~ApiMessageWriter() {
-  ::free(forward_list_);
-  delete finalizable_data_;
-}
-
-NO_SANITIZE_UNDEFINED(
-    "enum")  // TODO(https://github.com/dart-lang/sdk/issues/39427)
-void ApiMessageWriter::MarkCObject(Dart_CObject* object, intptr_t object_id) {
-  // Mark the object as serialized by adding the object id to the
-  // upper bits of the type field in the Dart_CObject structure. Add
-  // an offset for making marking of object id 0 possible.
-  ASSERT(!IsCObjectMarked(object));
-  intptr_t mark_value = object_id + kDartCObjectMarkOffset;
-  object->type = static_cast<Dart_CObject_Type>(
-      ((mark_value) << kDartCObjectTypeBits) | object->type);
-}
-
-NO_SANITIZE_UNDEFINED(
-    "enum")  // TODO(https://github.com/dart-lang/sdk/issues/39427)
-void ApiMessageWriter::UnmarkCObject(Dart_CObject* object) {
-  ASSERT(IsCObjectMarked(object));
-  object->type =
-      static_cast<Dart_CObject_Type>(object->type & kDartCObjectTypeMask);
-}
-
-NO_SANITIZE_UNDEFINED(
-    "enum")  // TODO(https://github.com/dart-lang/sdk/issues/39427)
-bool ApiMessageWriter::IsCObjectMarked(Dart_CObject* object) {
-  return (object->type & kDartCObjectMarkMask) != 0;
-}
-
-NO_SANITIZE_UNDEFINED(
-    "enum")  // TODO(https://github.com/dart-lang/sdk/issues/39427)
-intptr_t ApiMessageWriter::GetMarkedCObjectMark(Dart_CObject* object) {
-  ASSERT(IsCObjectMarked(object));
-  intptr_t mark_value =
-      ((object->type & kDartCObjectMarkMask) >> kDartCObjectTypeBits);
-  // An offset was added to object id for making marking object id 0 possible.
-  return mark_value - kDartCObjectMarkOffset;
-}
-
-void ApiMessageWriter::UnmarkAllCObjects(Dart_CObject* object) {
-  if (!IsCObjectMarked(object)) return;
-  UnmarkCObject(object);
-  if (object->type == Dart_CObject_kArray) {
-    for (int i = 0; i < object->value.as_array.length; i++) {
-      Dart_CObject* element = object->value.as_array.values[i];
-      UnmarkAllCObjects(element);
-    }
-  }
-}
-
-void ApiMessageWriter::AddToForwardList(Dart_CObject* object) {
-  if (forward_id_ >= forward_list_length_) {
-    void* new_list = NULL;
-    if (forward_list_length_ == 0) {
-      forward_list_length_ = 4;
-      intptr_t new_size = forward_list_length_ * sizeof(object);
-      new_list = dart::malloc(new_size);
-    } else {
-      forward_list_length_ *= 2;
-      intptr_t new_size = (forward_list_length_ * sizeof(object));
-      new_list = dart::realloc(forward_list_, new_size);
-    }
-    ASSERT(new_list != NULL);
-    forward_list_ = reinterpret_cast<Dart_CObject**>(new_list);
-  }
-  forward_list_[forward_id_] = object;
-  forward_id_ += 1;
-}
-
-void ApiMessageWriter::WriteSmi(int64_t value) {
-  ASSERT(Smi::IsValid(value));
-  Write<ObjectPtr>(Smi::New(static_cast<intptr_t>(value)));
-}
-
-void ApiMessageWriter::WriteNullObject() {
-  WriteVMIsolateObject(kNullObject);
-}
-
-void ApiMessageWriter::WriteMint(Dart_CObject* object, int64_t value) {
-  ASSERT(!Smi::IsValid(value));
-  // Write out the serialization header value for mint object.
-  WriteInlinedHeader(object);
-  // Write out the class and tags information.
-  WriteIndexedObject(kMintCid);
-  WriteTags(0);
-  // Write the 64-bit value.
-  Write<int64_t>(value);
-}
-
-void ApiMessageWriter::WriteInt32(Dart_CObject* object) {
-  int64_t value = object->value.as_int32;
-  if (Smi::IsValid(value)) {
-    WriteSmi(value);
-  } else {
-    WriteMint(object, value);
-  }
-}
-
-void ApiMessageWriter::WriteInt64(Dart_CObject* object) {
-  int64_t value = object->value.as_int64;
-  if (Smi::IsValid(value)) {
-    WriteSmi(value);
-  } else {
-    WriteMint(object, value);
-  }
-}
-
-void ApiMessageWriter::WriteInlinedHeader(Dart_CObject* object) {
-  // Write out the serialization header value for this object.
-  WriteInlinedObjectHeader(kMaxPredefinedObjectIds + object_id_);
-  // Mark object with its object id.
-  MarkCObject(object, object_id_);
-  // Advance object id.
-  object_id_++;
-}
-
-bool ApiMessageWriter::WriteCObject(Dart_CObject* object) {
-  if (IsCObjectMarked(object)) {
-    intptr_t object_id = GetMarkedCObjectMark(object);
-    WriteIndexedObject(kMaxPredefinedObjectIds + object_id);
-    return true;
-  }
-
-  Dart_CObject_Type type = object->type;
-  if (type == Dart_CObject_kArray) {
-    const intptr_t array_length = object->value.as_array.length;
-    if (!Array::IsValidLength(array_length)) {
-      return false;
-    }
-
-    // Write out the serialization header value for this object.
-    WriteInlinedHeader(object);
-    // Write out the class and tags information.
-    WriteIndexedObject(kArrayCid);
-    WriteTags(0);
-    // Write out the length information.
-    WriteSmi(array_length);
-    // Write out the type arguments.
-    WriteNullObject();
-    // Write out array elements.
-    for (int i = 0; i < array_length; i++) {
-      bool success = WriteCObjectRef(object->value.as_array.values[i]);
-      if (!success) return false;
-    }
-    return true;
-  }
-  return WriteCObjectInlined(object, type);
-}
-
-bool ApiMessageWriter::WriteCObjectRef(Dart_CObject* object) {
-  if (IsCObjectMarked(object)) {
-    intptr_t object_id = GetMarkedCObjectMark(object);
-    WriteIndexedObject(kMaxPredefinedObjectIds + object_id);
-    return true;
-  }
-
-  Dart_CObject_Type type = object->type;
-  if (type == Dart_CObject_kArray) {
-    const intptr_t array_length = object->value.as_array.length;
-    if (!Array::IsValidLength(array_length)) {
-      return false;
-    }
-    // Write out the serialization header value for this object.
-    WriteInlinedHeader(object);
-    // Write out the class information.
-    WriteIndexedObject(kArrayCid);
-    WriteTags(0);
-    // Write out the length information.
-    WriteSmi(array_length);
-    // Add object to forward list so that this object is serialized later.
-    AddToForwardList(object);
-    return true;
-  }
-  return WriteCObjectInlined(object, type);
-}
-
-NO_SANITIZE_UNDEFINED(
-    "enum")  // TODO(https://github.com/dart-lang/sdk/issues/39427)
-bool ApiMessageWriter::WriteForwardedCObject(Dart_CObject* object) {
-  ASSERT(IsCObjectMarked(object));
-  Dart_CObject_Type type =
-      static_cast<Dart_CObject_Type>(object->type & kDartCObjectTypeMask);
-  ASSERT(type == Dart_CObject_kArray);
-  const intptr_t array_length = object->value.as_array.length;
-  if (!Array::IsValidLength(array_length)) {
-    return false;
-  }
-
-  // Write out the serialization header value for this object.
-  intptr_t object_id = GetMarkedCObjectMark(object);
-  WriteInlinedObjectHeader(kMaxPredefinedObjectIds + object_id);
-  // Write out the class and tags information.
-  WriteIndexedObject(kArrayCid);
-  WriteTags(0);
-  // Write out the length information.
-  WriteSmi(array_length);
-  // Write out the type arguments.
-  WriteNullObject();
-  // Write out array elements.
-  for (int i = 0; i < array_length; i++) {
-    bool success = WriteCObjectRef(object->value.as_array.values[i]);
-    if (!success) return false;
-  }
-  return true;
-}
-
-bool ApiMessageWriter::WriteCObjectInlined(Dart_CObject* object,
-                                           Dart_CObject_Type type) {
-  switch (type) {
-    case Dart_CObject_kNull:
-      WriteNullObject();
-      break;
-    case Dart_CObject_kBool:
-      if (object->value.as_bool) {
-        WriteVMIsolateObject(kTrueValue);
-      } else {
-        WriteVMIsolateObject(kFalseValue);
-      }
-      break;
-    case Dart_CObject_kInt32:
-      WriteInt32(object);
-      break;
-    case Dart_CObject_kInt64:
-      WriteInt64(object);
-      break;
-    case Dart_CObject_kDouble:
-      WriteVMIsolateObject(kDoubleObject);
-      WriteDouble(object->value.as_double);
-      break;
-    case Dart_CObject_kString: {
-      const uint8_t* utf8_str =
-          reinterpret_cast<const uint8_t*>(object->value.as_string);
-      intptr_t utf8_len = strlen(object->value.as_string);
-      if (!Utf8::IsValid(utf8_str, utf8_len)) {
-        return false;
-      }
-
-      Utf8::Type type = Utf8::kLatin1;
-      intptr_t len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
-      if (len > String::kMaxElements) {
-        return false;
-      }
-
-      // Write out the serialization header value for this object.
-      WriteInlinedHeader(object);
-      // Write out the class and tags information.
-      WriteIndexedObject(type == Utf8::kLatin1 ? kOneByteStringCid
-                                               : kTwoByteStringCid);
-      WriteTags(0);
-      // Write string length and content.
-      WriteSmi(len);
-      if (type == Utf8::kLatin1) {
-        uint8_t* latin1_str =
-            reinterpret_cast<uint8_t*>(dart::malloc(len * sizeof(uint8_t)));
-        bool success =
-            Utf8::DecodeToLatin1(utf8_str, utf8_len, latin1_str, len);
-        ASSERT(success);
-        for (intptr_t i = 0; i < len; i++) {
-          Write<uint8_t>(latin1_str[i]);
-        }
-        ::free(latin1_str);
-      } else {
-        uint16_t* utf16_str =
-            reinterpret_cast<uint16_t*>(dart::malloc(len * sizeof(uint16_t)));
-        bool success = Utf8::DecodeToUTF16(utf8_str, utf8_len, utf16_str, len);
-        ASSERT(success);
-        for (intptr_t i = 0; i < len; i++) {
-          Write<uint16_t>(utf16_str[i]);
-        }
-        ::free(utf16_str);
-      }
-      break;
-    }
-    case Dart_CObject_kTypedData: {
-      // Write out the serialization header value for this object.
-      WriteInlinedHeader(object);
-      // Write out the class and tags information.
-      intptr_t class_id;
-      switch (object->value.as_typed_data.type) {
-        case Dart_TypedData_kInt8:
-          class_id = kTypedDataInt8ArrayCid;
-          break;
-        case Dart_TypedData_kUint8:
-          class_id = kTypedDataUint8ArrayCid;
-          break;
-        case Dart_TypedData_kUint32:
-          class_id = kTypedDataUint32ArrayCid;
-          break;
-        default:
-          class_id = kTypedDataUint8ArrayCid;
-          UNIMPLEMENTED();
-      }
-
-      intptr_t len = object->value.as_typed_data.length;
-      if (len < 0 || len > TypedData::MaxElements(class_id)) {
-        return false;
-      }
-
-      WriteIndexedObject(class_id);
-      WriteTags(0);
-      WriteSmi(len);
-      switch (class_id) {
-        case kTypedDataInt8ArrayCid:
-        case kTypedDataUint8ArrayCid: {
-          uint8_t* bytes = object->value.as_typed_data.values;
-          Align(Zone::kAlignment);
-          WriteBytes(bytes, len);
-          break;
-        }
-        case kTypedDataUint32ArrayCid: {
-          uint8_t* bytes = object->value.as_typed_data.values;
-          Align(Zone::kAlignment);
-          WriteBytes(bytes, len * sizeof(uint32_t));
-          break;
-        }
-        default:
-          UNIMPLEMENTED();
-      }
-      break;
-    }
-    case Dart_CObject_kExternalTypedData: {
-      // TODO(ager): we are writing C pointers into the message in
-      // order to post external arrays through ports. We need to make
-      // sure that messages containing pointers can never be posted
-      // to other processes.
-
-      // Write out serialization header value for this object.
-      WriteInlinedHeader(object);
-      // Write out the class and tag information.
-      WriteIndexedObject(kExternalTypedDataUint8ArrayCid);
-      WriteTags(0);
-      intptr_t length = object->value.as_external_typed_data.length;
-      if (length < 0 || length > ExternalTypedData::MaxElements(
-                                     kExternalTypedDataUint8ArrayCid)) {
-        return false;
-      }
-      uint8_t* data = object->value.as_external_typed_data.data;
-      void* peer = object->value.as_external_typed_data.peer;
-      Dart_HandleFinalizer callback =
-          object->value.as_external_typed_data.callback;
-      if (callback == NULL) {
-        return false;
-      }
-      WriteSmi(length);
-      finalizable_data_->Put(length, reinterpret_cast<void*>(data), peer,
-                             callback);
-      break;
-    }
-    case Dart_CObject_kSendPort: {
-      WriteInlinedHeader(object);
-      WriteIndexedObject(kSendPortCid);
-      WriteTags(0);
-      Write<int64_t>(object->value.as_send_port.id);
-      Write<uint64_t>(object->value.as_send_port.origin_id);
-      break;
-    }
-    case Dart_CObject_kCapability: {
-      WriteInlinedHeader(object);
-      WriteIndexedObject(kCapabilityCid);
-      WriteTags(0);
-      Write<uint64_t>(object->value.as_capability.id);
-      break;
-    }
-    default:
-      FATAL1("Unexpected Dart_CObject_Type %d\n", type);
-  }
-
-  return true;
-}
-
-std::unique_ptr<Message> ApiMessageWriter::WriteCMessage(
-    Dart_CObject* object,
-    Dart_Port dest_port,
-    Message::Priority priority) {
-  bool success = WriteCObject(object);
-  if (!success) {
-    UnmarkAllCObjects(object);
-    intptr_t unused;
-    free(Steal(&unused));
-    return nullptr;
-  }
-
-  // Write out all objects that were added to the forward list and have
-  // not been serialized yet. These would typically be fields of arrays.
-  // NOTE: The forward list might grow as we process the list.
-  for (intptr_t i = 0; i < forward_id_; i++) {
-    success = WriteForwardedCObject(forward_list_[i]);
-    if (!success) {
-      UnmarkAllCObjects(object);
-      intptr_t unused;
-      free(Steal(&unused));
-      return nullptr;
-    }
-  }
-
-  UnmarkAllCObjects(object);
-  MessageFinalizableData* finalizable_data = finalizable_data_;
-  finalizable_data_ = nullptr;
-  intptr_t size;
-  uint8_t* buffer = Steal(&size);
-  return Message::New(dest_port, buffer, size, finalizable_data, priority);
-}
-
-}  // namespace dart
diff --git a/runtime/vm/dart_api_message.h b/runtime/vm/dart_api_message.h
index ace7dd3..f5994ce 100644
--- a/runtime/vm/dart_api_message.h
+++ b/runtime/vm/dart_api_message.h
@@ -15,185 +15,6 @@
 
 namespace dart {
 
-// Use this C structure for reading internal objects in the serialized
-// data. These are objects that we need to process in order to
-// generate the Dart_CObject graph but that we don't want to expose in
-// that graph.
-struct Dart_CObject_Internal : public Dart_CObject {
-  enum Type {
-    kTypeArguments = Dart_CObject_kNumberOfTypes,
-    kDynamicType,
-    kClass,
-    kView,
-    kUninitialized,
-  };
-  struct Dart_CObject_Internal* cls;
-  union {
-    struct {
-      struct _Dart_CObject* library_url;
-      struct _Dart_CObject* class_name;
-    } as_class;
-    struct {
-      struct _Dart_CObject* buffer;
-      int offset_in_bytes;
-      int length;
-    } as_view;
-  } internal;
-};
-
-// Reads a message snapshot into a C structure.
-class ApiMessageReader : public BaseReader {
- public:
-  // The ApiMessageReader object must be enclosed by an ApiNativeScope.
-  // Allocation of all C Heap objects is done in the zone associated with
-  // the enclosing ApiNativeScope.
-  explicit ApiMessageReader(Message* message);
-  ~ApiMessageReader();
-
-  Dart_CObject* ReadMessage();
-
- private:
-  class BackRefNode {
-   public:
-    BackRefNode(Dart_CObject* reference, DeserializeState state)
-        : reference_(reference), state_(state) {}
-    Dart_CObject* reference() const { return reference_; }
-    void set_reference(Dart_CObject* reference) { reference_ = reference; }
-    bool is_deserialized() const { return state_ == kIsDeserialized; }
-    void set_state(DeserializeState value) { state_ = value; }
-
-   private:
-    Dart_CObject* reference_;
-    DeserializeState state_;
-
-    DISALLOW_COPY_AND_ASSIGN(BackRefNode);
-  };
-
-  // Allocates a Dart_CObject object.
-  Dart_CObject* AllocateDartCObject();
-  // Allocates a Dart_CObject object with the specified type.
-  Dart_CObject* AllocateDartCObject(Dart_CObject_Type type);
-  // Allocates a Dart_CObject object representing an unsupported
-  // object in the API message.
-  Dart_CObject* AllocateDartCObjectUnsupported();
-  // Allocates a Dart_CObject object for the null object.
-  Dart_CObject* AllocateDartCObjectNull();
-  // Allocates a Dart_CObject object for a boolean object.
-  Dart_CObject* AllocateDartCObjectBool(bool value);
-  // Allocates a Dart_CObject object for for a 32-bit integer.
-  Dart_CObject* AllocateDartCObjectInt32(int32_t value);
-  // Allocates a Dart_CObject object for for a 64-bit integer.
-  Dart_CObject* AllocateDartCObjectInt64(int64_t value);
-  // Allocates a Dart_CObject object for a double.
-  Dart_CObject* AllocateDartCObjectDouble(double value);
-  // Allocates a Dart_CObject object for string data.
-  Dart_CObject* AllocateDartCObjectString(intptr_t length);
-  // Allocates a C Dart_CObject object for a typed data.
-  Dart_CObject* AllocateDartCObjectTypedData(Dart_TypedData_Type type,
-                                             intptr_t length);
-  // Allocates a C array of Dart_CObject objects.
-  Dart_CObject* AllocateDartCObjectArray(intptr_t length);
-  // Allocate a C Dart_CObject object for a VM isolate object.
-  Dart_CObject* AllocateDartCObjectVmIsolateObj(intptr_t id);
-  // Allocates a Dart_CObject_Internal object with the specified type.
-  Dart_CObject_Internal* AllocateDartCObjectInternal(
-      Dart_CObject_Internal::Type type);
-  // Allocates a Dart_CObject_Internal object for a class object.
-  Dart_CObject_Internal* AllocateDartCObjectClass();
-  // Allocates a backwards reference node.
-  BackRefNode* AllocateBackRefNode(Dart_CObject* ref, DeserializeState state);
-
-  void Init();
-
-  intptr_t LookupInternalClass(intptr_t class_header);
-  Dart_CObject* ReadVMIsolateObject(intptr_t value);
-  Dart_CObject* ReadInternalVMObject(intptr_t class_id, intptr_t object_id);
-  Dart_CObject* ReadInlinedObject(intptr_t object_id);
-  Dart_CObject* ReadObjectImpl();
-  Dart_CObject* ReadIndexedObject(intptr_t object_id);
-  Dart_CObject* ReadPredefinedSymbol(intptr_t object_id);
-  Dart_CObject* ReadObjectRef();
-  Dart_CObject* ReadObject();
-
-  // Add object to backward references.
-  void AddBackRef(intptr_t id, Dart_CObject* obj, DeserializeState state);
-
-  // Get an object from the backward references list.
-  Dart_CObject* GetBackRef(intptr_t id);
-
-  intptr_t NextAvailableObjectId() const;
-
-  Dart_CObject_Internal* AsInternal(Dart_CObject* object) {
-    ASSERT(object->type >= Dart_CObject_kNumberOfTypes);
-    return reinterpret_cast<Dart_CObject_Internal*>(object);
-  }
-
-  ObjectPtr VmIsolateSnapshotObject(intptr_t index) const {
-    return Object::vm_isolate_snapshot_object_table().At(index);
-  }
-
-  Dart_CObject* CreateDartCObjectString(ObjectPtr raw);
-  Dart_CObject* GetCanonicalMintObject(Dart_CObject_Type type, int64_t value64);
-
-  uint8_t* allocator(intptr_t size) {
-    return zone_->Realloc<uint8_t>(NULL, 0, size);
-  }
-
-  Zone* zone_;  // Zone in which C heap objects are allocated.
-  ApiGrowableArray<BackRefNode*> backward_references_;
-  ApiGrowableArray<Dart_CObject*> vm_isolate_references_;
-  Dart_CObject** vm_symbol_references_;
-
-  Dart_CObject type_arguments_marker;
-  Dart_CObject dynamic_type_marker;
-
-  MessageFinalizableData* finalizable_data_;
-};
-
-class ApiMessageWriter : public BaseWriter {
- public:
-  static const intptr_t kInitialSize = 512;
-  ApiMessageWriter();
-  ~ApiMessageWriter();
-
-  // Writes a message with a single object.
-  std::unique_ptr<Message> WriteCMessage(Dart_CObject* object,
-                                         Dart_Port dest_port,
-                                         Message::Priority priority);
-
- private:
-  static const intptr_t kDartCObjectTypeBits = 4;
-  static const intptr_t kDartCObjectTypeMask = (1 << kDartCObjectTypeBits) - 1;
-  static const intptr_t kDartCObjectMarkMask = ~kDartCObjectTypeMask;
-  static const intptr_t kDartCObjectMarkOffset = 1;
-
-  void MarkCObject(Dart_CObject* object, intptr_t object_id);
-  void UnmarkCObject(Dart_CObject* object);
-  bool IsCObjectMarked(Dart_CObject* object);
-  intptr_t GetMarkedCObjectMark(Dart_CObject* object);
-  void UnmarkAllCObjects(Dart_CObject* object);
-  void AddToForwardList(Dart_CObject* object);
-
-  void WriteSmi(int64_t value);
-  void WriteNullObject();
-  void WriteMint(Dart_CObject* object, int64_t value);
-  void WriteInt32(Dart_CObject* object);
-  void WriteInt64(Dart_CObject* object);
-  void WriteInlinedHeader(Dart_CObject* object);
-  bool WriteCObject(Dart_CObject* object);
-  bool WriteCObjectRef(Dart_CObject* object);
-  bool WriteForwardedCObject(Dart_CObject* object);
-  bool WriteCObjectInlined(Dart_CObject* object, Dart_CObject_Type type);
-
-  intptr_t object_id_;
-  Dart_CObject** forward_list_;
-  intptr_t forward_list_length_;
-  intptr_t forward_id_;
-  MessageFinalizableData* finalizable_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(ApiMessageWriter);
-};
-
 // This class handles translation of certain RawObjects to CObjects for
 // NativeMessageHandlers.
 //
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 461d575..f062909 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -222,7 +222,7 @@
       if (matches && type_args_len > 0 && function.IsClosureFunction()) {
         // Though the closure function is generic, the closure itself may
         // not be because it closes over delayed function type arguments.
-        matches = Closure::Cast(instance).IsGeneric(thread);
+        matches = Closure::Cast(instance).IsGeneric();
       }
 
       if (matches) {
@@ -633,17 +633,10 @@
 ObjectPtr DartLibraryCalls::ToString(const Instance& receiver) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Function& function = Function::Handle(
+  const auto& function = Function::Handle(
       zone,
       thread->isolate_group()->object_store()->_object_to_string_function());
-  if (function.IsNull()) {
-    const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
-    ASSERT(!core_lib.IsNull());
-    function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectToString());
-    ASSERT(!function.IsNull());
-    thread->isolate_group()->object_store()->set__object_to_string_function(
-        function);
-  }
+  ASSERT(!function.IsNull());
   const int kNumArguments = 1;
   const Array& args = Array::Handle(zone, Array::New(kNumArguments));
   args.SetAt(0, receiver);
@@ -656,17 +649,10 @@
 ObjectPtr DartLibraryCalls::HashCode(const Instance& receiver) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Function& function = Function::Handle(
+  const auto& function = Function::Handle(
       zone,
       thread->isolate_group()->object_store()->_object_hash_code_function());
-  if (function.IsNull()) {
-    const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
-    ASSERT(!core_lib.IsNull());
-    function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectHashCode());
-    ASSERT(!function.IsNull());
-    thread->isolate_group()->object_store()->set__object_hash_code_function(
-        function);
-  }
+  ASSERT(!function.IsNull());
   const int kNumArguments = 1;
   const Array& args = Array::Handle(zone, Array::New(kNumArguments));
   args.SetAt(0, receiver);
@@ -680,16 +666,9 @@
                                    const Instance& right) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Function& function = Function::Handle(
+  const auto& function = Function::Handle(
       zone, thread->isolate_group()->object_store()->_object_equals_function());
-  if (function.IsNull()) {
-    const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
-    ASSERT(!core_lib.IsNull());
-    function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectEquals());
-    ASSERT(!function.IsNull());
-    thread->isolate_group()->object_store()->set__object_equals_function(
-        function);
-  }
+  ASSERT(!function.IsNull());
   const int kNumArguments = 2;
   const Array& args = Array::Handle(zone, Array::New(kNumArguments));
   args.SetAt(0, left);
@@ -721,23 +700,10 @@
 ObjectPtr DartLibraryCalls::LookupHandler(Dart_Port port_id) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Function& function = Function::Handle(
+  const auto& function = Function::Handle(
       zone, thread->isolate_group()->object_store()->lookup_port_handler());
-  const int kTypeArgsLen = 0;
   const int kNumArguments = 1;
-  if (function.IsNull()) {
-    Library& isolate_lib = Library::Handle(zone, Library::IsolateLibrary());
-    ASSERT(!isolate_lib.IsNull());
-    const String& class_name = String::Handle(
-        zone, isolate_lib.PrivateName(Symbols::_RawReceivePortImpl()));
-    const String& function_name = String::Handle(
-        zone, isolate_lib.PrivateName(Symbols::_lookupHandler()));
-    function = Resolver::ResolveStatic(isolate_lib, class_name, function_name,
-                                       kTypeArgsLen, kNumArguments,
-                                       Object::empty_array());
-    ASSERT(!function.IsNull());
-    thread->isolate_group()->object_store()->set_lookup_port_handler(function);
-  }
+  ASSERT(!function.IsNull());
   Array& args = Array::Handle(
       zone, thread->isolate()->isolate_object_store()->dart_args_1());
   if (args.IsNull()) {
@@ -755,21 +721,7 @@
   Zone* zone = thread->zone();
   Function& function = Function::Handle(
       zone, thread->isolate_group()->object_store()->lookup_open_ports());
-  const int kTypeArgsLen = 0;
-  const int kNumArguments = 0;
-  if (function.IsNull()) {
-    Library& isolate_lib = Library::Handle(zone, Library::IsolateLibrary());
-    ASSERT(!isolate_lib.IsNull());
-    const String& class_name = String::Handle(
-        zone, isolate_lib.PrivateName(Symbols::_RawReceivePortImpl()));
-    const String& function_name = String::Handle(
-        zone, isolate_lib.PrivateName(Symbols::_lookupOpenPorts()));
-    function = Resolver::ResolveStatic(isolate_lib, class_name, function_name,
-                                       kTypeArgsLen, kNumArguments,
-                                       Object::empty_array());
-    ASSERT(!function.IsNull());
-    thread->isolate_group()->object_store()->set_lookup_open_ports(function);
-  }
+  ASSERT(!function.IsNull());
   const Object& result = Object::Handle(
       zone, DartEntry::InvokeFunction(function, Object::empty_array()));
   return result.ptr();
@@ -781,23 +733,10 @@
   auto zone = thread->zone();
   auto isolate = thread->isolate();
   auto object_store = thread->isolate_group()->object_store();
-  Function& function =
+  const auto& function =
       Function::Handle(zone, object_store->handle_message_function());
-  const int kTypeArgsLen = 0;
   const int kNumArguments = 2;
-  if (function.IsNull()) {
-    Library& isolate_lib = Library::Handle(zone, Library::IsolateLibrary());
-    ASSERT(!isolate_lib.IsNull());
-    const String& class_name = String::Handle(
-        zone, isolate_lib.PrivateName(Symbols::_RawReceivePortImpl()));
-    const String& function_name = String::Handle(
-        zone, isolate_lib.PrivateName(Symbols::_handleMessage()));
-    function = Resolver::ResolveStatic(isolate_lib, class_name, function_name,
-                                       kTypeArgsLen, kNumArguments,
-                                       Object::empty_array());
-    ASSERT(!function.IsNull());
-    object_store->set_handle_message_function(function);
-  }
+  ASSERT(!function.IsNull());
   Array& args =
       Array::Handle(zone, isolate->isolate_object_store()->dart_args_2());
   if (args.IsNull()) {
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 57025df..5740337 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -180,8 +180,6 @@
   // A cache of VM heap allocated arguments descriptors.
   static ArrayPtr cached_args_descriptors_[kCachedDescriptorCount];
 
-  friend class SnapshotReader;
-  friend class SnapshotWriter;
   friend class Serializer;
   friend class Deserializer;
   friend class Simulator;
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index 942ed59..a4f550f 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -22,15 +22,24 @@
 class ElfWriteStream : public ValueObject {
  public:
   explicit ElfWriteStream(BaseWriteStream* stream, const Elf& elf)
-      : stream_(ASSERT_NOTNULL(stream)), elf_(elf) {}
+      : stream_(ASSERT_NOTNULL(stream)),
+        elf_(elf),
+        start_(stream_->Position()) {
+    // So that we can use the underlying stream's Align, as all alignments
+    // will be less than or equal to this alignment.
+    ASSERT(Utils::IsAligned(start_, Elf::kPageSize));
+  }
 
   // Subclasses of Section may need to query the Elf object during Write(),
   // so we store it in the ElfWriteStream for easy access.
   const Elf& elf() const { return elf_; }
 
-  intptr_t Position() const { return stream_->Position(); }
+  // We return positions in terms of the ELF content that has been written,
+  // ignoring any previous content on the stream.
+  intptr_t Position() const { return stream_->Position() - start_; }
   void Align(const intptr_t alignment) {
     ASSERT(Utils::IsPowerOfTwo(alignment));
+    ASSERT(alignment <= Elf::kPageSize);
     stream_->Align(alignment);
   }
   void WriteBytes(const uint8_t* b, intptr_t size) {
@@ -48,6 +57,7 @@
  private:
   BaseWriteStream* const stream_;
   const Elf& elf_;
+  const intptr_t start_;
 };
 
 static constexpr intptr_t kLinearInitValue = -1;
@@ -66,10 +76,24 @@
 
 #define DEFINE_LINEAR_FIELD(name) intptr_t name##_ = kLinearInitValue;
 
+// We only allow for dynamic casting to a subset of section types, since
+// these are the only ones we need to distinguish at runtime.
+#define FOR_EACH_SECTION_TYPE(V)                                               \
+  V(ReservedSection)                                                           \
+  V(SymbolTable)                                                               \
+  V(DynamicTable)                                                              \
+  V(BitsContainer)                                                             \
+  V(TextSection) V(DataSection) V(BssSection) V(PseudoSection) V(SectionTable)
+#define DEFINE_TYPE_CHECK_FOR(Type)                                            \
+  bool Is##Type() const { return true; }
+
+#define DECLARE_SECTION_TYPE_CLASS(Type) class Type;
+FOR_EACH_SECTION_TYPE(DECLARE_SECTION_TYPE_CLASS)
+#undef DECLARE_SECTION_TYPE_CLASS
+
 class BitsContainer;
 class Segment;
 
-static constexpr intptr_t kDefaultAlignment = -1;
 // Align note sections and segments to 4 byte boundries.
 static constexpr intptr_t kNoteAlignment = 4;
 
@@ -79,14 +103,16 @@
           bool allocate,
           bool executable,
           bool writable,
-          intptr_t align = kDefaultAlignment)
+          intptr_t align = compiler::target::kWordSize)
       : type(t),
         flags(EncodeFlags(allocate, executable, writable)),
-        alignment(align == kDefaultAlignment ? DefaultAlignment(t) : align),
+        alignment(align),
         // Non-segments will never have a memory offset, here represented by 0.
         memory_offset_(allocate ? kLinearInitValue : 0) {
-    // Only sections with type SHT_NULL are allowed to have an alignment of 0.
-    ASSERT(type == elf::SectionHeaderType::SHT_NULL || alignment > 0);
+    // Only SHT_NULL sections (namely, the reserved section) are allowed to have
+    // an alignment of 0 (as the written section header entry for the reserved
+    // section must be all 0s).
+    ASSERT(alignment > 0 || type == elf::SectionHeaderType::SHT_NULL);
     // Non-zero alignments must be a power of 2.
     ASSERT(alignment == 0 || Utils::IsPowerOfTwo(alignment));
   }
@@ -94,6 +120,7 @@
   virtual ~Section() {}
 
   // Linker view.
+
   const elf::SectionHeaderType type;
   const intptr_t flags;
   const intptr_t alignment;
@@ -103,26 +130,38 @@
   intptr_t link = elf::SHN_UNDEF;
   intptr_t info = 0;
   intptr_t entry_size = 0;
-  const char* symbol_name = nullptr;
+  // This field is set for all sections, but due to reordering, we may set it
+  // more than once.
+  intptr_t index = elf::SHN_UNDEF;
 
 #define FOR_EACH_SECTION_LINEAR_FIELD(M)                                       \
   M(name)                                                                      \
-  M(index)                                                                     \
   M(file_offset)
 
   FOR_EACH_SECTION_LINEAR_FIELD(DEFINE_LINEAR_FIELD_METHODS);
 
-  virtual intptr_t FileSize() const = 0;
+  // Only needs to be overridden for sections that may not be allocated or
+  // for allocated sections where MemorySize() and FileSize() may differ.
+  virtual intptr_t FileSize() const {
+    if (!IsAllocated()) {
+      UNREACHABLE();
+    }
+    return MemorySize();
+  }
 
   // Loader view.
+
 #define FOR_EACH_SEGMENT_LINEAR_FIELD(M) M(memory_offset)
 
   FOR_EACH_SEGMENT_LINEAR_FIELD(DEFINE_LINEAR_FIELD_METHODS);
 
-  // Each section belongs to at most one PT_LOAD segment.
-  Segment* load_segment = nullptr;
-
-  virtual intptr_t MemorySize() const = 0;
+  // Only needs to be overridden for sections that may be allocated.
+  virtual intptr_t MemorySize() const {
+    if (IsAllocated()) {
+      UNREACHABLE();
+    }
+    return 0;
+  }
 
   // Other methods.
 
@@ -137,23 +176,37 @@
   // Returns whether the size of a section can change.
   bool HasBeenFinalized() const {
     // Sections can grow or shrink up until Elf::ComputeOffsets has been run,
-    // which sets the file offset (and memory offset for allocated sections).
+    // which sets the file (and memory, if applicable) offsets.
     return file_offset_is_set();
   }
 
-  virtual const BitsContainer* AsBitsContainer() const { return nullptr; }
+#define DEFINE_BASE_TYPE_CHECKS(Type)                                          \
+  Type* As##Type() {                                                           \
+    return Is##Type() ? reinterpret_cast<Type*>(this) : nullptr;               \
+  }                                                                            \
+  const Type* As##Type() const {                                               \
+    return const_cast<Type*>(const_cast<Section*>(this)->As##Type());          \
+  }                                                                            \
+  virtual bool Is##Type() const { return false; }
+
+  FOR_EACH_SECTION_TYPE(DEFINE_BASE_TYPE_CHECKS)
+#undef DEFINE_BASE_TYPE_CHECKS
+
+  // Only some sections support merging.
+  virtual bool CanMergeWith(const Section& other) const { return false; }
+  virtual void Merge(const Section& other) { UNREACHABLE(); }
 
   // Writes the file contents of the section.
-  virtual void Write(ElfWriteStream* stream) = 0;
+  virtual void Write(ElfWriteStream* stream) const { UNREACHABLE(); }
 
-  virtual void WriteSectionHeader(ElfWriteStream* stream) {
+  virtual void WriteSectionHeader(ElfWriteStream* stream) const {
 #if defined(TARGET_ARCH_IS_32_BIT)
     stream->WriteWord(name());
     stream->WriteWord(static_cast<uint32_t>(type));
     stream->WriteWord(flags);
     stream->WriteAddr(memory_offset());
     stream->WriteOff(file_offset());
-    stream->WriteWord(FileSize());  // Has different meaning for BSS.
+    stream->WriteWord(FileSize());
     stream->WriteWord(link);
     stream->WriteWord(info);
     stream->WriteWord(alignment);
@@ -164,7 +217,7 @@
     stream->WriteXWord(flags);
     stream->WriteAddr(memory_offset());
     stream->WriteOff(file_offset());
-    stream->WriteXWord(FileSize());  // Has different meaning for BSS.
+    stream->WriteXWord(FileSize());
     stream->WriteWord(link);
     stream->WriteWord(info);
     stream->WriteXWord(alignment);
@@ -174,25 +227,17 @@
 
  private:
   static intptr_t EncodeFlags(bool allocate, bool executable, bool writable) {
+    // Executable and writable only make sense if this is an allocated section.
+    ASSERT(allocate || (!executable && !writable));
     if (!allocate) return 0;
     intptr_t flags = elf::SHF_ALLOC;
+    // We currently don't allow sections that are both executable and writable.
+    ASSERT(!executable || !writable);
     if (executable) flags |= elf::SHF_EXECINSTR;
     if (writable) flags |= elf::SHF_WRITE;
     return flags;
   }
 
-  static intptr_t DefaultAlignment(elf::SectionHeaderType type) {
-    switch (type) {
-      case elf::SectionHeaderType::SHT_SYMTAB:
-      case elf::SectionHeaderType::SHT_DYNSYM:
-      case elf::SectionHeaderType::SHT_HASH:
-      case elf::SectionHeaderType::SHT_DYNAMIC:
-        return compiler::target::kWordSize;
-      default:
-        return 1;
-    }
-  }
-
   FOR_EACH_SECTION_LINEAR_FIELD(DEFINE_LINEAR_FIELD);
   FOR_EACH_SEGMENT_LINEAR_FIELD(DEFINE_LINEAR_FIELD);
 
@@ -217,49 +262,52 @@
     // so we never should pass this value.
     ASSERT(segment_type != elf::ProgramHeaderType::PT_NULL);
     // All segments should have at least one section.
+    ASSERT(initial_section != nullptr);
     ASSERT(initial_section->IsAllocated());
     sections_.Add(initial_section);
-    if (type == elf::ProgramHeaderType::PT_LOAD) {
-      ASSERT(initial_section->load_segment == nullptr);
-    }
   }
 
   virtual ~Segment() {}
 
-  static intptr_t Alignment(elf::ProgramHeaderType segment_type) {
-    switch (segment_type) {
+  const GrowableArray<Section*>& sections() const { return sections_; }
+
+  intptr_t Alignment() const {
+    switch (type) {
+      case elf::ProgramHeaderType::PT_LOAD:
+        return Elf::kPageSize;
       case elf::ProgramHeaderType::PT_PHDR:
       case elf::ProgramHeaderType::PT_DYNAMIC:
         return compiler::target::kWordSize;
       case elf::ProgramHeaderType::PT_NOTE:
         return kNoteAlignment;
       default:
-        return Elf::kPageSize;
+        UNREACHABLE();
+        return 0;
     }
   }
 
   bool IsExecutable() const { return (flags & elf::PF_X) == elf::PF_X; }
   bool IsWritable() const { return (flags & elf::PF_W) == elf::PF_W; }
 
-  void WriteProgramHeader(ElfWriteStream* stream) {
+  void WriteProgramHeader(ElfWriteStream* stream) const {
 #if defined(TARGET_ARCH_IS_32_BIT)
     stream->WriteWord(static_cast<uint32_t>(type));
     stream->WriteOff(FileOffset());
     stream->WriteAddr(MemoryOffset());  // Virtual address.
-    stream->WriteAddr(MemoryOffset());  // Physical address, not used.
+    stream->WriteAddr(MemoryOffset());  // Physical address.
     stream->WriteWord(FileSize());
     stream->WriteWord(MemorySize());
     stream->WriteWord(flags);
-    stream->WriteWord(Alignment(type));
+    stream->WriteWord(Alignment());
 #else
     stream->WriteWord(static_cast<uint32_t>(type));
     stream->WriteWord(flags);
     stream->WriteOff(FileOffset());
     stream->WriteAddr(MemoryOffset());  // Virtual address.
-    stream->WriteAddr(MemoryOffset());  // Physical address, not used.
+    stream->WriteAddr(MemoryOffset());  // Physical address.
     stream->WriteXWord(FileSize());
     stream->WriteXWord(MemorySize());
-    stream->WriteXWord(Alignment(type));
+    stream->WriteXWord(Alignment());
 #endif
   }
 
@@ -267,36 +315,16 @@
   // section was successfully added.
   bool Add(Section* section) {
     ASSERT(section != nullptr);
+    // We can't add if memory offsets have already been calculated.
+    ASSERT(!section->memory_offset_is_set());
     // We only add additional sections to load segments.
     ASSERT(type == elf::ProgramHeaderType::PT_LOAD);
-    // Don't use this to change a section's segment.
-    ASSERT(section->load_segment == nullptr);
     // We only add sections with the same executable and writable bits.
     if (IsExecutable() != section->IsExecutable() ||
         IsWritable() != section->IsWritable()) {
       return false;
     }
     sections_.Add(section);
-    section->load_segment = this;
-    return true;
-  }
-
-  bool Merge(Segment* other) {
-    ASSERT(other != nullptr);
-    // We only add additional sections to load segments.
-    ASSERT(type == elf::ProgramHeaderType::PT_LOAD);
-    // We only merge segments with the same executable and writable bits.
-    if (IsExecutable() != other->IsExecutable() ||
-        IsWritable() != other->IsWritable()) {
-      return false;
-    }
-    for (auto* section : other->sections_) {
-      // Don't merge segments where the memory offsets have already been
-      // calculated.
-      ASSERT(!section->memory_offset_is_set());
-      sections_.Add(section);
-      section->load_segment = this;
-    }
     return true;
   }
 
@@ -318,10 +346,10 @@
 
   intptr_t MemoryEnd() const { return MemoryOffset() + MemorySize(); }
 
- private:
-  static constexpr intptr_t kInitValue = -1;
-  static_assert(kInitValue < 0, "init value must be negative");
+  const elf::ProgramHeaderType type;
+  const intptr_t flags;
 
+ private:
   static intptr_t EncodeFlags(bool executable, bool writable) {
     intptr_t flags = elf::PF_R;
     if (executable) flags |= elf::PF_X;
@@ -329,11 +357,6 @@
     return flags;
   }
 
- public:
-  const elf::ProgramHeaderType type;
-  const intptr_t flags;
-
- private:
   GrowableArray<Section*> sections_;
 };
 
@@ -347,84 +370,11 @@
                 /*executable=*/false,
                 /*writable=*/false,
                 /*alignment=*/0) {
-    set_name(0);
-    set_index(0);
     set_file_offset(0);
   }
 
+  DEFINE_TYPE_CHECK_FOR(ReservedSection);
   intptr_t FileSize() const { return 0; }
-  intptr_t MemorySize() const { return 0; }
-  void Write(ElfWriteStream* stream) {}
-};
-
-// Represents portions of the file/memory space which do not correspond to
-// actual sections. Should never be added to sections_.
-class PseudoSection : public Section {
- public:
-  PseudoSection(bool executable,
-                bool writable,
-                intptr_t file_offset,
-                intptr_t file_size,
-                intptr_t memory_offset,
-                intptr_t memory_size)
-      : Section(elf::SectionHeaderType::SHT_NULL,
-                /*allocate=*/true,
-                executable,
-                writable,
-                /*alignment=*/0),
-        file_size_(file_size),
-        memory_size_(memory_size) {
-    set_file_offset(file_offset);
-    set_memory_offset(memory_offset);
-  }
-
-  intptr_t FileSize() const { return file_size_; }
-  intptr_t MemorySize() const { return memory_size_; }
-  void WriteSectionHeader(ElfWriteStream* stream) { UNREACHABLE(); }
-  void Write(ElfWriteStream* stream) { UNREACHABLE(); }
-
- private:
-  const intptr_t file_size_;
-  const intptr_t memory_size_;
-};
-
-// A segment for representing the program header table self-reference in the
-// program header table.
-class ProgramTableSelfSegment : public Segment {
- public:
-  ProgramTableSelfSegment(Zone* zone, intptr_t offset, intptr_t size)
-      : Segment(zone,
-                new (zone) PseudoSection(/*executable=*/false,
-                                         /*writable=*/false,
-                                         offset,
-                                         size,
-                                         offset,
-                                         size),
-                elf::ProgramHeaderType::PT_PHDR) {}
-};
-
-// A segment for representing the program header table load segment in the
-// program header table.
-class ProgramTableLoadSegment : public Segment {
- public:
-  // The Android dynamic linker in Jelly Bean incorrectly assumes that all
-  // non-writable segments are continguous. Since the BSS segment comes directly
-  // after the program header segment, we must make this segment writable so
-  // later non-writable segments does not cause the BSS to be also marked as
-  // read-only.
-  //
-  // The bug is here:
-  //   https://github.com/aosp-mirror/platform_bionic/blob/94963af28e445384e19775a838a29e6a71708179/linker/linker.c#L1991-L2001
-  explicit ProgramTableLoadSegment(Zone* zone, intptr_t size)
-      : Segment(zone,
-                // This segment should always start at address 0.
-                new (zone) PseudoSection(/*executable=*/false,
-                                         /*writable=*/true,
-                                         0,
-                                         size,
-                                         0,
-                                         size),
-                elf::ProgramHeaderType::PT_LOAD) {}
 };
 
 class StringTable : public Section {
@@ -437,18 +387,18 @@
         dynamic_(allocate),
         text_(zone, 128),
         text_indices_(zone) {
-    AddString("");
+    Add("");
   }
 
   intptr_t FileSize() const { return text_.length(); }
   intptr_t MemorySize() const { return dynamic_ ? FileSize() : 0; }
 
-  void Write(ElfWriteStream* stream) {
+  void Write(ElfWriteStream* stream) const {
     stream->WriteBytes(reinterpret_cast<const uint8_t*>(text_.buffer()),
                        text_.length());
   }
 
-  intptr_t AddString(const char* str) {
+  intptr_t Add(const char* str) {
     ASSERT(str != nullptr);
     if (auto const kv = text_indices_.Lookup(str)) {
       return kv->value;
@@ -460,8 +410,8 @@
     return offset;
   }
 
-  const char* At(intptr_t index) {
-    ASSERT(index < text_.length());
+  const char* At(intptr_t index) const {
+    if (index >= text_.length()) return nullptr;
     return text_.buffer() + index;
   }
 
@@ -491,51 +441,31 @@
         dynamic_(dynamic),
         symbols_(zone, 1),
         by_name_index_(zone) {
+    link = table_->index;
     entry_size = sizeof(elf::Symbol);
     // The first symbol table entry is reserved and must be all zeros.
     // (String tables always have the empty string at the 0th index.)
-    const char* const kReservedName = "";
-    AddSymbol(kReservedName, elf::STB_LOCAL, elf::STT_NOTYPE, elf::SHN_UNDEF,
-              /*size=*/0);
-    FinalizeSymbol(kReservedName, elf::SHN_UNDEF, /*offset=*/0);
+    ASSERT_EQUAL(table_->Lookup(""), 0);
+    symbols_.Add({/*name_index=*/0, elf::STB_LOCAL, elf::STT_NOTYPE, /*size=*/0,
+                  elf::SHN_UNDEF, /*offset=*/0});
+    // The info field on a symbol table section holds the index of the first
+    // non-local symbol, so since there are none yet, it points past the single
+    // symbol we do have.
+    info = 1;
   }
 
-  intptr_t FileSize() const { return Length() * entry_size; }
+  DEFINE_TYPE_CHECK_FOR(SymbolTable)
+  const StringTable& strtab() const { return *table_; }
+  intptr_t FileSize() const { return symbols_.length() * entry_size; }
   intptr_t MemorySize() const { return dynamic_ ? FileSize() : 0; }
 
-  class Symbol : public ZoneAllocated {
-   public:
-    Symbol(const char* cstr,
-           intptr_t name,
-           intptr_t binding,
-           intptr_t type,
-           intptr_t initial_section_index,
-           intptr_t size)
-        : name_index(name),
-          binding(binding),
-          type(type),
-          size(size),
-          section_index(initial_section_index),
-          cstr_(cstr) {}
-
-    void Finalize(intptr_t final_section_index, intptr_t offset) {
-      ASSERT(!HasBeenFinalized());  // No symbol should be re-finalized.
-      section_index = final_section_index;
-      offset_ = offset;
-    }
-    bool HasBeenFinalized() const { return offset_ != kNotFinalizedMarker; }
-    intptr_t offset() const {
-      ASSERT(HasBeenFinalized());
-      // Only the reserved initial symbol should have an offset of 0.
-      ASSERT_EQUAL(type == elf::STT_NOTYPE, offset_ == 0);
-      return offset_;
-    }
-
+  struct Symbol {
     void Write(ElfWriteStream* stream) const {
       const intptr_t start = stream->Position();
+      ASSERT(section_index == elf::SHN_UNDEF || offset > 0);
       stream->WriteWord(name_index);
 #if defined(TARGET_ARCH_IS_32_BIT)
-      stream->WriteAddr(offset());
+      stream->WriteAddr(offset);
       stream->WriteWord(size);
       stream->WriteByte(elf::SymbolInfo(binding, type));
       stream->WriteByte(0);
@@ -544,35 +474,34 @@
       stream->WriteByte(elf::SymbolInfo(binding, type));
       stream->WriteByte(0);
       stream->WriteHalf(section_index);
-      stream->WriteAddr(offset());
+      stream->WriteAddr(offset);
       stream->WriteXWord(size);
 #endif
       ASSERT_EQUAL(stream->Position() - start, sizeof(elf::Symbol));
     }
 
-    const intptr_t name_index;
-    const intptr_t binding;
-    const intptr_t type;
-    const intptr_t size;
-    // Is set twice: once in Elf::AddSection to the section's initial index into
-    // sections_, and then in Elf::FinalizeSymbols to the section's final index
-    // into sections_ after reordering.
+    intptr_t name_index;
+    intptr_t binding;
+    intptr_t type;
+    intptr_t size;
+    // Must be updated whenever sections are reordered.
     intptr_t section_index;
+    // Initialized to the section-relative offset, must be updated to the
+    // snapshot-relative offset before writing.
+    intptr_t offset;
 
    private:
-    static const intptr_t kNotFinalizedMarker = -1;
-
-    const char* const cstr_;
-    intptr_t offset_ = kNotFinalizedMarker;
-
-    friend class SymbolHashTable;  // For cstr_ access.
+    DISALLOW_ALLOCATION();
   };
 
-  void Write(ElfWriteStream* stream) {
-    for (intptr_t i = 0; i < Length(); i++) {
-      auto const symbol = At(i);
+  const GrowableArray<Symbol>& symbols() const { return symbols_; }
+
+  void Initialize(const GrowableArray<Section*>& sections);
+
+  void Write(ElfWriteStream* stream) const {
+    for (const auto& symbol : symbols_) {
       const intptr_t start = stream->Position();
-      symbol->Write(stream);
+      symbol.Write(stream);
       ASSERT_EQUAL(stream->Position() - start, entry_size);
     }
   }
@@ -580,131 +509,162 @@
   void AddSymbol(const char* name,
                  intptr_t binding,
                  intptr_t type,
-                 intptr_t section_index,
-                 intptr_t size) {
+                 intptr_t size,
+                 intptr_t index,
+                 intptr_t offset) {
     ASSERT(!table_->HasBeenFinalized());
-    auto const name_index = table_->AddString(name);
-    ASSERT(by_name_index_.Lookup(name_index) == nullptr);
-    auto const symbol = new (zone_)
-        Symbol(name, name_index, binding, type, section_index, size);
-    symbols_.Add(symbol);
-    by_name_index_.Insert(name_index, symbol);
+    auto const name_index = table_->Add(name);
+    ASSERT(name_index != 0);
+    const intptr_t new_index = symbols_.length();
+    symbols_.Add({name_index, binding, type, size, index, offset});
+    by_name_index_.Insert(name_index, new_index);
     // The info field on a symbol table section holds the index of the first
     // non-local symbol, so they can be skipped if desired. Thus, we need to
     // make sure local symbols are before any non-local ones.
     if (binding == elf::STB_LOCAL) {
-      if (info != symbols_.length() - 1) {
+      if (info != new_index) {
         // There are non-local symbols, as otherwise [info] would be the
         // index of the new symbol. Since the order doesn't otherwise matter,
         // swap the new local symbol with the value at index [info], so when
         // [info] is incremented it will point just past the new local symbol.
-        ASSERT(symbols_[info]->binding != elf::STB_LOCAL);
-        symbols_.Swap(info, symbols_.length() - 1);
+        ASSERT(symbols_[info].binding != elf::STB_LOCAL);
+        symbols_.Swap(info, new_index);
+        // Since by_name_index has indices into symbols_, we need to update it.
+        by_name_index_.Update({symbols_[info].name_index, info});
+        by_name_index_.Update({symbols_[new_index].name_index, new_index});
       }
       info += 1;
     }
   }
 
-  void FinalizeSymbol(const char* name,
-                      intptr_t final_section_index,
-                      intptr_t offset) {
-    const intptr_t name_index = table_->Lookup(name);
-    ASSERT(name_index != StringTable::kNotIndexed);
-    Symbol* symbol = by_name_index_.Lookup(name_index);
-    ASSERT(symbol != nullptr);
-    symbol->Finalize(final_section_index, offset);
+  void UpdateSectionIndices(const GrowableArray<intptr_t>& index_map) {
+#if defined(DEBUG)
+    const intptr_t map_size = index_map.length();
+    // The first entry must be 0 so that symbols with index SHN_UNDEF, like
+    // the initial reserved symbol, are unchanged.
+    ASSERT_EQUAL(index_map[0], 0);
+    for (intptr_t i = 1; i < map_size; i++) {
+      ASSERT(index_map[i] != 0);
+      ASSERT(index_map[i] < map_size);
+    }
+#endif
+    for (auto& symbol : symbols_) {
+      DEBUG_ASSERT(symbol.section_index < map_size);
+      symbol.section_index = index_map[symbol.section_index];
+    }
   }
 
-  intptr_t Length() const { return symbols_.length(); }
-  const Symbol* At(intptr_t i) const { return symbols_[i]; }
+  void Finalize(const GrowableArray<intptr_t>& address_map) {
+#if defined(DEBUG)
+    const intptr_t map_size = address_map.length();
+    // The first entry must be 0 so that symbols with index SHN_UNDEF, like
+    // the initial reserved symbol, are unchanged.
+    ASSERT_EQUAL(address_map[0], 0);
+    for (intptr_t i = 1; i < map_size; i++) {
+      // No section begins at the start of the snapshot.
+      ASSERT(address_map[i] != 0);
+    }
+#endif
+    for (auto& symbol : symbols_) {
+      DEBUG_ASSERT(symbol.section_index < map_size);
+      symbol.offset += address_map[symbol.section_index];
+    }
+  }
 
   const Symbol* Find(const char* name) const {
     ASSERT(name != nullptr);
-    auto const name_index = table_->Lookup(name);
-    return by_name_index_.Lookup(name_index);
+    const intptr_t name_index = table_->Lookup(name);
+    // 0 is kNoValue for by_name_index, but luckily that's the name of the
+    // initial reserved symbol.
+    if (name_index == 0) return &symbols_[0];
+    const intptr_t symbols_index = by_name_index_.Lookup(name_index);
+    if (symbols_index == 0) return nullptr;  // Not found.
+    return &symbols_[symbols_index];
   }
 
  private:
   Zone* const zone_;
   StringTable* const table_;
   const bool dynamic_;
-  GrowableArray<Symbol*> symbols_;
-  mutable IntMap<Symbol*> by_name_index_;
+  GrowableArray<Symbol> symbols_;
+  // Maps name indexes in table_ to indexes in symbols_. Does not include an
+  // entry for the reserved symbol (name ""), as 0 is kNoValue.
+  IntMap<intptr_t> by_name_index_;
 };
 
-static uint32_t ElfHash(const unsigned char* name) {
-  uint32_t h = 0;
-  while (*name != '\0') {
-    h = (h << 4) + *name++;
-    uint32_t g = h & 0xf0000000;
-    h ^= g;
-    h ^= g >> 24;
-  }
-  return h;
-}
-
 class SymbolHashTable : public Section {
  public:
-  SymbolHashTable(Zone* zone, StringTable* strtab, SymbolTable* symtab)
+  SymbolHashTable(Zone* zone, SymbolTable* symtab)
       : Section(elf::SectionHeaderType::SHT_HASH,
                 /*allocate=*/true,
                 /*executable=*/false,
-                /*writable=*/false) {
+                /*writable=*/false),
+        buckets_(zone, 0),
+        chains_(zone, 0) {
+    link = symtab->index;
     entry_size = sizeof(int32_t);
 
-    nchain_ = symtab->Length();
-    nbucket_ = symtab->Length();
+    const auto& symbols = symtab->symbols();
+    const intptr_t num_symbols = symbols.length();
+    buckets_.FillWith(elf::STN_UNDEF, 0, num_symbols);
+    chains_.FillWith(elf::STN_UNDEF, 0, num_symbols);
 
-    bucket_ = zone->Alloc<int32_t>(nbucket_);
-    for (intptr_t i = 0; i < nbucket_; i++) {
-      bucket_[i] = elf::STN_UNDEF;
-    }
-
-    chain_ = zone->Alloc<int32_t>(nchain_);
-    for (intptr_t i = 0; i < nchain_; i++) {
-      chain_[i] = elf::STN_UNDEF;
-    }
-
-    for (intptr_t i = 1; i < symtab->Length(); i++) {
-      auto const symbol = symtab->At(i);
-      uint32_t hash = ElfHash((const unsigned char*)symbol->cstr_);
-      uint32_t probe = hash % nbucket_;
-      chain_[i] = bucket_[probe];  // next = head
-      bucket_[probe] = i;          // head = symbol
+    for (intptr_t i = 1; i < num_symbols; i++) {
+      const auto& symbol = symbols[i];
+      uint32_t hash = HashSymbolName(symtab->strtab().At(symbol.name_index));
+      uint32_t probe = hash % num_symbols;
+      chains_[i] = buckets_[probe];  // next = head
+      buckets_[probe] = i;           // head = symbol
     }
   }
 
-  intptr_t FileSize() const { return entry_size * (nbucket_ + nchain_ + 2); }
-  intptr_t MemorySize() const { return FileSize(); }
+  intptr_t MemorySize() const {
+    return entry_size * (buckets_.length() + chains_.length() + 2);
+  }
 
-  void Write(ElfWriteStream* stream) {
-    stream->WriteWord(nbucket_);
-    stream->WriteWord(nchain_);
-    for (intptr_t i = 0; i < nbucket_; i++) {
-      stream->WriteWord(bucket_[i]);
+  void Write(ElfWriteStream* stream) const {
+    stream->WriteWord(buckets_.length());
+    stream->WriteWord(chains_.length());
+    for (const int32_t bucket : buckets_) {
+      stream->WriteWord(bucket);
     }
-    for (intptr_t i = 0; i < nchain_; i++) {
-      stream->WriteWord(chain_[i]);
+    for (const int32_t chain : chains_) {
+      stream->WriteWord(chain);
     }
   }
 
+  static uint32_t HashSymbolName(const void* p) {
+    auto* name = reinterpret_cast<const uint8_t*>(p);
+    uint32_t h = 0;
+    while (*name != '\0') {
+      h = (h << 4) + *name++;
+      uint32_t g = h & 0xf0000000;
+      h ^= g;
+      h ^= g >> 24;
+    }
+    return h;
+  }
+
  private:
-  int32_t nbucket_;
-  int32_t nchain_;
-  int32_t* bucket_;  // "Head"
-  int32_t* chain_;   // "Next"
+  GrowableArray<int32_t> buckets_;  // "Head"
+  GrowableArray<int32_t> chains_;   // "Next"
 };
 
 class DynamicTable : public Section {
  public:
-  explicit DynamicTable(Zone* zone)
+  // .dynamic section is expected to be writable on most Linux systems
+  // unless dynamic linker is explicitly built with support for an read-only
+  // .dynamic section (DL_RO_DYN_SECTION).
+  DynamicTable(Zone* zone, SymbolTable* symtab, SymbolHashTable* hash)
       : Section(elf::SectionHeaderType::SHT_DYNAMIC,
                 /*allocate=*/true,
                 /*executable=*/false,
-                /*writable=*/true) {
+                /*writable=*/true),
+        symtab_(symtab),
+        hash_(hash) {
+    link = strtab().index;
     entry_size = sizeof(elf::DynamicEntry);
 
-    // Entries that are not constants are fixed during Elf::Finalize().
     AddEntry(zone, elf::DynamicEntryType::DT_HASH, kInvalidEntry);
     AddEntry(zone, elf::DynamicEntryType::DT_STRTAB, kInvalidEntry);
     AddEntry(zone, elf::DynamicEntryType::DT_STRSZ, kInvalidEntry);
@@ -715,19 +675,30 @@
 
   static constexpr intptr_t kInvalidEntry = -1;
 
-  intptr_t FileSize() const { return entries_.length() * entry_size; }
-  intptr_t MemorySize() const { return FileSize(); }
+  DEFINE_TYPE_CHECK_FOR(DynamicTable)
+  const SymbolHashTable& hash() const { return *hash_; }
+  const SymbolTable& symtab() const { return *symtab_; }
+  const StringTable& strtab() const { return symtab().strtab(); }
+  intptr_t MemorySize() const { return entries_.length() * entry_size; }
 
-  void Write(ElfWriteStream* stream) {
+  void Write(ElfWriteStream* stream) const {
     for (intptr_t i = 0; i < entries_.length(); i++) {
       entries_[i]->Write(stream);
     }
   }
 
+  void Finalize() {
+    FinalizeEntry(elf::DynamicEntryType::DT_HASH, hash().memory_offset());
+    FinalizeEntry(elf::DynamicEntryType::DT_STRTAB, strtab().memory_offset());
+    FinalizeEntry(elf::DynamicEntryType::DT_STRSZ, strtab().MemorySize());
+    FinalizeEntry(elf::DynamicEntryType::DT_SYMTAB, symtab().memory_offset());
+  }
+
+ private:
   struct Entry : public ZoneAllocated {
     Entry(elf::DynamicEntryType tag, intptr_t value) : tag(tag), value(value) {}
 
-    void Write(ElfWriteStream* stream) {
+    void Write(ElfWriteStream* stream) const {
       ASSERT(value != kInvalidEntry);
       const intptr_t start = stream->Position();
 #if defined(TARGET_ARCH_IS_32_BIT)
@@ -758,74 +729,28 @@
     }
   }
 
-  void FinalizeEntries(StringTable* strtab,
-                       SymbolTable* symtab,
-                       SymbolHashTable* hash) {
-    FinalizeEntry(elf::DynamicEntryType::DT_HASH, hash->memory_offset());
-    FinalizeEntry(elf::DynamicEntryType::DT_STRTAB, strtab->memory_offset());
-    FinalizeEntry(elf::DynamicEntryType::DT_STRSZ, strtab->MemorySize());
-    FinalizeEntry(elf::DynamicEntryType::DT_SYMTAB, symtab->memory_offset());
-  }
-
- private:
+  SymbolTable* const symtab_;
+  SymbolHashTable* const hash_;
   GrowableArray<Entry*> entries_;
 };
 
-// A segment for representing the dynamic table segment in the program header
-// table. There is no corresponding section for this segment.
-class DynamicSegment : public Segment {
- public:
-  explicit DynamicSegment(Zone* zone, DynamicTable* dynamic)
-      : Segment(zone, dynamic, elf::ProgramHeaderType::PT_DYNAMIC) {}
-};
-
-// A segment for representing the dynamic table segment in the program header
-// table. There is no corresponding section for this segment.
-class NoteSegment : public Segment {
- public:
-  NoteSegment(Zone* zone, Section* note)
-      : Segment(zone, note, elf::ProgramHeaderType::PT_NOTE) {
-    ASSERT_EQUAL(static_cast<uint32_t>(note->type),
-                 static_cast<uint32_t>(elf::SectionHeaderType::SHT_NOTE));
-  }
-};
-
 class BitsContainer : public Section {
  public:
-  // Fully specified BitsContainer information.
+  // Fully specified BitsContainer information. Unless otherwise specified,
+  // BitContainers are aligned on byte boundaries (i.e., no padding is used).
   BitsContainer(elf::SectionHeaderType type,
                 bool allocate,
                 bool executable,
                 bool writable,
-                intptr_t size,
-                const uint8_t* bytes,
-                const ZoneGrowableArray<Elf::Relocation>* relocations,
-                const ZoneGrowableArray<Elf::SymbolData>* symbols,
-                int alignment = kDefaultAlignment)
-      : Section(type, allocate, executable, writable, alignment),
-        file_size_(type == elf::SectionHeaderType::SHT_NOBITS ? 0 : size),
-        memory_size_(allocate ? size : 0),
-        bytes_(bytes),
-        relocations_(relocations),
-        symbols_(symbols) {
-    ASSERT(type == elf::SectionHeaderType::SHT_NOBITS || bytes != nullptr);
-  }
+                int alignment = 1)
+      : Section(type, allocate, executable, writable, alignment) {}
 
-  // For BitsContainers used only as sections.
-  BitsContainer(elf::SectionHeaderType type,
-                intptr_t size,
-                const uint8_t* bytes,
-                const ZoneGrowableArray<Elf::Relocation>* relocations,
-                const ZoneGrowableArray<Elf::SymbolData>* symbols,
-                intptr_t alignment = kDefaultAlignment)
+  // For BitsContainers used only as unallocated sections.
+  explicit BitsContainer(elf::SectionHeaderType type, intptr_t alignment = 1)
       : BitsContainer(type,
                       /*allocate=*/false,
                       /*executable=*/false,
                       /*writable=*/false,
-                      size,
-                      bytes,
-                      relocations,
-                      symbols,
                       alignment) {}
 
   // For BitsContainers used as segments whose type differ on the type of the
@@ -834,61 +759,54 @@
   BitsContainer(Elf::Type t,
                 bool executable,
                 bool writable,
-                intptr_t size,
-                const uint8_t* bytes,
-                const ZoneGrowableArray<Elf::Relocation>* relocations,
-                const ZoneGrowableArray<Elf::SymbolData>* symbols,
-                intptr_t alignment = kDefaultAlignment)
+                intptr_t alignment = 1)
       : BitsContainer(t == Elf::Type::Snapshot
                           ? elf::SectionHeaderType::SHT_PROGBITS
                           : elf::SectionHeaderType::SHT_NOBITS,
                       /*allocate=*/true,
                       executable,
                       writable,
-                      size,
-                      bytes,
-                      relocations,
-                      symbols,
                       alignment) {}
 
-  const BitsContainer* AsBitsContainer() const { return this; }
-  const ZoneGrowableArray<Elf::SymbolData>* symbols() const { return symbols_; }
+  DEFINE_TYPE_CHECK_FOR(BitsContainer)
 
-  void Write(ElfWriteStream* stream) {
-    if (type == elf::SectionHeaderType::SHT_NOBITS) return;
-    if (relocations_ == nullptr) {
-      return stream->WriteBytes(bytes(), FileSize());
-    }
-    const SymbolTable* symtab = ASSERT_NOTNULL(stream->elf().symtab());
-    // Resolve relocations as we write.
-    intptr_t current_pos = 0;
-    for (const auto& reloc : *relocations_) {
-      // We assume here that the relocations are sorted in increasing order,
-      // with unique section offsets.
-      ASSERT(current_pos <= reloc.section_offset);
-      if (current_pos < reloc.section_offset) {
-        stream->WriteBytes(bytes_ + current_pos,
-                           reloc.section_offset - current_pos);
+  bool IsNoBits() const { return type == elf::SectionHeaderType::SHT_NOBITS; }
+  bool HasBytes() const {
+    return portions_.length() != 0 && portions_[0].bytes != nullptr;
+  }
+
+  struct Portion {
+    void Write(ElfWriteStream* stream, intptr_t section_start) const {
+      ASSERT(bytes != nullptr);
+      if (relocations == nullptr) {
+        stream->WriteBytes(bytes, size);
+        return;
       }
-      intptr_t source_address = reloc.source_offset;
-      intptr_t target_address = reloc.target_offset;
-      // Null symbols denote that the corresponding offset should be treated
-      // as an absolute offset in the ELF memory space.
-      if (reloc.source_symbol != nullptr) {
-        if (strcmp(reloc.source_symbol, ".") == 0) {
-          source_address += memory_offset() + reloc.section_offset;
-        } else {
-          auto* const source_symbol = symtab->Find(reloc.source_symbol);
-          ASSERT(source_symbol != nullptr);
-          source_address += source_symbol->offset();
+      const SymbolTable& symtab = stream->elf().symtab();
+      // Resolve relocations as we write.
+      intptr_t current_pos = 0;
+      for (const auto& reloc : *relocations) {
+        // We assume here that the relocations are sorted in increasing order,
+        // with unique section offsets.
+        ASSERT(current_pos <= reloc.section_offset);
+        if (current_pos < reloc.section_offset) {
+          stream->WriteBytes(bytes + current_pos,
+                             reloc.section_offset - current_pos);
         }
-      }
-      if (reloc.target_symbol != nullptr) {
-        if (strcmp(reloc.target_symbol, ".") == 0) {
-          target_address += memory_offset() + reloc.section_offset;
+        intptr_t source_address = reloc.source_offset;
+        if (reloc.source_symbol != nullptr) {
+          auto* const source_symbol = symtab.Find(reloc.source_symbol);
+          ASSERT(source_symbol != nullptr);
+          source_address += source_symbol->offset;
         } else {
-          auto* const target_symbol = symtab->Find(reloc.target_symbol);
-          if (target_symbol == nullptr) {
+          source_address += section_start + offset + reloc.section_offset;
+        }
+        ASSERT(reloc.size_in_bytes <= kWordSize);
+        word to_write = reloc.target_offset - source_address;
+        if (reloc.target_symbol != nullptr) {
+          if (auto* const symbol = symtab.Find(reloc.target_symbol)) {
+            to_write += symbol->offset;
+          } else {
             ASSERT_EQUAL(strcmp(reloc.target_symbol, kSnapshotBuildIdAsmSymbol),
                          0);
             ASSERT_EQUAL(reloc.target_offset, 0);
@@ -897,142 +815,378 @@
             // TODO(dartbug.com/43516): Special case for snapshots with deferred
             // sections that handles the build ID relocation in an
             // InstructionsSection when there is no build ID.
-            const word to_write = Image::kNoRelocatedAddress;
-            stream->WriteBytes(reinterpret_cast<const uint8_t*>(&to_write),
-                               reloc.size_in_bytes);
-            current_pos = reloc.section_offset + reloc.size_in_bytes;
-            continue;
+            to_write = Image::kNoRelocatedAddress;
           }
-          target_address += target_symbol->offset();
+        } else {
+          to_write += section_start + offset + reloc.section_offset;
         }
+        ASSERT(Utils::IsInt(reloc.size_in_bytes * kBitsPerByte, to_write));
+        stream->WriteBytes(reinterpret_cast<const uint8_t*>(&to_write),
+                           reloc.size_in_bytes);
+        current_pos = reloc.section_offset + reloc.size_in_bytes;
       }
-      ASSERT(reloc.size_in_bytes <= kWordSize);
-      const word to_write = target_address - source_address;
-      ASSERT(Utils::IsInt(reloc.size_in_bytes * kBitsPerByte, to_write));
-      stream->WriteBytes(reinterpret_cast<const uint8_t*>(&to_write),
-                         reloc.size_in_bytes);
-      current_pos = reloc.section_offset + reloc.size_in_bytes;
+      stream->WriteBytes(bytes + current_pos, size - current_pos);
     }
-    stream->WriteBytes(bytes_ + current_pos, FileSize() - current_pos);
+
+    intptr_t offset;
+    const char* symbol_name;
+    const uint8_t* bytes;
+    intptr_t size;
+    const ZoneGrowableArray<Elf::Relocation>* relocations;
+    const ZoneGrowableArray<Elf::SymbolData>* symbols;
+
+   private:
+    DISALLOW_ALLOCATION();
+  };
+
+  const GrowableArray<Portion>& portions() const { return portions_; }
+
+  const Portion& AddPortion(
+      const uint8_t* bytes,
+      intptr_t size,
+      const ZoneGrowableArray<Elf::Relocation>* relocations = nullptr,
+      const ZoneGrowableArray<Elf::SymbolData>* symbols = nullptr,
+      const char* symbol_name = nullptr) {
+    ASSERT(IsNoBits() || bytes != nullptr);
+    ASSERT(bytes != nullptr || relocations == nullptr);
+    // Make sure all portions are consistent in containing bytes.
+    ASSERT(portions_.is_empty() || HasBytes() == (bytes != nullptr));
+    const intptr_t offset = Utils::RoundUp(total_size_, alignment);
+    portions_.Add({offset, symbol_name, bytes, size, relocations, symbols});
+    const Portion& portion = portions_.Last();
+    total_size_ = offset + size;
+    return portion;
   }
 
-  uint32_t Hash() const {
-    ASSERT(bytes() != nullptr);
-    return Utils::StringHash(bytes(), MemorySize());
+  void Write(ElfWriteStream* stream) const {
+    if (type == elf::SectionHeaderType::SHT_NOBITS) return;
+    intptr_t start_position = stream->Position();  // Used for checks.
+    for (const auto& portion : portions_) {
+      stream->Align(alignment);
+      ASSERT_EQUAL(stream->Position(), start_position + portion.offset);
+      portion.Write(stream, memory_offset());
+    }
+    ASSERT_EQUAL(stream->Position(), start_position + total_size_);
   }
 
-  intptr_t FileSize() const { return file_size_; }
-  intptr_t MemorySize() const { return memory_size_; }
-  const uint8_t* bytes() const { return bytes_; }
+  // Returns the hash for the portion corresponding to symbol_name.
+  // Returns 0 if the portion has no bytes or no portions have that name.
+  uint32_t Hash(const char* symbol_name) const {
+    for (const auto& portion : portions_) {
+      if (strcmp(symbol_name, portion.symbol_name) == 0) {
+        if (portion.bytes == nullptr) return 0;
+        const uint32_t hash = Utils::StringHash(portion.bytes, portion.size);
+        // Ensure a non-zero return.
+        return hash == 0 ? 1 : hash;
+      }
+    }
+    return 0;
+  }
+
+  intptr_t FileSize() const { return IsNoBits() ? 0 : total_size_; }
+  intptr_t MemorySize() const { return IsAllocated() ? total_size_ : 0; }
 
  private:
-  const intptr_t file_size_;
-  const intptr_t memory_size_;
-  const uint8_t* const bytes_;
-  const ZoneGrowableArray<Elf::Relocation>* const relocations_;
-  const ZoneGrowableArray<Elf::SymbolData>* const symbols_;
+  GrowableArray<Portion> portions_;
+  intptr_t total_size_ = 0;
 };
 
+class NoteSection : public BitsContainer {
+ public:
+  NoteSection()
+      : BitsContainer(elf::SectionHeaderType::SHT_NOTE,
+                      /*allocate=*/true,
+                      /*executable=*/false,
+                      /*writable=*/false,
+                      kNoteAlignment) {}
+};
+
+// Abstract bits container that allows merging by just appending the portion
+// information (with properly adjusted offsets) of the other to this one.
+class ConcatenableBitsContainer : public BitsContainer {
+ public:
+  ConcatenableBitsContainer(Elf::Type type,
+                            bool executable,
+                            bool writable,
+                            intptr_t alignment)
+      : BitsContainer(type, executable, writable, alignment) {}
+
+  virtual bool CanMergeWith(const Section& other) const = 0;
+  virtual void Merge(const Section& other) {
+    ASSERT(other.IsBitsContainer());
+    ASSERT(CanMergeWith(other));
+    for (const auto& portion : other.AsBitsContainer()->portions()) {
+      AddPortion(portion.bytes, portion.size, portion.relocations,
+                 portion.symbols, portion.symbol_name);
+    }
+  }
+};
+
+class TextSection : public ConcatenableBitsContainer {
+ public:
+  explicit TextSection(Elf::Type t)
+      : ConcatenableBitsContainer(t,
+                                  /*executable=*/true,
+                                  /*writable=*/false,
+                                  ImageWriter::kTextAlignment) {}
+
+  DEFINE_TYPE_CHECK_FOR(TextSection);
+
+  virtual bool CanMergeWith(const Section& other) const {
+    return other.IsTextSection();
+  }
+};
+
+class DataSection : public ConcatenableBitsContainer {
+ public:
+  explicit DataSection(Elf::Type t)
+      : ConcatenableBitsContainer(t,
+                                  /*executable=*/false,
+                                  /*writable=*/false,
+                                  ImageWriter::kRODataAlignment) {}
+
+  DEFINE_TYPE_CHECK_FOR(DataSection);
+
+  virtual bool CanMergeWith(const Section& other) const {
+    return other.IsDataSection();
+  }
+};
+
+class BssSection : public ConcatenableBitsContainer {
+ public:
+  explicit BssSection(Elf::Type t)
+      : ConcatenableBitsContainer(t,
+                                  /*executable=*/false,
+                                  /*writable=*/true,
+                                  ImageWriter::kBssAlignment) {}
+
+  DEFINE_TYPE_CHECK_FOR(BssSection);
+
+  virtual bool CanMergeWith(const Section& other) const {
+    return other.IsBssSection();
+  }
+};
+
+// Represents portions of the file/memory space which do not correspond to
+// sections from the section header. Should never be added to the section table,
+// but may be added to segments.
+class PseudoSection : public Section {
+ public:
+  // All PseudoSections are aligned to target word size.
+  static const intptr_t kAlignment = compiler::target::kWordSize;
+
+  PseudoSection(bool allocate, bool executable, bool writable)
+      : Section(elf::SectionHeaderType::SHT_NULL,
+                allocate,
+                executable,
+                writable,
+                kAlignment) {}
+
+  DEFINE_TYPE_CHECK_FOR(PseudoSection)
+
+  void Write(ElfWriteStream* stream) const = 0;
+};
+
+class ProgramTable : public PseudoSection {
+ public:
+  explicit ProgramTable(Zone* zone)
+      : PseudoSection(/*allocate=*/true,
+                      /*executable=*/false,
+                      /*writable=*/false),
+        segments_(zone, 0) {
+    entry_size = sizeof(elf::ProgramHeader);
+  }
+
+  const GrowableArray<Segment*>& segments() const { return segments_; }
+  intptr_t SegmentCount() const { return segments_.length(); }
+  intptr_t MemorySize() const {
+    return segments_.length() * sizeof(elf::ProgramHeader);
+  }
+
+  void Add(Segment* segment) {
+    ASSERT(segment != nullptr);
+    segments_.Add(segment);
+  }
+
+  void Write(ElfWriteStream* stream) const;
+
+ private:
+  GrowableArray<Segment*> segments_;
+};
+
+// This particular PseudoSection should not appear in segments either (hence
+// being marked non-allocated), but is directly held by the Elf object.
+class SectionTable : public PseudoSection {
+ public:
+  explicit SectionTable(Zone* zone)
+      : PseudoSection(/*allocate=*/false,
+                      /*executable=*/false,
+                      /*writable=*/false),
+        zone_(zone),
+        sections_(zone_, 2),
+        shstrtab_(zone_, /*allocate=*/false) {
+    entry_size = sizeof(elf::SectionHeader);
+    // The section at index 0 (elf::SHN_UNDEF) must be all 0s.
+    ASSERT_EQUAL(shstrtab_.Lookup(""), 0);
+    Add(new (zone_) ReservedSection(), "");
+    Add(&shstrtab_, ".shstrtab");
+  }
+
+  const GrowableArray<Section*>& sections() const { return sections_; }
+  intptr_t SectionCount() const { return sections_.length(); }
+  intptr_t StringTableIndex() const { return shstrtab_.index; }
+
+  bool HasSectionNamed(const char* name) {
+    return shstrtab_.Lookup(name) != StringTable::kNotIndexed;
+  }
+
+  void Add(Section* section, const char* name = nullptr) {
+    ASSERT(!section->IsPseudoSection());
+    ASSERT(name != nullptr || section->name_is_set());
+    if (name != nullptr) {
+      // First, check for an existing section with the same table name.
+      if (auto* const old_section = Find(name)) {
+        ASSERT(old_section->CanMergeWith(*section));
+        old_section->Merge(*section);
+        return;
+      }
+      // No existing section with this name.
+      const intptr_t name_index = shstrtab_.Add(name);
+      section->set_name(name_index);
+    }
+    section->index = sections_.length();
+    sections_.Add(section);
+  }
+
+  Section* Find(const char* name) {
+    const intptr_t name_index = shstrtab_.Lookup(name);
+    if (name_index == StringTable::kNotIndexed) {
+      // We're guaranteed that no section with this name has been added yet.
+      return nullptr;
+    }
+    // We check walk all sections to check for uniqueness in DEBUG mode.
+    Section* result = nullptr;
+    for (Section* const section : sections_) {
+      if (section->name() == name_index) {
+#if defined(DEBUG)
+        ASSERT(result == nullptr);
+        result = section;
+#else
+        return section;
+#endif
+      }
+    }
+    return result;
+  }
+
+  intptr_t FileSize() const {
+    return sections_.length() * sizeof(elf::SectionHeader);
+  }
+
+  void Write(ElfWriteStream* stream) const;
+
+  // Reorders the sections for creating a minimal amount of segments and
+  // creates and returns an appropriate program table.
+  //
+  // Also takes and adjusts section indices in the static symbol table, since it
+  // is not recorded in sections_ for stripped outputs.
+  ProgramTable* CreateProgramTable(SymbolTable* symtab);
+
+ private:
+  Zone* const zone_;
+  GrowableArray<Section*> sections_;
+  StringTable shstrtab_;
+};
+
+class ElfHeader : public PseudoSection {
+ public:
+  ElfHeader(const ProgramTable& program_table,
+            const SectionTable& section_table)
+      : PseudoSection(/*allocate=*/true,
+                      /*executable=*/false,
+                      /*writable=*/false),
+        program_table_(program_table),
+        section_table_(section_table) {}
+
+  intptr_t MemorySize() const { return sizeof(elf::ElfHeader); }
+
+  void Write(ElfWriteStream* stream) const;
+
+ private:
+  const ProgramTable& program_table_;
+  const SectionTable& section_table_;
+};
+
+#undef DEFINE_TYPE_CHECK_FOR
+#undef FOR_EACH_SECTION_TYPE
+
 Elf::Elf(Zone* zone, BaseWriteStream* stream, Type type, Dwarf* dwarf)
     : zone_(zone),
       unwrapped_stream_(stream),
       type_(type),
       dwarf_(dwarf),
-      shstrtab_(new (zone) StringTable(zone, /*allocate=*/false)),
-      dynstrtab_(new (zone) StringTable(zone, /*allocate=*/true)),
-      dynsym_(new (zone) SymbolTable(zone, dynstrtab_, /*dynamic=*/true)),
-      strtab_(new (zone_) StringTable(zone_, /*allocate=*/false)),
-      symtab_(new (zone_) SymbolTable(zone, strtab_, /*dynamic=*/false)) {
+      section_table_(new (zone) SectionTable(zone)) {
   // Separate debugging information should always have a Dwarf object.
   ASSERT(type_ == Type::Snapshot || dwarf_ != nullptr);
   // Assumed by various offset logic in this file.
   ASSERT_EQUAL(unwrapped_stream_->Position(), 0);
 }
 
-void Elf::AddSection(Section* section,
-                     const char* name,
-                     const char* symbol_name) {
-  ASSERT(section_table_file_size_ < 0);
-  ASSERT(!shstrtab_->HasBeenFinalized());
-  section->set_name(shstrtab_->AddString(name));
-  // We do not set the section index yet, that will be done during Finalize().
-  sections_.Add(section);
-  // We do set the initial section index in initialized symbols for quick lookup
-  // until reordering happens.
-  const intptr_t initial_section_index = sections_.length() - 1;
-  if (symbol_name != nullptr) {
-    ASSERT(section->IsAllocated());
-    section->symbol_name = symbol_name;
-    // While elf::STT_SECTION might seem more appropriate, section symbols are
-    // usually local and dlsym won't return them.
-    ASSERT(!dynsym_->HasBeenFinalized());
-    dynsym_->AddSymbol(symbol_name, elf::STB_GLOBAL, elf::STT_FUNC,
-                       initial_section_index, section->MemorySize());
-    // Some tools assume the static symbol table is a superset of the dynamic
-    // symbol table when it exists (see dartbug.com/41783).
-    ASSERT(!symtab_->HasBeenFinalized());
-    symtab_->AddSymbol(symbol_name, elf::STB_GLOBAL, elf::STT_FUNC,
-                       initial_section_index, section->FileSize());
-  }
-  if (auto const container = section->AsBitsContainer()) {
-    if (container->symbols() != nullptr) {
-      ASSERT(section->IsAllocated());
-      for (const auto& symbol_data : *container->symbols()) {
-        ASSERT(!symtab_->HasBeenFinalized());
-        symtab_->AddSymbol(symbol_data.name, elf::STB_LOCAL, symbol_data.type,
-                           initial_section_index, symbol_data.size);
-      }
-    }
-  }
-}
-
 void Elf::AddText(const char* name,
                   const uint8_t* bytes,
                   intptr_t size,
                   const ZoneGrowableArray<Relocation>* relocations,
                   const ZoneGrowableArray<SymbolData>* symbols) {
-  auto const image =
-      new (zone_) BitsContainer(type_, /*executable=*/true,
-                                /*writable=*/false, size, bytes, relocations,
-                                symbols, ImageWriter::kTextAlignment);
-  AddSection(image, ".text", name);
+  auto* const container = new (zone_) TextSection(type_);
+  container->AddPortion(bytes, size, relocations, symbols, name);
+  section_table_->Add(container, kTextName);
 }
 
-// Here, both VM and isolate will be compiled into a single snapshot.
-// In assembly generation, each serialized text section gets a separate
-// pointer into the BSS segment and BSS slots are created for each, since
-// we may not serialize both VM and isolate. Here, we always serialize both,
-// so make a BSS segment large enough for both, with the VM entries coming
-// first.
-static constexpr intptr_t kBssVmSize =
-    BSS::kVmEntryCount * compiler::target::kWordSize;
-static constexpr intptr_t kBssIsolateSize =
-    BSS::kIsolateEntryCount * compiler::target::kWordSize;
-static constexpr intptr_t kBssSize = kBssVmSize + kBssIsolateSize;
-
 void Elf::CreateBSS() {
-  uint8_t* bytes = nullptr;
-  if (type_ == Type::Snapshot) {
-    // Ideally the BSS segment would take no space in the object, but Android's
-    // "strip" utility truncates the memory-size of our segments to their
-    // file-size.
-    //
-    // Therefore we must insert zero-filled data for the BSS.
-    bytes = zone_->Alloc<uint8_t>(kBssSize);
-    memset(bytes, 0, kBssSize);
+  // Not idempotent.
+  ASSERT(section_table_->Find(kBssName) == nullptr);
+  // No text section means no BSS section.
+  auto* const text_section = section_table_->Find(kTextName);
+  if (text_section == nullptr) return;
+  ASSERT(text_section->IsTextSection());
+
+  auto* const bss_container = new (zone_) BssSection(type_);
+  for (const auto& portion : text_section->AsBitsContainer()->portions()) {
+    size_t size;
+    const char* symbol_name;
+    // First determine whether this is the VM's text portion or the isolate's.
+    if (strcmp(portion.symbol_name, kVmSnapshotInstructionsAsmSymbol) == 0) {
+      size = BSS::kVmEntryCount * compiler::target::kWordSize;
+      symbol_name = kVmSnapshotBssAsmSymbol;
+    } else if (strcmp(portion.symbol_name,
+                      kIsolateSnapshotInstructionsAsmSymbol) == 0) {
+      size = BSS::kIsolateEntryCount * compiler::target::kWordSize;
+      symbol_name = kIsolateSnapshotBssAsmSymbol;
+    } else {
+      // Not VM or isolate text.
+      UNREACHABLE();
+      continue;
+    }
+
+    uint8_t* bytes = nullptr;
+    if (type_ == Type::Snapshot) {
+      // Ideally the BSS segment would take no space in the object, but
+      // Android's "strip" utility truncates the memory-size of our segments to
+      // their file-size.
+      //
+      // Therefore we must insert zero-filled data for the BSS.
+      bytes = zone_->Alloc<uint8_t>(size);
+      memset(bytes, 0, size);
+    }
+    // For the BSS section, we add the section symbols as local symbols in the
+    // static symbol table, as these addresses are only used for relocation.
+    // (This matches the behavior in the assembly output.)
+    auto* symbols = new (zone_) ZoneGrowableArray<Elf::SymbolData>();
+    symbols->Add({symbol_name, elf::STT_SECTION, 0, size});
+    bss_container->AddPortion(bytes, size, /*relocations=*/nullptr, symbols);
   }
-  // For the BSS section, we add two local symbols to the static symbol table,
-  // one for each isolate. We use local symbols because these addresses are only
-  // used for relocation. (This matches the behavior in the assembly output,
-  // where these symbols are also local.)
-  auto* bss_symbols = new (zone_) ZoneGrowableArray<Elf::SymbolData>();
-  bss_symbols->Add({kVmSnapshotBssAsmSymbol, elf::STT_SECTION, 0, kBssVmSize});
-  bss_symbols->Add({kIsolateSnapshotBssAsmSymbol, elf::STT_SECTION, kBssVmSize,
-                    kBssIsolateSize});
-  bss_ = new (zone_) BitsContainer(
-      type_, /*executable=*/false, /*writable=*/true, kBssSize, bytes,
-      /*relocations=*/nullptr, bss_symbols, ImageWriter::kBssAlignment);
-  AddSection(bss_, ".bss");
+
+  section_table_->Add(bss_container, kBssName);
 }
 
 void Elf::AddROData(const char* name,
@@ -1040,11 +1194,9 @@
                     intptr_t size,
                     const ZoneGrowableArray<Relocation>* relocations,
                     const ZoneGrowableArray<SymbolData>* symbols) {
-  auto const image =
-      new (zone_) BitsContainer(type_, /*executable=*/false,
-                                /*writable=*/false, size, bytes, relocations,
-                                symbols, ImageWriter::kRODataAlignment);
-  AddSection(image, ".rodata", name);
+  auto* const container = new (zone_) DataSection(type_);
+  container->AddPortion(bytes, size, relocations, symbols, name);
+  section_table_->Add(container, kDataName);
 }
 
 #if defined(DART_PRECOMPILER)
@@ -1057,6 +1209,7 @@
 
   const uint8_t* buffer() const { return stream_->buffer(); }
   intptr_t bytes_written() const { return stream_->bytes_written(); }
+  intptr_t Position() const { return stream_->Position(); }
 
   void sleb128(intptr_t value) { stream_->WriteSLEB128(value); }
   void uleb128(uintptr_t value) { stream_->WriteLEB128(value); }
@@ -1092,12 +1245,12 @@
 
   void OffsetFromSymbol(const char* symbol, intptr_t offset) {
     relocations_->Add(
-        {kAddressSize, stream_->Position(), nullptr, 0, symbol, offset});
+        {kAddressSize, stream_->Position(), "", 0, symbol, offset});
     addr(0);  // Resolved later.
   }
   template <typename T>
   void RelativeSymbolOffset(const char* symbol) {
-    relocations_->Add({sizeof(T), stream_->Position(), ".", 0, symbol, 0});
+    relocations_->Add({sizeof(T), stream_->Position(), nullptr, 0, symbol, 0});
     stream_->WriteFixed<T>(0);  // Resolved later.
   }
   void InitializeAbstractOrigins(intptr_t size) {
@@ -1143,43 +1296,79 @@
 static constexpr intptr_t kInitialDwarfBufferSize = 64 * KB;
 #endif
 
-const Section* Elf::FindSectionBySymbolName(const char* name) const {
-  auto* const symbol = symtab_->Find(name);
-  if (symbol == nullptr) return nullptr;
-  // Should not be run between OrderSectionsAndCreateSegments (when section
-  // indices may change) and FinalizeSymbols() (sets the final section index).
-  ASSERT(segments_.length() == 0 || symbol->HasBeenFinalized());
-  const Section* const section = sections_[symbol->section_index];
-  ASSERT_EQUAL(strcmp(section->symbol_name, name), 0);
-  return section;
-}
-
-void Elf::FinalizeSymbols() {
-  // Must be run after OrderSectionsAndCreateSegments and ComputeOffsets.
-  ASSERT(segments_.length() > 0);
-  ASSERT(section_table_file_offset_ > 0);
-  for (const auto& section : sections_) {
-    if (section->symbol_name != nullptr) {
-      dynsym_->FinalizeSymbol(section->symbol_name, section->index(),
-                              section->memory_offset());
-      symtab_->FinalizeSymbol(section->symbol_name, section->index(),
-                              section->memory_offset());
-    }
-    if (auto const container = section->AsBitsContainer()) {
-      if (container->symbols() != nullptr) {
-        for (const auto& symbol_data : *container->symbols()) {
-          symtab_->FinalizeSymbol(
-              symbol_data.name, section->index(),
-              section->memory_offset() + symbol_data.offset);
+void SymbolTable::Initialize(const GrowableArray<Section*>& sections) {
+  for (auto* const section : sections) {
+    // The values of all added symbols are memory addresses.
+    if (!section->IsAllocated()) continue;
+    if (auto* const bits = section->AsBitsContainer()) {
+      for (const auto& portion : section->AsBitsContainer()->portions()) {
+        if (portion.symbol_name != nullptr) {
+          // Global dynamic symbols for the content of a given section, which is
+          // always a single structured element (and thus we use STT_OBJECT).
+          const intptr_t binding = elf::STB_GLOBAL;
+          const intptr_t type = elf::STT_OBJECT;
+          // Some tools assume the static symbol table is a superset of the
+          // dynamic symbol table when it exists and only use it, so put all
+          // dynamic symbols there also. (see dartbug.com/41783).
+          AddSymbol(portion.symbol_name, binding, type, portion.size,
+                    section->index, portion.offset);
+        }
+        if (!dynamic_ && portion.symbols != nullptr) {
+          for (const auto& symbol_data : *portion.symbols) {
+            // Local static-only symbols, e.g., code payloads or RO objects.
+            AddSymbol(symbol_data.name, elf::STB_LOCAL, symbol_data.type,
+                      symbol_data.size, section->index,
+                      portion.offset + symbol_data.offset);
+          }
         }
       }
     }
   }
 }
 
+void Elf::InitializeSymbolTables() {
+  // Not idempotent.
+  ASSERT(symtab_ == nullptr);
+
+  // Create static and dynamic symbol tables.
+  auto* const dynstrtab = new (zone_) StringTable(zone_, /*allocate=*/true);
+  section_table_->Add(dynstrtab, ".dynstr");
+  auto* const dynsym =
+      new (zone_) SymbolTable(zone_, dynstrtab, /*dynamic=*/true);
+  section_table_->Add(dynsym, ".dynsym");
+  dynsym->Initialize(section_table_->sections());
+  // Now the dynamic symbol table is populated, set up the hash table and
+  // dynamic table.
+  auto* const hash = new (zone_) SymbolHashTable(zone_, dynsym);
+  section_table_->Add(hash, ".hash");
+  auto* const dynamic = new (zone_) DynamicTable(zone_, dynsym, hash);
+  section_table_->Add(dynamic, kDynamicTableName);
+
+  // We only add the static string and symbol tables to the section table if
+  // this is an unstripped output, but we always create them as they are used
+  // to resolve relocations.
+  auto* const strtab = new (zone_) StringTable(zone_, /*allocate=*/false);
+  if (!IsStripped()) {
+    section_table_->Add(strtab, ".strtab");
+  }
+  symtab_ = new (zone_) SymbolTable(zone_, strtab, /*dynamic=*/false);
+  if (!IsStripped()) {
+    section_table_->Add(symtab_, ".symtab");
+  }
+  symtab_->Initialize(section_table_->sections());
+}
+
 void Elf::FinalizeEhFrame() {
-#if defined(DART_PRECOMPILER) &&                                               \
-    (defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64))
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+  // No text section added means no .eh_frame.
+  TextSection* text_section = nullptr;
+  if (auto* const section = section_table_->Find(kTextName)) {
+    text_section = section->AsTextSection();
+    ASSERT(text_section != nullptr);
+  }
+  // No text section added means no .eh_frame.
+  if (text_section == nullptr) return;
+
   // Multiplier which will be used to scale operands of DW_CFA_offset and
   // DW_CFA_val_offset.
   const intptr_t kDataAlignment = compiler::target::kWordSize;
@@ -1211,17 +1400,15 @@
   });
 
   // Emit an FDE covering each .text section.
-  const auto text_name = shstrtab_->Lookup(".text");
-  ASSERT(text_name != StringTable::kNotIndexed);
-  for (auto section : sections_) {
-    if (section->name() != text_name) continue;
+  for (const auto& portion : text_section->portions()) {
+    ASSERT(portion.symbol_name != nullptr);  // Needed for relocations.
     dwarf_stream.WritePrefixedLength([&]() {
       // Offset to CIE. Note that unlike pcrel this offset is encoded
       // backwards: it will be subtracted from the current position.
       dwarf_stream.u4(stream.Position() - cie_start);
       // Start address as a PC relative reference.
-      dwarf_stream.RelativeSymbolOffset<int32_t>(section->symbol_name);
-      dwarf_stream.u4(section->MemorySize());  // Size.
+      dwarf_stream.RelativeSymbolOffset<int32_t>(portion.symbol_name);
+      dwarf_stream.u4(portion.size);           // Size.
       dwarf_stream.u1(0);                      // Augmentation Data length.
 
       // FP at FP+kSavedCallerPcSlotFromFp*kWordSize
@@ -1248,25 +1435,28 @@
     });
   }
 
-  dwarf_stream.u4(0);  // end of section
+  dwarf_stream.u4(0);  // end of section (FDE with zero length)
 
-  auto const eh_frame = new (zone_)
-      BitsContainer(type_, /*writable=*/false, /*executable=*/false,
-                    dwarf_stream.bytes_written(), dwarf_stream.buffer(),
-                    dwarf_stream.relocations(), /*symbols=*/nullptr);
-  AddSection(eh_frame, ".eh_frame");
-#endif  // defined(DART_PRECOMPILER) && \
-        //   (defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64))
+  auto* const eh_frame = new (zone_)
+      BitsContainer(type_, /*writable=*/false, /*executable=*/false);
+  eh_frame->AddPortion(dwarf_stream.buffer(), dwarf_stream.bytes_written(),
+                       dwarf_stream.relocations());
+  section_table_->Add(eh_frame, ".eh_frame");
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
 }
 
 void Elf::FinalizeDwarfSections() {
   if (dwarf_ == nullptr) return;
-#if defined(DART_PRECOMPILER)
+
+  // Currently we only output DWARF information involving code.
+  ASSERT(section_table_->HasSectionNamed(kTextName));
+
   auto add_debug = [&](const char* name, const DwarfElfStream& stream) {
-    auto const image = new (zone_) BitsContainer(
-        elf::SectionHeaderType::SHT_PROGBITS, stream.bytes_written(),
-        stream.buffer(), stream.relocations(), /*symbols=*/nullptr);
-    AddSection(image, name);
+    auto const container =
+        new (zone_) BitsContainer(elf::SectionHeaderType::SHT_PROGBITS);
+    container->AddPortion(stream.buffer(), stream.bytes_written(),
+                          stream.relocations());
+    section_table_->Add(container, name);
   };
   {
     ZoneWriteStream stream(zone(), kInitialDwarfBufferSize);
@@ -1288,148 +1478,240 @@
     dwarf_->WriteLineNumberProgram(&dwarf_stream);
     add_debug(".debug_line", dwarf_stream);
   }
-#endif
 }
 
-void Elf::OrderSectionsAndCreateSegments() {
-  GrowableArray<Section*> reordered_sections;
-  // The first section in the section header table is always a reserved
-  // entry containing only 0 values.
-  reordered_sections.Add(new (zone_) ReservedSection());
+ProgramTable* SectionTable::CreateProgramTable(SymbolTable* symtab) {
+  const intptr_t num_sections = sections_.length();
+  // Should have at least the reserved entry in sections_.
+  ASSERT(!sections_.is_empty());
+  ASSERT_EQUAL(sections_[0]->alignment, 0);
+
+  // The new program table that collects the segments for allocated sections
+  // and a few special segments.
+  auto* const program_table = new (zone_) ProgramTable(zone_);
+
+  GrowableArray<Section*> reordered_sections(zone_, num_sections);
+  // Maps the old indices of sections to the new ones.
+  GrowableArray<intptr_t> index_map(zone_, num_sections);
+  index_map.FillWith(0, 0, num_sections);
 
   Segment* current_segment = nullptr;
+  // Only called for sections in the section table (i.e., not special sections
+  // appearing in segments only or the section table itself).
   auto add_to_reordered_sections = [&](Section* section) {
-    section->set_index(reordered_sections.length());
+    intptr_t new_index = reordered_sections.length();
+    index_map[section->index] = new_index;
+    section->index = new_index;
     reordered_sections.Add(section);
-    if (!section->IsAllocated()) return;
-    const bool was_added =
-        current_segment == nullptr ? false : current_segment->Add(section);
-    if (!was_added) {
-      // There is no current segment or it is incompatible for merging, so
-      // following compatible segments will be merged into this one if possible.
-      current_segment =
-          new (zone_) Segment(zone_, section, elf::ProgramHeaderType::PT_LOAD);
-      section->load_segment = current_segment;
-      segments_.Add(current_segment);
+    if (section->IsAllocated()) {
+      ASSERT(current_segment != nullptr);
+      if (!current_segment->Add(section)) {
+        // The current segment is incompatible for the current sectioni, so
+        // create a new one.
+        current_segment = new (zone_)
+            Segment(zone_, section, elf::ProgramHeaderType::PT_LOAD);
+        program_table->Add(current_segment);
+      }
     }
   };
 
-  // Add writable, non-executable sections first, due to a bug in Jelly Bean's
-  // ELF loader when a writable segment is placed between two non-writable
-  // segments. See also Elf::WriteProgramTable(), which double-checks this.
-  for (auto* const section : sections_) {
-    if (section->IsAllocated() && section->IsWritable() &&
-        !section->IsExecutable()) {
-      add_to_reordered_sections(section);
-    }
+  // The first section in the section header table is always a reserved
+  // entry containing only 0 values, so copy it over from sections_.
+  add_to_reordered_sections(sections_[0]);
+
+  // There are few important invariants originating from Android idiosyncrasies
+  // we are trying to maintain when ordering sections:
+  //
+  //   - Android requires the program header table be in the first load segment,
+  //     so create PseudoSections representing the ELF header and program header
+  //     table to initialize that segment.
+  //
+  //   - The Android dynamic linker in Jelly Bean incorrectly assumes that all
+  //     non-writable segments are continguous. Thus we write them all together.
+  //     The bug is here: https://github.com/aosp-mirror/platform_bionic/blob/94963af28e445384e19775a838a29e6a71708179/linker/linker.c#L1991-L2001
+  //
+  //   - On Android native libraries can be mapped directly from an APK
+  //     they are stored uncompressed in it. In such situations the name
+  //     of the mapping no longer provides enough information for libunwindstack
+  //     to find the original ELF file and instead it has to rely on heuristics
+  //     to locate program header table. These heuristics currently assume that
+  //     program header table will be located in the RO mapping which precedes
+  //     RX mapping.
+  //
+  // These invariants imply the following order of segments: RO (program
+  // header,  .note.gnu.build-id, .dynstr, .dynsym, .hash, .rodata
+  // and .eh_frame), RX (.text), RW (.dynamic and .bss).
+  //
+  auto* const elf_header = new (zone_) ElfHeader(*program_table, *this);
+
+  // Self-reference to program header table. Required by Android but not by
+  // Linux. Must appear before any PT_LOAD entries.
+  program_table->Add(new (zone_) Segment(zone_, program_table,
+                                         elf::ProgramHeaderType::PT_PHDR));
+
+  // Create the initial load segment which contains the ELF header and program
+  // table.
+  current_segment =
+      new (zone_) Segment(zone_, elf_header, elf::ProgramHeaderType::PT_LOAD);
+  program_table->Add(current_segment);
+  current_segment->Add(program_table);
+
+  // We now do several passes over the collected sections to reorder them in
+  // a way that minimizes segments (and thus padding) in the resulting snapshot.
+
+  // If a build ID was created, we put it after the program table so it can
+  // be read with a minimum number of bytes from the ELF file.
+  auto* const build_id = Find(Elf::kBuildIdNoteName);
+  if (build_id != nullptr) {
+    ASSERT(build_id->type == elf::SectionHeaderType::SHT_NOTE);
+    add_to_reordered_sections(build_id);
   }
 
-  // Now add the non-writable, non-executable allocated sections in a new
-  // segment, starting with the data sections.
+  // Now add the other non-writable, non-executable allocated sections.
   for (auto* const section : sections_) {
+    if (section == build_id) continue;  // Already added.
     if (section->IsAllocated() && !section->IsWritable() &&
         !section->IsExecutable()) {
       add_to_reordered_sections(section);
     }
   }
 
-  // Now add the non-writable, executable sections in a new segment.
+  // Now add the executable sections in a new segment.
   for (auto* const section : sections_) {
-    if (section->IsAllocated() && !section->IsWritable() &&
-        section->IsExecutable()) {
+    if (section->IsExecutable()) {  // Implies IsAllocated() && !IsWritable()
       add_to_reordered_sections(section);
     }
   }
 
-  // We put all unallocated sections last because otherwise, they would
+  // Now add all the writable sections.
+  for (auto* const section : sections_) {
+    if (section->IsWritable()) {  // Implies IsAllocated() && !IsExecutable()
+      add_to_reordered_sections(section);
+    }
+  }
+
+  // We put all non-reserved unallocated sections last. Otherwise, they would
   // affect the file offset but not the memory offset of any following allocated
   // sections. Doing it in this order makes it easier to keep file and memory
   // offsets page-aligned with respect to each other, which is required for
   // some loaders.
-  for (auto* const section : sections_) {
-    if (!section->IsAllocated()) {
-      add_to_reordered_sections(section);
-    }
+  for (intptr_t i = 1; i < num_sections; i++) {
+    auto* const section = sections_[i];
+    if (section->IsAllocated()) continue;
+    add_to_reordered_sections(section);
   }
 
-  // Now replace sections_.
+  // All sections should have been accounted for in the loops above.
+  ASSERT_EQUAL(sections_.length(), reordered_sections.length());
+  // Replace the content of sections_ with the reordered sections.
   sections_.Clear();
   sections_.AddArray(reordered_sections);
-}
 
-void Elf::Finalize() {
-  ASSERT(program_table_file_size_ < 0);
+  // This must be true for uses of the map to be correct.
+  ASSERT_EQUAL(index_map[elf::SHN_UNDEF], elf::SHN_UNDEF);
 
-  // Generate the build ID now that we have all user-provided sections.
-  // Generating it at this point also means it'll be the first writable
-  // non-executable section added to sections_ and thus end up right after the
-  // program table after reordering. This limits how much of the ELF file needs
-  // to be read to get the build ID (header + program table + note segment).
-  GenerateBuildId();
-
-  // We add BSS in all cases, even to the separate debugging information ELF,
-  // to ensure that relocated addresses are consistent between ELF snapshots
-  // and ELF separate debugging information.
-  CreateBSS();
-
-  // Adding the dynamic symbol table and associated sections.
-  AddSection(dynstrtab_, ".dynstr");
-  AddSection(dynsym_, ".dynsym");
-
-  auto const hash = new (zone_) SymbolHashTable(zone_, dynstrtab_, dynsym_);
-  AddSection(hash, ".hash");
-
-  auto const dynamic = new (zone_) DynamicTable(zone_);
-  AddSection(dynamic, ".dynamic");
-
-  if (!IsStripped()) {
-    AddSection(strtab_, ".strtab");
-    AddSection(symtab_, ".symtab");
+  // Since the section indices have been updated, change links to match
+  // and update the indexes of symbols in any symbol tables.
+  for (auto* const section : sections_) {
+    // SHN_UNDEF maps to SHN_UNDEF, so no need to check for it.
+    section->link = index_map[section->link];
+    if (auto* const table = section->AsSymbolTable()) {
+      table->UpdateSectionIndices(index_map);
+    }
   }
-  AddSection(shstrtab_, ".shstrtab");
-  FinalizeEhFrame();
-  FinalizeDwarfSections();
-
-  OrderSectionsAndCreateSegments();
-
-  // Now that the sections have indices, set up links between them as needed.
-  dynsym_->link = dynstrtab_->index();
-  hash->link = dynsym_->index();
-  dynamic->link = dynstrtab_->index();
-  if (!IsStripped()) {
-    symtab_->link = strtab_->index();
+  if (symtab->index == elf::SHN_UNDEF) {
+    // The output is stripped, so this wasn't finalized during the loop above.
+    symtab->UpdateSectionIndices(index_map);
   }
 
-  // Now add any special non-load segments.
-
-  if (build_id_ != nullptr) {
+  // Add any special non-load segments.
+  if (build_id != nullptr) {
     // Add a PT_NOTE segment for the build ID.
-    segments_.Add(new (zone_) NoteSegment(zone_, build_id_));
+    program_table->Add(
+        new (zone_) Segment(zone_, build_id, elf::ProgramHeaderType::PT_NOTE));
   }
 
   // Add a PT_DYNAMIC segment for the dynamic symbol table.
-  segments_.Add(new (zone_) DynamicSegment(zone_, dynamic));
+  ASSERT(HasSectionNamed(Elf::kDynamicTableName));
+  auto* const dynamic = Find(Elf::kDynamicTableName)->AsDynamicTable();
+  program_table->Add(
+      new (zone_) Segment(zone_, dynamic, elf::ProgramHeaderType::PT_DYNAMIC));
 
-  // At this point, all sections have been added and ordered and all sections
-  // appropriately grouped into segments. Add the program table and then
-  // calculate file and memory offsets.
-  FinalizeProgramTable();
+  return program_table;
+}
+
+void Elf::Finalize() {
+  // Generate the build ID now that we have all user-provided sections.
+  GenerateBuildId();
+
+  // We add a BSS section in all cases, even to the separate debugging
+  // information, to ensure that relocated addresses are consistent between ELF
+  // snapshots and the corresponding separate debugging information.
+  CreateBSS();
+
+  FinalizeEhFrame();
+  FinalizeDwarfSections();
+
+  // Create and initialize the dynamic and static symbol tables and any
+  // other associated sections now that all other sections have been added.
+  InitializeSymbolTables();
+  // Creates an appropriate program table containing load segments for allocated
+  // sections and any other segments needed. May reorder sections to minimize
+  // the number of load segments, so also takes the static symbol table so
+  // symbol section indices can be adjusted if needed.
+  program_table_ = section_table_->CreateProgramTable(symtab_);
+  // Calculate file and memory offsets, and finalizes symbol values in any
+  // symbol tables.
   ComputeOffsets();
 
-  // Now that we have reordered the sections and set memory offsets, we can
-  // update the symbol tables to add index and address information. This must
-  // be done prior to writing the symbol tables and any sections with
-  // relocations.
-  FinalizeSymbols();
-  // Also update the entries in the dynamic table.
-  dynamic->FinalizeEntries(dynstrtab_, dynsym_, hash);
+#if defined(DEBUG)
+  if (type_ == Type::Snapshot) {
+    // For files that will be dynamically loaded, ensure the file offsets
+    // of allocated sections are page aligned to the memory offsets.
+    for (auto* const segment : program_table_->segments()) {
+      for (auto* const section : segment->sections()) {
+        ASSERT_EQUAL(section->file_offset() % Elf::kPageSize,
+                     section->memory_offset() % Elf::kPageSize);
+      }
+    }
+  }
+#endif
 
   // Finally, write the ELF file contents.
   ElfWriteStream wrapped(unwrapped_stream_, *this);
-  WriteHeader(&wrapped);
-  WriteProgramTable(&wrapped);
-  WriteSections(&wrapped);
-  WriteSectionTable(&wrapped);
+
+  auto write_section = [&](const Section* section) {
+    wrapped.Align(section->alignment);
+    ASSERT_EQUAL(wrapped.Position(), section->file_offset());
+    section->Write(&wrapped);
+    ASSERT_EQUAL(wrapped.Position(),
+                 section->file_offset() + section->FileSize());
+  };
+
+  // To match ComputeOffsets, first we write allocated sections and then
+  // unallocated sections. We access the allocated sections via the load
+  // segments so we can properly align the stream for each entered segment.
+  intptr_t section_index = 1;  // We don't visit the reserved section.
+  for (auto* const segment : program_table_->segments()) {
+    if (segment->type != elf::ProgramHeaderType::PT_LOAD) continue;
+    wrapped.Align(segment->Alignment());
+    for (auto* const section : segment->sections()) {
+      ASSERT(section->IsAllocated());
+      write_section(section);
+      if (!section->IsPseudoSection()) {
+        ASSERT_EQUAL(section->index, section_index);
+        section_index++;
+      }
+    }
+  }
+  const auto& sections = section_table_->sections();
+  for (; section_index < sections.length(); section_index++) {
+    auto* const section = sections[section_index];
+    ASSERT(!section->IsAllocated());
+    write_section(section);
+  }
+  // Finally, write the section table.
+  write_section(section_table_);
 }
 
 // For the build ID, we generate a 128-bit hash, where each 32 bits is a hash of
@@ -1449,32 +1731,40 @@
     sizeof(elf::Note) + sizeof(elf::ELF_NOTE_GNU);
 
 void Elf::GenerateBuildId() {
+  // Not idempotent.
+  ASSERT(section_table_->Find(kBuildIdNoteName) == nullptr);
   uint32_t hashes[kBuildIdSegmentNamesLength];
+  // Currently, we construct the build ID out of data from two different
+  // sections: the .text section and the .rodata section. We only create
+  // a build ID when we have all four sections and when we have the actual
+  // bytes from those sections.
+  //
+  // TODO(dartbug.com/43274): Generate build IDs for separate debugging
+  // information for assembly snapshots.
+  //
+  // TODO(dartbug.com/43516): Generate build IDs for snapshots with deferred
+  // sections.
+  auto* const text_section = section_table_->Find(kTextName);
+  if (text_section == nullptr) return;
+  ASSERT(text_section->IsTextSection());
+  auto* const text_bits = text_section->AsBitsContainer();
+  auto* const data_section = section_table_->Find(kDataName);
+  if (data_section == nullptr) return;
+  ASSERT(data_section->IsDataSection());
+  auto* const data_bits = data_section->AsBitsContainer();
+  // Now try to find
   for (intptr_t i = 0; i < kBuildIdSegmentNamesLength; i++) {
-    auto const name = kBuildIdSegmentNames[i];
-    auto const section = FindSectionBySymbolName(name);
-    // If we're missing a section, then we don't generate a final build ID.
-    if (section == nullptr) return;
-    auto const bits = section->AsBitsContainer();
-    if (bits == nullptr) {
-      FATAL1("Section for symbol %s is not a BitsContainer", name);
+    auto* const name = kBuildIdSegmentNames[i];
+    hashes[i] = text_bits->Hash(name);
+    if (hashes[i] == 0) {
+      hashes[i] = data_bits->Hash(name);
     }
-    // For now, if we don't have section contents (because we're generating
-    // assembly), don't generate a final build ID, as we'll have different
-    // build IDs in the snapshot and the separate debugging information.
-    //
-    // TODO(dartbug.com/43274): Change once we generate consistent build IDs
-    // between assembly snapshots and their debugging information.
-    if (bits->bytes() == nullptr) return;
-    hashes[i] = bits->Hash();
+    // The symbol wasn't found in either section or there were no bytes
+    // associated with the symbol.
+    if (hashes[i] == 0) return;
   }
   auto const description_bytes = reinterpret_cast<uint8_t*>(hashes);
   const size_t description_length = sizeof(hashes);
-  // To ensure we can quickly check for a final build ID, we ensure the first
-  // byte contains a non-zero value.
-  if (description_bytes[0] == 0) {
-    description_bytes[0] = 1;
-  }
   // Now that we have the description field contents, create the section.
   ZoneWriteStream stream(zone(), kBuildIdHeaderSize + description_length);
   stream.WriteFixed<decltype(elf::Note::name_size)>(sizeof(elf::ELF_NOTE_GNU));
@@ -1484,101 +1774,93 @@
   stream.WriteBytes(elf::ELF_NOTE_GNU, sizeof(elf::ELF_NOTE_GNU));
   ASSERT_EQUAL(stream.bytes_written(), kBuildIdHeaderSize);
   stream.WriteBytes(description_bytes, description_length);
-  // While the build ID section does not need to be writable, the first segment
-  // in our ELF files is writable (see Elf::WriteProgramTable) and so this
-  // ensures we can put it right after the program table without padding.
-  build_id_ = new (zone_) BitsContainer(
-      elf::SectionHeaderType::SHT_NOTE,
-      /*allocate=*/true, /*executable=*/false,
-      /*writable=*/true, stream.bytes_written(), stream.buffer(),
-      /*relocations=*/nullptr, /*symbols=*/nullptr, kNoteAlignment);
-  AddSection(build_id_, kBuildIdNoteName, kSnapshotBuildIdAsmSymbol);
+  auto* const container = new (zone_) NoteSection();
+  container->AddPortion(stream.buffer(), stream.bytes_written(),
+                        /*relocations=*/nullptr, /*symbols=*/nullptr,
+                        kSnapshotBuildIdAsmSymbol);
+  section_table_->Add(container, kBuildIdNoteName);
 }
 
-void Elf::FinalizeProgramTable() {
-  ASSERT(program_table_file_size_ < 0);
-
-  program_table_file_offset_ = sizeof(elf::ElfHeader);
-
-  // There is one additional segment we need the size of the program table to
-  // create, so calculate it as if that segment were already in place.
-  program_table_file_size_ =
-      (1 + segments_.length()) * sizeof(elf::ProgramHeader);
-
-  auto const program_table_segment_size =
-      program_table_file_offset_ + program_table_file_size_;
-
-  // Segment for loading the initial part of the ELF file, including the
-  // program header table. Required by Android but not by Linux.
-  Segment* const initial_load =
-      new (zone_) ProgramTableLoadSegment(zone_, program_table_segment_size);
-  // Merge the initial writable segment into this one and replace it (so it
-  // doesn't change the number of segments).
-  const bool was_merged = initial_load->Merge(segments_[0]);
-  ASSERT(was_merged);
-  segments_[0] = initial_load;
-
-  // Self-reference to program header table. Required by Android but not by
-  // Linux. Must appear before any PT_LOAD entries.
-  segments_.InsertAt(
-      0, new (zone_) ProgramTableSelfSegment(zone_, program_table_file_offset_,
-                                             program_table_file_size_));
-}
-
-static const intptr_t kElfSectionTableAlignment = compiler::target::kWordSize;
-
 void Elf::ComputeOffsets() {
-  // We calculate the size and offset of the program header table during
-  // finalization.
-  ASSERT(program_table_file_offset_ > 0 && program_table_file_size_ > 0);
-  intptr_t file_offset = program_table_file_offset_ + program_table_file_size_;
-  // Program table memory size is same as file size.
-  intptr_t memory_offset = file_offset;
+  intptr_t file_offset = 0;
+  intptr_t memory_offset = 0;
 
-  // When calculating memory and file offsets for sections, we'll need to know
-  // if we've changed segments. Start with the one for the program table.
-  ASSERT(segments_[0]->type != elf::ProgramHeaderType::PT_LOAD);
-  const auto* current_segment = segments_[1];
-  ASSERT(current_segment->type == elf::ProgramHeaderType::PT_LOAD);
+  // Maps indices of allocated sections in the section table to memory offsets.
+  const intptr_t num_sections = section_table_->SectionCount();
+  GrowableArray<intptr_t> address_map(zone_, num_sections);
+  address_map.Add(0);  // Don't adjust offsets for symbols with index SHN_UNDEF.
 
-  // The non-reserved sections are output to the file in order after the program
-  // header table. If we're entering a new segment, then we need to align
-  // according to the PT_LOAD segment alignment as well to keep the file offsets
-  // aligned with the memory addresses.
-  for (intptr_t i = 1; i < sections_.length(); i++) {
-    auto const section = sections_[i];
+  auto calculate_section_offsets = [&](Section* section) {
     file_offset = Utils::RoundUp(file_offset, section->alignment);
-    memory_offset = Utils::RoundUp(memory_offset, section->alignment);
-    if (section->IsAllocated() && section->load_segment != current_segment) {
-      current_segment = section->load_segment;
-      ASSERT(current_segment->type == elf::ProgramHeaderType::PT_LOAD);
-      const intptr_t load_align = Segment::Alignment(current_segment->type);
-      file_offset = Utils::RoundUp(file_offset, load_align);
-      memory_offset = Utils::RoundUp(memory_offset, load_align);
-    }
     section->set_file_offset(file_offset);
-    if (section->IsAllocated()) {
-      section->set_memory_offset(memory_offset);
-#if defined(DEBUG)
-      if (type_ == Type::Snapshot) {
-        // For files that will be dynamically loaded, make sure the file offsets
-        // of allocated sections are page aligned to the memory offsets.
-        ASSERT_EQUAL(section->file_offset() % Elf::kPageSize,
-                     section->memory_offset() % Elf::kPageSize);
-      }
-#endif
-    }
     file_offset += section->FileSize();
-    memory_offset += section->MemorySize();
+    if (section->IsAllocated()) {
+      memory_offset = Utils::RoundUp(memory_offset, section->alignment);
+      section->set_memory_offset(memory_offset);
+      memory_offset += section->MemorySize();
+    }
+  };
+
+  intptr_t section_index = 1;  // We don't visit the reserved section.
+  for (auto* const segment : program_table_->segments()) {
+    if (segment->type != elf::ProgramHeaderType::PT_LOAD) continue;
+    // Adjust file and memory offsets for segment alignment on entry.
+    file_offset = Utils::RoundUp(file_offset, segment->Alignment());
+    memory_offset = Utils::RoundUp(memory_offset, segment->Alignment());
+    for (auto* const section : segment->sections()) {
+      ASSERT(section->IsAllocated());
+      calculate_section_offsets(section);
+      if (!section->IsPseudoSection()) {
+        // Note: this assumes that the sections in the section header has all
+        // allocated sections before all (non-reserved) unallocated sections and
+        // in the same order as the load segments in in the program table.
+        address_map.Add(section->memory_offset());
+        ASSERT_EQUAL(section->index, section_index);
+        section_index++;
+      }
+    }
   }
 
-  file_offset = Utils::RoundUp(file_offset, kElfSectionTableAlignment);
-  section_table_file_offset_ = file_offset;
-  section_table_file_size_ = sections_.length() * sizeof(elf::SectionHeader);
-  file_offset += section_table_file_size_;
+  const auto& sections = section_table_->sections();
+  for (; section_index < sections.length(); section_index++) {
+    auto* const section = sections[section_index];
+    ASSERT(!section->IsAllocated());
+    calculate_section_offsets(section);
+  }
+
+  ASSERT_EQUAL(section_index, sections.length());
+  // Now that all sections have been handled, set the file offset for the
+  // section table, as it will be written after the last section.
+  calculate_section_offsets(section_table_);
+
+#if defined(DEBUG)
+  // Double check that segment starts are aligned as expected.
+  for (auto* const segment : program_table_->segments()) {
+    ASSERT(Utils::IsAligned(segment->MemoryOffset(), segment->Alignment()));
+  }
+#endif
+
+  // This must be true for uses of the map to be correct.
+  ASSERT_EQUAL(address_map[elf::SHN_UNDEF], 0);
+  // Adjust addresses in symbol tables as we now have section memory offsets.
+  // Also finalize the entries of the dynamic table, as some are memory offsets.
+  for (auto* const section : sections) {
+    if (auto* const table = section->AsSymbolTable()) {
+      table->Finalize(address_map);
+    } else if (auto* const dynamic = section->AsDynamicTable()) {
+      dynamic->Finalize();
+    }
+  }
+  // Also adjust addresses in symtab for stripped snapshots.
+  if (IsStripped()) {
+    ASSERT_EQUAL(symtab_->index, elf::SHN_UNDEF);
+    symtab_->Finalize(address_map);
+  }
 }
 
-void Elf::WriteHeader(ElfWriteStream* stream) {
+void ElfHeader::Write(ElfWriteStream* stream) const {
+  ASSERT_EQUAL(file_offset(), 0);
+  ASSERT_EQUAL(memory_offset(), 0);
 #if defined(TARGET_ARCH_IS_32_BIT)
   uint8_t size = elf::ELFCLASS32;
 #else
@@ -1618,8 +1900,8 @@
 
   stream->WriteWord(elf::EV_CURRENT);  // Version
   stream->WriteAddr(0);                // "Entry point"
-  stream->WriteOff(program_table_file_offset_);
-  stream->WriteOff(section_table_file_offset_);
+  stream->WriteOff(program_table_.file_offset());
+  stream->WriteOff(section_table_.file_offset());
 
 #if defined(TARGET_ARCH_ARM)
   uword flags = elf::EF_ARM_ABI | (TargetCPUFeatures::hardfp_supported()
@@ -1631,26 +1913,32 @@
   stream->WriteWord(flags);
 
   stream->WriteHalf(sizeof(elf::ElfHeader));
-  stream->WriteHalf(sizeof(elf::ProgramHeader));
-  stream->WriteHalf(segments_.length());
-  stream->WriteHalf(sizeof(elf::SectionHeader));
-  stream->WriteHalf(sections_.length());
-  stream->WriteHalf(shstrtab_->index());
-
-  ASSERT_EQUAL(stream->Position(), sizeof(elf::ElfHeader));
+  stream->WriteHalf(program_table_.entry_size);
+  stream->WriteHalf(program_table_.SegmentCount());
+  stream->WriteHalf(section_table_.entry_size);
+  stream->WriteHalf(section_table_.SectionCount());
+  stream->WriteHalf(stream->elf().section_table().StringTableIndex());
 }
 
-void Elf::WriteProgramTable(ElfWriteStream* stream) {
-  ASSERT(program_table_file_size_ >= 0);  // Check for finalization.
-  ASSERT(stream->Position() == program_table_file_offset_);
+void ProgramTable::Write(ElfWriteStream* stream) const {
+  ASSERT(segments_.length() > 0);
+  // Make sure all relevant segments were created by checking the type of the
+  // first.
+  ASSERT(segments_[0]->type == elf::ProgramHeaderType::PT_PHDR);
+  const intptr_t start = stream->Position();
+  // Should be immediately following the ELF header.
+  ASSERT_EQUAL(start, sizeof(elf::ElfHeader));
 #if defined(DEBUG)
   // Here, we count the number of times that a PT_LOAD writable segment is
-  // followed by a non-writable segment. We initialize last_writable to true so
-  // that we catch the case where the first segment is non-writable.
+  // followed by a non-writable segment. We initialize last_writable to true
+  // so that we catch the case where the first segment is non-writable.
   bool last_writable = true;
   int non_writable_groups = 0;
 #endif
-  for (auto const segment : segments_) {
+  for (intptr_t i = 0; i < segments_.length(); i++) {
+    const Segment* const segment = segments_[i];
+    ASSERT(segment->type != elf::ProgramHeaderType::PT_NULL);
+    ASSERT_EQUAL(i == 0, segment->type == elf::ProgramHeaderType::PT_PHDR);
 #if defined(DEBUG)
     if (segment->type == elf::ProgramHeaderType::PT_LOAD) {
       if (last_writable && !segment->IsWritable()) {
@@ -1662,7 +1950,7 @@
     const intptr_t start = stream->Position();
     segment->WriteProgramHeader(stream);
     const intptr_t end = stream->Position();
-    ASSERT_EQUAL(end - start, sizeof(elf::ProgramHeader));
+    ASSERT_EQUAL(end - start, entry_size);
   }
 #if defined(DEBUG)
   // All PT_LOAD non-writable segments must be contiguous. If not, some older
@@ -1672,49 +1960,16 @@
 #endif
 }
 
-void Elf::WriteSectionTable(ElfWriteStream* stream) {
-  ASSERT(section_table_file_size_ >= 0);  // Check for finalization.
-  stream->Align(kElfSectionTableAlignment);
-  ASSERT_EQUAL(stream->Position(), section_table_file_offset_);
-
-  for (auto const section : sections_) {
+void SectionTable::Write(ElfWriteStream* stream) const {
+  for (intptr_t i = 0; i < sections_.length(); i++) {
+    const Section* const section = sections_[i];
+    ASSERT_EQUAL(i == 0, section->IsReservedSection());
+    ASSERT_EQUAL(section->index, i);
+    ASSERT(section->link < sections_.length());
     const intptr_t start = stream->Position();
     section->WriteSectionHeader(stream);
     const intptr_t end = stream->Position();
-    ASSERT_EQUAL(end - start, sizeof(elf::SectionHeader));
-  }
-}
-
-void Elf::WriteSections(ElfWriteStream* stream) {
-  ASSERT(section_table_file_size_ >= 0);  // Check for finalization.
-  // Should be writing the first section immediately after the program table.
-  ASSERT_EQUAL(stream->Position(),
-               program_table_file_offset_ + program_table_file_size_);
-  // Skip the reserved first section, as its alignment is 0 (which will cause
-  // stream->Align() to fail) and it never contains file contents anyway.
-  ASSERT_EQUAL(static_cast<uint32_t>(sections_[0]->type),
-               static_cast<uint32_t>(elf::SectionHeaderType::SHT_NULL));
-  ASSERT_EQUAL(sections_[0]->alignment, 0);
-  // The program table is considered part of the first load segment (the
-  // second segment in segments_), so other sections in the same segment should
-  // not have extra segment alignment added.
-  ASSERT(segments_[0]->type != elf::ProgramHeaderType::PT_LOAD);
-  const Segment* current_segment = segments_[1];
-  ASSERT(current_segment->type == elf::ProgramHeaderType::PT_LOAD);
-  for (intptr_t i = 1; i < sections_.length(); i++) {
-    Section* section = sections_[i];
-    stream->Align(section->alignment);
-    if (section->IsAllocated() && section->load_segment != current_segment) {
-      // Changing segments, so align accordingly.
-      current_segment = section->load_segment;
-      ASSERT(current_segment->type == elf::ProgramHeaderType::PT_LOAD);
-      const intptr_t load_align = Segment::Alignment(current_segment->type);
-      stream->Align(load_align);
-    }
-    ASSERT_EQUAL(stream->Position(), section->file_offset());
-    section->Write(stream);
-    ASSERT_EQUAL(stream->Position(),
-                 section->file_offset() + section->FileSize());
+    ASSERT_EQUAL(end - start, entry_size);
   }
 }
 
diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h
index c98f423..579c49f 100644
--- a/runtime/vm/elf.h
+++ b/runtime/vm/elf.h
@@ -16,10 +16,9 @@
 #if defined(DART_PRECOMPILER)
 
 class Dwarf;
-class ElfWriteStream;
+class ProgramTable;
 class Section;
-class Segment;
-class StringTable;
+class SectionTable;
 class SymbolTable;
 
 class Elf : public ZoneAllocated {
@@ -34,21 +33,28 @@
 
   Elf(Zone* zone, BaseWriteStream* stream, Type type, Dwarf* dwarf = nullptr);
 
+  // The max page size on all supported architectures. Used to determine
+  // the alignment of load segments, so that they are guaranteed page-aligned,
+  // and no ELF section or segment should have a larger alignment.
   static constexpr intptr_t kPageSize = 16 * KB;
-  static constexpr uword kNoSectionStart = 0;
 
   bool IsStripped() const { return dwarf_ == nullptr; }
 
   Zone* zone() const { return zone_; }
   const Dwarf* dwarf() const { return dwarf_; }
   Dwarf* dwarf() { return dwarf_; }
-  const SymbolTable* symtab() const { return symtab_; }
+  const SymbolTable& symtab() const {
+    ASSERT(symtab_ != nullptr);
+    return *symtab_;
+  }
+  const SectionTable& section_table() const { return *section_table_; }
 
   // Stores the information needed to appropriately generate a
   // relocation from the target to the source at the given section offset.
-  // If a given symbol is nullptr, then the offset is absolute (from 0).
-  // Both source and target symbols could be "." which is pseudosymbol
-  // corresponding to the location of the relocation itself.
+  // If a given symbol name is nullptr, then the corresponding offset is
+  // relative from the location of the relocation itself.
+  // If a given symbol name is "", then the corresponding offset is relative to
+  // the start of the snapshot.
   struct Relocation {
     size_t size_in_bytes;
     intptr_t section_offset;
@@ -81,36 +87,18 @@
   void Finalize();
 
  private:
-  static constexpr const char* kBuildIdNoteName = ".note.gnu.build-id";
-
-  // Adds the section and also creates a PT_LOAD segment for the section if it
-  // is an allocated section.
-  //
-  // For allocated sections, if a symbol_name is provided, a symbol for the
-  // section will be added to the dynamic table (if allocated) and static
-  // table (if not stripped) during finalization.
-  void AddSection(Section* section,
-                  const char* name,
-                  const char* symbol_name = nullptr);
-
-  const Section* FindSectionBySymbolName(const char* symbol_name) const;
+  static constexpr const char kBuildIdNoteName[] = ".note.gnu.build-id";
+  static constexpr const char kTextName[] = ".text";
+  static constexpr const char kDataName[] = ".rodata";
+  static constexpr const char kBssName[] = ".bss";
+  static constexpr const char kDynamicTableName[] = ".dynamic";
 
   void CreateBSS();
   void GenerateBuildId();
-
-  void OrderSectionsAndCreateSegments();
-
-  void FinalizeSymbols();
+  void InitializeSymbolTables();
   void FinalizeDwarfSections();
-  void FinalizeProgramTable();
-  void ComputeOffsets();
-
   void FinalizeEhFrame();
-
-  void WriteHeader(ElfWriteStream* stream);
-  void WriteSectionTable(ElfWriteStream* stream);
-  void WriteProgramTable(ElfWriteStream* stream);
-  void WriteSections(ElfWriteStream* stream);
+  void ComputeOffsets();
 
   Zone* const zone_;
   BaseWriteStream* const unwrapped_stream_;
@@ -120,33 +108,18 @@
   // the static symbol table (and its corresponding string table).
   Dwarf* const dwarf_;
 
-  // All our strings would fit in a single page. However, we use separate
-  // .shstrtab and .dynstr to work around a bug in Android's strip utility.
-  StringTable* const shstrtab_;
-  StringTable* const dynstrtab_;
-  SymbolTable* const dynsym_;
+  // Contains all sections that will have entries in the section header table.
+  SectionTable* const section_table_;
+
+  // Contains all segments in the program header table. Set after finalizing
+  // the section table.
+  ProgramTable* program_table_ = nullptr;
 
   // The static tables are always created for use in relocation calculations,
   // even though they may not end up in the final ELF file.
-  StringTable* const strtab_;
-  SymbolTable* const symtab_;
+  SymbolTable* symtab_ = nullptr;
 
-  // We always create a BSS section for all Elf files to keep memory offsets
-  // consistent, though it is NOBITS for separate debugging information.
-  Section* bss_ = nullptr;
-
-  // We currently create a GNU build ID for all ELF snapshots and associated
-  // debugging information.
-  Section* build_id_ = nullptr;
-
-  GrowableArray<Section*> sections_;
-  GrowableArray<Segment*> segments_;
-
-  intptr_t memory_offset_;
-  intptr_t section_table_file_offset_ = -1;
-  intptr_t section_table_file_size_ = -1;
-  intptr_t program_table_file_offset_ = -1;
-  intptr_t program_table_file_size_ = -1;
+  friend class SectionTable;  // For section name static fields.
 };
 
 #endif  // DART_PRECOMPILER
diff --git a/runtime/vm/field_table.cc b/runtime/vm/field_table.cc
index 6809ff4..7e147c5 100644
--- a/runtime/vm/field_table.cc
+++ b/runtime/vm/field_table.cc
@@ -88,11 +88,6 @@
   free_head_ = field_id;
 }
 
-void FieldTable::SetAt(intptr_t index, ObjectPtr raw_instance) {
-  ASSERT(index < capacity_);
-  table_[index] = raw_instance;
-}
-
 void FieldTable::AllocateIndex(intptr_t index) {
   if (index >= capacity_) {
     const intptr_t new_capacity = index + kCapacityIncrement;
diff --git a/runtime/vm/field_table.h b/runtime/vm/field_table.h
index 84b3b5e..71c01ef 100644
--- a/runtime/vm/field_table.h
+++ b/runtime/vm/field_table.h
@@ -58,11 +58,33 @@
   // to an existing static field value.
   void Free(intptr_t index);
 
-  ObjectPtr At(intptr_t index) const {
+  ObjectPtr At(intptr_t index, bool concurrent_use = false) const {
     ASSERT(IsValidIndex(index));
-    return table_[index];
+    ObjectPtr* slot = &table_[index];
+    if (concurrent_use) {
+      return reinterpret_cast<AcqRelAtomic<ObjectPtr>*>(slot)->load();
+    } else {
+      // There is no concurrent access expected for this field, so we avoid
+      // using atomics. This will allow us to detect via TSAN if there are
+      // racy uses.
+      return *slot;
+    }
   }
-  void SetAt(intptr_t index, ObjectPtr raw_instance);
+
+  void SetAt(intptr_t index,
+             ObjectPtr raw_instance,
+             bool concurrent_use = false) {
+    ASSERT(index < capacity_);
+    ObjectPtr* slot = &table_[index];
+    if (concurrent_use) {
+      reinterpret_cast<AcqRelAtomic<ObjectPtr>*>(slot)->store(raw_instance);
+    } else {
+      // There is no concurrent access expected for this field, so we avoid
+      // using atomics. This will allow us to detect via TSAN if there are
+      // racy uses.
+      *slot = raw_instance;
+    }
+  }
 
   FieldTable* Clone(Isolate* for_isolate);
 
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 7e7a773..543b601 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -196,10 +196,6 @@
     "needed in the precompiled runtime.")                                      \
   P(enable_isolate_groups, bool, false,                                        \
     "Enable isolate group support in AOT.")                                    \
-  P(experimental_enable_isolate_groups_jit, bool, false,                       \
-    "As an experimental feature enable isolate group support in JIT"           \
-    "(goes into effect only when enable_isolate_groups is turned on as "       \
-    "well).")                                                                  \
   P(show_invisible_frames, bool, false,                                        \
     "Show invisible frames in stack traces.")                                  \
   D(trace_cha, bool, false, "Trace CHA operations")                            \
diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc
index d082e9dc..26ff8e2 100644
--- a/runtime/vm/flags.cc
+++ b/runtime/vm/flags.cc
@@ -473,7 +473,7 @@
   // graudally remove those restrictions.
 
 #if !defined(DART_PRCOMPILED_RUNTIME)
-  if (!FLAG_precompiled_mode && IsolateGroup::AreIsolateGroupsEnabled()) {
+  if (!FLAG_precompiled_mode && FLAG_enable_isolate_groups) {
     // Our compiler should not make rely on a global field being initialized at
     // compile-time, since that compiled code might be re-used in another
     // isolate that has not yet initialized the global field.
diff --git a/runtime/vm/handles.h b/runtime/vm/handles.h
index ca6b5f4..ed4e9db 100644
--- a/runtime/vm/handles.h
+++ b/runtime/vm/handles.h
@@ -100,6 +100,13 @@
     return scoped_blocks_->AllocateHandle();
   }
 
+  bool IsEmpty() const {
+    if (zone_blocks_ != nullptr) return false;
+    if (first_scoped_block_.HandleCount() != 0) return false;
+    if (scoped_blocks_ != &first_scoped_block_) return false;
+    return true;
+  }
+
  protected:
   // Returns a count of active handles (used for testing purposes).
   int CountScopedHandles() const;
diff --git a/runtime/vm/hash_map.h b/runtime/vm/hash_map.h
index 3273f4c..ec5ea08 100644
--- a/runtime/vm/hash_map.h
+++ b/runtime/vm/hash_map.h
@@ -631,7 +631,7 @@
     DirectChainedHashMap<IntKeyRawPointerValueTrait<V> >::Insert(pair);
   }
 
-  inline V Lookup(const Key& key) {
+  inline V Lookup(const Key& key) const {
     Pair* pair =
         DirectChainedHashMap<IntKeyRawPointerValueTrait<V> >::Lookup(key);
     if (pair == NULL) {
@@ -641,7 +641,7 @@
     }
   }
 
-  inline Pair* LookupPair(const Key& key) {
+  inline Pair* LookupPair(const Key& key) const {
     return DirectChainedHashMap<IntKeyRawPointerValueTrait<V> >::Lookup(key);
   }
 
diff --git a/runtime/vm/hash_table.h b/runtime/vm/hash_table.h
index 06fbd70..318dbf4 100644
--- a/runtime/vm/hash_table.h
+++ b/runtime/vm/hash_table.h
@@ -33,6 +33,24 @@
   static bool IsImmutable(const ArrayHandle& handle) {
     return handle.ptr()->untag()->InVMIsolateHeap();
   }
+
+  static ObjectPtr At(ArrayHandle* array, intptr_t index) {
+    return array->At(index);
+  }
+
+  static void SetAt(ArrayHandle* array, intptr_t index, const Object& value) {
+    array->SetAt(index, value);
+  }
+};
+
+struct AcqRelStorageTraits : ArrayStorageTraits {
+  static ObjectPtr At(ArrayHandle* array, intptr_t index) {
+    return array->AtAcquire(index);
+  }
+
+  static void SetAt(ArrayHandle* array, intptr_t index, const Object& value) {
+    array->SetAtRelease(index, value);
+  }
 };
 
 class HashTableBase : public ValueObject {
@@ -162,19 +180,19 @@
   void Initialize() const {
     ASSERT(data_->Length() >= ArrayLengthForNumOccupied(0));
     *smi_handle_ = Smi::New(0);
-    data_->SetAt(kOccupiedEntriesIndex, *smi_handle_);
-    data_->SetAt(kDeletedEntriesIndex, *smi_handle_);
+    StorageTraits::SetAt(data_, kOccupiedEntriesIndex, *smi_handle_);
+    StorageTraits::SetAt(data_, kDeletedEntriesIndex, *smi_handle_);
 
 #if !defined(PRODUCT)
-    data_->SetAt(kNumGrowsIndex, *smi_handle_);
-    data_->SetAt(kNumLT5LookupsIndex, *smi_handle_);
-    data_->SetAt(kNumLT25LookupsIndex, *smi_handle_);
-    data_->SetAt(kNumGT25LookupsIndex, *smi_handle_);
-    data_->SetAt(kNumProbesIndex, *smi_handle_);
+    StorageTraits::SetAt(data_, kNumGrowsIndex, *smi_handle_);
+    StorageTraits::SetAt(data_, kNumLT5LookupsIndex, *smi_handle_);
+    StorageTraits::SetAt(data_, kNumLT25LookupsIndex, *smi_handle_);
+    StorageTraits::SetAt(data_, kNumGT25LookupsIndex, *smi_handle_);
+    StorageTraits::SetAt(data_, kNumProbesIndex, *smi_handle_);
 #endif  // !defined(PRODUCT)
 
     for (intptr_t i = kHeaderSize; i < data_->Length(); ++i) {
-      data_->SetAt(i, UnusedMarker());
+      StorageTraits::SetAt(data_, i, UnusedMarker());
     }
   }
 
@@ -298,14 +316,14 @@
   ObjectPtr GetPayload(intptr_t entry, intptr_t component) const {
     ASSERT(IsOccupied(entry));
     return WeakSerializationReference::Unwrap(
-        data_->At(PayloadIndex(entry, component)));
+        StorageTraits::At(data_, PayloadIndex(entry, component)));
   }
   void UpdatePayload(intptr_t entry,
                      intptr_t component,
                      const Object& value) const {
     ASSERT(IsOccupied(entry));
     ASSERT(0 <= component && component < kPayloadSize);
-    data_->SetAt(PayloadIndex(entry, component), value);
+    StorageTraits::SetAt(data_, PayloadIndex(entry, component), value);
   }
   // Deletes both the key and payload of the specified entry.
   void DeleteEntry(intptr_t entry) const {
@@ -411,22 +429,23 @@
   }
 
   ObjectPtr InternalGetKey(intptr_t entry) const {
-    return WeakSerializationReference::Unwrap(data_->At(KeyIndex(entry)));
+    return WeakSerializationReference::Unwrap(
+        StorageTraits::At(data_, KeyIndex(entry)));
   }
 
   void InternalSetKey(intptr_t entry, const Object& key) const {
-    data_->SetAt(KeyIndex(entry), key);
+    StorageTraits::SetAt(data_, KeyIndex(entry), key);
   }
 
   intptr_t GetSmiValueAt(intptr_t index) const {
     ASSERT(!data_->IsNull());
-    ASSERT(!data_->At(index)->IsHeapObject());
-    return Smi::Value(Smi::RawCast(data_->At(index)));
+    ASSERT(!StorageTraits::At(data_, index)->IsHeapObject());
+    return Smi::Value(Smi::RawCast(StorageTraits::At(data_, index)));
   }
 
   void SetSmiValueAt(intptr_t index, intptr_t value) const {
     *smi_handle_ = Smi::New(value);
-    data_->SetAt(index, *smi_handle_);
+    StorageTraits::SetAt(data_, index, *smi_handle_);
   }
 
   void AdjustSmiValueAt(intptr_t index, intptr_t delta) const {
@@ -450,10 +469,13 @@
 };
 
 // Table with unspecified iteration order. No payload overhead or metadata.
-template <typename KeyTraits, intptr_t kUserPayloadSize>
-class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> {
+template <typename KeyTraits,
+          intptr_t kUserPayloadSize,
+          typename StorageTraits = ArrayStorageTraits>
+class UnorderedHashTable
+    : public HashTable<KeyTraits, kUserPayloadSize, 0, StorageTraits> {
  public:
-  typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable;
+  typedef HashTable<KeyTraits, kUserPayloadSize, 0, StorageTraits> BaseTable;
   static const intptr_t kPayloadSize = kUserPayloadSize;
   explicit UnorderedHashTable(ArrayPtr data)
       : BaseTable(Thread::Current()->zone(), data) {}
@@ -776,10 +798,13 @@
   }
 };
 
-template <typename KeyTraits>
-class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > {
+template <typename KeyTraits, typename TableStorageTraits = ArrayStorageTraits>
+class UnorderedHashSet
+    : public HashSet<UnorderedHashTable<KeyTraits, 0, TableStorageTraits>> {
+  using UnderlyingTable = UnorderedHashTable<KeyTraits, 0, TableStorageTraits>;
+
  public:
-  typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet;
+  typedef HashSet<UnderlyingTable> BaseSet;
   explicit UnorderedHashSet(ArrayPtr data)
       : BaseSet(Thread::Current()->zone(), data) {
     ASSERT(data != Array::null());
@@ -791,7 +816,8 @@
   void Dump() const {
     Object& entry = Object::Handle();
     for (intptr_t i = 0; i < this->data_->Length(); i++) {
-      entry = WeakSerializationReference::Unwrap(this->data_->At(i));
+      entry = WeakSerializationReference::Unwrap(
+          TableStorageTraits::At(this->data_, i));
       if (entry.ptr() == BaseSet::UnusedMarker().ptr() ||
           entry.ptr() == BaseSet::DeletedMarker().ptr() || entry.IsSmi()) {
         // empty, deleted, num_used/num_deleted
diff --git a/runtime/vm/heap/heap_test.cc b/runtime/vm/heap/heap_test.cc
index ee48775..e1f9c82 100644
--- a/runtime/vm/heap/heap_test.cc
+++ b/runtime/vm/heap/heap_test.cc
@@ -16,6 +16,7 @@
 #include "vm/heap/become.h"
 #include "vm/heap/heap.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/object_graph.h"
 #include "vm/port.h"
 #include "vm/symbols.h"
@@ -544,8 +545,7 @@
       isolate()->group()->api_state()->FreePersistentHandle(handle);
     } else {
       Thread* thread = Thread::Current();
-      MessageSnapshotReader reader(message.get(), thread);
-      response_obj = reader.ReadObject();
+      response_obj = ReadMessage(thread, message.get());
     }
     if (response_obj.IsString()) {
       String& response = String::Handle();
@@ -575,7 +575,7 @@
 
 VM_UNIT_TEST_CASE(CleanupBequestNeverReceived) {
   // This test uses features from isolate groups
-  IsolateGroup::ForceEnableIsolateGroupsForTesting();
+  FLAG_enable_isolate_groups = true;
 
   const char* TEST_MESSAGE = "hello, world";
   Dart_Isolate parent = TestCase::CreateTestIsolate("parent");
@@ -610,7 +610,7 @@
 
 VM_UNIT_TEST_CASE(ReceivesSendAndExitMessage) {
   // This test uses features from isolate groups
-  IsolateGroup::ForceEnableIsolateGroupsForTesting();
+  FLAG_enable_isolate_groups = true;
 
   const char* TEST_MESSAGE = "hello, world";
   Dart_Isolate parent = TestCase::CreateTestIsolate("parent");
diff --git a/runtime/vm/heap/safepoint.cc b/runtime/vm/heap/safepoint.cc
index 4a7e5de..52da48b 100644
--- a/runtime/vm/heap/safepoint.cc
+++ b/runtime/vm/heap/safepoint.cc
@@ -155,7 +155,7 @@
       if (!Thread::IsAtSafepoint(level_, state)) {
         // Send OOB message to get it to safepoint.
         if (current->IsMutatorThread()) {
-          current->ScheduleInterruptsLocked(Thread::kVMInterrupt);
+          current->ScheduleInterrupts(Thread::kVMInterrupt);
         }
         MonitorLocker sl(&parked_lock_);
         num_threads_not_parked_++;
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index ed36fe1..810a26e 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -12,6 +12,7 @@
 #include "vm/flags.h"
 #include "vm/globals.h"
 #include "vm/heap/spaces.h"
+#include "vm/isolate.h"
 #include "vm/lockers.h"
 #include "vm/raw_object.h"
 #include "vm/ring_buffer.h"
diff --git a/runtime/vm/heap/verifier.cc b/runtime/vm/heap/verifier.cc
index abeb1cc..15b26f5 100644
--- a/runtime/vm/heap/verifier.cc
+++ b/runtime/vm/heap/verifier.cc
@@ -117,23 +117,16 @@
   // Therefore we disable the handle verification here.
   const bool old_verify_flag = FLAG_verify_handles;
   FLAG_verify_handles = false;
-
-  // TODO(dartbug.com/36097): The heap walk can encounter canonical objects of
-  // other isolates. We should either scan live objects from the roots of each
-  // individual isolate, or wait until we are ready to share constants across
-  // isolates.
-  if (!IsolateGroup::AreIsolateGroupsEnabled() || FLAG_precompiled_mode) {
-    if ((obj->GetClassId() >= kInstanceCid) &&
-        (obj->GetClassId() != kTypeArgumentsCid)) {
-      if (obj->untag()->IsCanonical()) {
-        instanceHandle_ ^= obj;
-        const bool is_canonical = instanceHandle_.CheckIsCanonical(thread_);
-        if (!is_canonical) {
-          OS::PrintErr("Instance `%s` is not canonical!\n",
-                       instanceHandle_.ToCString());
-        }
-        ASSERT(is_canonical);
+  if ((obj->GetClassId() >= kInstanceCid) &&
+      (obj->GetClassId() != kTypeArgumentsCid)) {
+    if (obj->untag()->IsCanonical()) {
+      instanceHandle_ ^= obj;
+      const bool is_canonical = instanceHandle_.CheckIsCanonical(thread_);
+      if (!is_canonical) {
+        OS::PrintErr("Instance `%s` is not canonical!\n",
+                     instanceHandle_.ToCString());
       }
+      ASSERT(is_canonical);
     }
   }
   FLAG_verify_handles = old_verify_flag;
diff --git a/runtime/vm/heap/weak_table.cc b/runtime/vm/heap/weak_table.cc
index 4070590..36c903004 100644
--- a/runtime/vm/heap/weak_table.cc
+++ b/runtime/vm/heap/weak_table.cc
@@ -30,7 +30,7 @@
 }
 
 void WeakTable::SetValueExclusive(ObjectPtr key, intptr_t val) {
-  intptr_t mask = size() - 1;
+  const intptr_t mask = size() - 1;
   intptr_t idx = Hash(key) & mask;
   intptr_t empty_idx = -1;
   ObjectPtr obj = ObjectAtExclusive(idx);
@@ -74,6 +74,46 @@
   }
 }
 
+bool WeakTable::MarkValueExclusive(ObjectPtr key, intptr_t val) {
+  const intptr_t mask = size() - 1;
+  intptr_t idx = Hash(key) & mask;
+  intptr_t empty_idx = -1;
+  ObjectPtr obj = ObjectAtExclusive(idx);
+
+  while (obj != static_cast<ObjectPtr>(kNoEntry)) {
+    if (obj == key) {
+      return false;
+    } else if ((empty_idx < 0) &&
+               (static_cast<intptr_t>(obj) == kDeletedEntry)) {
+      empty_idx = idx;  // Insert at this location if not found.
+    }
+    idx = (idx + 1) & mask;
+    obj = ObjectAtExclusive(idx);
+  }
+
+  ASSERT(val != 0);
+
+  if (empty_idx >= 0) {
+    // We will be reusing a slot below.
+    set_used(used() - 1);
+    idx = empty_idx;
+  }
+
+  ASSERT(!IsValidEntryAtExclusive(idx));
+  // Set the key and value.
+  SetObjectAt(idx, key);
+  SetValueAt(idx, val);
+  // Update the counts.
+  set_used(used() + 1);
+  set_count(count() + 1);
+
+  // Rehash if needed to ensure that there are empty slots available.
+  if (used_ >= limit()) {
+    Rehash();
+  }
+  return true;
+}
+
 void WeakTable::Reset() {
   intptr_t* old_data = data_;
   used_ = 0;
diff --git a/runtime/vm/heap/weak_table.h b/runtime/vm/heap/weak_table.h
index 3062b53..ade129d 100644
--- a/runtime/vm/heap/weak_table.h
+++ b/runtime/vm/heap/weak_table.h
@@ -104,6 +104,7 @@
   }
 
   void SetValueExclusive(ObjectPtr key, intptr_t val);
+  bool MarkValueExclusive(ObjectPtr key, intptr_t val);
 
   intptr_t GetValueExclusive(ObjectPtr key) const {
     intptr_t mask = size() - 1;
@@ -203,7 +204,9 @@
 
   void Rehash();
 
-  static uword Hash(ObjectPtr key) { return static_cast<uword>(key) * 92821; }
+  static uword Hash(ObjectPtr key) {
+    return (static_cast<uword>(key) * 92821) ^ (static_cast<uword>(key) >> 8);
+  }
 
   Mutex mutex_;
 
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index bee78c8..587267c 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -613,7 +613,6 @@
       FLAG_precompiled_mode && FLAG_use_bare_instructions;
 
   // Start snapshot at page boundary.
-  ASSERT(ImageWriter::kTextAlignment >= VirtualMemory::PageSize());
   if (!EnterSection(ProgramSection::Text, vm, ImageWriter::kTextAlignment)) {
     return;
   }
@@ -693,7 +692,7 @@
     // 2) The BSS offset from this section.
     text_offset += Relocation(text_offset, instructions_symbol, bss_symbol);
     // 3) The relocated address of the instructions.
-    text_offset += Relocation(text_offset, instructions_symbol);
+    text_offset += RelocatedAddress(text_offset, instructions_symbol);
     // 4) The GNU build ID note offset from this section.
     text_offset += Relocation(text_offset, instructions_symbol,
                               SectionSymbol(ProgramSection::BuildId, vm));
@@ -1222,10 +1221,7 @@
                                          intptr_t source_offset,
                                          const char* target_symbol,
                                          intptr_t target_offset) {
-  if (source_symbol == nullptr || target_symbol == nullptr) {
-    // We can't use absolute addresses in assembly relocations.
-    return WriteTargetWord(Image::kNoRelocatedAddress);
-  }
+  ASSERT(source_symbol != nullptr);
   ASSERT(target_symbol != nullptr);
 
   // TODO(dartbug.com/43274): Remove once we generate consistent build IDs
@@ -1238,23 +1234,24 @@
 
   // All relocations are word-sized.
   assembly_stream_->Printf("%s ", kWordDirective);
-  if (strcmp(target_symbol, current_section_symbol_) == 0 &&
-      target_offset == section_offset) {
+  if (strcmp(target_symbol, current_section_symbol_) == 0) {
     assembly_stream_->WriteString("(.)");
+    target_offset -= section_offset;
   } else {
     assembly_stream_->Printf("%s", target_symbol);
-    if (target_offset != 0) {
-      assembly_stream_->Printf(" + %" Pd "", target_offset);
-    }
   }
-  if (strcmp(source_symbol, current_section_symbol_) == 0 &&
-      source_offset == section_offset) {
+  if (target_offset != 0) {
+    assembly_stream_->Printf(" + %" Pd "", target_offset);
+  }
+
+  if (strcmp(source_symbol, current_section_symbol_) == 0) {
     assembly_stream_->WriteString(" - (.)");
+    source_offset -= section_offset;
   } else {
     assembly_stream_->Printf(" - %s", source_symbol);
-    if (source_offset != 0) {
-      assembly_stream_->Printf(" - %" Pd "", source_offset);
-    }
+  }
+  if (source_offset != 0) {
+    assembly_stream_->Printf(" - %" Pd "", source_offset);
   }
   assembly_stream_->WriteString("\n");
   return compiler::target::kWordSize;
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 3b2ed09..fc2bbdd 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -241,15 +241,8 @@
   // ROData sections contain objects wrapped in an Image object.
   static constexpr intptr_t kRODataAlignment = kMaxObjectAlignment;
   // Text sections contain objects (even in bare instructions mode) wrapped
-  // in an Image object, and for now we also align them to the same page
-  // size assumed by Elf objects.
-  static constexpr intptr_t kTextAlignment = 16 * KB;
-#if defined(DART_PRECOMPILER)
-  static_assert(kTextAlignment == Elf::kPageSize,
-                "Page alignment must be consistent with max object alignment");
-  static_assert(Elf::kPageSize >= kMaxObjectAlignment,
-                "Page alignment must be consistent with max object alignment");
-#endif
+  // in an Image object.
+  static constexpr intptr_t kTextAlignment = kMaxObjectAlignment;
 
   void ResetOffsets() {
     next_data_offset_ = Image::kHeaderSize;
@@ -404,13 +397,15 @@
   // relocated address of the target section and S is the final relocated
   // address of the source, the final value is:
   //   (T + target_offset + target_addend) - (S + source_offset)
-  // If either symbol is nullptr, then the corresponding is treated as an
-  // absolute address.
   virtual intptr_t Relocation(intptr_t section_offset,
                               const char* source_symbol,
                               intptr_t source_offset,
                               const char* target_symbol,
                               intptr_t target_offset) = 0;
+  // Writes a target word-sized value that contains the relocated address
+  // pointed to by the given symbol.
+  virtual intptr_t RelocatedAddress(intptr_t section_offset,
+                                    const char* symbol) = 0;
   // Creates a static symbol for the given Code object when appropriate.
   virtual void AddCodeSymbol(const Code& code,
                              const char* symbol,
@@ -425,11 +420,6 @@
                       const char* target_symbol) {
     return Relocation(section_offset, source_symbol, 0, target_symbol, 0);
   }
-  // An overload of Relocation for outputting the relocated address of the
-  // target symbol at the given section offset.
-  intptr_t Relocation(intptr_t section_offset, const char* target_symbol) {
-    return Relocation(section_offset, nullptr, 0, target_symbol, 0);
-  }
 #endif
   // Writes a fixed-sized value of type T to the section contents.
   template <typename T>
@@ -556,6 +546,11 @@
                               intptr_t source_offset,
                               const char* target_symbol,
                               intptr_t target_offset);
+  virtual intptr_t RelocatedAddress(intptr_t section_offset,
+                                    const char* symbol) {
+    // Cannot calculate snapshot-relative addresses in assembly snapshots.
+    return WriteTargetWord(Image::kNoRelocatedAddress);
+  }
   virtual void FrameUnwindPrologue();
   virtual void FrameUnwindEpilogue();
   virtual void AddCodeSymbol(const Code& code,
@@ -606,6 +601,11 @@
                               intptr_t source_offset,
                               const char* target_symbol,
                               intptr_t target_offset);
+  virtual intptr_t RelocatedAddress(intptr_t section_offset,
+                                    const char* target_symbol) {
+    // ELF symbol tables always have a reserved symbol with name "" and value 0.
+    return ImageWriter::Relocation(section_offset, "", target_symbol);
+  }
   virtual void AddCodeSymbol(const Code& code,
                              const char* symbol,
                              intptr_t offset);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index cb00d29..b1a7315 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -31,6 +31,7 @@
 #include "vm/lockers.h"
 #include "vm/log.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/object.h"
 #include "vm/object_id_ring.h"
 #include "vm/object_store.h"
@@ -123,18 +124,14 @@
 
 static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
                                                  const Instance& obj) {
-  if (ApiObjectConverter::CanConvert(obj.ptr())) {
-    return Message::New(dest_port, obj.ptr(), Message::kNormalPriority);
-  } else {
-    MessageWriter writer(false);
-    return writer.WriteMessage(obj, dest_port, Message::kNormalPriority);
-  }
+  return WriteMessage(/* can_send_any_object */ false, obj, dest_port,
+                      Message::kNormalPriority);
 }
 
-static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
+static std::unique_ptr<Message> SerializeMessage(Zone* zone,
+                                                 Dart_Port dest_port,
                                                  Dart_CObject* obj) {
-  ApiMessageWriter writer;
-  return writer.WriteCMessage(obj, dest_port, Message::kNormalPriority);
+  return WriteApiMessage(zone, obj, dest_port, Message::kNormalPriority);
 }
 
 void IsolateGroupSource::add_loaded_blob(
@@ -359,7 +356,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
       background_compiler_(new BackgroundCompiler(this)),
 #endif
-      symbols_lock_(new SafepointRwLock()),
+      symbols_mutex_(NOT_IN_PRODUCT("IsolateGroup::symbols_mutex_")),
       type_canonicalization_mutex_(
           NOT_IN_PRODUCT("IsolateGroup::type_canonicalization_mutex_")),
       type_arguments_canonicalization_mutex_(NOT_IN_PRODUCT(
@@ -785,8 +782,6 @@
   JSONObject jsobj(stream);
   // This is the same "MemoryUsage" that the isolate-specific "getMemoryUsage"
   // rpc method returns.
-  // TODO(dartbug.com/36097): Once the heap moves from Isolate to IsolateGroup
-  // this code needs to be adjusted to not double-count memory.
   jsobj.AddProperty("type", "MemoryUsage");
   jsobj.AddProperty64("heapUsage", used * kWordSize);
   jsobj.AddProperty64("heapCapacity", capacity * kWordSize);
@@ -867,19 +862,6 @@
   return Isolate::IsSystemIsolate(isolate);
 }
 
-NoOOBMessageScope::NoOOBMessageScope(Thread* thread)
-    : ThreadStackResource(thread) {
-  if (thread->isolate() != nullptr) {
-    thread->DeferOOBMessageInterrupts();
-  }
-}
-
-NoOOBMessageScope::~NoOOBMessageScope() {
-  if (thread()->isolate() != nullptr) {
-    thread()->RestoreOOBMessageInterrupts();
-  }
-}
-
 Bequest::~Bequest() {
   if (handle_ == nullptr) {
     return;
@@ -1006,6 +988,8 @@
   NoBackgroundCompilerScope no_bg_compiler(Thread::Current());
   heap()->CollectAllGarbage();
   Thread* thread = Thread::Current();
+  SafepointMutexLocker ml(
+      thread->isolate_group()->constant_canonicalization_mutex());
   HeapIterationScope iteration(thread);
   VerifyCanonicalVisitor check_canonical(thread);
   iteration.IterateObjects(&check_canonical);
@@ -1023,9 +1007,8 @@
   element = Capability::New(capability);
   msg.SetAt(2, element);
 
-  MessageWriter writer(false);
-  PortMap::PostMessage(
-      writer.WriteMessage(msg, main_port(), Message::kOOBPriority));
+  PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, msg,
+                                    main_port(), Message::kOOBPriority));
 }
 
 void IsolateGroup::set_object_store(ObjectStore* object_store) {
@@ -1345,11 +1328,7 @@
 
   // Parse the message.
   Object& msg_obj = Object::Handle(zone);
-  if (message->IsRaw()) {
-    msg_obj = message->raw_obj();
-    // We should only be sending RawObjects that can be converted to CObjects.
-    ASSERT(ApiObjectConverter::CanConvert(msg_obj.ptr()));
-  } else if (message->IsPersistentHandle()) {
+  if (message->IsPersistentHandle()) {
     // msg_array = [<message>, <object-in-message-to-rehash>]
     const auto& msg_array = Array::Handle(
         zone, Array::RawCast(message->persistent_handle()->ptr()));
@@ -1363,8 +1342,7 @@
       }
     }
   } else {
-    MessageSnapshotReader reader(message.get(), thread);
-    msg_obj = reader.ReadObject();
+    msg_obj = ReadMessage(thread, message.get());
   }
   if (msg_obj.IsError()) {
     // An error occurred while reading the message.
@@ -2375,7 +2353,7 @@
     listener ^= listeners.At(i);
     if (!listener.IsNull()) {
       Dart_Port port_id = listener.Id();
-      PortMap::PostMessage(SerializeMessage(port_id, &arr));
+      PortMap::PostMessage(SerializeMessage(current_zone(), port_id, &arr));
     }
   }
   return listeners.Length() > 0;
@@ -2398,6 +2376,25 @@
                          reinterpret_cast<uword>(this));
 }
 
+#if !defined(PRODUCT)
+void Isolate::set_current_sample_block(SampleBlock* current) {
+  ASSERT(current_sample_block_lock_.IsOwnedByCurrentThread());
+  if (current != nullptr) {
+    current->set_is_allocation_block(false);
+    current->set_owner(this);
+  }
+  current_sample_block_ = current;
+}
+
+void Isolate::set_current_allocation_sample_block(SampleBlock* current) {
+  if (current != nullptr) {
+    current->set_is_allocation_block(true);
+    current->set_owner(this);
+  }
+  current_allocation_sample_block_ = current;
+}
+#endif  // !defined(PRODUCT)
+
 // static
 void Isolate::NotifyLowMemory() {
   Isolate::KillAllIsolates(Isolate::kLowMemoryMsg);
@@ -2531,11 +2528,12 @@
 }
 
 void Isolate::LowLevelCleanup(Isolate* isolate) {
-#if !defined(DART_PECOMPILED_RUNTIME)
+#if !defined(DART_PRECOMPILED_RUNTIME)
   if (KernelIsolate::IsKernelIsolate(isolate)) {
     KernelIsolate::SetKernelIsolate(nullptr);
+  }
 #endif
-  } else if (ServiceIsolate::IsServiceIsolate(isolate)) {
+  if (ServiceIsolate::IsServiceIsolate(isolate)) {
     ServiceIsolate::SetServiceIsolate(nullptr);
   }
 
@@ -2553,6 +2551,26 @@
   // requests anymore.
   Thread::ExitIsolate();
 
+#if !defined(PRODUCT)
+  // Cleanup profiler state.
+  SampleBlock* cpu_block = isolate->current_sample_block();
+  if (cpu_block != nullptr) {
+    cpu_block->release_block();
+  }
+  SampleBlock* allocation_block = isolate->current_allocation_sample_block();
+  if (allocation_block != nullptr) {
+    allocation_block->release_block();
+  }
+
+  // Process the previously assigned sample blocks if we're using the
+  // profiler's sample buffer. Some tests create their own SampleBlockBuffer
+  // and handle block processing themselves.
+  if ((cpu_block != nullptr || allocation_block != nullptr) &&
+      Profiler::sample_block_buffer() != nullptr) {
+    Profiler::sample_block_buffer()->ProcessCompletedBlocks();
+  }
+#endif  // !defined(PRODUCT)
+
   // Now it's safe to delete the isolate.
   delete isolate;
 
@@ -2600,7 +2618,7 @@
       Dart::thread_pool()->Run<ShutdownGroupTask>(isolate_group);
     }
   } else {
-    if (IsolateGroup::AreIsolateGroupsEnabled()) {
+    if (FLAG_enable_isolate_groups) {
       // TODO(dartbug.com/36097): An isolate just died. A significant amount of
       // memory might have become unreachable. We should evaluate how to best
       // inform the GC about this situation.
@@ -2773,7 +2791,7 @@
   auto thread = Thread::Current();
   StoppedMutatorsScope stopped_mutators_scope(thread);
 
-  if (thread->IsMutatorThread() && !IsolateGroup::AreIsolateGroupsEnabled()) {
+  if (thread->IsMutatorThread() && !FLAG_enable_isolate_groups) {
     single_current_mutator->Call();
     return;
   }
@@ -3272,9 +3290,9 @@
     msg.SetAt(1, element);
     element = Smi::New(Isolate::kBeforeNextEventAction);
     msg.SetAt(2, element);
-    MessageWriter writer(false);
-    std::unique_ptr<Message> message =
-        writer.WriteMessage(msg, main_port(), Message::kOOBPriority);
+    std::unique_ptr<Message> message = WriteMessage(
+        /* can_send_any_object */ false, msg, main_port(),
+        Message::kOOBPriority);
     bool posted = PortMap::PostMessage(std::move(message));
     ASSERT(posted);
   }
@@ -3518,9 +3536,9 @@
   list_values[3] = &imm;
 
   {
-    ApiMessageWriter writer;
-    std::unique_ptr<Message> message =
-        writer.WriteCMessage(&kill_msg, main_port(), Message::kOOBPriority);
+    AllocOnlyStackZone zone;
+    std::unique_ptr<Message> message = WriteApiMessage(
+        zone.GetZone(), &kill_msg, main_port(), Message::kOOBPriority);
     ASSERT(message != nullptr);
 
     // Post the message at the given port.
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index c17a81d..d7c8e5d 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -74,6 +74,8 @@
 class SafepointRwLock;
 class SafepointHandler;
 class SampleBuffer;
+class SampleBlock;
+class SampleBlockBuffer;
 class SendPort;
 class SerializedObjectBuffer;
 class ServiceIdZone;
@@ -134,16 +136,6 @@
   DISALLOW_COPY_AND_ASSIGN(LambdaCallable);
 };
 
-// Disallow OOB message handling within this scope.
-class NoOOBMessageScope : public ThreadStackResource {
- public:
-  explicit NoOOBMessageScope(Thread* thread);
-  ~NoOOBMessageScope();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NoOOBMessageScope);
-};
-
 // Fixed cache for exception handler lookup.
 typedef FixedCache<intptr_t, ExceptionHandlerInfo, 16> HandlerInfoCache;
 // Fixed cache for catch entry state lookup.
@@ -182,21 +174,8 @@
   V(PRODUCT, null_safety, NullSafety, null_safety, false)
 
 // Represents the information used for spawning the first isolate within an
-// isolate group.
-//
-// Any subsequent isolates created via `Isolate.spawn()` will be created using
-// the same [IsolateGroupSource] (the object itself is shared among all isolates
-// within the same group).
-//
-// Issue(http://dartbug.com/36097): It is still possible to run into issues if
-// an isolate has spawned another one and then loads more code into the first
-// one, which the latter will not get. Though it makes the status quo better
-// than what we had before (where the embedder needed to maintain the
-// same-source guarantee).
-//
-// => This is only the first step towards having multiple isolates share the
-//    same heap (and therefore the same program structure).
-//
+// isolate group. All isolates within a group will refer to this
+// [IsolateGroupSource].
 class IsolateGroupSource {
  public:
   IsolateGroupSource(const char* script_uri,
@@ -239,11 +218,6 @@
   const uint8_t* script_kernel_buffer;
   intptr_t script_kernel_size;
 
-  // During AppJit training we perform a permutation of the class ids before
-  // invoking the "main" script.
-  // Any newly spawned isolates need to use this permutation map.
-  std::unique_ptr<intptr_t[]> cid_permutation_map;
-
   // List of weak pointers to external typed data for loaded blobs.
   ArrayPtr loaded_blobs_;
   intptr_t num_blob_loads_;
@@ -534,7 +508,7 @@
   StoreBuffer* store_buffer() const { return store_buffer_.get(); }
   ClassTable* class_table() const { return class_table_.get(); }
   ObjectStore* object_store() const { return object_store_.get(); }
-  SafepointRwLock* symbols_lock() { return symbols_lock_.get(); }
+  Mutex* symbols_mutex() { return &symbols_mutex_; }
   Mutex* type_canonicalization_mutex() { return &type_canonicalization_mutex_; }
   Mutex* type_arguments_canonicalization_mutex() {
     return &type_arguments_canonicalization_mutex_;
@@ -789,20 +763,6 @@
   void RegisterStaticField(const Field& field, const Object& initial_value);
   void FreeStaticField(const Field& field);
 
-  static bool AreIsolateGroupsEnabled() {
-#if defined(DART_PRECOMPILED_RUNTIME)
-    return FLAG_enable_isolate_groups;
-#else
-    return FLAG_enable_isolate_groups &&
-           FLAG_experimental_enable_isolate_groups_jit;
-#endif
-  }
-
-  static void ForceEnableIsolateGroupsForTesting() {
-    FLAG_enable_isolate_groups = true;
-    FLAG_experimental_enable_isolate_groups_jit = true;
-  }
-
  private:
   friend class Dart;  // For `object_store_ = ` in Dart::Init
   friend class Heap;
@@ -908,7 +868,7 @@
 
   NOT_IN_PRECOMPILED(std::unique_ptr<BackgroundCompiler> background_compiler_);
 
-  std::unique_ptr<SafepointRwLock> symbols_lock_;
+  Mutex symbols_mutex_;
   Mutex type_canonicalization_mutex_;
   Mutex type_arguments_canonicalization_mutex_;
   Mutex subtype_test_cache_mutex_;
@@ -1126,6 +1086,27 @@
 #if !defined(PRODUCT)
   Debugger* debugger() const { return debugger_; }
 
+  // NOTE: this lock should only be acquired within the profiler signal handler.
+  Mutex* current_sample_block_lock() const {
+    return const_cast<Mutex*>(&current_sample_block_lock_);
+  }
+
+  // Returns the current SampleBlock used to track CPU profiling samples.
+  //
+  // NOTE: current_sample_block_lock() should be held when accessing this
+  // block.
+  SampleBlock* current_sample_block() const { return current_sample_block_; }
+  void set_current_sample_block(SampleBlock* current);
+
+  // Returns the current SampleBlock used to track Dart allocation samples.
+  //
+  // Allocations should only occur on the mutator thread for an isolate, so we
+  // don't need to worry about grabbing a lock while accessing this block.
+  SampleBlock* current_allocation_sample_block() const {
+    return current_allocation_sample_block_;
+  }
+  void set_current_allocation_sample_block(SampleBlock* current);
+
   void set_single_step(bool value) { single_step_ = value; }
   bool single_step() const { return single_step_; }
   static intptr_t single_step_offset() {
@@ -1570,6 +1551,21 @@
 // the top.
 #if !defined(PRODUCT)
   Debugger* debugger_ = nullptr;
+
+  // SampleBlock containing CPU profiling samples.
+  //
+  // Can be accessed by multiple threads, so current_sample_block_lock_ should
+  // be acquired before accessing.
+  SampleBlock* current_sample_block_ = nullptr;
+  Mutex current_sample_block_lock_;
+
+  // SampleBlock containing Dart allocation profiling samples.
+  //
+  // Allocations should only occur on the mutator thread for an isolate, so we
+  // shouldn't need to worry about grabbing a lock for the allocation sample
+  // block.
+  SampleBlock* current_allocation_sample_block_ = nullptr;
+
   int64_t last_resume_timestamp_;
 
   VMTagCounters vm_tag_counters_;
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 5be85a1..182c090 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -95,12 +95,6 @@
   return heap->old_space()->tasks() == 0;
 }
 
-// TODO(dartbug.com/36097): Once classes are split up into a read-only
-// descriptor which can be shared across isolates, we can make this function
-// take descriptors instead of the isolate-specific [Class] objects.
-//
-// (The information we access from [from]/[to] *must* be the same across
-// isolates.)
 InstanceMorpher* InstanceMorpher::CreateFromClassDescriptors(
     Zone* zone,
     SharedClassTable* shared_class_table,
@@ -1867,9 +1861,13 @@
       saved_class_table_.load(std::memory_order_relaxed);
   ClassPtr* local_saved_tlc_class_table =
       saved_tlc_class_table_.load(std::memory_order_relaxed);
-  IG->class_table()->ResetAfterHotReload(
-      local_saved_class_table, local_saved_tlc_class_table, saved_num_cids_,
-      saved_num_tlc_cids_, is_rollback);
+  {
+    auto thread = Thread::Current();
+    SafepointWriteRwLocker sl(thread, thread->isolate_group()->program_lock());
+    IG->class_table()->ResetAfterHotReload(
+        local_saved_class_table, local_saved_tlc_class_table, saved_num_cids_,
+        saved_num_tlc_cids_, is_rollback);
+  }
   saved_class_table_.store(nullptr, std::memory_order_release);
   saved_tlc_class_table_.store(nullptr, std::memory_order_release);
 }
@@ -2115,6 +2113,7 @@
         type_(AbstractType::Handle(zone)),
         cache_(SubtypeTestCache::Handle(zone)),
         entries_(Array::Handle(zone)),
+        closure_function_(Function::Handle(zone)),
         instantiator_type_arguments_(TypeArguments::Handle(zone)),
         function_type_arguments_(TypeArguments::Handle(zone)),
         instance_cid_or_signature_(Object::Handle(zone)),
@@ -2143,7 +2142,8 @@
         // At that point it doesn't have the field table setup yet.
         if (field_table->IsReadyToUse()) {
           value_ = field_table->At(field_id);
-          if (value_.ptr() != Object::sentinel().ptr()) {
+          if ((value_.ptr() != Object::sentinel().ptr()) &&
+              (value_.ptr() != Object::transition_sentinel().ptr())) {
             CheckValueType(null_safety, value_, field);
           }
         }
@@ -2217,13 +2217,12 @@
     cls_ = value.clazz();
     const intptr_t cid = cls_.id();
     if (cid == kClosureCid) {
-      instance_cid_or_signature_ = Closure::Cast(value).signature();
-      instance_type_arguments_ =
-          Closure::Cast(value).instantiator_type_arguments();
-      parent_function_type_arguments_ =
-          Closure::Cast(value).function_type_arguments();
-      delayed_function_type_arguments_ =
-          Closure::Cast(value).delayed_type_arguments();
+      const auto& closure = Closure::Cast(value);
+      closure_function_ = closure.function();
+      instance_cid_or_signature_ = closure_function_.signature();
+      instance_type_arguments_ = closure.instantiator_type_arguments();
+      parent_function_type_arguments_ = closure.function_type_arguments();
+      delayed_function_type_arguments_ = closure.delayed_type_arguments();
     } else {
       instance_cid_or_signature_ = Smi::New(cid);
       if (cls_.NumTypeArguments() > 0) {
@@ -2295,6 +2294,7 @@
   AbstractType& type_;
   SubtypeTestCache& cache_;
   Array& entries_;
+  Function& closure_function_;
   TypeArguments& instantiator_type_arguments_;
   TypeArguments& function_type_arguments_;
   Object& instance_cid_or_signature_;
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 9402106..2003591 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -145,106 +145,4 @@
   barrier.Exit();
 }
 
-class IsolateTestHelper {
- public:
-  static uword GetStackLimit(Thread* thread) { return thread->stack_limit_; }
-  static uword GetSavedStackLimit(Thread* thread) {
-    return thread->saved_stack_limit_;
-  }
-  static uword GetDeferredInterruptsMask(Thread* thread) {
-    return thread->deferred_interrupts_mask_;
-  }
-  static uword GetDeferredInterrupts(Thread* thread) {
-    return thread->deferred_interrupts_;
-  }
-};
-
-TEST_CASE(NoOOBMessageScope) {
-  // Finish any GC in progress so that no kVMInterrupt is added for GC reasons.
-  {
-    TransitionNativeToVM transition(thread);
-    GCTestHelper::CollectAllGarbage();
-    const Error& error = Error::Handle(thread->HandleInterrupts());
-    RELEASE_ASSERT(error.IsNull());
-  }
-
-  // EXPECT_EQ is picky about type agreement for its arguments.
-  const uword kZero = 0;
-  const uword kMessageInterrupt = Thread::kMessageInterrupt;
-  const uword kVMInterrupt = Thread::kVMInterrupt;
-  uword stack_limit;
-  uword interrupt_bits;
-
-  // Initially no interrupts are scheduled or deferred.
-  EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
-            IsolateTestHelper::GetSavedStackLimit(thread));
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
-
-  {
-    // Defer message interrupts.
-    NoOOBMessageScope no_msg_scope(thread);
-    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
-              IsolateTestHelper::GetSavedStackLimit(thread));
-    EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterruptsMask(thread));
-    EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
-
-    // Schedule a message, it is deferred.
-    thread->ScheduleInterrupts(Thread::kMessageInterrupt);
-    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
-              IsolateTestHelper::GetSavedStackLimit(thread));
-    EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterruptsMask(thread));
-    EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterrupts(thread));
-
-    // Schedule a vm interrupt, it is not deferred.
-    thread->ScheduleInterrupts(Thread::kVMInterrupt);
-    stack_limit = IsolateTestHelper::GetStackLimit(thread);
-    EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(thread));
-    EXPECT((stack_limit & Thread::kVMInterrupt) != 0);
-    EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterruptsMask(thread));
-    EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterrupts(thread));
-
-    // Clear the vm interrupt.  Message is still deferred.
-    interrupt_bits = thread->GetAndClearInterrupts();
-    EXPECT_EQ(kVMInterrupt, interrupt_bits);
-    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
-              IsolateTestHelper::GetSavedStackLimit(thread));
-    EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterruptsMask(thread));
-    EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterrupts(thread));
-  }
-
-  // Restore message interrupts.  Message is now pending.
-  stack_limit = IsolateTestHelper::GetStackLimit(thread);
-  EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(thread));
-  EXPECT((stack_limit & Thread::kMessageInterrupt) != 0);
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
-
-  {
-    // Defer message interrupts, again.  The pending interrupt is deferred.
-    NoOOBMessageScope no_msg_scope(thread);
-    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
-              IsolateTestHelper::GetSavedStackLimit(thread));
-    EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterruptsMask(thread));
-    EXPECT_EQ(kMessageInterrupt,
-              IsolateTestHelper::GetDeferredInterrupts(thread));
-  }
-
-  // Restore, then clear interrupts.  The world is as it was.
-  interrupt_bits = thread->GetAndClearInterrupts();
-  EXPECT_EQ(kMessageInterrupt, interrupt_bits);
-  EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
-            IsolateTestHelper::GetSavedStackLimit(thread));
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
-  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
-}
-
 }  // namespace dart
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 57b229a..fb8c532 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 = 67;
-static const uint32_t kMaxSupportedKernelFormatVersion = 67;
+static const uint32_t kMinSupportedKernelFormatVersion = 69;
+static const uint32_t kMaxSupportedKernelFormatVersion = 69;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -33,7 +33,7 @@
   V(Field, 4)                                                                  \
   V(Constructor, 5)                                                            \
   V(Procedure, 6)                                                              \
-  V(RedirectingFactoryConstructor, 108)                                        \
+  V(RedirectingFactory, 108)                                                   \
   V(InvalidInitializer, 7)                                                     \
   V(FieldInitializer, 8)                                                       \
   V(SuperInitializer, 9)                                                       \
@@ -49,13 +49,10 @@
   V(InvalidExpression, 19)                                                     \
   V(VariableGet, 20)                                                           \
   V(VariableSet, 21)                                                           \
-  V(PropertyGet, 22)                                                           \
-  V(PropertySet, 23)                                                           \
   V(SuperPropertyGet, 24)                                                      \
   V(SuperPropertySet, 25)                                                      \
   V(StaticGet, 26)                                                             \
   V(StaticSet, 27)                                                             \
-  V(MethodInvocation, 28)                                                      \
   V(SuperMethodInvocation, 29)                                                 \
   V(StaticInvocation, 30)                                                      \
   V(ConstructorInvocation, 31)                                                 \
@@ -98,6 +95,7 @@
   V(ConstMapLiteral, 59)                                                       \
   V(ConstructorTearOff, 60)                                                    \
   V(TypedefTearOff, 83)                                                        \
+  V(RedirectingFactoryTearOff, 84)                                             \
   V(ExpressionStatement, 61)                                                   \
   V(Block, 62)                                                                 \
   V(EmptyStatement, 63)                                                        \
@@ -175,6 +173,7 @@
   kUnevaluatedConstant = 12,
   kTypedefTearOffConstant = 14,
   kConstructorTearOffConstant = 15,
+  kRedirectingFactoryTearOffConstant = 16,
 };
 
 // Keep in sync with package:kernel/lib/ast.dart
@@ -208,9 +207,9 @@
 };
 
 // Keep in sync with package:kernel/lib/ast.dart
-enum MethodInvocationFlags {
-  kMethodInvocationFlagInvariant = 1 << 0,
-  kMethodInvocationFlagBoundsSafe = 1 << 1,
+enum InstanceInvocationFlags {
+  kInstanceInvocationFlagInvariant = 1 << 0,
+  kInstanceInvocationFlagBoundsSafe = 1 << 1,
 };
 
 // Keep in sync with package:kernel/lib/ast.dart
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 1ba9c22..066c7d4 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -88,6 +88,7 @@
     Dart_IsolateFlags api_flags;
     Isolate::FlagsInitialize(&api_flags);
     api_flags.enable_asserts = false;
+    api_flags.null_safety = true;
     api_flags.is_system_isolate = true;
 #if !defined(DART_PRECOMPILER)
     api_flags.use_field_guards = true;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index d6cbc64..a45e80c 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1946,7 +1946,7 @@
   // additional functions can cause strain on the VM. They are therefore skipped
   // in jit mode and their associated origin function is used instead as
   // interface call target.
-  if (procedure_helper.IsRedirectingFactoryConstructor() ||
+  if (procedure_helper.IsRedirectingFactory() ||
       (!FLAG_precompiled_mode && procedure_helper.IsMemberSignature())) {
     helper_.SetOffset(procedure_end);
     return;
diff --git a/runtime/vm/malloc_hooks_test.cc b/runtime/vm/malloc_hooks_test.cc
index 8edd992..d04ab64 100644
--- a/runtime/vm/malloc_hooks_test.cc
+++ b/runtime/vm/malloc_hooks_test.cc
@@ -176,7 +176,7 @@
   EnableMallocHooksAndStacksScope scope;
 
   ClearProfileVisitor cpv(Isolate::Current());
-  Profiler::sample_buffer()->VisitSamples(&cpv);
+  Profiler::sample_block_buffer()->VisitSamples(&cpv);
 
   char* var = static_cast<char*>(malloc(16 * sizeof(char)));
   JSONStream js;
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
new file mode 100644
index 0000000..37bb767
--- /dev/null
+++ b/runtime/vm/message_snapshot.cc
@@ -0,0 +1,3615 @@
+// 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/message_snapshot.h"
+
+#include <memory>
+
+#include "platform/assert.h"
+#include "platform/unicode.h"
+#include "vm/class_finalizer.h"
+#include "vm/class_id.h"
+#include "vm/dart_api_message.h"
+#include "vm/dart_api_state.h"
+#include "vm/dart_entry.h"
+#include "vm/flags.h"
+#include "vm/growable_array.h"
+#include "vm/heap/heap.h"
+#include "vm/heap/weak_table.h"
+#include "vm/longjump.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/symbols.h"
+#include "vm/type_testing_stubs.h"
+
+namespace dart {
+
+static Dart_CObject cobj_null = {.type = Dart_CObject_kNull,
+                                 .value = {.as_int64 = 0}};
+static Dart_CObject cobj_sentinel = {.type = Dart_CObject_kUnsupported};
+static Dart_CObject cobj_transition_sentinel = {.type =
+                                                    Dart_CObject_kUnsupported};
+static Dart_CObject cobj_empty_array = {
+    .type = Dart_CObject_kArray,
+    .value = {.as_array = {.length = 0, .values = nullptr}}};
+static Dart_CObject cobj_zero_array_element = {.type = Dart_CObject_kInt32,
+                                               .value = {.as_int32 = 0}};
+static Dart_CObject* cobj_zero_array_values[1] = {&cobj_zero_array_element};
+static Dart_CObject cobj_zero_array = {
+    .type = Dart_CObject_kArray,
+    .value = {.as_array = {.length = 1, .values = &cobj_zero_array_values[0]}}};
+static Dart_CObject cobj_dynamic_type = {.type = Dart_CObject_kUnsupported};
+static Dart_CObject cobj_void_type = {.type = Dart_CObject_kUnsupported};
+static Dart_CObject cobj_empty_type_arguments = {.type =
+                                                     Dart_CObject_kUnsupported};
+static Dart_CObject cobj_true = {.type = Dart_CObject_kBool,
+                                 .value = {.as_bool = true}};
+static Dart_CObject cobj_false = {.type = Dart_CObject_kBool,
+                                  .value = {.as_bool = false}};
+
+enum class MessagePhase {
+  kBeforeTypes = 0,
+  kTypes = 1,
+  kCanonicalInstances = 2,
+  kNonCanonicalInstances = 3,
+
+  kNumPhases = 4,
+};
+
+class MessageSerializer;
+class MessageDeserializer;
+class ApiMessageSerializer;
+class ApiMessageDeserializer;
+class WeakPropertyMessageSerializationCluster;
+
+class MessageSerializationCluster : public ZoneAllocated {
+ public:
+  explicit MessageSerializationCluster(const char* name,
+                                       MessagePhase phase,
+                                       intptr_t cid,
+                                       bool is_canonical = false)
+      : name_(name), phase_(phase), cid_(cid), is_canonical_(is_canonical) {}
+  virtual ~MessageSerializationCluster() {}
+
+  virtual void Trace(MessageSerializer* s, Object* object) = 0;
+  virtual void WriteNodes(MessageSerializer* s) = 0;
+  virtual void WriteEdges(MessageSerializer* s) {}
+
+  virtual void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {}
+  virtual void WriteNodesApi(ApiMessageSerializer* s) {}
+  virtual void WriteEdgesApi(ApiMessageSerializer* s) {}
+
+  const char* name() const { return name_; }
+  MessagePhase phase() const { return phase_; }
+  intptr_t cid() const { return cid_; }
+  bool is_canonical() const { return is_canonical_; }
+
+ protected:
+  const char* const name_;
+  const MessagePhase phase_;
+  const intptr_t cid_;
+  const bool is_canonical_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessageSerializationCluster);
+};
+
+class MessageDeserializationCluster : public ZoneAllocated {
+ public:
+  explicit MessageDeserializationCluster(const char* name,
+                                         bool is_canonical = false)
+      : name_(name),
+        is_canonical_(is_canonical),
+        start_index_(0),
+        stop_index_(0) {}
+  virtual ~MessageDeserializationCluster() {}
+
+  virtual void ReadNodes(MessageDeserializer* d) = 0;
+  virtual void ReadEdges(MessageDeserializer* d) {}
+  virtual ObjectPtr PostLoad(MessageDeserializer* d) { return nullptr; }
+  virtual void ReadNodesApi(ApiMessageDeserializer* d) {}
+  virtual void ReadEdgesApi(ApiMessageDeserializer* d) {}
+  virtual void PostLoadApi(ApiMessageDeserializer* d) {}
+
+  void ReadNodesWrapped(MessageDeserializer* d);
+  void ReadNodesWrappedApi(ApiMessageDeserializer* d);
+
+  const char* name() const { return name_; }
+  bool is_canonical() const { return is_canonical_; }
+
+ protected:
+  ObjectPtr PostLoadAbstractType(MessageDeserializer* d);
+  ObjectPtr PostLoadLinkedHash(MessageDeserializer* d);
+
+  const char* const name_;
+  const bool is_canonical_;
+  // The range of the ref array that belongs to this cluster.
+  intptr_t start_index_;
+  intptr_t stop_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessageDeserializationCluster);
+};
+
+class BaseSerializer : public StackResource {
+ public:
+  BaseSerializer(Thread* thread, Zone* zone);
+  ~BaseSerializer();
+
+  // Writes raw data to the stream (basic type).
+  // sizeof(T) must be in {1,2,4,8}.
+  template <typename T>
+  void Write(T value) {
+    BaseWriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
+  }
+  void WriteUnsigned(intptr_t value) { stream_.WriteUnsigned(value); }
+  void WriteWordWith32BitWrites(uword value) {
+    stream_.WriteWordWith32BitWrites(value);
+  }
+  void WriteBytes(const uint8_t* addr, intptr_t len) {
+    stream_.WriteBytes(addr, len);
+  }
+  void WriteAscii(const String& str) {
+    intptr_t len = str.Length();
+    WriteUnsigned(len);
+    for (intptr_t i = 0; i < len; i++) {
+      int64_t c = str.CharAt(i);
+      ASSERT(c < 128);
+      Write<uint8_t>(c);
+    }
+    Write<uint8_t>(0);
+  }
+
+  MessageSerializationCluster* NewClusterForClass(intptr_t cid,
+                                                  bool is_canonical);
+  void WriteCluster(MessageSerializationCluster* cluster);
+
+  std::unique_ptr<Message> Finish(Dart_Port dest_port,
+                                  Message::Priority priority) {
+    MessageFinalizableData* finalizable_data = finalizable_data_;
+    finalizable_data_ = nullptr;
+    finalizable_data->SerializationSucceeded();
+    intptr_t size;
+    uint8_t* buffer = stream_.Steal(&size);
+    return Message::New(dest_port, buffer, size, finalizable_data, priority);
+  }
+
+  Zone* zone() const { return zone_; }
+  MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
+  intptr_t next_ref_index() const { return next_ref_index_; }
+
+ protected:
+  Zone* const zone_;
+  MallocWriteStream stream_;
+  MessageFinalizableData* finalizable_data_;
+  GrowableArray<MessageSerializationCluster*> clusters_;
+  WeakPropertyMessageSerializationCluster* ephemeron_cluster_;
+  intptr_t num_base_objects_;
+  intptr_t num_written_objects_;
+  intptr_t next_ref_index_;
+};
+
+class MessageSerializer : public BaseSerializer {
+ public:
+  MessageSerializer(Thread* thread, bool can_send_any_object);
+  ~MessageSerializer();
+
+  bool MarkObjectId(ObjectPtr object, intptr_t id) {
+    ASSERT(id != WeakTable::kNoValue);
+    WeakTable* table;
+    if (!object->IsSmiOrOldObject()) {
+      table = isolate()->forward_table_new();
+    } else {
+      table = isolate()->forward_table_old();
+    }
+    return table->MarkValueExclusive(object, id);
+  }
+
+  void SetObjectId(ObjectPtr object, intptr_t id) {
+    ASSERT(id != WeakTable::kNoValue);
+    WeakTable* table;
+    if (!object->IsSmiOrOldObject()) {
+      table = isolate()->forward_table_new();
+    } else {
+      table = isolate()->forward_table_old();
+    }
+    table->SetValueExclusive(object, id);
+  }
+
+  intptr_t GetObjectId(ObjectPtr object) const {
+    const WeakTable* table;
+    if (!object->IsSmiOrOldObject()) {
+      table = isolate()->forward_table_new();
+    } else {
+      table = isolate()->forward_table_old();
+    }
+    return table->GetValueExclusive(object);
+  }
+
+  DART_NOINLINE void AddBaseObject(ObjectPtr base_object) {
+    AssignRef(base_object);
+    num_base_objects_++;
+  }
+  DART_NOINLINE void AssignRef(ObjectPtr object) {
+    SetObjectId(object, next_ref_index_);
+    next_ref_index_++;
+  }
+  void AssignRef(Object* object) { AssignRef(object->ptr()); }
+
+  void Push(ObjectPtr object);
+
+  void Trace(Object* object);
+
+  void IllegalObject(const Object& object, const char* message);
+
+  void AddBaseObjects();
+  void Serialize(const Object& root);
+
+  DART_NOINLINE void WriteRef(ObjectPtr object) {
+    intptr_t index = GetObjectId(object);
+    ASSERT(index != WeakTable::kNoValue);
+    WriteUnsigned(index);
+  }
+
+  bool can_send_any_object() const { return can_send_any_object_; }
+  const char* exception_message() const { return exception_message_; }
+  Thread* thread() const {
+    return static_cast<Thread*>(StackResource::thread());
+  }
+  Isolate* isolate() const { return thread()->isolate(); }
+  IsolateGroup* isolate_group() const { return thread()->isolate_group(); }
+
+  bool HasRef(ObjectPtr object) const {
+    return GetObjectId(object) != WeakTable::kNoValue;
+  }
+
+ private:
+  WeakTable* forward_table_new_;
+  WeakTable* forward_table_old_;
+  GrowableArray<Object*> stack_;
+  bool const can_send_any_object_;
+  const char* exception_message_;
+};
+
+class ApiMessageSerializer : public BaseSerializer {
+ public:
+  explicit ApiMessageSerializer(Zone* zone);
+  ~ApiMessageSerializer();
+
+  bool MarkObjectId(Dart_CObject* object, intptr_t id) {
+    ASSERT(id != WeakTable::kNoValue);
+    return forward_table_.MarkValueExclusive(
+        static_cast<ObjectPtr>(reinterpret_cast<uword>(object)), id);
+  }
+
+  void SetObjectId(Dart_CObject* object, intptr_t id) {
+    ASSERT(id != WeakTable::kNoValue);
+    forward_table_.SetValueExclusive(
+        static_cast<ObjectPtr>(reinterpret_cast<uword>(object)), id);
+  }
+
+  intptr_t GetObjectId(Dart_CObject* object) const {
+    return forward_table_.GetValueExclusive(
+        static_cast<ObjectPtr>(reinterpret_cast<uword>(object)));
+  }
+
+  DART_NOINLINE void AddBaseObject(Dart_CObject* base_object) {
+    AssignRef(base_object);
+    num_base_objects_++;
+  }
+  DART_NOINLINE intptr_t AssignRef(Dart_CObject* object) {
+    SetObjectId(object, next_ref_index_);
+    return next_ref_index_++;
+  }
+  void ForwardRef(Dart_CObject* old, Dart_CObject* nue) {
+    intptr_t id = GetObjectId(nue);
+    ASSERT(id != WeakTable::kNoValue);
+    SetObjectId(old, id);
+    num_written_objects_--;
+  }
+
+  void Push(Dart_CObject* object);
+
+  bool Trace(Dart_CObject* object);
+
+  void AddBaseObjects();
+  bool Serialize(Dart_CObject* root);
+
+  void WriteRef(Dart_CObject* object) {
+    intptr_t index = GetObjectId(object);
+    ASSERT(index != WeakTable::kNoValue);
+    WriteUnsigned(index);
+  }
+
+  bool Fail(const char* message) {
+    exception_message_ = message;
+    return false;
+  }
+
+ private:
+  WeakTable forward_table_;
+  GrowableArray<Dart_CObject*> stack_;
+  const char* exception_message_;
+};
+
+class BaseDeserializer : public ValueObject {
+ public:
+  BaseDeserializer(Zone* zone, Message* message);
+  ~BaseDeserializer();
+
+  // Reads raw data (for basic types).
+  // sizeof(T) must be in {1,2,4,8}.
+  template <typename T>
+  T Read() {
+    return ReadStream::Raw<sizeof(T), T>::Read(&stream_);
+  }
+  intptr_t ReadUnsigned() { return stream_.ReadUnsigned(); }
+  uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); }
+  void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); }
+  const char* ReadAscii() {
+    intptr_t len = ReadUnsigned();
+    const char* result = reinterpret_cast<const char*>(CurrentBufferAddress());
+    Advance(len + 1);
+    return result;
+  }
+
+  const uint8_t* CurrentBufferAddress() const {
+    return stream_.AddressOfCurrentPosition();
+  }
+
+  void Advance(intptr_t value) { stream_.Advance(value); }
+
+  MessageDeserializationCluster* ReadCluster();
+
+  Zone* zone() const { return zone_; }
+  intptr_t next_index() const { return next_ref_index_; }
+  MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
+
+ protected:
+  Zone* zone_;
+  ReadStream stream_;
+  MessageFinalizableData* finalizable_data_;
+  intptr_t next_ref_index_;
+};
+
+class MessageDeserializer : public BaseDeserializer {
+ public:
+  MessageDeserializer(Thread* thread, Message* message)
+      : BaseDeserializer(thread->zone(), message),
+        thread_(thread),
+        refs_(Array::Handle(thread->zone())) {}
+  ~MessageDeserializer() {}
+
+  DART_NOINLINE void AddBaseObject(ObjectPtr base_object) {
+    AssignRef(base_object);
+  }
+  void AssignRef(ObjectPtr object) {
+    refs_.untag()->set_element(next_ref_index_, object);
+    next_ref_index_++;
+  }
+
+  ObjectPtr Ref(intptr_t index) const {
+    ASSERT(index > 0);
+    ASSERT(index <= next_ref_index_);
+    return refs_.At(index);
+  }
+  void UpdateRef(intptr_t index, const Object& new_object) {
+    ASSERT(index > 0);
+    ASSERT(index <= next_ref_index_);
+    refs_.SetAt(index, new_object);
+  }
+
+  ObjectPtr ReadRef() { return Ref(ReadUnsigned()); }
+
+  void AddBaseObjects();
+  ObjectPtr Deserialize();
+
+  Thread* thread() const { return thread_; }
+  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
+  ArrayPtr refs() const { return refs_.ptr(); }
+
+ private:
+  Thread* const thread_;
+  Array& refs_;
+};
+
+class ApiMessageDeserializer : public BaseDeserializer {
+ public:
+  ApiMessageDeserializer(Zone* zone, Message* message)
+      : BaseDeserializer(zone, message), refs_(nullptr) {}
+  ~ApiMessageDeserializer() {}
+
+  void AddBaseObject(Dart_CObject* base_object) { AssignRef(base_object); }
+  void AssignRef(Dart_CObject* object) {
+    refs_[next_ref_index_] = object;
+    next_ref_index_++;
+  }
+
+  Dart_CObject* Allocate(Dart_CObject_Type type) {
+    Dart_CObject* result = zone()->Alloc<Dart_CObject>(1);
+    result->type = type;
+    return result;
+  }
+
+  Dart_CObject* Ref(intptr_t index) const {
+    ASSERT(index > 0);
+    ASSERT(index <= next_ref_index_);
+    return refs_[index];
+  }
+
+  Dart_CObject* ReadRef() { return Ref(ReadUnsigned()); }
+
+  void AddBaseObjects();
+  Dart_CObject* Deserialize();
+
+ private:
+  Dart_CObject** refs_;
+};
+
+void MessageDeserializationCluster::ReadNodesWrapped(MessageDeserializer* d) {
+  start_index_ = d->next_index();
+  this->ReadNodes(d);
+  stop_index_ = d->next_index();
+}
+
+void MessageDeserializationCluster::ReadNodesWrappedApi(
+    ApiMessageDeserializer* d) {
+  start_index_ = d->next_index();
+  this->ReadNodesApi(d);
+  stop_index_ = d->next_index();
+}
+
+ObjectPtr MessageDeserializationCluster::PostLoadAbstractType(
+    MessageDeserializer* d) {
+  ClassFinalizer::FinalizationKind finalization =
+      is_canonical() ? ClassFinalizer::kCanonicalize
+                     : ClassFinalizer::kFinalize;
+  AbstractType& type = AbstractType::Handle(d->zone());
+  Code& code = Code::Handle(d->zone());
+  for (intptr_t id = start_index_; id < stop_index_; id++) {
+    type ^= d->Ref(id);
+
+    code = TypeTestingStubGenerator::DefaultCodeForType(type);
+    type.InitializeTypeTestingStubNonAtomic(code);
+
+    type ^= ClassFinalizer::FinalizeType(type, finalization);
+    d->UpdateRef(id, type);
+  }
+  return nullptr;
+}
+
+ObjectPtr MessageDeserializationCluster::PostLoadLinkedHash(
+    MessageDeserializer* d) {
+  ASSERT(!is_canonical());
+  Array& maps = Array::Handle(d->zone(), d->refs());
+  maps = maps.Slice(start_index_, stop_index_ - start_index_,
+                    /*with_type_argument=*/false);
+  return DartLibraryCalls::RehashObjects(d->thread(), maps);
+}
+
+class ClassMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  ClassMessageSerializationCluster()
+      : MessageSerializationCluster("Class",
+                                    MessagePhase::kBeforeTypes,
+                                    kClassCid),
+        objects_() {}
+  ~ClassMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Class* cls = static_cast<Class*>(object);
+    objects_.Add(cls);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    Library& lib = Library::Handle(s->zone());
+    String& str = String::Handle(s->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      Class* cls = objects_[i];
+      s->AssignRef(cls);
+      intptr_t cid = cls->id();
+      if (cid < kNumPredefinedCids) {
+        ASSERT(cid != 0);
+        s->WriteUnsigned(cid);
+      } else {
+        s->WriteUnsigned(0);
+        lib = cls->library();
+        str = lib.url();
+        s->WriteAscii(str);
+        str = cls->Name();
+        s->WriteAscii(str);
+      }
+    }
+  }
+
+ private:
+  GrowableArray<Class*> objects_;
+};
+
+class ClassMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  ClassMessageDeserializationCluster()
+      : MessageDeserializationCluster("Class") {}
+  ~ClassMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    auto* class_table = d->isolate_group()->class_table();
+    String& str = String::Handle(d->zone());
+    Library& lib = Library::Handle(d->zone());
+    Class& cls = Class::Handle(d->zone());
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t cid = d->ReadUnsigned();
+      if (cid != 0) {
+        cls = class_table->At(cid);
+      } else {
+        str = String::New(d->ReadAscii());  // Library URI.
+        lib = Library::LookupLibrary(d->thread(), str);
+        RELEASE_ASSERT(!lib.IsNull());
+        str = String::New(d->ReadAscii());  // Class name.
+        if (str.Equals(Symbols::TopLevel())) {
+          cls = lib.toplevel_class();
+        } else {
+          cls = lib.LookupClass(str);
+        }
+        RELEASE_ASSERT(!cls.IsNull());
+        cls.EnsureIsFinalized(d->thread());
+      }
+      d->AssignRef(cls.ptr());
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t cid = d->ReadUnsigned();
+      if (cid == 0) {
+        d->ReadAscii();  // Library URI.
+        d->ReadAscii();  // Class name.
+      }
+      d->AssignRef(nullptr);
+    }
+  }
+};
+
+class TypeArgumentsMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit TypeArgumentsMessageSerializationCluster(bool is_canonical)
+      : MessageSerializationCluster("TypeArguments",
+                                    MessagePhase::kTypes,
+                                    kTypeArgumentsCid,
+                                    is_canonical) {}
+  ~TypeArgumentsMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    TypeArguments* type_args = static_cast<TypeArguments*>(object);
+    objects_.Add(type_args);
+
+    s->Push(type_args->untag()->instantiations());
+    intptr_t length = Smi::Value(type_args->untag()->length());
+    for (intptr_t i = 0; i < length; i++) {
+      s->Push(type_args->untag()->element(i));
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TypeArguments* type_args = objects_[i];
+      s->AssignRef(type_args);
+      intptr_t length = Smi::Value(type_args->untag()->length());
+      s->WriteUnsigned(length);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      TypeArguments* type_args = objects_[i];
+      intptr_t hash = Smi::Value(type_args->untag()->hash());
+      s->Write<int32_t>(hash);
+      const intptr_t nullability =
+          Smi::Value(type_args->untag()->nullability());
+      s->WriteUnsigned(nullability);
+
+      intptr_t length = Smi::Value(type_args->untag()->length());
+      s->WriteUnsigned(length);
+      for (intptr_t j = 0; j < length; j++) {
+        s->WriteRef(type_args->untag()->element(j));
+      }
+    }
+  }
+
+ private:
+  GrowableArray<TypeArguments*> objects_;
+};
+
+class TypeArgumentsMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit TypeArgumentsMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("TypeArguments", is_canonical) {}
+  ~TypeArgumentsMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      d->AssignRef(TypeArguments::New(length));
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      TypeArgumentsPtr type_args = static_cast<TypeArgumentsPtr>(d->Ref(id));
+
+      type_args->untag()->hash_ = Smi::New(d->Read<int32_t>());
+      type_args->untag()->nullability_ = Smi::New(d->ReadUnsigned());
+
+      intptr_t length = d->ReadUnsigned();
+      for (intptr_t j = 0; j < length; j++) {
+        type_args->untag()->types()[j] =
+            static_cast<AbstractTypePtr>(d->ReadRef());
+      }
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    if (is_canonical()) {
+      TypeArguments& type_args = TypeArguments::Handle(d->zone());
+      for (intptr_t id = start_index_; id < stop_index_; id++) {
+        type_args ^= d->Ref(id);
+        type_args ^= type_args.Canonicalize(d->thread());
+        d->UpdateRef(id, type_args);
+      }
+    }
+    return nullptr;
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->ReadUnsigned();  // Length.
+      d->AssignRef(nullptr);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      d->Read<int32_t>();  // Hash.
+      d->ReadUnsigned();   // Nullability.
+      intptr_t length = d->ReadUnsigned();
+      for (intptr_t j = 0; j < length; j++) {
+        d->ReadRef();  // Element.
+      }
+    }
+  }
+};
+
+class FunctionMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  FunctionMessageSerializationCluster()
+      : MessageSerializationCluster("Function",
+                                    MessagePhase::kBeforeTypes,
+                                    kFunctionCid) {}
+  ~FunctionMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Function* func = static_cast<Function*>(object);
+    objects_.Add(func);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    Library& lib = Library::Handle(s->zone());
+    Class& cls = Class::Handle(s->zone());
+    String& str = String::Handle(s->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      Function* func = objects_[i];
+      s->AssignRef(func);
+      cls ^= func->Owner();
+      lib = cls.library();
+      str = lib.url();
+      s->WriteAscii(str);
+      str = cls.Name();
+      s->WriteAscii(str);
+      str = func->name();
+      s->WriteAscii(str);
+    }
+  }
+
+ private:
+  GrowableArray<Function*> objects_;
+};
+
+class FunctionMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  FunctionMessageDeserializationCluster()
+      : MessageDeserializationCluster("Function") {}
+  ~FunctionMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    String& str = String::Handle(d->zone());
+    Library& lib = Library::Handle(d->zone());
+    Class& cls = Class::Handle(d->zone());
+    Function& func = Function::Handle(d->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      str = String::New(d->ReadAscii());  // Library URI.
+      lib = Library::LookupLibrary(d->thread(), str);
+      RELEASE_ASSERT(!lib.IsNull());
+      str = String::New(d->ReadAscii());  // Class name.
+      if (str.Equals(Symbols::TopLevel())) {
+        cls = lib.toplevel_class();
+      } else {
+        cls = lib.LookupClass(str);
+      }
+      RELEASE_ASSERT(!cls.IsNull());
+      cls.EnsureIsFinalized(d->thread());
+      str = String::New(d->ReadAscii());  // Function name.
+      func = cls.LookupStaticFunction(str);
+      RELEASE_ASSERT(!func.IsNull());
+      d->AssignRef(func.ptr());
+    }
+  }
+};
+
+class InstanceMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  InstanceMessageSerializationCluster(bool is_canonical, intptr_t cid)
+      : MessageSerializationCluster("Instance",
+                                    is_canonical
+                                        ? MessagePhase::kCanonicalInstances
+                                        : MessagePhase::kNonCanonicalInstances,
+                                    cid,
+                                    is_canonical),
+        cls_(Class::Handle()) {
+    cls_ = IsolateGroup::Current()->class_table()->At(cid);
+    next_field_offset_ = cls_.host_next_field_offset();
+  }
+  ~InstanceMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Instance* instance = static_cast<Instance*>(object);
+    objects_.Add(instance);
+
+    const intptr_t next_field_offset = next_field_offset_;
+    const auto unboxed_fields_bitmap =
+        s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
+    for (intptr_t offset = Instance::NextFieldOffset();
+         offset < next_field_offset; offset += kCompressedWordSize) {
+      if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+        continue;
+      }
+      s->Push(reinterpret_cast<CompressedObjectPtr*>(
+                  reinterpret_cast<uword>(instance->untag()) + offset)
+                  ->Decompress(instance->untag()->heap_base()));
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    s->WriteRef(cls_.ptr());
+
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Instance* instance = objects_[i];
+      s->AssignRef(instance);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      Instance* instance = objects_[i];
+
+      const intptr_t next_field_offset = next_field_offset_;
+      const auto unboxed_fields_bitmap =
+          s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
+      for (intptr_t offset = Instance::NextFieldOffset();
+           offset < next_field_offset; offset += kCompressedWordSize) {
+        if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+          // Writes 32 bits of the unboxed value at a time
+          const uword value = *reinterpret_cast<compressed_uword*>(
+              reinterpret_cast<uword>(instance->untag()) + offset);
+          s->WriteWordWith32BitWrites(value);
+        } else {
+          s->WriteRef(reinterpret_cast<CompressedObjectPtr*>(
+                          reinterpret_cast<uword>(instance->untag()) + offset)
+                          ->Decompress(instance->untag()->heap_base()));
+        }
+      }
+    }
+  }
+
+ private:
+  Class& cls_;
+  intptr_t next_field_offset_;
+  GrowableArray<Instance*> objects_;
+};
+
+class InstanceMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit InstanceMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("Instance", is_canonical),
+        cls_(Class::Handle()) {}
+  ~InstanceMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    cls_ ^= d->ReadRef();
+
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(Instance::New(cls_));
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    const intptr_t next_field_offset = cls_.host_next_field_offset();
+    const intptr_t type_argument_field_offset =
+        cls_.host_type_arguments_field_offset();
+    const auto unboxed_fields_bitmap =
+        d->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
+            cls_.id());
+    const bool use_field_guards = d->isolate_group()->use_field_guards();
+    const Array& field_map = Array::Handle(d->zone(), cls_.OffsetToFieldMap());
+    Instance& instance = Instance::Handle(d->zone());
+    Object& value = Object::Handle(d->zone());
+    Field& field = Field::Handle(d->zone());
+
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      instance ^= d->Ref(id);
+      for (intptr_t offset = Instance::NextFieldOffset();
+           offset < next_field_offset; offset += kCompressedWordSize) {
+        if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+          compressed_uword* p = reinterpret_cast<compressed_uword*>(
+              reinterpret_cast<uword>(instance.untag()) + offset);
+          // Reads 32 bits of the unboxed value at a time
+          *p = d->ReadWordWith32BitReads();
+        } else {
+          value = d->ReadRef();
+          instance.SetFieldAtOffset(offset, value);
+          if (use_field_guards && (offset != type_argument_field_offset) &&
+              (value.ptr() != Object::sentinel().ptr())) {
+            field ^= field_map.At(offset >> kCompressedWordSizeLog2);
+            ASSERT(!field.IsNull());
+            ASSERT(field.HostOffset() == offset);
+            field.RecordStore(value);
+          }
+        }
+      }
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    if (is_canonical()) {
+      SafepointMutexLocker ml(
+          d->isolate_group()->constant_canonicalization_mutex());
+      Instance& instance = Instance::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        instance ^= d->Ref(i);
+        instance = instance.CanonicalizeLocked(d->thread());
+        d->UpdateRef(i, instance);
+      }
+    }
+
+    if (cls_.ptr() == d->isolate_group()->object_store()->expando_class()) {
+      Instance& instance = Instance::Handle(d->zone());
+      const String& selector = Library::PrivateCoreLibName(Symbols::_rehash());
+      Array& args = Array::Handle(d->zone(), Array::New(1));
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        instance ^= d->Ref(i);
+        args.SetAt(0, instance);
+        ObjectPtr error = instance.Invoke(selector, args, Object::empty_array(),
+                                          false, false);
+        if (error != Object::null()) {
+          return error;
+        }
+      }
+    }
+    return nullptr;
+  }
+
+ private:
+  Class& cls_;
+};
+
+class TypeMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit TypeMessageSerializationCluster(bool is_canonical)
+      : MessageSerializationCluster("Type",
+                                    MessagePhase::kTypes,
+                                    kTypeCid,
+                                    is_canonical) {}
+  ~TypeMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Type* type = static_cast<Type*>(object);
+    objects_.Add(type);
+
+    s->Push(type->type_class());
+    s->Push(type->arguments());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Type* type = objects_[i];
+      s->AssignRef(type);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      Type* type = objects_[i];
+      s->WriteRef(type->type_class());
+      s->WriteRef(type->arguments());
+      s->Write<uint8_t>(static_cast<uint8_t>(type->nullability()));
+    }
+  }
+
+ private:
+  GrowableArray<Type*> objects_;
+};
+
+class TypeMessageDeserializationCluster : public MessageDeserializationCluster {
+ public:
+  explicit TypeMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("Type", is_canonical) {}
+  ~TypeMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(Type::New());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    Class& cls = Class::Handle(d->zone());
+    Type& type = Type::Handle(d->zone());
+    TypeArguments& type_args = TypeArguments::Handle(d->zone());
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      type ^= d->Ref(id);
+      cls ^= d->ReadRef();
+      type.set_type_class(cls);
+      type_args ^= d->ReadRef();
+      type.set_arguments(type_args);
+      type.untag()->set_hash(Smi::New(0));
+      type.set_nullability(static_cast<Nullability>(d->Read<uint8_t>()));
+      type.SetIsFinalized();
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) { return PostLoadAbstractType(d); }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(nullptr);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      d->ReadRef();        // Class.
+      d->ReadRef();        // Type arguments.
+      d->Read<uint8_t>();  // Nullability.
+    }
+  }
+};
+
+class TypeRefMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit TypeRefMessageSerializationCluster(bool is_canonical)
+      : MessageSerializationCluster("TypeRef",
+                                    MessagePhase::kTypes,
+                                    kTypeRefCid,
+                                    is_canonical) {}
+  ~TypeRefMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    TypeRef* type = static_cast<TypeRef*>(object);
+    objects_.Add(type);
+
+    s->Push(type->type());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TypeRef* type = objects_[i];
+      s->AssignRef(type);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      TypeRef* type = objects_[i];
+      s->WriteRef(type->type());
+    }
+  }
+
+ private:
+  GrowableArray<TypeRef*> objects_;
+};
+
+class TypeRefMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit TypeRefMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("TypeRef", is_canonical) {}
+  ~TypeRefMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(TypeRef::New());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      TypeRefPtr type = static_cast<TypeRefPtr>(d->Ref(id));
+      type->untag()->set_type(static_cast<AbstractTypePtr>(d->ReadRef()));
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    ClassFinalizer::FinalizationKind finalization =
+        is_canonical() ? ClassFinalizer::kCanonicalize
+                       : ClassFinalizer::kFinalize;
+    Code& code = Code::Handle(d->zone());
+    TypeRef& type = TypeRef::Handle(d->zone());
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      type ^= d->Ref(id);
+      type ^= ClassFinalizer::FinalizeType(type, finalization);
+      d->UpdateRef(id, type);
+
+      code = TypeTestingStubGenerator::DefaultCodeForType(type);
+      type.InitializeTypeTestingStubNonAtomic(code);
+    }
+    return nullptr;
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(nullptr);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      d->ReadRef();  // Type.
+    }
+  }
+};
+
+class ClosureMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit ClosureMessageSerializationCluster(bool is_canonical)
+      : MessageSerializationCluster("Closure",
+                                    MessagePhase::kCanonicalInstances,
+                                    kClosureCid,
+                                    is_canonical) {}
+  ~ClosureMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Closure* closure = static_cast<Closure*>(object);
+
+    if (!s->can_send_any_object() ||
+        !Function::IsImplicitStaticClosureFunction(closure->function())) {
+      const char* message = OS::SCreate(
+          s->zone(),
+          "Illegal argument in isolate message : (object is a closure - %s)",
+          Function::Handle(closure->function()).ToCString());
+      s->IllegalObject(*object, message);
+    }
+
+    objects_.Add(closure);
+
+    s->Push(closure->function());
+    s->Push(closure->delayed_type_arguments());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Closure* closure = objects_[i];
+      s->AssignRef(closure);
+      s->WriteRef(closure->function());
+      s->WriteRef(closure->delayed_type_arguments());
+    }
+  }
+
+ private:
+  GrowableArray<Closure*> objects_;
+};
+
+class ClosureMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit ClosureMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("Closure", is_canonical) {}
+  ~ClosureMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    const Context& null_context = Context::Handle(d->zone());
+    TypeArguments& delayed_type_arguments = TypeArguments::Handle(d->zone());
+    Function& func = Function::Handle(d->zone());
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      func ^= d->ReadRef();
+      ASSERT(func.is_static());
+      func = func.ImplicitClosureFunction();
+      delayed_type_arguments ^= d->ReadRef();
+      if (delayed_type_arguments.IsNull()) {
+        d->AssignRef(func.ImplicitStaticClosure());
+      } else {
+        // If delayed type arguments were provided, create and return new
+        // closure with those, otherwise return associated implicit static
+        // closure. Note that static closures can't have instantiator or
+        // function types since statics can't refer to class type arguments,
+        // don't have outer functions.
+        d->AssignRef(Closure::New(
+            /*instantiator_type_arguments=*/Object::null_type_arguments(),
+            /*function_type_arguments=*/Object::null_type_arguments(),
+            delayed_type_arguments, func, null_context, Heap::kOld));
+      }
+    }
+  }
+};
+
+class SmiMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit SmiMessageSerializationCluster(Zone* zone)
+      : MessageSerializationCluster("Smi",
+                                    MessagePhase::kBeforeTypes,
+                                    kSmiCid,
+                                    true),
+        objects_(zone, 0) {}
+  ~SmiMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Smi* smi = static_cast<Smi*>(object);
+    objects_.Add(smi);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Smi* smi = static_cast<Smi*>(objects_[i]);
+      s->AssignRef(smi);
+      s->Write<intptr_t>(smi->Value());
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<Smi*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* smi = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(smi);
+      intptr_t value = smi->type == Dart_CObject_kInt32 ? smi->value.as_int32
+                                                        : smi->value.as_int64;
+      s->Write<intptr_t>(value);
+    }
+  }
+
+ private:
+  GrowableArray<Smi*> objects_;
+};
+
+class SmiMessageDeserializationCluster : public MessageDeserializationCluster {
+ public:
+  SmiMessageDeserializationCluster()
+      : MessageDeserializationCluster("Smi", true) {}
+  ~SmiMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(Smi::New(d->Read<intptr_t>()));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t value = d->Read<intptr_t>();
+      Dart_CObject* smi;
+      if ((kMinInt32 <= value) && (value <= kMaxInt32)) {
+        smi = d->Allocate(Dart_CObject_kInt32);
+        smi->value.as_int32 = value;
+      } else {
+        smi = d->Allocate(Dart_CObject_kInt64);
+        smi->value.as_int64 = value;
+      }
+      d->AssignRef(smi);
+    }
+  }
+};
+
+class MintMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit MintMessageSerializationCluster(Zone* zone, bool is_canonical)
+      : MessageSerializationCluster("Mint",
+                                    MessagePhase::kBeforeTypes,
+                                    kMintCid,
+                                    is_canonical),
+        objects_(zone, 0) {}
+  ~MintMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Mint* mint = static_cast<Mint*>(object);
+    objects_.Add(mint);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Mint* mint = static_cast<Mint*>(objects_[i]);
+      s->AssignRef(mint);
+      s->Write<int64_t>(mint->value());
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<Mint*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* mint = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(mint);
+      int64_t value = mint->type == Dart_CObject_kInt32 ? mint->value.as_int32
+                                                        : mint->value.as_int64;
+      s->Write<int64_t>(value);
+    }
+  }
+
+ private:
+  GrowableArray<Mint*> objects_;
+};
+
+class MintMessageDeserializationCluster : public MessageDeserializationCluster {
+ public:
+  explicit MintMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("int", is_canonical) {}
+  ~MintMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      int64_t value = d->Read<int64_t>();
+      d->AssignRef(is_canonical() ? Mint::NewCanonical(value)
+                                  : Mint::New(value));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      int64_t value = d->Read<int64_t>();
+      Dart_CObject* mint;
+      if ((kMinInt32 <= value) && (value <= kMaxInt32)) {
+        mint = d->Allocate(Dart_CObject_kInt32);
+        mint->value.as_int32 = value;
+      } else {
+        mint = d->Allocate(Dart_CObject_kInt64);
+        mint->value.as_int64 = value;
+      }
+      d->AssignRef(mint);
+    }
+  }
+};
+
+class DoubleMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit DoubleMessageSerializationCluster(Zone* zone, bool is_canonical)
+      : MessageSerializationCluster("double",
+                                    MessagePhase::kBeforeTypes,
+                                    kDoubleCid,
+                                    is_canonical),
+        objects_(zone, 0) {}
+
+  ~DoubleMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Double* dbl = static_cast<Double*>(object);
+    objects_.Add(dbl);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Double* dbl = objects_[i];
+      s->AssignRef(dbl);
+      s->Write<double>(dbl->untag()->value_);
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<Double*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* dbl = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(dbl);
+      s->Write<double>(dbl->value.as_double);
+    }
+  }
+
+ private:
+  GrowableArray<Double*> objects_;
+};
+
+class DoubleMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit DoubleMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("double", is_canonical) {}
+  ~DoubleMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      double value = d->Read<double>();
+      d->AssignRef(is_canonical() ? Double::NewCanonical(value)
+                                  : Double::New(value));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* dbl = d->Allocate(Dart_CObject_kDouble);
+      dbl->value.as_double = d->Read<double>();
+      d->AssignRef(dbl);
+    }
+  }
+};
+
+class GrowableObjectArrayMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  GrowableObjectArrayMessageSerializationCluster()
+      : MessageSerializationCluster("GrowableObjectArray",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kGrowableObjectArrayCid) {}
+  ~GrowableObjectArrayMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    GrowableObjectArray* array = static_cast<GrowableObjectArray*>(object);
+    objects_.Add(array);
+
+    s->Push(array->GetTypeArguments());
+    for (intptr_t i = 0, n = array->Length(); i < n; i++) {
+      s->Push(array->At(i));
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      GrowableObjectArray* array = objects_[i];
+      s->WriteUnsigned(array->Length());
+      s->AssignRef(array);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      GrowableObjectArray* array = objects_[i];
+      s->WriteRef(array->GetTypeArguments());
+      for (intptr_t i = 0, n = array->Length(); i < n; i++) {
+        s->WriteRef(array->At(i));
+      }
+    }
+  }
+
+ private:
+  GrowableArray<GrowableObjectArray*> objects_;
+};
+
+class GrowableObjectArrayMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  GrowableObjectArrayMessageDeserializationCluster()
+      : MessageDeserializationCluster("GrowableObjectArray") {}
+  ~GrowableObjectArrayMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    GrowableObjectArray& array = GrowableObjectArray::Handle(d->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      array = GrowableObjectArray::New(length);  // Here length is capacity.
+      array.SetLength(length);
+      d->AssignRef(array.ptr());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    GrowableObjectArray& array = GrowableObjectArray::Handle(d->zone());
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      array ^= d->Ref(id);
+      array.untag()->set_type_arguments(
+          static_cast<TypeArgumentsPtr>(d->ReadRef()));
+      for (intptr_t i = 0, n = array.Length(); i < n; i++) {
+        array.untag()->data()->untag()->set_element(i, d->ReadRef());
+      }
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    ASSERT(!is_canonical());
+    return nullptr;
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* array = d->Allocate(Dart_CObject_kArray);
+      intptr_t length = d->ReadUnsigned();
+      array->value.as_array.length = length;
+      if (length > 0) {
+        array->value.as_array.values = d->zone()->Alloc<Dart_CObject*>(length);
+      } else {
+        ASSERT(length == 0);
+        array->value.as_array.values = NULL;
+      }
+      d->AssignRef(array);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      Dart_CObject* array = d->Ref(id);
+      intptr_t length = array->value.as_array.length;
+      d->ReadRef();  // type_arguments
+      for (intptr_t i = 0; i < length; i++) {
+        array->value.as_array.values[i] = d->ReadRef();
+      }
+    }
+  }
+};
+
+class TypedDataMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit TypedDataMessageSerializationCluster(Zone* zone, intptr_t cid)
+      : MessageSerializationCluster("TypedData",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    cid),
+        objects_(zone, 0) {}
+  ~TypedDataMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    TypedData* data = static_cast<TypedData*>(object);
+    objects_.Add(data);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TypedData* data = objects_[i];
+      s->AssignRef(data);
+      intptr_t length = data->Length();
+      s->WriteUnsigned(length);
+      NoSafepointScope no_safepoint;
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(data->untag()->data());
+      s->WriteBytes(cdata, length * element_size);
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<TypedData*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* data = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(data);
+      intptr_t length = data->value.as_external_typed_data.length;
+      s->WriteUnsigned(length);
+      uint8_t* cdata =
+          reinterpret_cast<uint8_t*>(data->value.as_typed_data.values);
+      s->WriteBytes(cdata, length * element_size);
+    }
+  }
+
+ private:
+  GrowableArray<TypedData*> objects_;
+};
+
+class TypedDataMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit TypedDataMessageDeserializationCluster(intptr_t cid)
+      : MessageDeserializationCluster("TypedData"), cid_(cid) {}
+  ~TypedDataMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+    intptr_t count = d->ReadUnsigned();
+    TypedData& data = TypedData::Handle(d->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      data = TypedData::New(cid_, length);
+      d->AssignRef(data.ptr());
+      const intptr_t length_in_bytes = length * element_size;
+      NoSafepointScope no_safepoint;
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(data.untag()->data());
+      d->ReadBytes(cdata, length_in_bytes);
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    Dart_TypedData_Type type;
+    switch (cid_) {
+      case kTypedDataInt8ArrayCid:
+        type = Dart_TypedData_kInt8;
+        break;
+      case kTypedDataUint8ArrayCid:
+        type = Dart_TypedData_kUint8;
+        break;
+      case kTypedDataUint8ClampedArrayCid:
+        type = Dart_TypedData_kUint8Clamped;
+        break;
+      case kTypedDataInt16ArrayCid:
+        type = Dart_TypedData_kInt16;
+        break;
+      case kTypedDataUint16ArrayCid:
+        type = Dart_TypedData_kUint16;
+        break;
+      case kTypedDataInt32ArrayCid:
+        type = Dart_TypedData_kInt32;
+        break;
+      case kTypedDataUint32ArrayCid:
+        type = Dart_TypedData_kUint32;
+        break;
+      case kTypedDataInt64ArrayCid:
+        type = Dart_TypedData_kInt64;
+        break;
+      case kTypedDataUint64ArrayCid:
+        type = Dart_TypedData_kUint64;
+        break;
+      case kTypedDataFloat32ArrayCid:
+        type = Dart_TypedData_kFloat32;
+        break;
+      case kTypedDataFloat64ArrayCid:
+        type = Dart_TypedData_kFloat64;
+        break;
+      case kTypedDataInt32x4ArrayCid:
+        type = Dart_TypedData_kInt32x4;
+        break;
+      case kTypedDataFloat32x4ArrayCid:
+        type = Dart_TypedData_kFloat32x4;
+        break;
+      case kTypedDataFloat64x2ArrayCid:
+        type = Dart_TypedData_kFloat64x2;
+        break;
+      default:
+        UNREACHABLE();
+    }
+
+    intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* data = d->Allocate(Dart_CObject_kTypedData);
+      intptr_t length = d->ReadUnsigned();
+      data->value.as_typed_data.type = type;
+      data->value.as_typed_data.length = length * element_size;
+      if (length == 0) {
+        data->value.as_typed_data.values = NULL;
+      } else {
+        data->value.as_typed_data.values =
+            const_cast<uint8_t*>(d->CurrentBufferAddress());
+        d->Advance(length * element_size);
+      }
+      d->AssignRef(data);
+    }
+  }
+
+ private:
+  const intptr_t cid_;
+};
+
+// This function's name can appear in Observatory.
+static void IsolateMessageTypedDataFinalizer(void* isolate_callback_data,
+                                             void* buffer) {
+  free(buffer);
+}
+
+class ExternalTypedDataMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit ExternalTypedDataMessageSerializationCluster(Zone* zone,
+                                                        intptr_t cid)
+      : MessageSerializationCluster("ExternalTypedData",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    cid),
+        objects_(zone, 0) {}
+  ~ExternalTypedDataMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    ExternalTypedData* data = static_cast<ExternalTypedData*>(object);
+    objects_.Add(data);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      ExternalTypedData* data = objects_[i];
+      s->AssignRef(data);
+      intptr_t length = Smi::Value(data->untag()->length_);
+      s->WriteUnsigned(length);
+
+      intptr_t length_in_bytes = length * element_size;
+      void* passed_data = malloc(length_in_bytes);
+      memmove(passed_data, data->untag()->data_, length_in_bytes);
+      s->finalizable_data()->Put(length_in_bytes,
+                                 passed_data,  // data
+                                 passed_data,  // peer,
+                                 IsolateMessageTypedDataFinalizer);
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<ExternalTypedData*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* data = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(data);
+
+      intptr_t length = data->value.as_external_typed_data.length;
+      s->WriteUnsigned(length);
+
+      s->finalizable_data()->Put(length * element_size,
+                                 data->value.as_external_typed_data.data,
+                                 data->value.as_external_typed_data.peer,
+                                 data->value.as_external_typed_data.callback);
+    }
+  }
+
+ private:
+  GrowableArray<ExternalTypedData*> objects_;
+};
+
+class ExternalTypedDataMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit ExternalTypedDataMessageDeserializationCluster(intptr_t cid)
+      : MessageDeserializationCluster("ExternalTypedData"), cid_(cid) {}
+  ~ExternalTypedDataMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+    intptr_t count = d->ReadUnsigned();
+    ExternalTypedData& data = ExternalTypedData::Handle(d->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      FinalizableData finalizable_data = d->finalizable_data()->Take();
+      data = ExternalTypedData::New(
+          cid_, reinterpret_cast<uint8_t*>(finalizable_data.data), length);
+      intptr_t external_size = length * element_size;
+      data.AddFinalizer(finalizable_data.peer, finalizable_data.callback,
+                        external_size);
+      d->AssignRef(data.ptr());
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+    Dart_TypedData_Type type;
+    switch (cid_) {
+      case kExternalTypedDataInt8ArrayCid:
+        type = Dart_TypedData_kInt8;
+        break;
+      case kExternalTypedDataUint8ArrayCid:
+        type = Dart_TypedData_kUint8;
+        break;
+      case kExternalTypedDataUint8ClampedArrayCid:
+        type = Dart_TypedData_kUint8Clamped;
+        break;
+      case kExternalTypedDataInt16ArrayCid:
+        type = Dart_TypedData_kInt16;
+        break;
+      case kExternalTypedDataUint16ArrayCid:
+        type = Dart_TypedData_kUint16;
+        break;
+      case kExternalTypedDataInt32ArrayCid:
+        type = Dart_TypedData_kInt32;
+        break;
+      case kExternalTypedDataUint32ArrayCid:
+        type = Dart_TypedData_kUint32;
+        break;
+      case kExternalTypedDataInt64ArrayCid:
+        type = Dart_TypedData_kInt64;
+        break;
+      case kExternalTypedDataUint64ArrayCid:
+        type = Dart_TypedData_kUint64;
+        break;
+      case kExternalTypedDataFloat32ArrayCid:
+        type = Dart_TypedData_kFloat32;
+        break;
+      case kExternalTypedDataFloat64ArrayCid:
+        type = Dart_TypedData_kFloat64;
+        break;
+      case kExternalTypedDataInt32x4ArrayCid:
+        type = Dart_TypedData_kInt32x4;
+        break;
+      case kExternalTypedDataFloat32x4ArrayCid:
+        type = Dart_TypedData_kFloat32x4;
+        break;
+      case kExternalTypedDataFloat64x2ArrayCid:
+        type = Dart_TypedData_kFloat64x2;
+        break;
+      default:
+        UNREACHABLE();
+    }
+
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* data = d->Allocate(Dart_CObject_kTypedData);
+      intptr_t length = d->ReadUnsigned();
+      FinalizableData finalizable_data = d->finalizable_data()->Get();
+      data->value.as_typed_data.type = type;
+      data->value.as_typed_data.length = length * element_size;
+      data->value.as_typed_data.values =
+          reinterpret_cast<uint8_t*>(finalizable_data.data);
+      d->AssignRef(data);
+    }
+  }
+
+ private:
+  const intptr_t cid_;
+};
+
+class TypedDataViewMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit TypedDataViewMessageSerializationCluster(Zone* zone, intptr_t cid)
+      : MessageSerializationCluster("TypedDataView",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    cid),
+        objects_(zone, 0) {}
+  ~TypedDataViewMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    TypedDataView* view = static_cast<TypedDataView*>(object);
+    objects_.Add(view);
+
+    s->Push(view->untag()->length());
+    s->Push(view->untag()->typed_data());
+    s->Push(view->untag()->offset_in_bytes());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TypedDataView* view = objects_[i];
+      s->AssignRef(view);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      TypedDataView* view = objects_[i];
+      s->WriteRef(view->untag()->length());
+      s->WriteRef(view->untag()->typed_data());
+      s->WriteRef(view->untag()->offset_in_bytes());
+    }
+  }
+
+ private:
+  GrowableArray<TypedDataView*> objects_;
+};
+
+class TypedDataViewMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit TypedDataViewMessageDeserializationCluster(intptr_t cid)
+      : MessageDeserializationCluster("TypedDataView"), cid_(cid) {}
+  ~TypedDataViewMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(TypedDataView::New(cid_));
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id));
+      view->untag()->set_length(static_cast<SmiPtr>(d->ReadRef()));
+      view->untag()->set_typed_data(
+          static_cast<TypedDataBasePtr>(d->ReadRef()));
+      view->untag()->set_offset_in_bytes(static_cast<SmiPtr>(d->ReadRef()));
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id));
+      view->untag()->RecomputeDataField();
+    }
+    return nullptr;
+  }
+
+  struct Dart_CTypedDataView : public Dart_CObject {
+    Dart_CObject* length;
+    Dart_CObject* typed_data;
+    Dart_CObject* offset_in_bytes;
+  };
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CTypedDataView* view = d->zone()->Alloc<Dart_CTypedDataView>(1);
+      d->AssignRef(view);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      Dart_CTypedDataView* view = static_cast<Dart_CTypedDataView*>(d->Ref(id));
+      view->length = d->ReadRef();
+      view->typed_data = d->ReadRef();
+      view->offset_in_bytes = d->ReadRef();
+    }
+  }
+
+  void PostLoadApi(ApiMessageDeserializer* d) {
+    intptr_t element_size = TypedDataView::ElementSizeInBytes(cid_);
+    Dart_TypedData_Type type;
+    switch (cid_) {
+      case kTypedDataInt8ArrayViewCid:
+        type = Dart_TypedData_kInt8;
+        break;
+      case kTypedDataUint8ArrayViewCid:
+        type = Dart_TypedData_kUint8;
+        break;
+      case kTypedDataUint8ClampedArrayViewCid:
+        type = Dart_TypedData_kUint8Clamped;
+        break;
+      case kTypedDataInt16ArrayViewCid:
+        type = Dart_TypedData_kInt16;
+        break;
+      case kTypedDataUint16ArrayViewCid:
+        type = Dart_TypedData_kUint16;
+        break;
+      case kTypedDataInt32ArrayViewCid:
+        type = Dart_TypedData_kInt32;
+        break;
+      case kTypedDataUint32ArrayViewCid:
+        type = Dart_TypedData_kUint32;
+        break;
+      case kTypedDataInt64ArrayViewCid:
+        type = Dart_TypedData_kInt64;
+        break;
+      case kTypedDataUint64ArrayViewCid:
+        type = Dart_TypedData_kUint64;
+        break;
+      case kTypedDataFloat32ArrayViewCid:
+        type = Dart_TypedData_kFloat32;
+        break;
+      case kTypedDataFloat64ArrayViewCid:
+        type = Dart_TypedData_kFloat64;
+        break;
+      case kTypedDataInt32x4ArrayViewCid:
+        type = Dart_TypedData_kInt32x4;
+        break;
+      case kTypedDataFloat32x4ArrayViewCid:
+        type = Dart_TypedData_kFloat32x4;
+        break;
+      case kTypedDataFloat64x2ArrayViewCid:
+        type = Dart_TypedData_kFloat64x2;
+        break;
+      default:
+        UNREACHABLE();
+    }
+
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      Dart_CTypedDataView* view = static_cast<Dart_CTypedDataView*>(d->Ref(id));
+      if (view->typed_data->type == Dart_CObject_kTypedData) {
+        view->type = Dart_CObject_kTypedData;
+        view->value.as_typed_data.type = type;
+        //            view->typed_data->value.as_typed_data.type;
+        view->value.as_typed_data.length =
+            view->length->value.as_int32 * element_size;
+        view->value.as_typed_data.values =
+            view->typed_data->value.as_typed_data.values +
+            view->offset_in_bytes->value.as_int32;
+      } else if (view->typed_data->type == Dart_CObject_kExternalTypedData) {
+        UNREACHABLE();  ///???
+        view->type = Dart_CObject_kTypedData;
+        view->value.as_typed_data.type = type;
+        //            view->typed_data->value.as_external_typed_data.type;
+        view->value.as_typed_data.length =
+            view->length->value.as_int32 * element_size;
+        view->value.as_typed_data.values =
+            view->typed_data->value.as_external_typed_data.data +
+            view->offset_in_bytes->value.as_int32;
+      } else {
+        UNREACHABLE();
+      }
+    }
+  }
+
+ private:
+  const intptr_t cid_;
+};
+
+class TransferableTypedDataMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  TransferableTypedDataMessageSerializationCluster()
+      : MessageSerializationCluster("TransferableTypedData",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kTransferableTypedDataCid) {}
+  ~TransferableTypedDataMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    TransferableTypedData* transferable =
+        static_cast<TransferableTypedData*>(object);
+    objects_.Add(transferable);
+
+    void* peer = s->thread()->heap()->GetPeer(transferable->ptr());
+    // Assume that object's Peer is only used to track transferrability state.
+    ASSERT(peer != nullptr);
+    TransferableTypedDataPeer* tpeer =
+        reinterpret_cast<TransferableTypedDataPeer*>(peer);
+    if (tpeer->data() == nullptr) {
+      s->IllegalObject(
+          *object,
+          "Illegal argument in isolate message"
+          " : (TransferableTypedData has been transferred already)");
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TransferableTypedData* transferable = objects_[i];
+      s->AssignRef(transferable);
+
+      void* peer = s->thread()->heap()->GetPeer(transferable->ptr());
+      // Assume that object's Peer is only used to track transferrability state.
+      ASSERT(peer != nullptr);
+      TransferableTypedDataPeer* tpeer =
+          reinterpret_cast<TransferableTypedDataPeer*>(peer);
+      intptr_t length = tpeer->length();  // In bytes.
+      void* data = tpeer->data();
+      ASSERT(data != nullptr);
+      s->WriteUnsigned(length);
+      s->finalizable_data()->Put(
+          length, data, tpeer,
+          // Finalizer does nothing - in case of failure to serialize,
+          // [data] remains wrapped in sender's [TransferableTypedData].
+          [](void* data, void* peer) {},
+          // This is invoked on successful serialization of the message
+          [](void* data, void* peer) {
+            TransferableTypedDataPeer* ttpeer =
+                reinterpret_cast<TransferableTypedDataPeer*>(peer);
+            ttpeer->handle()->EnsureFreedExternal(IsolateGroup::Current());
+            ttpeer->ClearData();
+          });
+    }
+  }
+
+ private:
+  GrowableArray<TransferableTypedData*> objects_;
+};
+
+class TransferableTypedDataMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  TransferableTypedDataMessageDeserializationCluster()
+      : MessageDeserializationCluster("TransferableTypedData") {}
+  ~TransferableTypedDataMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      const FinalizableData finalizable_data = d->finalizable_data()->Take();
+      d->AssignRef(TransferableTypedData::New(
+          reinterpret_cast<uint8_t*>(finalizable_data.data), length));
+    }
+  }
+};
+
+class RegExpMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  RegExpMessageSerializationCluster()
+      : MessageSerializationCluster("RegExp",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kRegExpCid) {}
+  ~RegExpMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    RegExp* regexp = static_cast<RegExp*>(object);
+    objects_.Add(regexp);
+
+    s->Push(regexp->capture_name_map());
+    s->Push(regexp->pattern());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      RegExp* regexp = objects_[i];
+      s->AssignRef(regexp);
+      s->WriteRef(regexp->capture_name_map());
+      s->WriteRef(regexp->pattern());
+      s->Write<int32_t>(regexp->num_bracket_expressions());
+      s->Write<int32_t>(regexp->num_registers(true));
+      s->Write<int32_t>(regexp->num_registers(false));
+      s->Write<int>(regexp->flags().value());
+    }
+  }
+
+ private:
+  GrowableArray<RegExp*> objects_;
+};
+
+class RegExpMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  RegExpMessageDeserializationCluster()
+      : MessageDeserializationCluster("RegExp") {}
+  ~RegExpMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    RegExp& regexp = RegExp::Handle(d->zone());
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      regexp = RegExp::New(d->zone());
+      d->AssignRef(regexp.ptr());
+      regexp.untag()->set_capture_name_map(static_cast<ArrayPtr>(d->ReadRef()));
+      regexp.untag()->set_pattern(static_cast<StringPtr>(d->ReadRef()));
+      regexp.set_num_bracket_expressions(d->Read<int32_t>());
+      regexp.set_num_registers(true, d->Read<int32_t>());
+      regexp.set_num_registers(false, d->Read<int32_t>());
+      regexp.set_flags(RegExpFlags(d->Read<int>()));
+    }
+  }
+};
+
+class SendPortMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit SendPortMessageSerializationCluster(Zone* zone)
+      : MessageSerializationCluster("SendPort",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kSendPortCid),
+        objects_(zone, 0) {}
+  ~SendPortMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    SendPort* port = static_cast<SendPort*>(object);
+    objects_.Add(port);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      SendPort* port = objects_[i];
+      s->AssignRef(port);
+      s->Write<Dart_Port>(port->untag()->id_);
+      s->Write<Dart_Port>(port->untag()->origin_id_);
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<SendPort*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* port = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(port);
+      s->Write<Dart_Port>(port->value.as_send_port.id);
+      s->Write<Dart_Port>(port->value.as_send_port.origin_id);
+    }
+  }
+
+ private:
+  GrowableArray<SendPort*> objects_;
+};
+
+class SendPortMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  SendPortMessageDeserializationCluster()
+      : MessageDeserializationCluster("SendPort") {}
+  ~SendPortMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_Port id = d->Read<Dart_Port>();
+      Dart_Port origin_id = d->Read<Dart_Port>();
+      d->AssignRef(SendPort::New(id, origin_id));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* port = d->Allocate(Dart_CObject_kSendPort);
+      port->value.as_send_port.id = d->Read<Dart_Port>();
+      port->value.as_send_port.origin_id = d->Read<Dart_Port>();
+      d->AssignRef(port);
+    }
+  }
+};
+
+class CapabilityMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit CapabilityMessageSerializationCluster(Zone* zone)
+      : MessageSerializationCluster("Capability",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kCapabilityCid),
+        objects_(zone, 0) {}
+  ~CapabilityMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Capability* cap = static_cast<Capability*>(object);
+    objects_.Add(cap);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Capability* cap = objects_[i];
+      s->AssignRef(cap);
+      s->Write<uint64_t>(cap->untag()->id_);
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<Capability*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* cap = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(cap);
+      s->Write<Dart_Port>(cap->value.as_capability.id);
+    }
+  }
+
+ private:
+  GrowableArray<Capability*> objects_;
+};
+
+class CapabilityMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  CapabilityMessageDeserializationCluster()
+      : MessageDeserializationCluster("Capability") {}
+  ~CapabilityMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      uint64_t id = d->Read<uint64_t>();
+      d->AssignRef(Capability::New(id));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* cap = d->Allocate(Dart_CObject_kCapability);
+      cap->value.as_capability.id = d->Read<uint64_t>();
+      d->AssignRef(cap);
+    }
+  }
+};
+
+class WeakPropertyMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  WeakPropertyMessageSerializationCluster()
+      : MessageSerializationCluster("WeakProperty",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kWeakPropertyCid) {}
+  ~WeakPropertyMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    WeakProperty* property = static_cast<WeakProperty*>(object);
+    objects_.Add(property);
+  }
+
+  void RetraceEphemerons(MessageSerializer* s) {
+    for (intptr_t i = 0; i < objects_.length(); i++) {
+      WeakProperty* property = objects_[i];
+      if (s->HasRef(property->untag()->key())) {
+        s->Push(property->untag()->value());
+      }
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      WeakProperty* property = objects_[i];
+      s->AssignRef(property);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      WeakProperty* property = objects_[i];
+      if (s->HasRef(property->untag()->key())) {
+        s->WriteRef(property->untag()->key());
+        s->WriteRef(property->untag()->value());
+      } else {
+        s->WriteRef(Object::null());
+        s->WriteRef(Object::null());
+      }
+    }
+  }
+
+ private:
+  GrowableArray<WeakProperty*> objects_;
+};
+
+class WeakPropertyMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  WeakPropertyMessageDeserializationCluster()
+      : MessageDeserializationCluster("WeakProperty") {}
+  ~WeakPropertyMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(WeakProperty::New());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    ASSERT(!is_canonical());  // Never canonical.
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      WeakPropertyPtr property = static_cast<WeakPropertyPtr>(d->Ref(id));
+      property->untag()->set_key(d->ReadRef());
+      property->untag()->set_value(d->ReadRef());
+    }
+  }
+};
+
+class LinkedHashMapMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  LinkedHashMapMessageSerializationCluster()
+      : MessageSerializationCluster("LinkedHashMap",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kLinkedHashMapCid) {}
+  ~LinkedHashMapMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    LinkedHashMap* map = static_cast<LinkedHashMap*>(object);
+    objects_.Add(map);
+
+    s->Push(map->untag()->type_arguments());
+    s->Push(map->untag()->data());
+    s->Push(map->untag()->used_data());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      LinkedHashMap* map = objects_[i];
+      s->AssignRef(map);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      LinkedHashMap* map = objects_[i];
+      s->WriteRef(map->untag()->type_arguments());
+      s->WriteRef(map->untag()->data());
+      s->WriteRef(map->untag()->used_data());
+    }
+  }
+
+ private:
+  GrowableArray<LinkedHashMap*> objects_;
+};
+
+class LinkedHashMapMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit LinkedHashMapMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("LinkedHashMap", is_canonical) {}
+  ~LinkedHashMapMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(LinkedHashMap::NewUninitialized());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      LinkedHashMapPtr map = static_cast<LinkedHashMapPtr>(d->Ref(id));
+      map->untag()->set_hash_mask(Smi::New(0));
+      map->untag()->set_type_arguments(
+          static_cast<TypeArgumentsPtr>(d->ReadRef()));
+      map->untag()->set_data(static_cast<ArrayPtr>(d->ReadRef()));
+      map->untag()->set_used_data(static_cast<SmiPtr>(d->ReadRef()));
+      map->untag()->set_deleted_keys(Smi::New(0));
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) { return PostLoadLinkedHash(d); }
+};
+
+class LinkedHashSetMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  LinkedHashSetMessageSerializationCluster()
+      : MessageSerializationCluster("LinkedHashSet",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kLinkedHashSetCid) {}
+  ~LinkedHashSetMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    LinkedHashSet* map = static_cast<LinkedHashSet*>(object);
+    objects_.Add(map);
+
+    s->Push(map->untag()->type_arguments());
+    s->Push(map->untag()->data());
+    s->Push(map->untag()->used_data());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      LinkedHashSet* map = objects_[i];
+      s->AssignRef(map);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      LinkedHashSet* map = objects_[i];
+      s->WriteRef(map->untag()->type_arguments());
+      s->WriteRef(map->untag()->data());
+      s->WriteRef(map->untag()->used_data());
+    }
+  }
+
+ private:
+  GrowableArray<LinkedHashSet*> objects_;
+};
+
+class LinkedHashSetMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit LinkedHashSetMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("LinkedHashSet", is_canonical) {}
+  ~LinkedHashSetMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(LinkedHashSet::NewUninitialized());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      LinkedHashSetPtr map = static_cast<LinkedHashSetPtr>(d->Ref(id));
+      map->untag()->set_hash_mask(Smi::New(0));
+      map->untag()->set_type_arguments(
+          static_cast<TypeArgumentsPtr>(d->ReadRef()));
+      map->untag()->set_data(static_cast<ArrayPtr>(d->ReadRef()));
+      map->untag()->set_used_data(static_cast<SmiPtr>(d->ReadRef()));
+      map->untag()->set_deleted_keys(Smi::New(0));
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) { return PostLoadLinkedHash(d); }
+};
+
+class ArrayMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  ArrayMessageSerializationCluster(Zone* zone, bool is_canonical, intptr_t cid)
+      : MessageSerializationCluster("Array",
+                                    is_canonical
+                                        ? MessagePhase::kCanonicalInstances
+                                        : MessagePhase::kNonCanonicalInstances,
+                                    cid,
+                                    is_canonical),
+        objects_(zone, 0) {}
+  ~ArrayMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Array* array = static_cast<Array*>(object);
+    objects_.Add(array);
+
+    s->Push(array->untag()->type_arguments());
+    intptr_t length = Smi::Value(array->untag()->length());
+    for (intptr_t i = 0; i < length; i++) {
+      s->Push(array->untag()->element(i));
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Array* array = objects_[i];
+      s->AssignRef(array);
+      intptr_t length = Smi::Value(array->untag()->length());
+      s->WriteUnsigned(length);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      Array* array = objects_[i];
+      intptr_t length = array->Length();
+      s->WriteRef(array->untag()->type_arguments());
+      for (intptr_t j = 0; j < length; j++) {
+        s->WriteRef(array->untag()->element(j));
+      }
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<Array*>(object));
+
+    for (intptr_t i = 0, n = object->value.as_array.length; i < n; i++) {
+      s->Push(object->value.as_array.values[i]);
+    }
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* array = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(array);
+      s->WriteUnsigned(array->value.as_array.length);
+    }
+  }
+
+  void WriteEdgesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* array = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      intptr_t length = array->value.as_array.length;
+      s->WriteRef(&cobj_null);  // TypeArguments
+      for (intptr_t j = 0; j < length; j++) {
+        s->WriteRef(array->value.as_array.values[j]);
+      }
+    }
+  }
+
+ private:
+  GrowableArray<Array*> objects_;
+};
+
+class ArrayMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit ArrayMessageDeserializationCluster(bool is_canonical, intptr_t cid)
+      : MessageDeserializationCluster("Array", is_canonical), cid_(cid) {}
+  ~ArrayMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      d->AssignRef(Array::New(cid_, length));
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      ArrayPtr array = static_cast<ArrayPtr>(d->Ref(id));
+      intptr_t length = Smi::Value(array->untag()->length());
+      array->untag()->set_type_arguments(
+          static_cast<TypeArgumentsPtr>(d->ReadRef()));
+      for (intptr_t j = 0; j < length; j++) {
+        array->untag()->set_element(j, d->ReadRef());
+      }
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    if (is_canonical()) {
+      SafepointMutexLocker ml(
+          d->isolate_group()->constant_canonicalization_mutex());
+      Instance& instance = Instance::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        instance ^= d->Ref(i);
+        instance = instance.CanonicalizeLocked(d->thread());
+        d->UpdateRef(i, instance);
+      }
+    }
+    return nullptr;
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* array = d->Allocate(Dart_CObject_kArray);
+      intptr_t length = d->ReadUnsigned();
+      array->value.as_array.length = length;
+      if (length == 0) {
+        array->value.as_array.values = NULL;
+      } else {
+        array->value.as_array.values = d->zone()->Alloc<Dart_CObject*>(length);
+      }
+      d->AssignRef(array);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      Dart_CObject* array = d->Ref(id);
+      intptr_t length = array->value.as_array.length;
+      d->ReadRef();  // type_arguments
+      for (intptr_t i = 0; i < length; i++) {
+        array->value.as_array.values[i] = d->ReadRef();
+      }
+    }
+  }
+
+ private:
+  const intptr_t cid_;
+};
+
+class OneByteStringMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit OneByteStringMessageSerializationCluster(Zone* zone,
+                                                    bool is_canonical)
+      : MessageSerializationCluster("OneByteString",
+                                    MessagePhase::kBeforeTypes,
+                                    kOneByteStringCid,
+                                    is_canonical),
+        objects_(zone, 0) {}
+  ~OneByteStringMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    String* str = static_cast<String*>(object);
+    objects_.Add(str);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      String* str = objects_[i];
+      s->AssignRef(str);
+      intptr_t length = str->Length();
+      s->WriteUnsigned(length);
+      NoSafepointScope no_safepoint;
+      s->WriteBytes(OneByteString::DataStart(*str), length * sizeof(uint8_t));
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<String*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* str = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(str);
+
+      const uint8_t* utf8_str =
+          reinterpret_cast<const uint8_t*>(str->value.as_string);
+      intptr_t utf8_len = strlen(str->value.as_string);
+      Utf8::Type type = Utf8::kLatin1;
+      intptr_t latin1_len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
+
+      uint8_t* latin1_str = reinterpret_cast<uint8_t*>(
+          dart::malloc(latin1_len * sizeof(uint8_t)));
+      bool success =
+          Utf8::DecodeToLatin1(utf8_str, utf8_len, latin1_str, latin1_len);
+      ASSERT(success);
+      s->WriteUnsigned(latin1_len);
+      s->WriteBytes(latin1_str, latin1_len);
+      ::free(latin1_str);
+    }
+  }
+
+ private:
+  GrowableArray<String*> objects_;
+};
+
+class OneByteStringMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit OneByteStringMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("OneByteString", is_canonical) {}
+  ~OneByteStringMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      const uint8_t* data = d->CurrentBufferAddress();
+      d->Advance(length * sizeof(uint8_t));
+      d->AssignRef(is_canonical()
+                       ? Symbols::FromLatin1(d->thread(), data, length)
+                       : String::FromLatin1(data, length));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* str = d->Allocate(Dart_CObject_kString);
+      intptr_t latin1_length = d->ReadUnsigned();
+      const uint8_t* data = d->CurrentBufferAddress();
+
+      d->Advance(latin1_length * sizeof(uint8_t));
+
+      intptr_t utf8_len = 0;
+      for (intptr_t i = 0; i < latin1_length; i++) {
+        utf8_len += Utf8::Length(data[i]);
+      }
+      char* utf8_data = d->zone()->Alloc<char>(utf8_len + 1);
+      str->value.as_string = utf8_data;
+      for (intptr_t i = 0; i < latin1_length; i++) {
+        utf8_data += Utf8::Encode(data[i], utf8_data);
+      }
+      *utf8_data = '\0';
+
+      d->AssignRef(str);
+    }
+  }
+};
+
+class TwoByteStringMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit TwoByteStringMessageSerializationCluster(Zone* zone,
+                                                    bool is_canonical)
+      : MessageSerializationCluster("TwoByteString",
+                                    MessagePhase::kBeforeTypes,
+                                    kTwoByteStringCid,
+                                    is_canonical),
+        objects_(zone, 0) {}
+  ~TwoByteStringMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    String* str = static_cast<String*>(object);
+    objects_.Add(str);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      String* str = objects_[i];
+      s->AssignRef(str);
+      intptr_t length = str->Length();
+      s->WriteUnsigned(length);
+      NoSafepointScope no_safepoint;
+      uint16_t* utf16 = TwoByteString::DataStart(*str);
+      s->WriteBytes(reinterpret_cast<const uint8_t*>(utf16),
+                    length * sizeof(uint16_t));
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<String*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* str = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(str);
+
+      const uint8_t* utf8_str =
+          reinterpret_cast<const uint8_t*>(str->value.as_string);
+      intptr_t utf8_len = strlen(str->value.as_string);
+      Utf8::Type type = Utf8::kLatin1;
+      intptr_t utf16_len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
+
+      uint16_t* utf16_str = reinterpret_cast<uint16_t*>(
+          dart::malloc(utf16_len * sizeof(uint16_t)));
+      bool success =
+          Utf8::DecodeToUTF16(utf8_str, utf8_len, utf16_str, utf16_len);
+      ASSERT(success);
+      s->WriteUnsigned(utf16_len);
+      s->WriteBytes(reinterpret_cast<const uint8_t*>(utf16_str),
+                    utf16_len * sizeof(uint16_t));
+      ::free(utf16_str);
+    }
+  }
+
+ private:
+  GrowableArray<String*> objects_;
+};
+
+class TwoByteStringMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit TwoByteStringMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("TwoByteString", is_canonical) {}
+  ~TwoByteStringMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      const uint16_t* data =
+          reinterpret_cast<const uint16_t*>(d->CurrentBufferAddress());
+      d->Advance(length * sizeof(uint16_t));
+      d->AssignRef(is_canonical()
+                       ? Symbols::FromUTF16(d->thread(), data, length)
+                       : String::FromUTF16(data, length));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t j = 0; j < count; j++) {
+      // Read all the UTF-16 code units.
+      intptr_t utf16_length = d->ReadUnsigned();
+      const uint16_t* utf16 =
+          reinterpret_cast<const uint16_t*>(d->CurrentBufferAddress());
+      d->Advance(utf16_length * sizeof(uint16_t));
+
+      // Calculate the UTF-8 length and check if the string can be
+      // UTF-8 encoded.
+      intptr_t utf8_len = 0;
+      bool valid = true;
+      intptr_t i = 0;
+      while (i < utf16_length && valid) {
+        int32_t ch = Utf16::Next(utf16, &i, utf16_length);
+        utf8_len += Utf8::Length(ch);
+        valid = !Utf16::IsSurrogate(ch);
+      }
+      if (!valid) {
+        d->AssignRef(d->Allocate(Dart_CObject_kUnsupported));
+      } else {
+        Dart_CObject* str = d->Allocate(Dart_CObject_kString);
+        char* utf8 = d->zone()->Alloc<char>(utf8_len + 1);
+        str->value.as_string = utf8;
+        i = 0;
+        while (i < utf16_length) {
+          utf8 += Utf8::Encode(Utf16::Next(utf16, &i, utf16_length), utf8);
+        }
+        *utf8 = '\0';
+        d->AssignRef(str);
+      }
+    }
+  }
+};
+
+static const intptr_t kFirstReference = 1;
+static const intptr_t kUnallocatedReference = -1;
+
+BaseSerializer::BaseSerializer(Thread* thread, Zone* zone)
+    : StackResource(thread),
+      zone_(zone),
+      stream_(100),
+      finalizable_data_(new MessageFinalizableData()),
+      clusters_(zone, 0),
+      ephemeron_cluster_(nullptr),
+      num_base_objects_(0),
+      num_written_objects_(0),
+      next_ref_index_(kFirstReference) {}
+
+BaseSerializer::~BaseSerializer() {
+  delete finalizable_data_;
+}
+
+MessageSerializer::MessageSerializer(Thread* thread, bool can_send_any_object)
+    : BaseSerializer(thread, thread->zone()),
+      forward_table_new_(),
+      forward_table_old_(),
+      stack_(thread->zone(), 0),
+      can_send_any_object_(can_send_any_object),
+      exception_message_(nullptr) {
+  isolate()->set_forward_table_new(new WeakTable());
+  isolate()->set_forward_table_old(new WeakTable());
+}
+
+MessageSerializer::~MessageSerializer() {
+  isolate()->set_forward_table_new(nullptr);
+  isolate()->set_forward_table_old(nullptr);
+}
+
+ApiMessageSerializer::ApiMessageSerializer(Zone* zone)
+    : BaseSerializer(nullptr, zone), forward_table_(), stack_(zone, 0) {}
+
+ApiMessageSerializer::~ApiMessageSerializer() {}
+
+void MessageSerializer::Push(ObjectPtr object) {
+  if (MarkObjectId(object, kUnallocatedReference)) {
+    stack_.Add(&Object::ZoneHandle(zone_, object));
+    num_written_objects_++;
+  }
+}
+
+void ApiMessageSerializer::Push(Dart_CObject* object) {
+  if (MarkObjectId(object, kUnallocatedReference)) {
+    stack_.Add(object);
+    num_written_objects_++;
+  }
+}
+
+void MessageSerializer::Trace(Object* object) {
+  intptr_t cid;
+  bool is_canonical;
+  if (!object->ptr()->IsHeapObject()) {
+    cid = kSmiCid;
+    is_canonical = true;
+  } else {
+    cid = object->GetClassId();
+    is_canonical = object->ptr()->untag()->IsCanonical();
+  }
+
+  MessageSerializationCluster* cluster = nullptr;
+  for (MessageSerializationCluster* c : clusters_) {
+    if ((c->cid() == cid) && (c->is_canonical() == is_canonical)) {
+      cluster = c;
+      break;
+    }
+  }
+  if (cluster == nullptr) {
+    if (cid >= kNumPredefinedCids || cid == kInstanceCid) {
+      const Class& clazz =
+          Class::Handle(zone(), isolate_group()->class_table()->At(cid));
+      if (!can_send_any_object()) {
+        ObjectStore* object_store = isolate_group()->object_store();
+        if ((clazz.library() != object_store->core_library()) &&
+            (clazz.library() != object_store->collection_library()) &&
+            (clazz.library() != object_store->typed_data_library())) {
+          IllegalObject(*object,
+                        "Illegal argument in isolate message"
+                        " : (object is a regular Dart Instance)");
+        }
+      }
+      if (clazz.num_native_fields() != 0) {
+        char* chars = OS::SCreate(thread()->zone(),
+                                  "Illegal argument in isolate message"
+                                  " : (object extends NativeWrapper - %s)",
+                                  clazz.ToCString());
+        IllegalObject(*object, chars);
+      }
+    }
+#define ILLEGAL(type)                                                          \
+  if (cid == k##type##Cid) {                                                   \
+    IllegalObject(*object,                                                     \
+                  "Illegal argument in isolate message"                        \
+                  " : (object is a " #type ")");                               \
+  }
+
+    ILLEGAL(FunctionType)
+    ILLEGAL(DynamicLibrary)
+    ILLEGAL(MirrorReference)
+    ILLEGAL(Pointer)
+    ILLEGAL(ReceivePort)
+    ILLEGAL(StackTrace)
+    ILLEGAL(UserTag)
+#undef ILLEGAL
+
+    switch (cid) {
+#define ILLEGAL(type) case kFfi##type##Cid:
+      CLASS_LIST_FFI(ILLEGAL)
+#undef ILLEGAL
+      IllegalObject(*object,
+                    "Native objects (from dart:ffi) such as Pointers and "
+                    "Structs cannot be passed between isolates.");
+    }
+
+    if (cid >= kNumPredefinedCids || cid == kInstanceCid ||
+        cid == kByteBufferCid) {
+      Push(isolate_group()->class_table()->At(cid));
+    }
+    cluster = NewClusterForClass(cid, is_canonical);
+    clusters_.Add(cluster);
+  }
+
+  cluster->Trace(this, object);
+}
+
+bool ApiMessageSerializer::Trace(Dart_CObject* object) {
+  const bool is_canonical = false;
+  intptr_t cid;
+  switch (object->type) {
+    case Dart_CObject_kNull:
+      ForwardRef(object, &cobj_null);
+      return true;
+    case Dart_CObject_kBool:
+      ForwardRef(object, object->value.as_bool ? &cobj_true : &cobj_false);
+      return true;
+    case Dart_CObject_kInt32:
+      cid = Smi::IsValid(object->value.as_int32) ? kSmiCid : kMintCid;
+      break;
+    case Dart_CObject_kInt64:
+      cid = Smi::IsValid(object->value.as_int64) ? kSmiCid : kMintCid;
+      break;
+    case Dart_CObject_kDouble:
+      cid = kDoubleCid;
+      break;
+    case Dart_CObject_kString: {
+      const uint8_t* utf8_str =
+          reinterpret_cast<const uint8_t*>(object->value.as_string);
+      intptr_t utf8_len = strlen(object->value.as_string);
+      if (!Utf8::IsValid(utf8_str, utf8_len)) {
+        return Fail("invalid utf8");
+      }
+      Utf8::Type type = Utf8::kLatin1;
+      intptr_t len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
+      if (len > String::kMaxElements) {
+        return Fail("invalid string length");
+      }
+      cid = type == Utf8::kLatin1 ? kOneByteStringCid : kTwoByteStringCid;
+      break;
+    }
+    case Dart_CObject_kArray:
+      cid = kArrayCid;
+      if (!Array::IsValidLength(object->value.as_array.length)) {
+        return Fail("invalid array length");
+      }
+      break;
+    case Dart_CObject_kTypedData:
+      switch (object->value.as_typed_data.type) {
+        case Dart_TypedData_kInt8:
+          cid = kTypedDataInt8ArrayCid;
+          break;
+        case Dart_TypedData_kUint8:
+          cid = kTypedDataUint8ArrayCid;
+          break;
+        case Dart_TypedData_kUint8Clamped:
+          cid = kTypedDataUint8ClampedArrayCid;
+          break;
+        case Dart_TypedData_kInt16:
+          cid = kTypedDataInt16ArrayCid;
+          break;
+        case Dart_TypedData_kUint16:
+          cid = kTypedDataUint16ArrayCid;
+          break;
+        case Dart_TypedData_kInt32:
+          cid = kTypedDataInt32ArrayCid;
+          break;
+        case Dart_TypedData_kUint32:
+          cid = kTypedDataUint32ArrayCid;
+          break;
+        case Dart_TypedData_kInt64:
+          cid = kTypedDataInt64ArrayCid;
+          break;
+        case Dart_TypedData_kUint64:
+          cid = kTypedDataUint64ArrayCid;
+          break;
+        case Dart_TypedData_kFloat32:
+          cid = kTypedDataFloat32ArrayCid;
+          break;
+        case Dart_TypedData_kFloat64:
+          cid = kTypedDataFloat64ArrayCid;
+          break;
+        case Dart_TypedData_kInt32x4:
+          cid = kTypedDataInt32x4ArrayCid;
+          break;
+        case Dart_TypedData_kFloat32x4:
+          cid = kTypedDataFloat32x4ArrayCid;
+          break;
+        case Dart_TypedData_kFloat64x2:
+          cid = kTypedDataFloat64x2ArrayCid;
+          break;
+        default:
+          return Fail("invalid TypedData type");
+      }
+      {
+        intptr_t len = object->value.as_typed_data.length;
+        if (len < 0 || len > TypedData::MaxElements(cid)) {
+          return Fail("invalid typeddata length");
+        }
+      }
+      break;
+    case Dart_CObject_kExternalTypedData:
+      switch (object->value.as_external_typed_data.type) {
+        case Dart_TypedData_kInt8:
+          cid = kExternalTypedDataInt8ArrayCid;
+          break;
+        case Dart_TypedData_kUint8:
+          cid = kExternalTypedDataUint8ArrayCid;
+          break;
+        case Dart_TypedData_kUint8Clamped:
+          cid = kExternalTypedDataUint8ClampedArrayCid;
+          break;
+        case Dart_TypedData_kInt16:
+          cid = kExternalTypedDataInt16ArrayCid;
+          break;
+        case Dart_TypedData_kUint16:
+          cid = kExternalTypedDataUint16ArrayCid;
+          break;
+        case Dart_TypedData_kInt32:
+          cid = kExternalTypedDataInt32ArrayCid;
+          break;
+        case Dart_TypedData_kUint32:
+          cid = kExternalTypedDataUint32ArrayCid;
+          break;
+        case Dart_TypedData_kInt64:
+          cid = kExternalTypedDataInt64ArrayCid;
+          break;
+        case Dart_TypedData_kUint64:
+          cid = kExternalTypedDataUint64ArrayCid;
+          break;
+        case Dart_TypedData_kFloat32:
+          cid = kExternalTypedDataFloat32ArrayCid;
+          break;
+        case Dart_TypedData_kFloat64:
+          cid = kExternalTypedDataFloat64ArrayCid;
+          break;
+        case Dart_TypedData_kInt32x4:
+          cid = kExternalTypedDataInt32x4ArrayCid;
+          break;
+        case Dart_TypedData_kFloat32x4:
+          cid = kExternalTypedDataFloat32x4ArrayCid;
+          break;
+        case Dart_TypedData_kFloat64x2:
+          cid = kExternalTypedDataFloat64x2ArrayCid;
+          break;
+        default:
+          return Fail("invalid TypedData type");
+      }
+      {
+        intptr_t len = object->value.as_typed_data.length;
+        if (len < 0 || len > ExternalTypedData::MaxElements(cid)) {
+          return Fail("invalid typeddata length");
+        }
+      }
+      break;
+    case Dart_CObject_kSendPort:
+      cid = kSendPortCid;
+      break;
+    case Dart_CObject_kCapability:
+      cid = kCapabilityCid;
+      break;
+    default:
+      return Fail("invalid Dart_CObject type");
+  }
+
+  MessageSerializationCluster* cluster = nullptr;
+  for (MessageSerializationCluster* c : clusters_) {
+    if (c->cid() == cid) {
+      cluster = c;
+      break;
+    }
+  }
+  if (cluster == nullptr) {
+    cluster = NewClusterForClass(cid, is_canonical);
+    clusters_.Add(cluster);
+  }
+
+  cluster->TraceApi(this, object);
+  return true;
+}
+
+void MessageSerializer::IllegalObject(const Object& object,
+                                      const char* message) {
+  exception_message_ = message;
+  thread()->long_jump_base()->Jump(1, Object::snapshot_writer_error());
+}
+
+BaseDeserializer::BaseDeserializer(Zone* zone, Message* message)
+    : zone_(zone),
+      stream_(message->snapshot(), message->snapshot_length()),
+      finalizable_data_(message->finalizable_data()),
+      next_ref_index_(kFirstReference) {}
+
+BaseDeserializer::~BaseDeserializer() {}
+
+MessageSerializationCluster* BaseSerializer::NewClusterForClass(
+    intptr_t cid,
+    bool is_canonical) {
+  Zone* Z = zone_;
+  if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid) ||
+      (cid == kByteBufferCid)) {
+    return new (Z) InstanceMessageSerializationCluster(is_canonical, cid);
+  }
+  if (IsTypedDataViewClassId(cid) || cid == kByteDataViewCid) {
+    return new (Z) TypedDataViewMessageSerializationCluster(Z, cid);
+  }
+  if (IsExternalTypedDataClassId(cid)) {
+    return new (Z) ExternalTypedDataMessageSerializationCluster(Z, cid);
+  }
+  if (IsTypedDataClassId(cid)) {
+    return new (Z) TypedDataMessageSerializationCluster(Z, cid);
+  }
+
+  switch (cid) {
+    case kClassCid:
+      return new (Z) ClassMessageSerializationCluster();
+    case kTypeArgumentsCid:
+      return new (Z) TypeArgumentsMessageSerializationCluster(is_canonical);
+    case kFunctionCid:
+      return new (Z) FunctionMessageSerializationCluster();
+    case kTypeCid:
+      return new (Z) TypeMessageSerializationCluster(is_canonical);
+    case kTypeRefCid:
+      return new (Z) TypeRefMessageSerializationCluster(is_canonical);
+    case kClosureCid:
+      return new (Z) ClosureMessageSerializationCluster(is_canonical);
+    case kSmiCid:
+      return new (Z) SmiMessageSerializationCluster(Z);
+    case kMintCid:
+      return new (Z) MintMessageSerializationCluster(Z, is_canonical);
+    case kDoubleCid:
+      return new (Z) DoubleMessageSerializationCluster(Z, is_canonical);
+    case kGrowableObjectArrayCid:
+      return new (Z) GrowableObjectArrayMessageSerializationCluster();
+    case kRegExpCid:
+      return new (Z) RegExpMessageSerializationCluster();
+    case kSendPortCid:
+      return new (Z) SendPortMessageSerializationCluster(Z);
+    case kCapabilityCid:
+      return new (Z) CapabilityMessageSerializationCluster(Z);
+    case kTransferableTypedDataCid:
+      return new (Z) TransferableTypedDataMessageSerializationCluster();
+    case kWeakPropertyCid:
+      ephemeron_cluster_ = new (Z) WeakPropertyMessageSerializationCluster();
+      return ephemeron_cluster_;
+    case kLinkedHashMapCid:
+      return new (Z) LinkedHashMapMessageSerializationCluster();
+    case kLinkedHashSetCid:
+      return new (Z) LinkedHashSetMessageSerializationCluster();
+    case kArrayCid:
+    case kImmutableArrayCid:
+      return new (Z) ArrayMessageSerializationCluster(Z, is_canonical, cid);
+    case kOneByteStringCid:
+      return new (Z) OneByteStringMessageSerializationCluster(Z, is_canonical);
+    case kTwoByteStringCid:
+      return new (Z) TwoByteStringMessageSerializationCluster(Z, is_canonical);
+    default:
+      break;
+  }
+
+  FATAL("No cluster defined for cid %" Pd, cid);
+  return nullptr;
+}
+
+void BaseSerializer::WriteCluster(MessageSerializationCluster* cluster) {
+  uint64_t cid_and_canonical = (static_cast<uint64_t>(cluster->cid()) << 1) |
+                               (cluster->is_canonical() ? 0x1 : 0x0);
+  WriteUnsigned(cid_and_canonical);
+}
+
+MessageDeserializationCluster* BaseDeserializer::ReadCluster() {
+  const uint64_t cid_and_canonical = ReadUnsigned();
+  const intptr_t cid = (cid_and_canonical >> 1) & kMaxUint32;
+  const bool is_canonical = (cid_and_canonical & 0x1) == 0x1;
+
+  Zone* Z = zone_;
+  if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid) ||
+      (cid == kByteBufferCid)) {
+    return new (Z) InstanceMessageDeserializationCluster(is_canonical);
+  }
+  if (IsTypedDataViewClassId(cid) || cid == kByteDataViewCid) {
+    ASSERT(!is_canonical);
+    return new (Z) TypedDataViewMessageDeserializationCluster(cid);
+  }
+  if (IsExternalTypedDataClassId(cid)) {
+    ASSERT(!is_canonical);
+    return new (Z) ExternalTypedDataMessageDeserializationCluster(cid);
+  }
+  if (IsTypedDataClassId(cid)) {
+    ASSERT(!is_canonical);
+    return new (Z) TypedDataMessageDeserializationCluster(cid);
+  }
+
+  switch (cid) {
+    case kClassCid:
+      ASSERT(!is_canonical);
+      return new (Z) ClassMessageDeserializationCluster();
+    case kTypeArgumentsCid:
+      return new (Z) TypeArgumentsMessageDeserializationCluster(is_canonical);
+    case kFunctionCid:
+      ASSERT(!is_canonical);
+      return new (Z) FunctionMessageDeserializationCluster();
+    case kTypeCid:
+      return new (Z) TypeMessageDeserializationCluster(is_canonical);
+    case kTypeRefCid:
+      return new (Z) TypeRefMessageDeserializationCluster(is_canonical);
+    case kClosureCid:
+      return new (Z) ClosureMessageDeserializationCluster(is_canonical);
+    case kSmiCid:
+      ASSERT(is_canonical);
+      return new (Z) SmiMessageDeserializationCluster();
+    case kMintCid:
+      return new (Z) MintMessageDeserializationCluster(is_canonical);
+    case kDoubleCid:
+      return new (Z) DoubleMessageDeserializationCluster(is_canonical);
+    case kGrowableObjectArrayCid:
+      ASSERT(!is_canonical);
+      return new (Z) GrowableObjectArrayMessageDeserializationCluster();
+    case kRegExpCid:
+      ASSERT(!is_canonical);
+      return new (Z) RegExpMessageDeserializationCluster();
+    case kSendPortCid:
+      ASSERT(!is_canonical);
+      return new (Z) SendPortMessageDeserializationCluster();
+    case kCapabilityCid:
+      ASSERT(!is_canonical);
+      return new (Z) CapabilityMessageDeserializationCluster();
+    case kTransferableTypedDataCid:
+      ASSERT(!is_canonical);
+      return new (Z) TransferableTypedDataMessageDeserializationCluster();
+    case kWeakPropertyCid:
+      ASSERT(!is_canonical);
+      return new (Z) WeakPropertyMessageDeserializationCluster();
+    case kLinkedHashMapCid:
+      return new (Z) LinkedHashMapMessageDeserializationCluster(is_canonical);
+    case kLinkedHashSetCid:
+      return new (Z) LinkedHashSetMessageDeserializationCluster(is_canonical);
+    case kArrayCid:
+    case kImmutableArrayCid:
+      return new (Z) ArrayMessageDeserializationCluster(is_canonical, cid);
+    case kOneByteStringCid:
+      return new (Z) OneByteStringMessageDeserializationCluster(is_canonical);
+    case kTwoByteStringCid:
+      return new (Z) TwoByteStringMessageDeserializationCluster(is_canonical);
+    default:
+      break;
+  }
+
+  FATAL("No cluster defined for cid %" Pd, cid);
+  return nullptr;
+}
+
+void MessageSerializer::AddBaseObjects() {
+  AddBaseObject(Object::null());
+  AddBaseObject(Object::sentinel().ptr());
+  AddBaseObject(Object::transition_sentinel().ptr());
+  AddBaseObject(Object::empty_array().ptr());
+  AddBaseObject(Object::zero_array().ptr());
+  AddBaseObject(Object::dynamic_type().ptr());
+  AddBaseObject(Object::void_type().ptr());
+  AddBaseObject(Object::empty_type_arguments().ptr());
+  AddBaseObject(Bool::True().ptr());
+  AddBaseObject(Bool::False().ptr());
+}
+
+void MessageDeserializer::AddBaseObjects() {
+  AddBaseObject(Object::null());
+  AddBaseObject(Object::sentinel().ptr());
+  AddBaseObject(Object::transition_sentinel().ptr());
+  AddBaseObject(Object::empty_array().ptr());
+  AddBaseObject(Object::zero_array().ptr());
+  AddBaseObject(Object::dynamic_type().ptr());
+  AddBaseObject(Object::void_type().ptr());
+  AddBaseObject(Object::empty_type_arguments().ptr());
+  AddBaseObject(Bool::True().ptr());
+  AddBaseObject(Bool::False().ptr());
+}
+
+void ApiMessageSerializer::AddBaseObjects() {
+  AddBaseObject(&cobj_null);
+  AddBaseObject(&cobj_sentinel);
+  AddBaseObject(&cobj_transition_sentinel);
+  AddBaseObject(&cobj_empty_array);
+  AddBaseObject(&cobj_zero_array);
+  AddBaseObject(&cobj_dynamic_type);
+  AddBaseObject(&cobj_void_type);
+  AddBaseObject(&cobj_empty_type_arguments);
+  AddBaseObject(&cobj_true);
+  AddBaseObject(&cobj_false);
+}
+
+void ApiMessageDeserializer::AddBaseObjects() {
+  AddBaseObject(&cobj_null);
+  AddBaseObject(&cobj_sentinel);
+  AddBaseObject(&cobj_transition_sentinel);
+  AddBaseObject(&cobj_empty_array);
+  AddBaseObject(&cobj_zero_array);
+  AddBaseObject(&cobj_dynamic_type);
+  AddBaseObject(&cobj_void_type);
+  AddBaseObject(&cobj_empty_type_arguments);
+  AddBaseObject(&cobj_true);
+  AddBaseObject(&cobj_false);
+}
+
+void MessageSerializer::Serialize(const Object& root) {
+  AddBaseObjects();
+
+  Push(root.ptr());
+
+  while (stack_.length() > 0) {
+    // Strong references.
+    while (stack_.length() > 0) {
+      Trace(stack_.RemoveLast());
+    }
+
+    // Ephemeron references.
+    if (ephemeron_cluster_ != nullptr) {
+      ephemeron_cluster_->RetraceEphemerons(this);
+    }
+  }
+
+  intptr_t num_objects = num_base_objects_ + num_written_objects_;
+  WriteUnsigned(num_base_objects_);
+  WriteUnsigned(num_objects);
+
+  for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+       i++) {
+    intptr_t num_clusters = 0;
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      num_clusters++;
+    }
+    WriteUnsigned(num_clusters);
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      WriteCluster(cluster);
+      cluster->WriteNodes(this);
+    }
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      cluster->WriteEdges(this);
+    }
+  }
+
+  // We should have assigned a ref to every object we pushed.
+  ASSERT((next_ref_index_ - 1) == num_objects);
+
+  WriteRef(root.ptr());
+}
+
+bool ApiMessageSerializer::Serialize(Dart_CObject* root) {
+  AddBaseObjects();
+
+  Push(root);
+
+  // Strong references only.
+  while (stack_.length() > 0) {
+    if (!Trace(stack_.RemoveLast())) {
+      return false;
+    }
+  }
+
+  intptr_t num_objects = num_base_objects_ + num_written_objects_;
+  WriteUnsigned(num_base_objects_);
+  WriteUnsigned(num_objects);
+
+  for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+       i++) {
+    intptr_t num_clusters = 0;
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      num_clusters++;
+    }
+    WriteUnsigned(num_clusters);
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      WriteCluster(cluster);
+      cluster->WriteNodesApi(this);
+    }
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      cluster->WriteEdgesApi(this);
+    }
+  }
+
+  // We should have assigned a ref to every object we pushed.
+  ASSERT((next_ref_index_ - 1) == num_objects);
+
+  WriteRef(root);
+  return true;
+}
+
+ObjectPtr MessageDeserializer::Deserialize() {
+  intptr_t num_base_objects = ReadUnsigned();
+  intptr_t num_objects = ReadUnsigned();
+
+  refs_ = Array::New(num_objects + kFirstReference);
+
+  AddBaseObjects();
+
+  // Writer and reader must agree on number of base objects.
+  ASSERT_EQUAL(num_base_objects, (next_ref_index_ - kFirstReference));
+
+  Object& error = Object::Handle(zone());
+  for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+       i++) {
+    intptr_t num_clusters = ReadUnsigned();
+    MessageDeserializationCluster** clusters =
+        zone()->Alloc<MessageDeserializationCluster*>(num_clusters);
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      clusters[i] = ReadCluster();
+      clusters[i]->ReadNodesWrapped(this);
+    }
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      clusters[i]->ReadEdges(this);
+    }
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      error = clusters[i]->PostLoad(this);
+      if (error.IsError()) {
+        return error.ptr();  // E.g., an UnwindError during rehashing.
+      }
+    }
+  }
+
+  // We should have completely filled the ref array.
+  ASSERT_EQUAL(next_ref_index_ - kFirstReference, num_objects);
+
+  return ReadRef();
+}
+
+Dart_CObject* ApiMessageDeserializer::Deserialize() {
+  intptr_t num_base_objects = ReadUnsigned();
+  intptr_t num_objects = ReadUnsigned();
+
+  refs_ = zone()->Alloc<Dart_CObject*>(num_objects + kFirstReference);
+
+  AddBaseObjects();
+
+  // Writer and reader must agree on number of base objects.
+  ASSERT_EQUAL(num_base_objects, (next_ref_index_ - kFirstReference));
+
+  for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+       i++) {
+    intptr_t num_clusters = ReadUnsigned();
+    MessageDeserializationCluster** clusters =
+        zone()->Alloc<MessageDeserializationCluster*>(num_clusters);
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      clusters[i] = ReadCluster();
+      clusters[i]->ReadNodesWrappedApi(this);
+    }
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      clusters[i]->ReadEdgesApi(this);
+    }
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      clusters[i]->PostLoadApi(this);
+    }
+  }
+
+  // We should have completely filled the ref array.
+  ASSERT_EQUAL(next_ref_index_ - kFirstReference, num_objects);
+
+  return ReadRef();
+}
+
+std::unique_ptr<Message> WriteMessage(bool can_send_any_object,
+                                      const Object& obj,
+                                      Dart_Port dest_port,
+                                      Message::Priority priority) {
+  if (ApiObjectConverter::CanConvert(obj.ptr())) {
+    return Message::New(dest_port, obj.ptr(), priority);
+  }
+
+  Thread* thread = Thread::Current();
+  MessageSerializer serializer(thread, can_send_any_object);
+
+  volatile bool has_exception = false;
+  {
+    LongJumpScope jump;
+    if (setjmp(*jump.Set()) == 0) {
+      serializer.Serialize(obj);
+    } else {
+      has_exception = true;
+    }
+  }
+
+  if (has_exception) {
+    {
+      NoSafepointScope no_safepoint;
+      ErrorPtr error = thread->StealStickyError();
+      ASSERT(error == Object::snapshot_writer_error().ptr());
+    }
+
+    const String& msg_obj =
+        String::Handle(String::New(serializer.exception_message()));
+    const Array& args = Array::Handle(Array::New(1));
+    args.SetAt(0, msg_obj);
+    Exceptions::ThrowByType(Exceptions::kArgument, args);
+  }
+
+  return serializer.Finish(dest_port, priority);
+}
+
+std::unique_ptr<Message> WriteApiMessage(Zone* zone,
+                                         Dart_CObject* obj,
+                                         Dart_Port dest_port,
+                                         Message::Priority priority) {
+  ApiMessageSerializer serializer(zone);
+  if (!serializer.Serialize(obj)) {
+    return nullptr;
+  }
+  return serializer.Finish(dest_port, priority);
+}
+
+ObjectPtr ReadMessage(Thread* thread, Message* message) {
+  if (message->IsRaw()) {
+    return message->raw_obj();
+  } else {
+    RELEASE_ASSERT(message->IsSnapshot());
+    MessageDeserializer deserializer(thread, message);
+    return deserializer.Deserialize();
+  }
+}
+
+Dart_CObject* ReadApiMessage(Zone* zone, Message* message) {
+  if (message->IsRaw()) {
+    Dart_CObject* result = zone->Alloc<Dart_CObject>(1);
+    ApiObjectConverter::Convert(message->raw_obj(), result);
+    return result;
+  } else {
+    RELEASE_ASSERT(message->IsSnapshot());
+    ApiMessageDeserializer deserializer(zone, message);
+    return deserializer.Deserialize();
+  }
+}
+
+}  // namespace dart
diff --git a/runtime/vm/message_snapshot.h b/runtime/vm/message_snapshot.h
new file mode 100644
index 0000000..d06640e
--- /dev/null
+++ b/runtime/vm/message_snapshot.h
@@ -0,0 +1,32 @@
+// 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_MESSAGE_SNAPSHOT_H_
+#define RUNTIME_VM_MESSAGE_SNAPSHOT_H_
+
+#include <memory>
+
+#include "include/dart_native_api.h"
+#include "vm/message.h"
+#include "vm/object.h"
+
+namespace dart {
+
+std::unique_ptr<Message> WriteMessage(bool can_send_any_object,
+                                      const Object& obj,
+                                      Dart_Port dest_port,
+                                      Message::Priority priority);
+
+std::unique_ptr<Message> WriteApiMessage(Zone* zone,
+                                         Dart_CObject* obj,
+                                         Dart_Port dest_port,
+                                         Message::Priority priority);
+
+ObjectPtr ReadMessage(Thread* thread, Message* message);
+
+Dart_CObject* ReadApiMessage(Zone* zone, Message* message);
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_MESSAGE_SNAPSHOT_H_
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index 20f7748..132ac95 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -12,6 +12,7 @@
 #include "vm/dart_api_message.h"
 #include "vm/dart_api_state.h"
 #include "vm/message.h"
+#include "vm/message_snapshot.h"
 #include "vm/native_message_handler.h"
 #include "vm/port.h"
 #include "vm/service_isolate.h"
@@ -43,9 +44,9 @@
 };
 
 static bool PostCObjectHelper(Dart_Port port_id, Dart_CObject* message) {
-  ApiMessageWriter writer;
-  std::unique_ptr<Message> msg =
-      writer.WriteCMessage(message, port_id, Message::kNormalPriority);
+  AllocOnlyStackZone zone;
+  std::unique_ptr<Message> msg = WriteApiMessage(
+      zone.GetZone(), message, port_id, Message::kNormalPriority);
 
   if (msg == nullptr) {
     return false;
diff --git a/runtime/vm/native_message_handler.cc b/runtime/vm/native_message_handler.cc
index 65d97fd..31639e9 100644
--- a/runtime/vm/native_message_handler.cc
+++ b/runtime/vm/native_message_handler.cc
@@ -9,6 +9,7 @@
 #include "vm/dart_api_message.h"
 #include "vm/isolate.h"
 #include "vm/message.h"
+#include "vm/message_snapshot.h"
 #include "vm/snapshot.h"
 
 namespace dart {
@@ -37,9 +38,7 @@
   // All allocation of objects for decoding the message is done in the
   // zone associated with this scope.
   ApiNativeScope scope;
-  Dart_CObject* object;
-  ApiMessageReader reader(message.get());
-  object = reader.ReadMessage();
+  Dart_CObject* object = ReadApiMessage(scope.zone(), message.get());
   (*func())(message->dest_port(), object);
   return kOK;
 }
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 06dcf56..a1b8649 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -606,7 +606,23 @@
     clazz fake_handle;                                                         \
     builtin_vtables_[k##clazz##Cid] = fake_handle.vtable();                    \
   }
-  CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(INIT_VTABLE)
+  CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(INIT_VTABLE)
+#undef INIT_VTABLE
+
+#define INIT_VTABLE(clazz)                                                     \
+  {                                                                            \
+    LinkedHashMap fake_handle;                                                 \
+    builtin_vtables_[k##clazz##Cid] = fake_handle.vtable();                    \
+  }
+  CLASS_LIST_MAPS(INIT_VTABLE)
+#undef INIT_VTABLE
+
+#define INIT_VTABLE(clazz)                                                     \
+  {                                                                            \
+    LinkedHashSet fake_handle;                                                 \
+    builtin_vtables_[k##clazz##Cid] = fake_handle.vtable();                    \
+  }
+  CLASS_LIST_SETS(INIT_VTABLE)
 #undef INIT_VTABLE
 
 #define INIT_VTABLE(clazz)                                                     \
@@ -1948,6 +1964,15 @@
     RegisterPrivateClass(cls, Symbols::_LinkedHashMap(), lib);
     pending_classes.Add(cls);
 
+    cls = Class::New<LinkedHashSet, RTN::LinkedHashSet>(isolate_group);
+    object_store->set_linked_hash_set_class(cls);
+    cls.set_type_arguments_field_offset(
+        LinkedHashSet::type_arguments_offset(),
+        RTN::LinkedHashSet::type_arguments_offset());
+    cls.set_num_type_arguments_unsafe(1);
+    RegisterPrivateClass(cls, Symbols::_LinkedHashSet(), lib);
+    pending_classes.Add(cls);
+
     // Pre-register the async library so we can place the vm class
     // FutureOr there rather than the core library.
     lib = Library::LookupLibrary(thread, Symbols::DartAsync());
@@ -2372,8 +2397,6 @@
     const bool injected = cls.InjectCIDFields();
     ASSERT(injected);
 
-    isolate_group->object_store()->InitKnownObjects();
-
     // Set up recognized state of all functions (core, math and typed data).
     MethodRecognizer::InitializeState();
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
@@ -2414,6 +2437,9 @@
     cls = Class::New<LinkedHashMap, RTN::LinkedHashMap>(isolate_group);
     object_store->set_linked_hash_map_class(cls);
 
+    cls = Class::New<LinkedHashSet, RTN::LinkedHashSet>(isolate_group);
+    object_store->set_linked_hash_set_class(cls);
+
     cls = Class::New<Float32x4, RTN::Float32x4>(isolate_group);
     object_store->set_float32x4_class(cls);
 
@@ -2995,8 +3021,11 @@
 }
 
 ArrayPtr Class::OffsetToFieldMap(bool original_classes) const {
-  if (untag()->offset_in_words_to_field() == Array::null()) {
-    ASSERT(is_finalized());
+  ASSERT(is_finalized());
+  if (untag()->offset_in_words_to_field<std::memory_order_acquire>() ==
+      Array::null()) {
+    // Even if multiple threads are calling this concurrently, all of them would
+    // compute the same array, so we intentionally don't acquire any locks here.
     const intptr_t length = untag()->host_instance_size_in_words_;
     const Array& array = Array::Handle(Array::New(length, Heap::kOld));
     Class& cls = Class::Handle(this->ptr());
@@ -3012,9 +3041,10 @@
       }
       cls = cls.SuperClass(original_classes);
     }
-    untag()->set_offset_in_words_to_field(array.ptr());
+    untag()->set_offset_in_words_to_field<std::memory_order_release>(
+        array.ptr());
   }
-  return untag()->offset_in_words_to_field();
+  return untag()->offset_in_words_to_field<std::memory_order_acquire>();
 }
 
 bool Class::HasInstanceFields() const {
@@ -3995,8 +4025,11 @@
     // fields.
     const auto host_bitmap = CalculateFieldOffsets();
     if (ptr() == isolate_group->class_table()->At(id())) {
-      // Sets the new size in the class table.
-      isolate_group->class_table()->SetAt(id(), ptr());
+      if (!ClassTable::IsTopLevelCid(id())) {
+        // Unless class is top-level, which don't get instantiated,
+        // sets the new size in the class table.
+        isolate_group->class_table()->UpdateClassSize(id(), ptr());
+      }
       if (FLAG_precompiled_mode && !ClassTable::IsTopLevelCid(id())) {
         isolate_group->shared_class_table()->SetUnboxedFieldsMapAt(id(),
                                                                    host_bitmap);
@@ -7486,7 +7519,7 @@
 }
 
 FunctionPtr Function::implicit_closure_function() const {
-  if (IsClosureFunction() || IsFactory() || IsDispatcherOrImplicitAccessor() ||
+  if (IsClosureFunction() || IsDispatcherOrImplicitAccessor() ||
       IsFieldInitializer() || IsFfiTrampoline()) {
     return Function::null();
   }
@@ -7656,6 +7689,7 @@
 //   native function:         Array[0] = String native name
 //                            Array[1] = Function implicit closure function
 //   regular function:        Function for implicit closure function
+//   constructor, factory:    Function for implicit closure function
 //   ffi trampoline function: FfiTrampolineData  (Dart->C)
 //   dyn inv forwarder:       Array[0] = Function target
 //                            Array[1] = TypeArguments default type args
@@ -7928,19 +7962,11 @@
 bool Function::HasRequiredNamedParameters() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
   if (signature() == FunctionType::null()) {
-    // Signature is not dropped in aot when any named parameter is required.
+    // Signatures for functions with required named parameters are not dropped.
     return false;
   }
 #endif
-  if (!HasOptionalNamedParameters()) {
-    return false;
-  }
-  const FunctionType& sig = FunctionType::Handle(signature());
-  const Array& parameter_names = Array::Handle(sig.named_parameter_names());
-  if (parameter_names.IsNull()) {
-    return false;
-  }
-  return parameter_names.Length() > NumOptionalNamedParameters();
+  return FunctionType::Handle(signature()).HasRequiredNamedParameters();
 }
 
 bool Function::IsRequiredAt(intptr_t index) const {
@@ -8010,6 +8036,15 @@
 #endif
 }
 
+bool FunctionType::HasRequiredNamedParameters() const {
+  const intptr_t num_named_params = NumOptionalNamedParameters();
+  if (num_named_params == 0) return false;
+  // Check for flag slots in the named parameter names array.
+  const auto& parameter_names = Array::Handle(named_parameter_names());
+  ASSERT(!parameter_names.IsNull());
+  return parameter_names.Length() > num_named_params;
+}
+
 static void ReportTooManyTypeParameters(const FunctionType& sig) {
   Report::MessageF(Report::kError, Script::Handle(), TokenPosition::kNoSource,
                    Report::AtLocation,
@@ -8037,10 +8072,41 @@
       value);
 }
 
+bool Function::IsGeneric() const {
+  return FunctionType::IsGeneric(signature());
+}
+intptr_t Function::NumTypeParameters() const {
+  return FunctionType::NumTypeParametersOf(signature());
+}
 intptr_t Function::NumParentTypeArguments() const {
-  // Don't allocate handle in cases where we know it is 0.
-  if (!IsClosureFunction()) return 0;
-  return FunctionType::Handle(signature()).NumParentTypeArguments();
+  return FunctionType::NumParentTypeArgumentsOf(signature());
+}
+intptr_t Function::NumTypeArguments() const {
+  return FunctionType::NumTypeArgumentsOf(signature());
+}
+intptr_t Function::num_fixed_parameters() const {
+  return FunctionType::NumFixedParametersOf(signature());
+}
+bool Function::HasOptionalParameters() const {
+  return FunctionType::HasOptionalParameters(signature());
+}
+bool Function::HasOptionalNamedParameters() const {
+  return FunctionType::HasOptionalNamedParameters(signature());
+}
+bool Function::HasOptionalPositionalParameters() const {
+  return FunctionType::HasOptionalPositionalParameters(signature());
+}
+intptr_t Function::NumOptionalParameters() const {
+  return FunctionType::NumOptionalParametersOf(signature());
+}
+intptr_t Function::NumOptionalPositionalParameters() const {
+  return FunctionType::NumOptionalPositionalParametersOf(signature());
+}
+intptr_t Function::NumOptionalNamedParameters() const {
+  return FunctionType::NumOptionalNamedParametersOf(signature());
+}
+intptr_t Function::NumParameters() const {
+  return FunctionType::NumParametersOf(signature());
 }
 
 TypeParameterPtr Function::TypeParameterAt(intptr_t index,
@@ -8134,10 +8200,6 @@
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-intptr_t Function::NumParameters() const {
-  return num_fixed_parameters() + NumOptionalParameters();
-}
-
 intptr_t Function::NumImplicitParameters() const {
   const UntaggedFunction::Kind k = kind();
   if (k == UntaggedFunction::kConstructor) {
@@ -9099,6 +9161,7 @@
 FunctionPtr Function::NewClosureFunctionWithKind(UntaggedFunction::Kind kind,
                                                  const String& name,
                                                  const Function& parent,
+                                                 bool is_static,
                                                  TokenPosition token_pos,
                                                  const Object& owner) {
   ASSERT((kind == UntaggedFunction::kClosureFunction) ||
@@ -9110,7 +9173,7 @@
                                                  : 0));
   const Function& result = Function::Handle(
       Function::New(signature, name, kind,
-                    /* is_static = */ parent.is_static(),
+                    /* is_static = */ is_static,
                     /* is_const = */ false,
                     /* is_abstract = */ false,
                     /* is_external = */ false,
@@ -9125,7 +9188,8 @@
   // Use the owner defining the parent function and not the class containing it.
   const Object& parent_owner = Object::Handle(parent.RawOwner());
   return NewClosureFunctionWithKind(UntaggedFunction::kClosureFunction, name,
-                                    parent, token_pos, parent_owner);
+                                    parent, parent.is_static(), token_pos,
+                                    parent_owner);
 }
 
 FunctionPtr Function::NewImplicitClosureFunction(const String& name,
@@ -9133,8 +9197,9 @@
                                                  TokenPosition token_pos) {
   // Use the owner defining the parent function and not the class containing it.
   const Object& parent_owner = Object::Handle(parent.RawOwner());
-  return NewClosureFunctionWithKind(UntaggedFunction::kImplicitClosureFunction,
-                                    name, parent, token_pos, parent_owner);
+  return NewClosureFunctionWithKind(
+      UntaggedFunction::kImplicitClosureFunction, name, parent,
+      parent.is_static() || parent.IsConstructor(), token_pos, parent_owner);
 }
 
 bool Function::SafeToClosurize() const {
@@ -9180,7 +9245,7 @@
       zone, NewImplicitClosureFunction(closure_name, *this, token_pos()));
 
   // Set closure function's context scope.
-  if (is_static()) {
+  if (is_static() || IsConstructor()) {
     closure_function.set_context_scope(Object::empty_context_scope());
   } else {
     const ContextScope& context_scope = ContextScope::Handle(
@@ -9191,15 +9256,46 @@
   FunctionType& closure_signature =
       FunctionType::Handle(zone, closure_function.signature());
 
-  // Set closure function's type parameters.
-  // This function cannot be local, therefore it has no generic parent.
-  // Its implicit closure function therefore has no generic parent function
-  // either. That is why it is safe to simply copy the type parameters.
-  closure_signature.SetTypeParameters(
-      TypeParameters::Handle(zone, type_parameters()));
+  // Set closure function's type parameters and result type.
+  if (IsConstructor()) {
+    // Inherit type parameters from owner class.
+    const auto& cls = Class::Handle(zone, Owner());
+    closure_signature.SetTypeParameters(
+        TypeParameters::Handle(zone, cls.type_parameters()));
+    ASSERT(closure_signature.NumTypeParameters() == cls.NumTypeParameters());
 
-  // Set closure function's result type to this result type.
-  closure_signature.set_result_type(AbstractType::Handle(zone, result_type()));
+    Type& result_type = Type::Handle(zone);
+    const Nullability result_nullability =
+        (nnbd_mode() == NNBDMode::kOptedInLib) ? Nullability::kNonNullable
+                                               : Nullability::kLegacy;
+    if (cls.IsGeneric()) {
+      TypeArguments& type_args = TypeArguments::Handle(zone);
+      const intptr_t num_type_params = cls.NumTypeParameters();
+      ASSERT(num_type_params > 0);
+      type_args = TypeArguments::New(num_type_params);
+      TypeParameter& type_param = TypeParameter::Handle(zone);
+      for (intptr_t i = 0; i < num_type_params; i++) {
+        type_param = closure_signature.TypeParameterAt(i);
+        type_args.SetTypeAt(i, type_param);
+      }
+      result_type = Type::New(cls, type_args, result_nullability);
+      result_type ^= ClassFinalizer::FinalizeType(result_type);
+    } else {
+      result_type = cls.DeclarationType();
+      result_type = result_type.ToNullability(result_nullability, Heap::kOld);
+    }
+    closure_signature.set_result_type(result_type);
+  } else {
+    // This function cannot be local, therefore it has no generic parent.
+    // Its implicit closure function therefore has no generic parent function
+    // either. That is why it is safe to simply copy the type parameters.
+    closure_signature.SetTypeParameters(
+        TypeParameters::Handle(zone, type_parameters()));
+
+    // Set closure function's result type to this result type.
+    closure_signature.set_result_type(
+        AbstractType::Handle(zone, result_type()));
+  }
 
   // Set closure function's end token to this end token.
   closure_function.set_end_token_pos(end_token_pos());
@@ -9213,8 +9309,9 @@
   // removing the receiver if this is an instance method and adding the closure
   // object as first parameter.
   const int kClosure = 1;
-  const int has_receiver = is_static() ? 0 : 1;
-  const int num_fixed_params = kClosure - has_receiver + num_fixed_parameters();
+  const int num_implicit_params = NumImplicitParameters();
+  const int num_fixed_params =
+      kClosure - num_implicit_params + num_fixed_parameters();
   const int num_opt_params = NumOptionalParameters();
   const bool has_opt_pos_params = HasOptionalPositionalParameters();
   const int num_params = num_fixed_params + num_opt_params;
@@ -9233,19 +9330,19 @@
   closure_signature.SetParameterTypeAt(0, param_type);
   closure_function.SetParameterNameAt(0, Symbols::ClosureParameter());
   for (int i = kClosure; i < num_pos_params; i++) {
-    param_type = ParameterTypeAt(has_receiver - kClosure + i);
+    param_type = ParameterTypeAt(num_implicit_params - kClosure + i);
     closure_signature.SetParameterTypeAt(i, param_type);
-    param_name = ParameterNameAt(has_receiver - kClosure + i);
+    param_name = ParameterNameAt(num_implicit_params - kClosure + i);
     // Set the name in the function for positional parameters.
     closure_function.SetParameterNameAt(i, param_name);
   }
   for (int i = num_pos_params; i < num_params; i++) {
-    param_type = ParameterTypeAt(has_receiver - kClosure + i);
+    param_type = ParameterTypeAt(num_implicit_params - kClosure + i);
     closure_signature.SetParameterTypeAt(i, param_type);
-    param_name = ParameterNameAt(has_receiver - kClosure + i);
+    param_name = ParameterNameAt(num_implicit_params - kClosure + i);
     // Set the name in the signature for named parameters.
     closure_signature.SetParameterNameAt(i, param_name);
-    if (IsRequiredAt(has_receiver - kClosure + i)) {
+    if (IsRequiredAt(num_implicit_params - kClosure + i)) {
       closure_signature.SetIsRequiredAt(i);
     }
   }
@@ -9254,7 +9351,7 @@
 
   // Change covariant parameter types to either Object? for an opted-in implicit
   // closure or to Object* for a legacy implicit closure.
-  if (!is_static()) {
+  if (!is_static() && !IsConstructor()) {
     BitVector is_covariant(zone, NumParameters());
     BitVector is_generic_covariant_impl(zone, NumParameters());
     kernel::ReadParameterCovariance(*this, &is_covariant,
@@ -9267,7 +9364,7 @@
                       : object_store->legacy_object_type();
     ASSERT(object_type.IsCanonical());
     for (intptr_t i = kClosure; i < num_params; ++i) {
-      const intptr_t original_param_index = has_receiver - kClosure + i;
+      const intptr_t original_param_index = num_implicit_params - kClosure + i;
       if (is_covariant.Contains(original_param_index) ||
           is_generic_covariant_impl.Contains(original_param_index)) {
         closure_signature.SetParameterTypeAt(i, object_type);
@@ -9279,6 +9376,7 @@
   closure_function.SetSignature(closure_signature);
   set_implicit_closure_function(closure_function);
   ASSERT(closure_function.IsImplicitClosureFunction());
+  ASSERT(HasImplicitClosureFunction());
   return closure_function.ptr();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
@@ -10206,10 +10304,6 @@
   untag()->packed_type_parameter_counts_ = packed_type_parameter_counts;
 }
 
-intptr_t FunctionType::NumParameters() const {
-  return num_fixed_parameters() + NumOptionalParameters();
-}
-
 void FunctionType::set_num_implicit_parameters(intptr_t value) const {
   ASSERT(value >= 0);
   untag()->packed_parameter_counts_.Update<PackedNumImplicitParameters>(value);
@@ -10264,6 +10358,8 @@
 void FunctionType::SetNumOptionalParameters(
     intptr_t value,
     bool are_optional_positional) const {
+  // HasOptionalNamedParameters only checks this bit, so only set it if there
+  // are actual named parameters.
   untag()->packed_parameter_counts_.Update<PackedHasNamedOptionalParameters>(
       (value > 0) && !are_optional_positional);
   untag()->packed_parameter_counts_.Update<PackedNumOptionalParameters>(value);
@@ -10735,7 +10831,9 @@
   }
   ASSERT(original.IsOriginal());
   Field& clone = Field::Handle();
-  clone ^= Object::Clone(*this, Heap::kOld);
+  // Using relaxed loading is fine because concurrent fields changes are all
+  // guarded, will be reconciled during optimized code installation.
+  clone ^= Object::Clone(*this, Heap::kOld, /*load_with_relaxed_atomics=*/true);
   clone.SetOriginal(original);
   clone.InheritKernelOffsetFrom(original);
   return clone.ptr();
@@ -11097,7 +11195,8 @@
 
   // We can safely cache the value of the static const field in the initial
   // field table.
-  auto& value = Object::Handle(zone, initial_field_table->At(field_id()));
+  auto& value = Object::Handle(
+      zone, initial_field_table->At(field_id(), /*concurrent_use=*/true));
   if (value.ptr() == Object::sentinel().ptr()) {
     ASSERT(has_initializer());
     value = EvaluateInitializer();
@@ -11119,14 +11218,14 @@
   ASSERT(initial_field_table->At(field_id()) == Object::sentinel().ptr() ||
          initial_field_table->At(field_id()) == value.ptr() ||
          !assert_initializing_store);
-  initial_field_table->SetAt(field_id(), value.IsNull()
-                                             ? Instance::null_instance().ptr()
-                                             : Instance::Cast(value).ptr());
+  initial_field_table->SetAt(field_id(),
+                             value.IsNull() ? Instance::null_instance().ptr()
+                                            : Instance::Cast(value).ptr(),
+                             /*concurrent_use=*/true);
 }
 
 ObjectPtr Field::EvaluateInitializer() const {
-  Thread* const thread = Thread::Current();
-  ASSERT(thread->IsMutatorThread());
+  ASSERT(Thread::Current()->IsMutatorThread());
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (is_static() && is_const()) {
@@ -11134,8 +11233,6 @@
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-  NoOOBMessageScope no_msg_scope(thread);
-  NoReloadScope no_reload_scope(thread);
   const Function& initializer = Function::Handle(EnsureInitializerFunction());
   return DartEntry::InvokeFunction(initializer, Object::empty_array());
 }
@@ -11550,14 +11647,14 @@
 
 void Field::RecordStore(const Object& value) const {
   ASSERT(IsOriginal());
-  if (!IsolateGroup::Current()->use_field_guards()) {
+  Thread* const thread = Thread::Current();
+  if (!thread->isolate_group()->use_field_guards()) {
     return;
   }
 
   // We should never try to record a sentinel.
   ASSERT(value.ptr() != Object::sentinel().ptr());
 
-  Thread* const thread = Thread::Current();
   SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   if ((guarded_cid() == kDynamicCid) ||
       (is_nullable() && value.ptr() == Object::null())) {
@@ -14333,6 +14430,7 @@
   all_libs.Add(&Library::ZoneHandle(Library::ConvertLibrary()));
   all_libs.Add(&Library::ZoneHandle(Library::InternalLibrary()));
   all_libs.Add(&Library::ZoneHandle(Library::FfiLibrary()));
+  all_libs.Add(&Library::ZoneHandle(Library::NativeWrappersLibrary()));
   INTERNAL_LIB_INTRINSIC_LIST(CHECK_FINGERPRINTS_ASM_INTRINSIC);
   OTHER_RECOGNIZED_LIST(CHECK_FINGERPRINTS_OTHER);
   POLYMORPHIC_TARGET_LIST(CHECK_FINGERPRINTS);
@@ -15464,10 +15562,8 @@
   // AOT
   ASSERT(target.HasCode());
   const Code& code = Code::Handle(target.CurrentCode());
-  const Smi& entry_point =
-      Smi::Handle(Smi::FromAlignedAddress(code.EntryPoint()));
   data.SetAt(data_pos + CodeIndexFor(num_args_tested), code);
-  data.SetAt(data_pos + EntryPointIndexFor(num_args_tested), entry_point);
+  data.SetAt(data_pos + EntryPointIndexFor(num_args_tested), target);
 #endif
 }
 
@@ -17852,16 +17948,7 @@
   }
 
 #if defined(DEBUG)
-  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    if (target.IsFunction()) {
-      const auto& function = Function::Cast(target);
-      const auto& entry_point = Smi::Handle(
-          Smi::FromAlignedAddress(Code::EntryPointOf(function.CurrentCode())));
-      ASSERT(LookupLocked(class_id) == entry_point.ptr());
-    }
-  } else {
-    ASSERT(LookupLocked(class_id) == target.ptr());
-  }
+  ASSERT(LookupLocked(class_id) == target.ptr());
 #endif  // define(DEBUG)
 }
 
@@ -17977,25 +18064,6 @@
                      name.ToCString());
 }
 
-void MegamorphicCache::SwitchToBareInstructions() {
-  NoSafepointScope no_safepoint_scope;
-
-  intptr_t capacity = mask() + 1;
-  for (intptr_t i = 0; i < capacity; ++i) {
-    const intptr_t target_index = i * kEntryLength + kTargetFunctionIndex;
-    CompressedObjectPtr* slot = &Array::DataOf(buckets())[target_index];
-    ObjectPtr decompressed_slot = slot->Decompress(buckets()->heap_base());
-    const intptr_t cid = decompressed_slot->GetClassIdMayBeSmi();
-    if (cid == kFunctionCid) {
-      CodePtr code =
-          Function::CurrentCodeOf(Function::RawCast(decompressed_slot));
-      *slot = Smi::FromAlignedAddress(Code::EntryPointOf(code));
-    } else {
-      ASSERT(cid == kSmiCid || cid == kNullCid);
-    }
-  }
-}
-
 void SubtypeTestCache::Init() {
   cached_array_ = Array::New(kTestEntryLength, Heap::kOld);
 }
@@ -18213,7 +18281,6 @@
     buffer->Printf("%sclass id: %" Pd "", separator,
                    Smi::Cast(instance_class_id_or_signature).Value());
   } else {
-    ASSERT(instance_class_id_or_signature.IsFunctionType());
     buffer->Printf(
         "%ssignature: %s", separator,
         FunctionType::Cast(instance_class_id_or_signature).ToCString());
@@ -18252,12 +18319,10 @@
                    function_type_arguments.ToCString());
   }
   if (!instance_parent_function_type_arguments.IsNull()) {
-    ASSERT(instance_class_id_or_signature.IsFunctionType());
     buffer->Printf("%sclosure parent function type arguments: %s", separator,
                    instance_parent_function_type_arguments.ToCString());
   }
   if (!instance_delayed_type_arguments.IsNull()) {
-    ASSERT(instance_class_id_or_signature.IsFunctionType());
     buffer->Printf("%sclosure delayed function type arguments: %s", separator,
                    instance_delayed_type_arguments.ToCString());
   }
@@ -18875,6 +18940,29 @@
   return true;
 }
 
+bool Symbol::IsSymbolCid(Thread* thread, classid_t class_id) {
+  auto object_store = thread->isolate_group()->object_store();
+  return Class::GetClassId(object_store->symbol_class()) == class_id;
+}
+
+// Must be kept in sync with Symbol.hashCode in symbol_patch.dart
+uint32_t Symbol::CanonicalizeHash(Thread* thread, const Instance& instance) {
+  ASSERT(IsSymbolCid(thread, instance.GetClassId()));
+
+  auto zone = thread->zone();
+  auto object_store = thread->isolate_group()->object_store();
+
+  const auto& symbol_name_field =
+      Field::Handle(zone, object_store->symbol_name_field());
+  ASSERT(!symbol_name_field.IsNull());
+
+  // Keep in sync with sdk/lib/_internal/vm/lib/symbol_patch.dart.
+  const auto& name =
+      String::Cast(Object::Handle(zone, instance.GetField(symbol_name_field)));
+  const uint32_t arbitrary_prime = 664597;
+  return 0x1fffffff & (arbitrary_prime * name.CanonicalizeHash());
+}
+
 uint32_t Instance::CanonicalizeHash() const {
   if (GetClassId() == kNullCid) {
     return 2011;  // Matches null_patch.dart.
@@ -18886,42 +18974,49 @@
   }
   Zone* zone = thread->zone();
   const Class& cls = Class::Handle(zone, clazz());
+  const bool is_symbol = Symbol::IsSymbolCid(thread, cls.id());
+
   NoSafepointScope no_safepoint(thread);
-  const intptr_t instance_size = SizeFromClass();
-  ASSERT(instance_size != 0);
-  hash = instance_size / kCompressedWordSize;
-  uword this_addr = reinterpret_cast<uword>(this->untag());
-  Object& obj = Object::Handle(zone);
-  Instance& instance = Instance::Handle(zone);
 
-  const auto unboxed_fields_bitmap =
-      thread->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
-          GetClassId());
+  if (is_symbol) {
+    hash = Symbol::CanonicalizeHash(thread, *this);
+  } else {
+    const intptr_t class_id = cls.id();
+    ASSERT(class_id != 0);
+    hash = class_id;
+    uword this_addr = reinterpret_cast<uword>(this->untag());
+    Object& obj = Object::Handle(zone);
+    Instance& instance = Instance::Handle(zone);
 
-  for (intptr_t offset = Instance::NextFieldOffset();
-       offset < cls.host_next_field_offset(); offset += kCompressedWordSize) {
-    if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
-      if (kCompressedWordSize == 8) {
-        hash = CombineHashes(hash,
-                             *reinterpret_cast<uint32_t*>(this_addr + offset));
-        hash = CombineHashes(
-            hash, *reinterpret_cast<uint32_t*>(this_addr + offset + 4));
+    const auto unboxed_fields_bitmap =
+        thread->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
+            GetClassId());
+
+    for (intptr_t offset = Instance::NextFieldOffset();
+         offset < cls.host_next_field_offset(); offset += kCompressedWordSize) {
+      if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+        if (kCompressedWordSize == 8) {
+          hash = CombineHashes(
+              hash, *reinterpret_cast<uint32_t*>(this_addr + offset));
+          hash = CombineHashes(
+              hash, *reinterpret_cast<uint32_t*>(this_addr + offset + 4));
+        } else {
+          hash = CombineHashes(
+              hash, *reinterpret_cast<uint32_t*>(this_addr + offset));
+        }
       } else {
-        hash = CombineHashes(hash,
-                             *reinterpret_cast<uint32_t*>(this_addr + offset));
-      }
-    } else {
-      obj = reinterpret_cast<CompressedObjectPtr*>(this_addr + offset)
-                ->Decompress(untag()->heap_base());
-      if (obj.IsSentinel()) {
-        hash = CombineHashes(hash, 11);
-      } else {
-        instance ^= obj.ptr();
-        hash = CombineHashes(hash, instance.CanonicalizeHash());
+        obj = reinterpret_cast<CompressedObjectPtr*>(this_addr + offset)
+                  ->Decompress(untag()->heap_base());
+        if (obj.IsSentinel()) {
+          hash = CombineHashes(hash, 11);
+        } else {
+          instance ^= obj.ptr();
+          hash = CombineHashes(hash, instance.CanonicalizeHash());
+        }
       }
     }
+    hash = FinalizeHash(hash, String::kHashBits);
   }
-  hash = FinalizeHash(hash, String::kHashBits);
   thread->heap()->SetCanonicalHash(ptr(), hash);
   return hash;
 }
@@ -19027,8 +19122,9 @@
   Zone* zone = thread->zone();
   Instance& result = Instance::Handle(zone);
   const Class& cls = Class::Handle(zone, this->clazz());
-  SafepointMutexLocker ml(
-      thread->isolate_group()->constant_canonicalization_mutex());
+  ASSERT(thread->isolate_group()
+             ->constant_canonicalization_mutex()
+             ->IsOwnedByCurrentThread());
   result ^= cls.LookupCanonicalInstance(zone, *this);
   return (result.ptr() == this->ptr());
 }
@@ -21005,7 +21101,9 @@
 
   ObjectStore* object_store = isolate_group->object_store();
   {
-    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
+    ASSERT(thread->isolate_group()
+               ->constant_canonicalization_mutex()
+               ->IsOwnedByCurrentThread());
     CanonicalTypeSet table(zone, object_store->canonical_types());
     type ^= table.GetOrNull(CanonicalTypeKey(*this));
     object_store->set_canonical_types(table.Release());
@@ -21362,7 +21460,9 @@
   FunctionType& type = FunctionType::Handle(zone);
   ObjectStore* object_store = isolate_group->object_store();
   {
-    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
+    ASSERT(thread->isolate_group()
+               ->constant_canonicalization_mutex()
+               ->IsOwnedByCurrentThread());
     CanonicalFunctionTypeSet table(zone,
                                    object_store->canonical_function_types());
     type ^= table.GetOrNull(CanonicalFunctionTypeKey(*this));
@@ -21913,7 +22013,9 @@
   TypeParameter& type_parameter = TypeParameter::Handle(zone);
   ObjectStore* object_store = isolate_group->object_store();
   {
-    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
+    ASSERT(thread->isolate_group()
+               ->constant_canonicalization_mutex()
+               ->IsOwnedByCurrentThread());
     CanonicalTypeParameterSet table(zone,
                                     object_store->canonical_type_parameters());
     type_parameter ^= table.GetOrNull(CanonicalTypeParameterKey(*this));
@@ -24417,6 +24519,54 @@
   return zone->PrintToString("_LinkedHashMap len:%" Pd, Length());
 }
 
+LinkedHashSetPtr LinkedHashSet::New(const Array& data,
+                                    const TypedData& index,
+                                    intptr_t hash_mask,
+                                    intptr_t used_data,
+                                    intptr_t deleted_keys,
+                                    Heap::Space space) {
+  ASSERT(IsolateGroup::Current()->object_store()->linked_hash_map_class() !=
+         Class::null());
+  LinkedHashSet& result =
+      LinkedHashSet::Handle(LinkedHashSet::NewUninitialized(space));
+  result.SetData(data);
+  result.SetIndex(index);
+  result.SetHashMask(hash_mask);
+  result.SetUsedData(used_data);
+  result.SetDeletedKeys(deleted_keys);
+  return result.ptr();
+}
+
+LinkedHashSetPtr LinkedHashSet::NewDefault(Heap::Space space) {
+  const Array& data = Array::Handle(Array::New(kInitialIndexSize, space));
+  const TypedData& index = TypedData::Handle(
+      TypedData::New(kTypedDataUint32ArrayCid, kInitialIndexSize, space));
+  // On 32-bit, the top bits are wasted to avoid Mint allocation.
+  static const intptr_t kAvailableBits = (kSmiBits >= 32) ? 32 : kSmiBits;
+  static const intptr_t kInitialHashMask =
+      (1 << (kAvailableBits - kInitialIndexBits)) - 1;
+  return LinkedHashSet::New(data, index, kInitialHashMask, 0, 0, space);
+}
+
+LinkedHashSetPtr LinkedHashSet::NewUninitialized(Heap::Space space) {
+  ASSERT(IsolateGroup::Current()->object_store()->linked_hash_map_class() !=
+         Class::null());
+  LinkedHashSet& result = LinkedHashSet::Handle();
+  {
+    ObjectPtr raw =
+        Object::Allocate(kLinkedHashSetCid, LinkedHashSet::InstanceSize(),
+                         space, LinkedHashSet::ContainsCompressedPointers());
+    NoSafepointScope no_safepoint;
+    result ^= raw;
+  }
+  return result.ptr();
+}
+
+const char* LinkedHashSet::ToCString() const {
+  Zone* zone = Thread::Current()->zone();
+  return zone->PrintToString("LinkedHashSet len:%" Pd, Length());
+}
+
 const char* FutureOr::ToCString() const {
   // FutureOr is an abstract class.
   UNREACHABLE();
@@ -25030,17 +25180,6 @@
   // Ignore function, context, hash.
 }
 
-intptr_t Closure::NumTypeParameters(Thread* thread) const {
-  // Only check for empty here, as the null TAV is used to mean that the
-  // closed-over delayed type parameters were all of dynamic type.
-  if (delayed_type_arguments() != Object::empty_type_arguments().ptr()) {
-    return 0;
-  } else {
-    const auto& closure_function = Function::Handle(thread->zone(), function());
-    return closure_function.NumTypeParameters();
-  }
-}
-
 const char* Closure::ToCString() const {
   auto const thread = Thread::Current();
   auto const zone = thread->zone();
@@ -25101,6 +25240,10 @@
                         const Function& function,
                         const Context& context,
                         Heap::Space space) {
+  // We store null delayed type arguments, not empty ones, in closures with
+  // non-generic functions a) to make method extraction slightly faster and
+  // b) to make the Closure::IsGeneric check fast.
+  // Keep in sync with StubCodeCompiler::GenerateBuildMethodExtractorStub.
   return Closure::New(instantiator_type_arguments, function_type_arguments,
                       function.IsGeneric() ? Object::empty_type_arguments()
                                            : Object::null_type_arguments(),
@@ -25158,7 +25301,7 @@
   // We detect the case of a partial tearoff type application and substitute the
   // type arguments for the type parameters of the function.
   intptr_t num_free_params;
-  if (delayed_type_args.ptr() != Object::empty_type_arguments().ptr()) {
+  if (!IsGeneric() && fun.IsGeneric()) {
     num_free_params = kCurrentAndEnclosingFree;
     fn_type_args = delayed_type_args.Prepend(
         zone, fn_type_args, sig.NumParentTypeArguments(),
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 7cc8063..eb0d9e3 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -215,11 +215,9 @@
 #define OBJECT_SERVICE_SUPPORT(object) protected: /* NOLINT */
 #endif                                            // !PRODUCT
 
-#define SNAPSHOT_READER_SUPPORT(object)                                        \
-  static object##Ptr ReadFrom(SnapshotReader* reader, intptr_t object_id,      \
-                              intptr_t tags, Snapshot::Kind,                   \
-                              bool as_reference);                              \
-  friend class SnapshotReader;
+#define SNAPSHOT_SUPPORT(object)                                               \
+  friend class object##MessageSerializationCluster;                            \
+  friend class object##MessageDeserializationCluster;
 
 #define OBJECT_IMPLEMENTATION(object, super)                                   \
  public: /* NOLINT */                                                          \
@@ -243,7 +241,7 @@
     ASSERT(ptr() != null());                                                   \
     return const_cast<Untagged##object*>(ptr()->untag());                      \
   }                                                                            \
-  SNAPSHOT_READER_SUPPORT(object)                                              \
+  SNAPSHOT_SUPPORT(object)                                                     \
   friend class StackFrame;                                                     \
   friend class Thread;
 
@@ -268,7 +266,7 @@
     return const_cast<Untagged##object*>(ptr()->untag());                      \
   }                                                                            \
   static intptr_t NextFieldOffset() { return -kWordSize; }                     \
-  SNAPSHOT_READER_SUPPORT(rettype)                                             \
+  SNAPSHOT_SUPPORT(rettype)                                                    \
   friend class Object;                                                         \
   friend class StackFrame;                                                     \
   friend class Thread;
@@ -620,6 +618,8 @@
   };
 
  protected:
+  friend ObjectPtr AllocateObject(intptr_t, intptr_t);
+
   // Used for extracting the C++ vtable during bringup.
   Object() : ptr_(null_) {}
 
@@ -858,7 +858,6 @@
   friend void ClassTable::Register(const Class& cls);
   friend void UntaggedObject::Validate(IsolateGroup* isolate_group) const;
   friend class Closure;
-  friend class SnapshotReader;
   friend class InstanceDeserializationCluster;
   friend class OneByteString;
   friend class TwoByteString;
@@ -1173,7 +1172,13 @@
   intptr_t NumTypeArguments() const;
 
   // Return true if this class declares type parameters.
-  bool IsGeneric() const { return NumTypeParameters(Thread::Current()) > 0; }
+  bool IsGeneric() const {
+    // If the declaration is not loaded, fall back onto NumTypeParameters.
+    if (!is_declaration_loaded()) {
+      return NumTypeParameters(Thread::Current()) > 0;
+    }
+    return type_parameters() != Object::null();
+  }
 
   // Returns a canonicalized vector of the type parameters instantiated
   // to bounds. If non-generic, the empty type arguments vector is returned.
@@ -1320,8 +1325,7 @@
   // Check if this class represents the 'Closure' class.
   bool IsClosureClass() const { return id() == kClosureCid; }
   static bool IsClosureClass(ClassPtr cls) {
-    NoSafepointScope no_safepoint;
-    return cls->untag()->id_ == kClosureCid;
+    return GetClassId(cls) == kClosureCid;
   }
 
   static bool IsInFullSnapshot(ClassPtr cls) {
@@ -1330,6 +1334,11 @@
         cls->untag()->library()->untag()->flags_);
   }
 
+  static intptr_t GetClassId(ClassPtr cls) {
+    NoSafepointScope no_safepoint;
+    return cls->untag()->id_;
+  }
+
   // Returns true if the type specified by cls, type_arguments, and nullability
   // is a subtype of the other type.
   static bool IsSubtypeOf(const Class& cls,
@@ -1511,6 +1520,9 @@
   void set_num_native_fields(uint16_t value) const {
     StoreNonPointer(&untag()->num_native_fields_, value);
   }
+  static uint16_t NumNativeFieldsOf(ClassPtr clazz) {
+    return clazz->untag()->num_native_fields_;
+  }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   CodePtr allocation_stub() const { return untag()->allocation_stub(); }
@@ -2467,7 +2479,6 @@
   friend class VMDeserializationRoots;
   friend class ICDataTestTask;
   friend class VMSerializationRoots;
-  friend class SnapshotWriter;
 };
 
 // Often used constants for number of free function type parameters.
@@ -2670,33 +2681,23 @@
     return signature()->untag()->type_parameters();
   }
 
-  intptr_t NumTypeParameters() const {
-    return signature()
-        ->untag()
-        ->packed_type_parameter_counts_
-        .Read<UntaggedFunctionType::PackedNumTypeParameters>();
-  }
-
+  // Returns the number of local type arguments for this function.
+  intptr_t NumTypeParameters() const;
   // Return the cumulative number of type arguments in all parent functions.
   intptr_t NumParentTypeArguments() const;
-
-  // Return the cumulative number of type arguments in all parent functions and
-  // own type arguments.
-  intptr_t NumTypeArguments() const {
-    return NumParentTypeArguments() + NumTypeParameters();
-  }
+  // Return the cumulative number of type arguments for this function, including
+  // type arguments for all parent functions.
+  intptr_t NumTypeArguments() const;
+  // Return whether this function declares local type arguments.
+  bool IsGeneric() const;
+  // Returns whether any parent function of this function is generic.
+  bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
 
   // Return the type parameter declared at index.
   TypeParameterPtr TypeParameterAt(
       intptr_t index,
       Nullability nullability = Nullability::kNonNullable) const;
 
-  // Return true if this function declares type parameters.
-  // Generic dispatchers only set the number without actual type parameters.
-  bool IsGeneric() const { return NumTypeParameters() > 0; }
-  // Return true if any parent function of this function is generic.
-  bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
-
   // Not thread-safe; must be called in the main thread.
   // Sets function's code and code's function.
   void InstallOptimizedCode(const Code& code) const;
@@ -2881,13 +2882,14 @@
 
   static const char* KindToCString(UntaggedFunction::Kind kind);
 
+  bool IsConstructor() const {
+    return kind() == UntaggedFunction::kConstructor;
+  }
   bool IsGenerativeConstructor() const {
-    return (kind() == UntaggedFunction::kConstructor) && !is_static();
+    return IsConstructor() && !is_static();
   }
   bool IsImplicitConstructor() const;
-  bool IsFactory() const {
-    return (kind() == UntaggedFunction::kConstructor) && is_static();
-  }
+  bool IsFactory() const { return IsConstructor() && is_static(); }
 
   bool HasThisParameter() const {
     return IsDynamicFunction(/*allow_abstract=*/true) ||
@@ -2996,46 +2998,25 @@
     return OFFSET_OF(UntaggedFunction, packed_fields_);
   }
 
-  intptr_t num_fixed_parameters() const {
-    return signature()
-        ->untag()
-        ->packed_parameter_counts_
-        .Read<UntaggedFunctionType::PackedNumFixedParameters>();
-  }
-
-  bool HasOptionalParameters() const {
-    return signature()
-               ->untag()
-               ->packed_parameter_counts_
-               .Read<UntaggedFunctionType::PackedNumOptionalParameters>() > 0;
-  }
-  bool HasOptionalNamedParameters() const {
-    return HasOptionalParameters() &&
-           signature()
-               ->untag()
-               ->packed_parameter_counts_
-               .Read<UntaggedFunctionType::PackedHasNamedOptionalParameters>();
-  }
+  // Returns the number of required positional parameters.
+  intptr_t num_fixed_parameters() const;
+  // Returns the number of optional parameters, whether positional or named.
+  bool HasOptionalParameters() const;
+  // Returns whether the function has optional named parameters.
+  bool HasOptionalNamedParameters() const;
+  // Returns whether the fuction has required named parameters.
   bool HasRequiredNamedParameters() const;
-  bool HasOptionalPositionalParameters() const {
-    return HasOptionalParameters() && !HasOptionalNamedParameters();
-  }
-  intptr_t NumOptionalParameters() const {
-    return signature()
-        ->untag()
-        ->packed_parameter_counts_
-        .Read<UntaggedFunctionType::PackedNumOptionalParameters>();
-  }
-  intptr_t NumOptionalPositionalParameters() const {
-    return HasOptionalPositionalParameters() ? NumOptionalParameters() : 0;
-  }
-
-  intptr_t NumOptionalNamedParameters() const {
-    return HasOptionalNamedParameters() ? NumOptionalParameters() : 0;
-  }
-
+  // Returns whether the function has optional positional parameters.
+  bool HasOptionalPositionalParameters() const;
+  // Returns the number of optional parameters, or 0 if none.
+  intptr_t NumOptionalParameters() const;
+  // Returns the number of optional positional parameters, or 0 if none.
+  intptr_t NumOptionalPositionalParameters() const;
+  // Returns the number of optional named parameters, or 0 if none.
+  intptr_t NumOptionalNamedParameters() const;
+  // Returns the total number of both required and optional parameters.
   intptr_t NumParameters() const;
-
+  // Returns the number of implicit parameters, e.g., this for instance methods.
   intptr_t NumImplicitParameters() const;
 
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -3117,7 +3098,7 @@
   bool ForceOptimize() const {
     return IsFfiFromAddress() || IsFfiGetAddress() || IsFfiLoad() ||
            IsFfiStore() || IsFfiTrampoline() || IsTypedDataViewFactory() ||
-           IsUtf8Scan();
+           IsUtf8Scan() || IsGetNativeField();
   }
 
   bool CanBeInlined() const;
@@ -3449,6 +3430,11 @@
     return kind == MethodRecognizer::kFfiGetAddress;
   }
 
+  bool IsGetNativeField() const {
+    const auto kind = recognized_kind();
+    return kind == MethodRecognizer::kGetNativeField;
+  }
+
   bool IsUtf8Scan() const {
     const auto kind = recognized_kind();
     return kind == MethodRecognizer::kUtf8DecoderScan;
@@ -3564,6 +3550,7 @@
   static FunctionPtr NewClosureFunctionWithKind(UntaggedFunction::Kind kind,
                                                 const String& name,
                                                 const Function& parent,
+                                                bool is_static,
                                                 TokenPosition token_pos,
                                                 const Object& owner);
 
@@ -3816,7 +3803,6 @@
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
   friend class Class;
-  friend class SnapshotWriter;
   friend class Parser;  // For set_eval_script.
   // UntaggedFunction::VisitFunctionPointers accesses the private constructor of
   // Function.
@@ -3860,7 +3846,6 @@
   FINAL_HEAP_OBJECT_IMPLEMENTATION(ClosureData, Object);
   friend class Class;
   friend class Function;
-  friend class HeapProfiler;
   friend class Precompiler;  // To wrap parent functions in WSRs.
 };
 
@@ -3901,7 +3886,6 @@
   FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
   friend class Class;
   friend class Function;
-  friend class HeapProfiler;
 };
 
 class Field : public Object {
@@ -4462,7 +4446,6 @@
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Field, Object);
   friend class Class;
-  friend class HeapProfiler;
   friend class UntaggedField;
   friend class FieldSerializationCluster;
   friend class FieldDeserializationCluster;
@@ -6714,7 +6697,6 @@
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Code, Object);
   friend class Class;
   friend class CodeTestHelper;
-  friend class SnapshotWriter;
   friend class StubCode;     // for set_object_pool
   friend class Precompiler;  // for set_object_pool
   friend class FunctionSerializationCluster;
@@ -6767,8 +6749,6 @@
   static const intptr_t kControllerIndex = 1;
   // Expected context index of chained futures in recognized async functions.
   // These are used to unwind async stacks.
-  static const intptr_t kFutureTimeoutFutureIndex = 2;
-  static const intptr_t kFutureWaitFutureIndex = 2;
   static const intptr_t kIsSyncIndex = 2;
 
   struct ArrayTraits {
@@ -6968,8 +6948,6 @@
   void EnsureContains(const Smi& class_id, const Object& target) const;
   ObjectPtr Lookup(const Smi& class_id) const;
 
-  void SwitchToBareInstructions();
-
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(UntaggedMegamorphicCache));
   }
@@ -7443,6 +7421,8 @@
 
   static intptr_t NextFieldOffset() { return sizeof(UntaggedInstance); }
 
+  static intptr_t NativeFieldsOffset() { return sizeof(UntaggedObject); }
+
  protected:
 #ifndef PRODUCT
   virtual void PrintSharedInstanceJSON(JSONObject* jsobj, bool ref) const;
@@ -7508,7 +7488,6 @@
   friend class Pointer;
   friend class DeferredObject;
   friend class RegExp;
-  friend class SnapshotWriter;
   friend class StubCode;
   friend class TypedDataView;
   friend class InstanceSerializationCluster;
@@ -8443,61 +8422,90 @@
 
   bool IsSubtypeOf(const FunctionType& other, Heap::Space space) const;
 
-  intptr_t NumParameters() const;
-
-  // Return the number of type arguments in enclosing signature.
-  intptr_t NumParentTypeArguments() const {
-    return untag()
+  static intptr_t NumParentTypeArgumentsOf(FunctionTypePtr ptr) {
+    return ptr->untag()
         ->packed_type_parameter_counts_.Read<PackedNumParentTypeArguments>();
   }
+  // Return the number of type arguments in the enclosing signature.
+  intptr_t NumParentTypeArguments() const {
+    return NumParentTypeArgumentsOf(ptr());
+  }
   void SetNumParentTypeArguments(intptr_t value) const;
-  intptr_t NumTypeParameters() const {
-    return PackedNumTypeParameters::decode(
-        untag()->packed_type_parameter_counts_);
+  static intptr_t NumTypeParametersOf(FunctionTypePtr ptr) {
+    return ptr->untag()
+        ->packed_type_parameter_counts_.Read<PackedNumTypeParameters>();
   }
+  intptr_t NumTypeParameters() const { return NumTypeParametersOf(ptr()); }
 
-  intptr_t NumTypeArguments() const {
-    return NumParentTypeArguments() + NumTypeParameters();
+  static intptr_t NumTypeArgumentsOf(FunctionTypePtr ptr) {
+    return NumTypeParametersOf(ptr) + NumParentTypeArgumentsOf(ptr);
   }
+  intptr_t NumTypeArguments() const { return NumTypeArgumentsOf(ptr()); }
 
   intptr_t num_implicit_parameters() const {
     return untag()
         ->packed_parameter_counts_.Read<PackedNumImplicitParameters>();
   }
   void set_num_implicit_parameters(intptr_t value) const;
-  intptr_t num_fixed_parameters() const {
-    return untag()->packed_parameter_counts_.Read<PackedNumFixedParameters>();
+
+  static intptr_t NumFixedParametersOf(FunctionTypePtr ptr) {
+    return ptr->untag()
+        ->packed_parameter_counts_.Read<PackedNumFixedParameters>();
   }
+  intptr_t num_fixed_parameters() const { return NumFixedParametersOf(ptr()); }
   void set_num_fixed_parameters(intptr_t value) const;
 
-  bool HasOptionalParameters() const {
-    return untag()
+  static bool HasOptionalParameters(FunctionTypePtr ptr) {
+    return ptr->untag()
                ->packed_parameter_counts_.Read<PackedNumOptionalParameters>() >
            0;
   }
+  bool HasOptionalParameters() const { return HasOptionalParameters(ptr()); }
+
+  static bool HasOptionalNamedParameters(FunctionTypePtr ptr) {
+    return ptr->untag()
+        ->packed_parameter_counts_.Read<PackedHasNamedOptionalParameters>();
+  }
   bool HasOptionalNamedParameters() const {
-    return HasOptionalParameters() &&
-           untag()
-               ->packed_parameter_counts_
-               .Read<PackedHasNamedOptionalParameters>();
+    return HasOptionalNamedParameters(ptr());
+  }
+  bool HasRequiredNamedParameters() const;
+
+  static bool HasOptionalPositionalParameters(FunctionTypePtr ptr) {
+    return !HasOptionalNamedParameters(ptr) && HasOptionalParameters(ptr);
   }
   bool HasOptionalPositionalParameters() const {
-    return HasOptionalParameters() && !HasOptionalNamedParameters();
+    return HasOptionalPositionalParameters(ptr());
+  }
+
+  static intptr_t NumOptionalParametersOf(FunctionTypePtr ptr) {
+    return ptr->untag()
+        ->packed_parameter_counts_.Read<PackedNumOptionalParameters>();
   }
   intptr_t NumOptionalParameters() const {
-    return untag()
-        ->packed_parameter_counts_.Read<PackedNumOptionalParameters>();
+    return NumOptionalParametersOf(ptr());
   }
   void SetNumOptionalParameters(intptr_t num_optional_parameters,
                                 bool are_optional_positional) const;
 
+  static intptr_t NumOptionalPositionalParametersOf(FunctionTypePtr ptr) {
+    return HasOptionalNamedParameters(ptr) ? 0 : NumOptionalParametersOf(ptr);
+  }
   intptr_t NumOptionalPositionalParameters() const {
-    return HasOptionalPositionalParameters() ? NumOptionalParameters() : 0;
+    return NumOptionalPositionalParametersOf(ptr());
   }
 
-  intptr_t NumOptionalNamedParameters() const {
-    return HasOptionalNamedParameters() ? NumOptionalParameters() : 0;
+  static intptr_t NumOptionalNamedParametersOf(FunctionTypePtr ptr) {
+    return HasOptionalNamedParameters(ptr) ? NumOptionalParametersOf(ptr) : 0;
   }
+  intptr_t NumOptionalNamedParameters() const {
+    return NumOptionalNamedParametersOf(ptr());
+  }
+
+  static intptr_t NumParametersOf(FunctionTypePtr ptr) {
+    return NumFixedParametersOf(ptr) + NumOptionalParametersOf(ptr);
+  }
+  intptr_t NumParameters() const { return NumParametersOf(ptr()); }
 
   uint32_t packed_parameter_counts() const {
     return untag()->packed_parameter_counts_;
@@ -8592,7 +8600,10 @@
                                       TrailPtr trail = nullptr) const;
 
   // Return true if this function type declares type parameters.
-  bool IsGeneric() const { return NumTypeParameters() > 0; }
+  static bool IsGeneric(FunctionTypePtr ptr) {
+    return ptr->untag()->type_parameters() != TypeParameters::null();
+  }
+  bool IsGeneric() const { return IsGeneric(ptr()); }
 
   // Return true if any enclosing signature of this signature is generic.
   bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
@@ -8980,6 +8991,11 @@
   static ClassPtr Class();
 
   static intptr_t Value(const SmiPtr raw_smi) { return RawSmiValue(raw_smi); }
+#if defined(DART_COMPRESSED_POINTERS)
+  static intptr_t Value(const CompressedSmiPtr raw_smi) {
+    return Smi::Value(static_cast<SmiPtr>(raw_smi.DecompressSmi()));
+  }
+#endif
 
   static intptr_t RawValue(intptr_t value) {
     return static_cast<intptr_t>(New(value));
@@ -9055,6 +9071,7 @@
  protected:
   // Only Integer::NewXXX is allowed to call Mint::NewXXX directly.
   friend class Integer;
+  friend class MintMessageDeserializationCluster;
 
   static MintPtr New(int64_t value, Heap::Space space = Heap::kNew);
 
@@ -9107,6 +9124,14 @@
   friend class Number;
 };
 
+// TODO(http://dartbug.com/46716): Recognize Symbol in the VM.
+class Symbol : public AllStatic {
+ public:
+  static bool IsSymbolCid(Thread* thread, classid_t class_id);
+
+  static uint32_t CanonicalizeHash(Thread* thread, const Instance& instance);
+};
+
 // String may not be '\0' terminated.
 class String : public Instance {
  public:
@@ -9457,14 +9482,6 @@
     ASSERT(hash_set == value);
   }
 
-  template <typename HandleType, typename ElementType, typename CallbackType>
-  static void ReadFromImpl(SnapshotReader* reader,
-                           String* str_obj,
-                           intptr_t len,
-                           intptr_t tags,
-                           CallbackType new_symbol,
-                           Snapshot::Kind kind);
-
   FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance);
 
   friend class Class;
@@ -9634,20 +9651,14 @@
     return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
   }
 
-  static OneByteStringPtr ReadFrom(SnapshotReader* reader,
-                                   intptr_t object_id,
-                                   intptr_t tags,
-                                   Snapshot::Kind kind,
-                                   bool as_reference);
-
   friend class Class;
   friend class ExternalOneByteString;
   friend class ImageWriter;
-  friend class SnapshotReader;
   friend class String;
   friend class StringHasher;
   friend class Symbols;
   friend class Utf8;
+  friend class OneByteStringMessageSerializationCluster;
 };
 
 class TwoByteString : public AllStatic {
@@ -9760,18 +9771,12 @@
     return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
   }
 
-  static TwoByteStringPtr ReadFrom(SnapshotReader* reader,
-                                   intptr_t object_id,
-                                   intptr_t tags,
-                                   Snapshot::Kind kind,
-                                   bool as_reference);
-
   friend class Class;
   friend class ImageWriter;
-  friend class SnapshotReader;
   friend class String;
   friend class StringHasher;
   friend class Symbols;
+  friend class TwoByteStringMessageSerializationCluster;
 };
 
 class ExternalOneByteString : public AllStatic {
@@ -9855,12 +9860,6 @@
                        Dart_WeakPersistentHandle handle,
                        void* peer);
 
-  static ExternalOneByteStringPtr ReadFrom(SnapshotReader* reader,
-                                           intptr_t object_id,
-                                           intptr_t tags,
-                                           Snapshot::Kind kind,
-                                           bool as_reference);
-
   static intptr_t NextFieldOffset() {
     // Indicates this class cannot be extended by dart code.
     return -kWordSize;
@@ -9869,7 +9868,6 @@
   friend class Class;
   friend class String;
   friend class StringHasher;
-  friend class SnapshotReader;
   friend class Symbols;
   friend class Utf8;
 };
@@ -9951,12 +9949,6 @@
                        Dart_WeakPersistentHandle handle,
                        void* peer);
 
-  static ExternalTwoByteStringPtr ReadFrom(SnapshotReader* reader,
-                                           intptr_t object_id,
-                                           intptr_t tags,
-                                           Snapshot::Kind kind,
-                                           bool as_reference);
-
   static intptr_t NextFieldOffset() {
     // Indicates this class cannot be extended by dart code.
     return -kWordSize;
@@ -9965,7 +9957,6 @@
   friend class Class;
   friend class String;
   friend class StringHasher;
-  friend class SnapshotReader;
   friend class Symbols;
 };
 
@@ -10201,6 +10192,7 @@
   friend class ImmutableArray;
   friend class Object;
   friend class String;
+  friend class MessageDeserializer;
 };
 
 class ImmutableArray : public AllStatic {
@@ -10211,12 +10203,6 @@
 
   static ImmutableArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew);
 
-  static ImmutableArrayPtr ReadFrom(SnapshotReader* reader,
-                                    intptr_t object_id,
-                                    intptr_t tags,
-                                    Snapshot::Kind kind,
-                                    bool as_reference);
-
   static const ClassId kClassId = kImmutableArrayCid;
 
   static intptr_t InstanceSize() { return Array::InstanceSize(); }
@@ -10874,8 +10860,6 @@
     return OFFSET_OF(UntaggedPointer, type_arguments_);
   }
 
-  static intptr_t NextFieldOffset() { return sizeof(UntaggedPointer); }
-
   static const intptr_t kNativeTypeArgPos = 0;
 
   // Fetches the NativeType type argument.
@@ -10885,7 +10869,7 @@
   }
 
  private:
-  HEAP_OBJECT_IMPLEMENTATION(Pointer, Instance);
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(Pointer, Instance);
 
   friend class Class;
 };
@@ -11072,6 +11056,113 @@
   friend class LinkedHashMapDeserializationCluster;
 };
 
+class LinkedHashSet : public LinkedHashBase {
+ public:
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(UntaggedLinkedHashSet));
+  }
+
+  // Allocates a set with some default capacity, just like "new Set()".
+  static LinkedHashSetPtr NewDefault(Heap::Space space = Heap::kNew);
+  static LinkedHashSetPtr New(const Array& data,
+                              const TypedData& index,
+                              intptr_t hash_mask,
+                              intptr_t used_data,
+                              intptr_t deleted_keys,
+                              Heap::Space space = Heap::kNew);
+
+  virtual TypeArgumentsPtr GetTypeArguments() const {
+    return untag()->type_arguments();
+  }
+  virtual void SetTypeArguments(const TypeArguments& value) const {
+    ASSERT(value.IsNull() ||
+           ((value.Length() >= 1) &&
+            value.IsInstantiated() /*&& value.IsCanonical()*/));
+    // TODO(asiva): Values read from a message snapshot are not properly marked
+    // as canonical. See for example tests/isolate/message3_test.dart.
+    untag()->set_type_arguments(value.ptr());
+  }
+
+  TypedDataPtr index() const { return untag()->index(); }
+  void SetIndex(const TypedData& value) const {
+    ASSERT(!value.IsNull());
+    untag()->set_index(value.ptr());
+  }
+
+  ArrayPtr data() const { return untag()->data(); }
+  void SetData(const Array& value) const { untag()->set_data(value.ptr()); }
+
+  SmiPtr hash_mask() const { return untag()->hash_mask(); }
+  void SetHashMask(intptr_t value) const {
+    untag()->set_hash_mask(Smi::New(value));
+  }
+
+  SmiPtr used_data() const { return untag()->used_data(); }
+  void SetUsedData(intptr_t value) const {
+    untag()->set_used_data(Smi::New(value));
+  }
+
+  SmiPtr deleted_keys() const { return untag()->deleted_keys(); }
+  void SetDeletedKeys(intptr_t value) const {
+    untag()->set_deleted_keys(Smi::New(value));
+  }
+
+  intptr_t Length() const {
+    // The map may be uninitialized.
+    if (untag()->used_data() == Object::null()) return 0;
+    if (untag()->deleted_keys() == Object::null()) return 0;
+
+    intptr_t used = Smi::Value(untag()->used_data());
+    intptr_t deleted = Smi::Value(untag()->deleted_keys());
+    return used - deleted;
+  }
+
+  // This iterator differs somewhat from its Dart counterpart (_CompactIterator
+  // in runtime/lib/compact_hash.dart):
+  //  - There are no checks for concurrent modifications.
+  //  - Accessing a key or value before the first call to MoveNext and after
+  //    MoveNext returns false will result in crashes.
+  class Iterator : ValueObject {
+   public:
+    explicit Iterator(const LinkedHashSet& set)
+        : data_(Array::Handle(set.data())),
+          scratch_(Object::Handle()),
+          offset_(-1),
+          length_(Smi::Value(set.used_data())) {}
+
+    bool MoveNext() {
+      while (true) {
+        offset_++;
+        if (offset_ >= length_) {
+          return false;
+        }
+        scratch_ = data_.At(offset_);
+        if (scratch_.ptr() != data_.ptr()) {
+          // Slot is not deleted (self-reference indicates deletion).
+          return true;
+        }
+      }
+    }
+
+    ObjectPtr CurrentKey() const { return data_.At(offset_); }
+
+   private:
+    const Array& data_;
+    Object& scratch_;
+    intptr_t offset_;
+    const intptr_t length_;
+  };
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(LinkedHashSet, LinkedHashBase);
+
+  // Allocate a set, but leave all fields set to null.
+  // Used during deserialization (since set might contain itself as key/value).
+  static LinkedHashSetPtr NewUninitialized(Heap::Space space = Heap::kNew);
+
+  friend class Class;
+};
+
 class Closure : public Instance {
  public:
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -11118,27 +11209,23 @@
   static intptr_t function_offset() {
     return OFFSET_OF(UntaggedClosure, function_);
   }
-
-#if defined(DART_PRECOMPILER)
-  FunctionTypePtr signature() const {
-    return FunctionType::RawCast(WeakSerializationReference::Unwrap(
-        untag()->function()->untag()->signature()));
+  static FunctionPtr FunctionOf(ClosurePtr closure) {
+    return closure.untag()->function();
   }
-#else
-  FunctionTypePtr signature() const {
-    return untag()->function()->untag()->signature();
-  }
-#endif
 
   ContextPtr context() const { return untag()->context(); }
   static intptr_t context_offset() {
     return OFFSET_OF(UntaggedClosure, context_);
   }
+  static ContextPtr ContextOf(ClosurePtr closure) {
+    return closure.untag()->context();
+  }
 
-  bool IsGeneric(Thread* thread) const { return NumTypeParameters(thread) > 0; }
-  intptr_t NumTypeParameters(Thread* thread) const;
-  // No need for num_parent_type_arguments, as a closure is always closed
-  // over its parents type parameters (i.e., function_type_parameters() above).
+  // Returns whether the closure is generic, that is, it has a generic closure
+  // function and no delayed type arguments.
+  bool IsGeneric() const {
+    return delayed_type_arguments() == Object::empty_type_arguments().ptr();
+  }
 
   SmiPtr hash() const { return untag()->hash(); }
   static intptr_t hash_offset() { return OFFSET_OF(UntaggedClosure, hash_); }
@@ -11856,17 +11943,6 @@
                                 const Object& target) {
   ASSERT(target.IsNull() || target.IsFunction() || target.IsSmi());
   array.SetAt((index * kEntryLength) + kClassIdIndex, class_id);
-#if defined(DART_PRECOMPILED_RUNTIME)
-  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    if (target.IsFunction()) {
-      const auto& function = Function::Cast(target);
-      const auto& entry_point = Smi::Handle(
-          Smi::FromAlignedAddress(Code::EntryPointOf(function.CurrentCode())));
-      array.SetAt((index * kEntryLength) + kTargetFunctionIndex, entry_point);
-      return;
-    }
-  }
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
   array.SetAt((index * kEntryLength) + kTargetFunctionIndex, target);
 }
 
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 1bd42fa..e05b2ef 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -944,6 +944,10 @@
       writer_->WriteUnsigned(kLengthData);
       writer_->WriteUnsigned(
           Smi::Value(static_cast<LinkedHashMapPtr>(obj)->untag()->used_data()));
+    } else if (cid == kLinkedHashSetCid) {
+      writer_->WriteUnsigned(kLengthData);
+      writer_->WriteUnsigned(
+          Smi::Value(static_cast<LinkedHashSetPtr>(obj)->untag()->used_data()));
     } else if (cid == kObjectPoolCid) {
       writer_->WriteUnsigned(kLengthData);
       writer_->WriteUnsigned(static_cast<ObjectPoolPtr>(obj)->untag()->length_);
@@ -1158,11 +1162,10 @@
 
         intptr_t field_count = 0;
         intptr_t min_offset = kIntptrMax;
-        for (intptr_t j = 0; OffsetsTable::offsets_table[j].class_id != -1;
-             j++) {
-          if (OffsetsTable::offsets_table[j].class_id == cid) {
+        for (const auto& entry : OffsetsTable::offsets_table()) {
+          if (entry.class_id == cid) {
             field_count++;
-            intptr_t offset = OffsetsTable::offsets_table[j].offset;
+            intptr_t offset = entry.offset;
             min_offset = Utils::Minimum(min_offset, offset);
           }
         }
@@ -1183,16 +1186,15 @@
         }
 
         WriteUnsigned(field_count);
-        for (intptr_t j = 0; OffsetsTable::offsets_table[j].class_id != -1;
-             j++) {
-          if (OffsetsTable::offsets_table[j].class_id == cid) {
+        for (const auto& entry : OffsetsTable::offsets_table()) {
+          if (entry.class_id == cid) {
             intptr_t flags = 1;  // Strong.
             WriteUnsigned(flags);
-            intptr_t offset = OffsetsTable::offsets_table[j].offset;
+            intptr_t offset = entry.offset;
             intptr_t index = (offset - min_offset) / kCompressedWordSize;
             ASSERT(index >= 0);
             WriteUnsigned(index);
-            WriteUtf8(OffsetsTable::offsets_table[j].field_name);
+            WriteUtf8(entry.field_name);
             WriteUtf8("");  // Reserved
           }
         }
@@ -1308,6 +1310,7 @@
     case kInstructionsSectionCid:
     case kInstructionsTableCid:
     case kLinkedHashMapCid:
+    case kLinkedHashSetCid:
     case kMintCid:
     case kNeverCid:
     case kSentinelCid:
diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc
new file mode 100644
index 0000000..7b9189f
--- /dev/null
+++ b/runtime/vm/object_graph_copy.cc
@@ -0,0 +1,1680 @@
+// 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/object_graph_copy.h"
+#include "vm/dart_api_state.h"
+#include "vm/flags.h"
+#include "vm/heap/weak_table.h"
+#include "vm/longjump.h"
+#include "vm/object.h"
+#include "vm/snapshot.h"
+#include "vm/symbols.h"
+
+#define Z zone_
+
+// The list here contains two kinds of classes of objects
+//   * objects that will be shared and we will therefore never need to copy
+//   * objects that user object graphs should never reference
+#define FOR_UNSUPPORTED_CLASSES(V)                                             \
+  V(AbstractType)                                                              \
+  V(ApiError)                                                                  \
+  V(Bool)                                                                      \
+  V(CallSiteData)                                                              \
+  V(Capability)                                                                \
+  V(Class)                                                                     \
+  V(ClosureData)                                                               \
+  V(Code)                                                                      \
+  V(CodeSourceMap)                                                             \
+  V(CompressedStackMaps)                                                       \
+  V(Context)                                                                   \
+  V(ContextScope)                                                              \
+  V(DynamicLibrary)                                                            \
+  V(Error)                                                                     \
+  V(ExceptionHandlers)                                                         \
+  V(FfiTrampolineData)                                                         \
+  V(Field)                                                                     \
+  V(Function)                                                                  \
+  V(FunctionType)                                                              \
+  V(FutureOr)                                                                  \
+  V(ICData)                                                                    \
+  V(Instance)                                                                  \
+  V(Instructions)                                                              \
+  V(InstructionsSection)                                                       \
+  V(InstructionsTable)                                                         \
+  V(Int32x4)                                                                   \
+  V(Integer)                                                                   \
+  V(KernelProgramInfo)                                                         \
+  V(LanguageError)                                                             \
+  V(Library)                                                                   \
+  V(LibraryPrefix)                                                             \
+  V(LoadingUnit)                                                               \
+  V(LocalVarDescriptors)                                                       \
+  V(MegamorphicCache)                                                          \
+  V(Mint)                                                                      \
+  V(MirrorReference)                                                           \
+  V(MonomorphicSmiableCall)                                                    \
+  V(Namespace)                                                                 \
+  V(Number)                                                                    \
+  V(ObjectPool)                                                                \
+  V(PatchClass)                                                                \
+  V(PcDescriptors)                                                             \
+  V(Pointer)                                                                   \
+  V(ReceivePort)                                                               \
+  V(RegExp)                                                                    \
+  V(Script)                                                                    \
+  V(Sentinel)                                                                  \
+  V(SendPort)                                                                  \
+  V(SingleTargetCache)                                                         \
+  V(Smi)                                                                       \
+  V(StackTrace)                                                                \
+  V(SubtypeTestCache)                                                          \
+  V(Type)                                                                      \
+  V(TypeArguments)                                                             \
+  V(TypeParameter)                                                             \
+  V(TypeParameters)                                                            \
+  V(TypeRef)                                                                   \
+  V(TypedDataBase)                                                             \
+  V(UnhandledException)                                                        \
+  V(UnlinkedCall)                                                              \
+  V(UnwindError)                                                               \
+  V(UserTag)                                                                   \
+  V(WeakProperty)                                                              \
+  V(WeakSerializationReference)
+
+namespace dart {
+
+DEFINE_FLAG(bool,
+            enable_fast_object_copy,
+            true,
+            "Enable fast path for fast object copy.");
+DEFINE_FLAG(bool,
+            gc_on_foc_slow_path,
+            false,
+            "Cause a GC when falling off the fast path for fast object copy.");
+
+const char* kFastAllocationFailed = "fast allocation failed";
+
+struct PtrTypes {
+  using Object = ObjectPtr;
+  static const dart::UntaggedObject* UntagObject(Object arg) {
+    return arg.untag();
+  }
+  static const dart::ObjectPtr GetObjectPtr(Object arg) { return arg; }
+  static const dart::Object& HandlifyObject(ObjectPtr arg) {
+    return dart::Object::Handle(arg);
+  }
+
+#define DO(V)                                                                  \
+  using V = V##Ptr;                                                            \
+  static Untagged##V* Untag##V(V##Ptr arg) { return arg.untag(); }             \
+  static V##Ptr Get##V##Ptr(V##Ptr arg) { return arg; }                        \
+  static V##Ptr Cast##V(ObjectPtr arg) { return dart::V::RawCast(arg); }
+  CLASS_LIST_FOR_HANDLES(DO)
+#undef DO
+};
+
+struct HandleTypes {
+  using Object = const dart::Object&;
+  static const dart::UntaggedObject* UntagObject(Object arg) {
+    return arg.ptr().untag();
+  }
+  static dart::ObjectPtr GetObjectPtr(Object arg) { return arg.ptr(); }
+  static Object HandlifyObject(Object arg) { return arg; }
+
+#define DO(V)                                                                  \
+  using V = const dart::V&;                                                    \
+  static Untagged##V* Untag##V(V arg) { return arg.ptr().untag(); }            \
+  static V##Ptr Get##V##Ptr(V arg) { return arg.ptr(); }                       \
+  static V Cast##V(const dart::Object& arg) { return dart::V::Cast(arg); }
+  CLASS_LIST_FOR_HANDLES(DO)
+#undef DO
+};
+
+DART_FORCE_INLINE
+static ObjectPtr Marker() {
+  return Object::unknown_constant().ptr();
+}
+
+DART_FORCE_INLINE
+static bool CanShareObject(uword tags) {
+  if ((tags & UntaggedObject::CanonicalBit::mask_in_place()) != 0) {
+    return true;
+  }
+  const auto cid = UntaggedObject::ClassIdTag::decode(tags);
+  if (cid == kOneByteStringCid) return true;
+  if (cid == kTwoByteStringCid) return true;
+  if (cid == kExternalOneByteStringCid) return true;
+  if (cid == kExternalTwoByteStringCid) return true;
+  if (cid == kMintCid) return true;
+  if (cid == kImmutableArrayCid) return true;
+  if (cid == kNeverCid) return true;
+  if (cid == kSentinelCid) return true;
+#if defined(DART_PRECOMPILED_RUNTIME)
+  // In JIT mode we have field guards enabled which means
+  // double/float32x4/float64x2 boxes can be mutable and we therefore cannot
+  // share them.
+  if (cid == kDoubleCid || cid == kFloat32x4Cid || cid == kFloat64x2Cid) {
+    return true;
+  }
+#endif
+  if (cid == kInt32x4Cid) return true;  // No field guards here.
+  if (cid == kSendPortCid) return true;
+  if (cid == kCapabilityCid) return true;
+  if (cid == kRegExpCid) return true;
+
+  return false;
+}
+
+// Whether executing `get:hashCode` (possibly in a different isolate) on an
+// object with the given [tags] might return a different answer than the source
+// object (if copying is needed) or on the same object (if the object is
+// shared).
+DART_FORCE_INLINE
+static bool MightNeedReHashing(ObjectPtr object) {
+  const uword tags = TagsFromUntaggedObject(object.untag());
+  const auto cid = UntaggedObject::ClassIdTag::decode(tags);
+  // These use structural hash codes and will therefore always result in the
+  // same hash codes.
+  if (cid == kOneByteStringCid) return false;
+  if (cid == kTwoByteStringCid) return false;
+  if (cid == kExternalOneByteStringCid) return false;
+  if (cid == kExternalTwoByteStringCid) return false;
+  if (cid == kMintCid) return false;
+  if (cid == kDoubleCid) return false;
+  if (cid == kBoolCid) return false;
+  if (cid == kSendPortCid) return false;
+  if (cid == kCapabilityCid) return false;
+  if (cid == kNullCid) return false;
+
+  // These are shared and use identity hash codes. If they are used as a key in
+  // a map or a value in a set, they will already have the identity hash code
+  // set.
+  if (cid == kImmutableArrayCid) return false;
+  if (cid == kRegExpCid) return false;
+  if (cid == kInt32x4Cid) return false;
+
+  // We copy those (instead of sharing them) - see [CanShareObjct]. They rely
+  // on the default hashCode implementation which uses identity hash codes
+  // (instead of structural hash code).
+  if (cid == kFloat32x4Cid || cid == kFloat64x2Cid) {
+    return !kDartPrecompiledRuntime;
+  }
+
+  // If the [tags] indicates this is a canonical object we'll share it instead
+  // of copying it. That would suggest we don't have to re-hash maps/sets
+  // containing this object on the receiver side.
+  //
+  // Though the object can be a constant of a user-defined class with a
+  // custom hash code that is misbehaving (e.g one that depends on global field
+  // state, ...). To be on the safe side we'll force re-hashing if such objects
+  // are encountered in maps/sets.
+  //
+  // => We might want to consider changing the implementation to avoid rehashing
+  // in such cases in the future and disambiguate the documentation.
+  return true;
+}
+
+DART_FORCE_INLINE
+uword TagsFromUntaggedObject(UntaggedObject* obj) {
+  return obj->tags_;
+}
+
+DART_FORCE_INLINE
+void SetNewSpaceTaggingWord(ObjectPtr to, classid_t cid, uint32_t size) {
+  uword tags = 0;
+
+  tags = UntaggedObject::SizeTag::update(size, tags);
+  tags = UntaggedObject::ClassIdTag::update(cid, tags);
+  tags = UntaggedObject::OldBit::update(false, tags);
+  tags = UntaggedObject::OldAndNotMarkedBit::update(false, tags);
+  tags = UntaggedObject::OldAndNotRememberedBit::update(false, tags);
+  tags = UntaggedObject::CanonicalBit::update(false, tags);
+  tags = UntaggedObject::NewBit::update(true, tags);
+#if defined(HASH_IN_OBJECT_HEADER)
+  tags = UntaggedObject::HashTag::update(0, tags);
+#endif
+  to.untag()->tags_ = tags;
+}
+
+DART_FORCE_INLINE
+ObjectPtr AllocateObject(intptr_t cid, intptr_t size) {
+#if defined(DART_COMPRESSED_POINTERS)
+  const bool compressed = true;
+#else
+  const bool compressed = false;
+#endif
+  return Object::Allocate(cid, size, Heap::kNew, compressed);
+}
+
+DART_FORCE_INLINE
+void UpdateLengthField(intptr_t cid, ObjectPtr from, ObjectPtr to) {
+  // We share these objects - never copy them.
+  ASSERT(!IsStringClassId(cid));
+  ASSERT(cid != kImmutableArrayCid);
+
+  // We update any in-heap variable sized object with the length to keep the
+  // length and the size in the object header in-sync for the GC.
+  if (cid == kArrayCid) {
+    static_cast<UntaggedArray*>(to.untag())->length_ =
+        static_cast<UntaggedArray*>(from.untag())->length_;
+  } else if (IsTypedDataClassId(cid)) {
+    static_cast<UntaggedTypedDataBase*>(to.untag())->length_ =
+        static_cast<UntaggedTypedDataBase*>(from.untag())->length_;
+  }
+}
+
+void InitializeExternalTypedData(intptr_t cid,
+                                 ExternalTypedDataPtr from,
+                                 ExternalTypedDataPtr to) {
+  auto raw_from = from.untag();
+  auto raw_to = to.untag();
+  const intptr_t length =
+      TypedData::ElementSizeInBytes(cid) * Smi::Value(raw_from->length_);
+
+  auto buffer = static_cast<uint8_t*>(malloc(length));
+  memmove(buffer, raw_from->data_, length);
+  raw_to->length_ = raw_from->length_;
+  raw_to->data_ = buffer;
+}
+
+void InitializeTypedDataView(TypedDataViewPtr obj) {
+  obj.untag()->typed_data_ = TypedDataBase::null();
+  obj.untag()->offset_in_bytes_ = 0;
+  obj.untag()->length_ = 0;
+}
+
+void FreeExternalTypedData(void* isolate_callback_data, void* buffer) {
+  free(buffer);
+}
+
+void FreeTransferablePeer(void* isolate_callback_data, void* peer) {
+  delete static_cast<TransferableTypedDataPeer*>(peer);
+}
+
+class ForwardMapBase {
+ public:
+  explicit ForwardMapBase(Thread* thread)
+      : thread_(thread), zone_(thread->zone()), isolate_(thread->isolate()) {}
+
+ protected:
+  friend class ObjectGraphCopier;
+
+  intptr_t GetObjectId(ObjectPtr object) {
+    if (object->IsNewObject()) {
+      return isolate_->forward_table_new()->GetValueExclusive(object);
+    } else {
+      return isolate_->forward_table_old()->GetValueExclusive(object);
+    }
+  }
+  void SetObjectId(ObjectPtr object, intptr_t id) {
+    if (object->IsNewObject()) {
+      isolate_->forward_table_new()->SetValueExclusive(object, id);
+    } else {
+      isolate_->forward_table_old()->SetValueExclusive(object, id);
+    }
+  }
+
+  void FinalizeTransferable(const TransferableTypedData& from,
+                            const TransferableTypedData& to) {
+    // Get the old peer.
+    auto fpeer = static_cast<TransferableTypedDataPeer*>(
+        thread_->heap()->GetPeer(from.ptr()));
+    ASSERT(fpeer != nullptr && fpeer->data() != nullptr);
+    const intptr_t length = fpeer->length();
+
+    // Allocate new peer object with (data, length).
+    auto tpeer = new TransferableTypedDataPeer(fpeer->data(), length);
+    thread_->heap()->SetPeer(to.ptr(), tpeer);
+
+    // Move the handle itself to the new object.
+    fpeer->handle()->EnsureFreedExternal(thread_->isolate_group());
+    tpeer->set_handle(FinalizablePersistentHandle::New(
+        thread_->isolate_group(), to, tpeer, FreeTransferablePeer, length,
+        /*auto_delete=*/true));
+    fpeer->ClearData();
+  }
+
+  void FinalizeExternalTypedData(const ExternalTypedData& to) {
+    to.AddFinalizer(to.DataAddr(0), &FreeExternalTypedData, to.LengthInBytes());
+  }
+
+  Thread* thread_;
+  Zone* zone_;
+  Isolate* isolate_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ForwardMapBase);
+};
+
+class FastForwardMap : public ForwardMapBase {
+ public:
+  explicit FastForwardMap(Thread* thread)
+      : ForwardMapBase(thread),
+        raw_from_to_(thread->zone(), 20),
+        raw_transferables_from_to_(thread->zone(), 0),
+        raw_objects_to_rehash_(thread->zone(), 0) {
+    raw_from_to_.Resize(2);
+    raw_from_to_[0] = Object::null();
+    raw_from_to_[1] = Object::null();
+    fill_cursor_ = 2;
+  }
+
+  ObjectPtr ForwardedObject(ObjectPtr object) {
+    const intptr_t id = GetObjectId(object);
+    if (id == 0) return Marker();
+    return raw_from_to_[id + 1];
+  }
+
+  void Insert(ObjectPtr from, ObjectPtr to) {
+    ASSERT(ForwardedObject(from) == Marker());
+    ASSERT(raw_from_to_.length() == raw_from_to_.length());
+    const auto id = raw_from_to_.length();
+    SetObjectId(from, id);
+    raw_from_to_.Resize(id + 2);
+    raw_from_to_[id] = from;
+    raw_from_to_[id + 1] = to;
+  }
+
+  void AddTransferable(TransferableTypedDataPtr from,
+                       TransferableTypedDataPtr to) {
+    raw_transferables_from_to_.Add(from);
+    raw_transferables_from_to_.Add(to);
+  }
+  void AddExternalTypedData(ExternalTypedDataPtr to) {
+    raw_external_typed_data_to_.Add(to);
+  }
+
+  void AddObjectToRehash(ObjectPtr to) { raw_objects_to_rehash_.Add(to); }
+
+ private:
+  friend class FastObjectCopy;
+  friend class ObjectGraphCopier;
+
+  GrowableArray<ObjectPtr> raw_from_to_;
+  GrowableArray<TransferableTypedDataPtr> raw_transferables_from_to_;
+  GrowableArray<ExternalTypedDataPtr> raw_external_typed_data_to_;
+  GrowableArray<ObjectPtr> raw_objects_to_rehash_;
+  intptr_t fill_cursor_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(FastForwardMap);
+};
+
+class SlowForwardMap : public ForwardMapBase {
+ public:
+  explicit SlowForwardMap(Thread* thread)
+      : ForwardMapBase(thread),
+        from_to_(thread->zone(), 20),
+        transferables_from_to_(thread->zone(), 0) {
+    from_to_.Resize(2);
+    from_to_[0] = &Object::null_object();
+    from_to_[1] = &Object::null_object();
+    fill_cursor_ = 2;
+  }
+
+  ObjectPtr ForwardedObject(ObjectPtr object) {
+    const intptr_t id = GetObjectId(object);
+    if (id == 0) return Marker();
+    return from_to_[id + 1]->ptr();
+  }
+
+  void Insert(ObjectPtr from, ObjectPtr to) {
+    ASSERT(ForwardedObject(from) == Marker());
+    const auto id = from_to_.length();
+    SetObjectId(from, id);
+    from_to_.Resize(id + 2);
+    from_to_[id] = &Object::Handle(Z, from);
+    from_to_[id + 1] = &Object::Handle(Z, to);
+  }
+
+  void AddTransferable(const TransferableTypedData& from,
+                       const TransferableTypedData& to) {
+    transferables_from_to_.Add(&TransferableTypedData::Handle(from.ptr()));
+    transferables_from_to_.Add(&TransferableTypedData::Handle(to.ptr()));
+  }
+
+  void AddExternalTypedData(ExternalTypedDataPtr to) {
+    external_typed_data_.Add(&ExternalTypedData::Handle(to));
+  }
+
+  void AddObjectToRehash(const Object& to) {
+    objects_to_rehash_.Add(&Object::Handle(to.ptr()));
+  }
+
+  void FinalizeTransferables() {
+    for (intptr_t i = 0; i < transferables_from_to_.length(); i += 2) {
+      auto from = transferables_from_to_[i];
+      auto to = transferables_from_to_[i + 1];
+      FinalizeTransferable(*from, *to);
+    }
+  }
+
+  void FinalizeExternalTypedData() {
+    for (intptr_t i = 0; i < external_typed_data_.length(); i++) {
+      auto to = external_typed_data_[i];
+      ForwardMapBase::FinalizeExternalTypedData(*to);
+    }
+  }
+
+ private:
+  friend class SlowObjectCopy;
+  friend class ObjectGraphCopier;
+
+  GrowableArray<const Object*> from_to_;
+  GrowableArray<const TransferableTypedData*> transferables_from_to_;
+  GrowableArray<const ExternalTypedData*> external_typed_data_;
+  GrowableArray<const Object*> objects_to_rehash_;
+  intptr_t fill_cursor_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(SlowForwardMap);
+};
+
+class ObjectCopyBase {
+ public:
+  explicit ObjectCopyBase(Thread* thread)
+      : thread_(thread),
+        heap_base_(thread->heap_base()),
+        zone_(thread->zone()),
+        heap_(thread->isolate_group()->heap()),
+        class_table_(thread->isolate_group()->class_table()),
+        new_space_(heap_->new_space()),
+        tmp_(Object::Handle(thread->zone())) {}
+  ~ObjectCopyBase() {}
+
+ protected:
+  static ObjectPtr LoadPointer(ObjectPtr src, intptr_t offset) {
+    return src.untag()->LoadPointer(reinterpret_cast<ObjectPtr*>(
+        reinterpret_cast<uint8_t*>(src.untag()) + offset));
+  }
+  static CompressedObjectPtr LoadCompressedPointer(ObjectPtr src,
+                                                   intptr_t offset) {
+    return src.untag()->LoadPointer(reinterpret_cast<CompressedObjectPtr*>(
+        reinterpret_cast<uint8_t*>(src.untag()) + offset));
+  }
+  static compressed_uword LoadCompressedNonPointerWord(ObjectPtr src,
+                                                       intptr_t offset) {
+    return *reinterpret_cast<compressed_uword*>(
+        reinterpret_cast<uint8_t*>(src.untag()) + offset);
+  }
+  static void StorePointerBarrier(ObjectPtr obj,
+                                  intptr_t offset,
+                                  ObjectPtr value) {
+    obj.untag()->StorePointer(
+        reinterpret_cast<ObjectPtr*>(reinterpret_cast<uint8_t*>(obj.untag()) +
+                                     offset),
+        value);
+  }
+  static void StoreCompressedPointerBarrier(ObjectPtr obj,
+                                            intptr_t offset,
+                                            ObjectPtr value) {
+    obj.untag()->StoreCompressedPointer(
+        reinterpret_cast<CompressedObjectPtr*>(
+            reinterpret_cast<uint8_t*>(obj.untag()) + offset),
+        value);
+  }
+  void StoreCompressedLargeArrayPointerBarrier(ObjectPtr obj,
+                                               intptr_t offset,
+                                               ObjectPtr value) {
+    obj.untag()->StoreCompressedArrayPointer(
+        reinterpret_cast<CompressedObjectPtr*>(
+            reinterpret_cast<uint8_t*>(obj.untag()) + offset),
+        value, thread_);
+  }
+  static void StorePointerNoBarrier(ObjectPtr obj,
+                                    intptr_t offset,
+                                    ObjectPtr value) {
+    *reinterpret_cast<ObjectPtr*>(reinterpret_cast<uint8_t*>(obj.untag()) +
+                                  offset) = value;
+  }
+  template <typename T = ObjectPtr>
+  static void StoreCompressedPointerNoBarrier(ObjectPtr obj,
+                                              intptr_t offset,
+                                              T value) {
+    *reinterpret_cast<CompressedObjectPtr*>(
+        reinterpret_cast<uint8_t*>(obj.untag()) + offset) = value;
+  }
+  static void StoreCompressedNonPointerWord(ObjectPtr obj,
+                                            intptr_t offset,
+                                            compressed_uword value) {
+    *reinterpret_cast<compressed_uword*>(
+        reinterpret_cast<uint8_t*>(obj.untag()) + offset) = value;
+  }
+
+  DART_FORCE_INLINE
+  bool CanCopyObject(uword tags, ObjectPtr object) {
+    const auto cid = UntaggedObject::ClassIdTag::decode(tags);
+    if (cid > kNumPredefinedCids) {
+      const bool has_native_fields =
+          Class::NumNativeFieldsOf(class_table_->At(cid)) != 0;
+      if (has_native_fields) {
+        exception_msg_ =
+            "Illegal argument in isolate message: (object has native fields)";
+        return false;
+      }
+      return true;
+    }
+#define HANDLE_ILLEGAL_CASE(Type)                                              \
+  case k##Type##Cid: {                                                         \
+    exception_msg_ =                                                           \
+        "Illegal argument in isolate message: "                                \
+        "(object is a" #Type ")";                                              \
+    return false;                                                              \
+  }
+
+    switch (cid) {
+      HANDLE_ILLEGAL_CASE(MirrorReference)
+      HANDLE_ILLEGAL_CASE(ReceivePort)
+      HANDLE_ILLEGAL_CASE(StackTrace)
+      HANDLE_ILLEGAL_CASE(UserTag)
+      HANDLE_ILLEGAL_CASE(DynamicLibrary)
+      HANDLE_ILLEGAL_CASE(Pointer)
+      case kClosureCid: {
+        if (!Function::IsImplicitStaticClosureFunction(
+                Closure::FunctionOf(Closure::RawCast(object)))) {
+          exception_msg_ =
+              "Illegal argument in isolate message: (object is a closure)";
+          return false;
+        }
+        ASSERT(Closure::ContextOf(Closure::RawCast(object)) == Object::null());
+        return true;
+      }
+      default:
+        return true;
+    }
+  }
+
+  Thread* thread_;
+  uword heap_base_;
+  Zone* zone_;
+  Heap* heap_;
+  ClassTable* class_table_;
+  Scavenger* new_space_;
+  Object& tmp_;
+
+  const char* exception_msg_ = nullptr;
+};
+
+class FastObjectCopyBase : public ObjectCopyBase {
+ public:
+  using Types = PtrTypes;
+
+  explicit FastObjectCopyBase(Thread* thread)
+      : ObjectCopyBase(thread), fast_forward_map_(thread) {}
+
+ protected:
+  DART_FORCE_INLINE
+  void ForwardCompressedPointers(ObjectPtr src,
+                                 ObjectPtr dst,
+                                 intptr_t offset,
+                                 intptr_t end_offset) {
+    for (; offset < end_offset; offset += kCompressedWordSize) {
+      ForwardCompressedPointer(src, dst, offset);
+    }
+  }
+
+  DART_FORCE_INLINE
+  void ForwardCompressedPointers(ObjectPtr src,
+                                 ObjectPtr dst,
+                                 intptr_t offset,
+                                 intptr_t end_offset,
+                                 UnboxedFieldBitmap bitmap) {
+    if (bitmap.IsEmpty()) {
+      ForwardCompressedPointers(src, dst, offset, end_offset);
+      return;
+    }
+    intptr_t bit = offset >> kCompressedWordSizeLog2;
+    for (; offset < end_offset; offset += kCompressedWordSize) {
+      if (bitmap.Get(bit++)) {
+        StoreCompressedNonPointerWord(
+            dst, offset, LoadCompressedNonPointerWord(src, offset));
+      } else {
+        ForwardCompressedPointer(src, dst, offset);
+      }
+    }
+  }
+
+  void ForwardCompressedArrayPointers(intptr_t array_length,
+                                      ObjectPtr src,
+                                      ObjectPtr dst,
+                                      intptr_t offset,
+                                      intptr_t end_offset) {
+    for (; offset < end_offset; offset += kCompressedWordSize) {
+      ForwardCompressedPointer(src, dst, offset);
+    }
+  }
+
+  DART_FORCE_INLINE
+  void ForwardCompressedPointer(ObjectPtr src, ObjectPtr dst, intptr_t offset) {
+    auto value = LoadCompressedPointer(src, offset);
+    if (!value.IsHeapObject()) {
+      StoreCompressedPointerNoBarrier(dst, offset, value);
+      return;
+    }
+    auto value_decompressed = value.Decompress(heap_base_);
+    const uword tags = TagsFromUntaggedObject(value_decompressed.untag());
+    if (CanShareObject(tags)) {
+      StoreCompressedPointerNoBarrier(dst, offset, value);
+      return;
+    }
+
+    ObjectPtr existing_to =
+        fast_forward_map_.ForwardedObject(value_decompressed);
+    if (existing_to != Marker()) {
+      StoreCompressedPointerNoBarrier(dst, offset, existing_to);
+      return;
+    }
+
+    if (UNLIKELY(!CanCopyObject(tags, value_decompressed))) {
+      ASSERT(exception_msg_ != nullptr);
+      StoreCompressedPointerNoBarrier(dst, offset, Object::null());
+      return;
+    }
+
+    auto to = Forward(tags, value.Decompress(heap_base_));
+    StoreCompressedPointerNoBarrier(dst, offset, to);
+  }
+
+  ObjectPtr Forward(uword tags, ObjectPtr from) {
+    const intptr_t header_size = UntaggedObject::SizeTag::decode(tags);
+    const auto cid = UntaggedObject::ClassIdTag::decode(tags);
+    const uword size =
+        header_size != 0 ? header_size : from.untag()->HeapSize();
+    if (Heap::IsAllocatableInNewSpace(size)) {
+      const uword alloc = new_space_->TryAllocate(thread_, size);
+      if (alloc != 0) {
+        ObjectPtr to(reinterpret_cast<UntaggedObject*>(alloc));
+        fast_forward_map_.Insert(from, to);
+
+        if (IsExternalTypedDataClassId(cid)) {
+          SetNewSpaceTaggingWord(to, cid, header_size);
+          InitializeExternalTypedData(cid, ExternalTypedData::RawCast(from),
+                                      ExternalTypedData::RawCast(to));
+          fast_forward_map_.AddExternalTypedData(
+              ExternalTypedData::RawCast(to));
+        } else if (IsTypedDataViewClassId(cid)) {
+          // We set the views backing store to `null` to satisfy an assertion in
+          // GCCompactor::VisitTypedDataViewPointers().
+          SetNewSpaceTaggingWord(to, cid, header_size);
+          InitializeTypedDataView(TypedDataView::RawCast(to));
+        }
+        return to;
+      }
+    }
+    exception_msg_ = kFastAllocationFailed;
+    return Marker();
+  }
+
+  void EnqueueTransferable(TransferableTypedDataPtr from,
+                           TransferableTypedDataPtr to) {
+    fast_forward_map_.AddTransferable(from, to);
+  }
+  void EnqueueObjectToRehash(ObjectPtr to) {
+    fast_forward_map_.AddObjectToRehash(to);
+  }
+
+  static void StoreCompressedArrayPointers(intptr_t array_length,
+                                           ObjectPtr src,
+                                           ObjectPtr dst,
+                                           intptr_t offset,
+                                           intptr_t end_offset) {
+    StoreCompressedPointers(src, dst, offset, end_offset);
+  }
+  static void StoreCompressedPointers(ObjectPtr src,
+                                      ObjectPtr dst,
+                                      intptr_t offset,
+                                      intptr_t end_offset) {
+    StoreCompressedPointersNoBarrier(src, dst, offset, end_offset);
+  }
+  static void StoreCompressedPointersNoBarrier(ObjectPtr src,
+                                               ObjectPtr dst,
+                                               intptr_t offset,
+                                               intptr_t end_offset) {
+    for (; offset <= end_offset; offset += kCompressedWordSize) {
+      StoreCompressedPointerNoBarrier(dst, offset,
+                                      LoadCompressedPointer(src, offset));
+    }
+  }
+
+ protected:
+  friend class ObjectGraphCopier;
+
+  FastForwardMap fast_forward_map_;
+};
+
+class SlowObjectCopyBase : public ObjectCopyBase {
+ public:
+  using Types = HandleTypes;
+
+  explicit SlowObjectCopyBase(Thread* thread)
+      : ObjectCopyBase(thread), slow_forward_map_(thread) {}
+
+ protected:
+  DART_FORCE_INLINE
+  void ForwardCompressedPointers(const Object& src,
+                                 const Object& dst,
+                                 intptr_t offset,
+                                 intptr_t end_offset) {
+    for (; offset < end_offset; offset += kCompressedWordSize) {
+      ForwardCompressedPointer(src, dst, offset);
+    }
+  }
+
+  DART_FORCE_INLINE
+  void ForwardCompressedPointers(const Object& src,
+                                 const Object& dst,
+                                 intptr_t offset,
+                                 intptr_t end_offset,
+                                 UnboxedFieldBitmap bitmap) {
+    intptr_t bit = offset >> kCompressedWordSizeLog2;
+    for (; offset < end_offset; offset += kCompressedWordSize) {
+      if (bitmap.Get(bit++)) {
+        StoreCompressedNonPointerWord(
+            dst.ptr(), offset, LoadCompressedNonPointerWord(src.ptr(), offset));
+      } else {
+        ForwardCompressedPointer(src, dst, offset);
+      }
+    }
+  }
+
+  void ForwardCompressedArrayPointers(intptr_t array_length,
+                                      const Object& src,
+                                      const Object& dst,
+                                      intptr_t offset,
+                                      intptr_t end_offset) {
+    if (Array::UseCardMarkingForAllocation(array_length)) {
+      for (; offset < end_offset; offset += kCompressedWordSize) {
+        ForwardCompressedLargeArrayPointer(src, dst, offset);
+      }
+    } else {
+      for (; offset < end_offset; offset += kCompressedWordSize) {
+        ForwardCompressedPointer(src, dst, offset);
+      }
+    }
+  }
+
+  DART_FORCE_INLINE
+  void ForwardCompressedLargeArrayPointer(const Object& src,
+                                          const Object& dst,
+                                          intptr_t offset) {
+    auto value = LoadCompressedPointer(src.ptr(), offset);
+    if (!value.IsHeapObject()) {
+      StoreCompressedPointerNoBarrier(dst.ptr(), offset, value);
+      return;
+    }
+
+    auto value_decompressed = value.Decompress(heap_base_);
+    const uword tags = TagsFromUntaggedObject(value_decompressed.untag());
+    if (CanShareObject(tags)) {
+      StoreCompressedLargeArrayPointerBarrier(dst.ptr(), offset,
+                                              value_decompressed);
+      return;
+    }
+
+    ObjectPtr existing_to =
+        slow_forward_map_.ForwardedObject(value_decompressed);
+    if (existing_to != Marker()) {
+      StoreCompressedLargeArrayPointerBarrier(dst.ptr(), offset, existing_to);
+      return;
+    }
+
+    if (UNLIKELY(!CanCopyObject(tags, value_decompressed))) {
+      ASSERT(exception_msg_ != nullptr);
+      StoreCompressedLargeArrayPointerBarrier(dst.ptr(), offset,
+                                              Object::null());
+      return;
+    }
+
+    tmp_ = value_decompressed;
+    tmp_ = Forward(tags, tmp_);  // Only this can cause allocation.
+    StoreCompressedLargeArrayPointerBarrier(dst.ptr(), offset, tmp_.ptr());
+  }
+  DART_FORCE_INLINE
+  void ForwardCompressedPointer(const Object& src,
+                                const Object& dst,
+                                intptr_t offset) {
+    auto value = LoadCompressedPointer(src.ptr(), offset);
+    if (!value.IsHeapObject()) {
+      StoreCompressedPointerNoBarrier(dst.ptr(), offset, value);
+      return;
+    }
+    auto value_decompressed = value.Decompress(heap_base_);
+    const uword tags = TagsFromUntaggedObject(value_decompressed.untag());
+    if (CanShareObject(tags)) {
+      StoreCompressedPointerBarrier(dst.ptr(), offset, value_decompressed);
+      return;
+    }
+
+    ObjectPtr existing_to =
+        slow_forward_map_.ForwardedObject(value_decompressed);
+    if (existing_to != Marker()) {
+      StoreCompressedPointerBarrier(dst.ptr(), offset, existing_to);
+      return;
+    }
+
+    if (UNLIKELY(!CanCopyObject(tags, value_decompressed))) {
+      ASSERT(exception_msg_ != nullptr);
+      StoreCompressedPointerNoBarrier(dst.ptr(), offset, Object::null());
+      return;
+    }
+
+    tmp_ = value_decompressed;
+    tmp_ = Forward(tags, tmp_);  // Only this can cause allocation.
+    StoreCompressedPointerBarrier(dst.ptr(), offset, tmp_.ptr());
+  }
+  ObjectPtr Forward(uword tags, const Object& from) {
+    const intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
+    intptr_t size = UntaggedObject::SizeTag::decode(tags);
+    if (size == 0) {
+      size = from.ptr().untag()->HeapSize();
+    }
+    ObjectPtr to = AllocateObject(cid, size);
+    slow_forward_map_.Insert(from.ptr(), to);
+    UpdateLengthField(cid, from.ptr(), to);
+    if (cid == kArrayCid && !Heap::IsAllocatableInNewSpace(size)) {
+      to.untag()->SetCardRememberedBitUnsynchronized();
+    }
+    if (IsExternalTypedDataClassId(cid)) {
+      InitializeExternalTypedData(cid, ExternalTypedData::RawCast(from.ptr()),
+                                  ExternalTypedData::RawCast(to));
+      slow_forward_map_.AddExternalTypedData(ExternalTypedData::RawCast(to));
+    } else if (IsTypedDataViewClassId(cid)) {
+      // We set the views backing store to `null` to satisfy an assertion in
+      // GCCompactor::VisitTypedDataViewPointers().
+      InitializeTypedDataView(TypedDataView::RawCast(to));
+    }
+    return to;
+  }
+  void EnqueueTransferable(const TransferableTypedData& from,
+                           const TransferableTypedData& to) {
+    slow_forward_map_.AddTransferable(from, to);
+  }
+  void EnqueueObjectToRehash(const Object& to) {
+    slow_forward_map_.AddObjectToRehash(to);
+  }
+
+  void StoreCompressedArrayPointers(intptr_t array_length,
+                                    const Object& src,
+                                    const Object& dst,
+                                    intptr_t offset,
+                                    intptr_t end_offset) {
+    auto src_ptr = src.ptr();
+    auto dst_ptr = dst.ptr();
+    if (Array::UseCardMarkingForAllocation(array_length)) {
+      for (; offset <= end_offset; offset += kCompressedWordSize) {
+        StoreCompressedLargeArrayPointerBarrier(
+            dst_ptr, offset,
+            LoadCompressedPointer(src_ptr, offset).Decompress(heap_base_));
+      }
+    } else {
+      for (; offset <= end_offset; offset += kCompressedWordSize) {
+        StoreCompressedPointerBarrier(
+            dst_ptr, offset,
+            LoadCompressedPointer(src_ptr, offset).Decompress(heap_base_));
+      }
+    }
+  }
+  void StoreCompressedPointers(const Object& src,
+                               const Object& dst,
+                               intptr_t offset,
+                               intptr_t end_offset) {
+    auto src_ptr = src.ptr();
+    auto dst_ptr = dst.ptr();
+    for (; offset <= end_offset; offset += kCompressedWordSize) {
+      StoreCompressedPointerBarrier(
+          dst_ptr, offset,
+          LoadCompressedPointer(src_ptr, offset).Decompress(heap_base_));
+    }
+  }
+  static void StoreCompressedPointersNoBarrier(const Object& src,
+                                               const Object& dst,
+                                               intptr_t offset,
+                                               intptr_t end_offset) {
+    auto src_ptr = src.ptr();
+    auto dst_ptr = dst.ptr();
+    for (; offset <= end_offset; offset += kCompressedWordSize) {
+      StoreCompressedPointerNoBarrier(dst_ptr, offset,
+                                      LoadCompressedPointer(src_ptr, offset));
+    }
+  }
+
+ protected:
+  friend class ObjectGraphCopier;
+
+  SlowForwardMap slow_forward_map_;
+};
+
+template <typename Base>
+class ObjectCopy : public Base {
+ public:
+  using Types = typename Base::Types;
+
+  explicit ObjectCopy(Thread* thread) : Base(thread) {}
+
+  void CopyPredefinedInstance(typename Types::Object from,
+                              typename Types::Object to,
+                              intptr_t cid) {
+    if (IsImplicitFieldClassId(cid)) {
+      CopyUserdefinedInstance(from, to);
+      return;
+    }
+    switch (cid) {
+#define COPY_TO(clazz)                                                         \
+  case clazz::kClassId: {                                                      \
+    typename Types::clazz casted_from = Types::Cast##clazz(from);              \
+    typename Types::clazz casted_to = Types::Cast##clazz(to);                  \
+    Copy##clazz(casted_from, casted_to);                                       \
+    return;                                                                    \
+  }
+
+      CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(COPY_TO)
+      COPY_TO(Array)
+      COPY_TO(LinkedHashMap)
+      COPY_TO(LinkedHashSet)
+#undef COPY_TO
+
+#define COPY_TO(clazz) case kTypedData##clazz##Cid:
+
+      CLASS_LIST_TYPED_DATA(COPY_TO) {
+        typename Types::TypedData casted_from = Types::CastTypedData(from);
+        typename Types::TypedData casted_to = Types::CastTypedData(to);
+        CopyTypedData(casted_from, casted_to);
+        return;
+      }
+#undef COPY_TO
+
+      case kByteDataViewCid:
+#define COPY_TO(clazz) case kTypedData##clazz##ViewCid:
+        CLASS_LIST_TYPED_DATA(COPY_TO) {
+          typename Types::TypedDataView casted_from =
+              Types::CastTypedDataView(from);
+          typename Types::TypedDataView casted_to =
+              Types::CastTypedDataView(to);
+          CopyTypedDataView(casted_from, casted_to);
+          return;
+        }
+#undef COPY_TO
+
+#define COPY_TO(clazz) case kExternalTypedData##clazz##Cid:
+
+        CLASS_LIST_TYPED_DATA(COPY_TO) {
+          typename Types::ExternalTypedData casted_from =
+              Types::CastExternalTypedData(from);
+          typename Types::ExternalTypedData casted_to =
+              Types::CastExternalTypedData(to);
+          CopyExternalTypedData(casted_from, casted_to);
+          return;
+        }
+#undef COPY_TO
+      default:
+        break;
+    }
+
+    const Object& obj = Types::HandlifyObject(from);
+    FATAL1("Unexpected object: %s\n", obj.ToCString());
+  }
+
+#if defined(DART_PRECOMPILED_RUNTIME)
+  void CopyUserdefinedInstanceAOT(typename Types::Object from,
+                                  typename Types::Object to,
+                                  UnboxedFieldBitmap bitmap) {
+    const intptr_t instance_size = UntagObject(from)->HeapSize();
+    Base::ForwardCompressedPointers(from, to, kWordSize, instance_size, bitmap);
+  }
+#endif
+
+  void CopyUserdefinedInstance(typename Types::Object from,
+                               typename Types::Object to) {
+    const intptr_t instance_size = UntagObject(from)->HeapSize();
+    Base::ForwardCompressedPointers(from, to, kWordSize, instance_size);
+  }
+
+  void CopyClosure(typename Types::Closure from, typename Types::Closure to) {
+    Base::StoreCompressedPointers(
+        from, to, OFFSET_OF(UntaggedClosure, instantiator_type_arguments_),
+        OFFSET_OF(UntaggedClosure, function_));
+    Base::ForwardCompressedPointer(from, to,
+                                   OFFSET_OF(UntaggedClosure, context_));
+    Base::StoreCompressedPointersNoBarrier(from, to,
+                                           OFFSET_OF(UntaggedClosure, hash_),
+                                           OFFSET_OF(UntaggedClosure, hash_));
+    ONLY_IN_PRECOMPILED(UntagClosure(to)->entry_point_ =
+                            UntagClosure(from)->entry_point_);
+  }
+
+  void CopyArray(typename Types::Array from, typename Types::Array to) {
+    const intptr_t length = Smi::Value(UntagArray(from)->length());
+    Base::StoreCompressedArrayPointers(
+        length, from, to, OFFSET_OF(UntaggedArray, type_arguments_),
+        OFFSET_OF(UntaggedArray, type_arguments_));
+    Base::StoreCompressedPointersNoBarrier(from, to,
+                                           OFFSET_OF(UntaggedArray, length_),
+                                           OFFSET_OF(UntaggedArray, length_));
+    Base::ForwardCompressedArrayPointers(
+        length, from, to, Array::data_offset(),
+        Array::data_offset() + kCompressedWordSize * length);
+  }
+
+  void CopyGrowableObjectArray(typename Types::GrowableObjectArray from,
+                               typename Types::GrowableObjectArray to) {
+    Base::StoreCompressedPointers(
+        from, to, OFFSET_OF(UntaggedGrowableObjectArray, type_arguments_),
+        OFFSET_OF(UntaggedGrowableObjectArray, type_arguments_));
+    Base::StoreCompressedPointersNoBarrier(
+        from, to, OFFSET_OF(UntaggedGrowableObjectArray, length_),
+        OFFSET_OF(UntaggedGrowableObjectArray, length_));
+    Base::ForwardCompressedPointer(
+        from, to, OFFSET_OF(UntaggedGrowableObjectArray, data_));
+  }
+
+  template <intptr_t one_for_set_two_for_map, typename T>
+  void CopyLinkedHashBase(T from,
+                          T to,
+                          UntaggedLinkedHashBase* from_untagged,
+                          UntaggedLinkedHashBase* to_untagged) {
+    // We have to find out whether the map needs re-hashing on the receiver side
+    // due to keys being copied and the keys therefore possibly having different
+    // hash codes (e.g. due to user-defined hashCode implementation or due to
+    // new identity hash codes of the copied objects).
+    bool needs_rehashing = false;
+    ArrayPtr data = from_untagged->data_.Decompress(Base::heap_base_);
+    if (data != Array::null()) {
+      UntaggedArray* untagged_data = data.untag();
+      const intptr_t length = Smi::Value(untagged_data->length_);
+      auto key_value_pairs = untagged_data->data();
+      for (intptr_t i = 0; i < length; i += one_for_set_two_for_map) {
+        ObjectPtr key = key_value_pairs[i].Decompress(Base::heap_base_);
+        if (key->IsHeapObject()) {
+          if (MightNeedReHashing(key)) {
+            needs_rehashing = true;
+            break;
+          }
+        }
+      }
+    }
+
+    Base::StoreCompressedPointers(
+        from, to, OFFSET_OF(UntaggedLinkedHashBase, type_arguments_),
+        OFFSET_OF(UntaggedLinkedHashBase, type_arguments_));
+
+    // Compared with the snapshot-based (de)serializer we do preserve the same
+    // backing store (i.e. used_data/deleted_keys/data) and therefore do not
+    // magically shrink backing store based on usage.
+    //
+    // We do this to avoid making assumptions about the object graph and the
+    // linked hash map (e.g. assuming there's no other references to the data,
+    // assuming the linked hashmap is in a consistent state)
+    if (needs_rehashing) {
+      to_untagged->hash_mask_ = Smi::New(0);
+      to_untagged->index_ = TypedData::RawCast(Object::null());
+      Base::EnqueueObjectToRehash(to);
+    }
+
+    // From this point on we shouldn't use the raw pointers, since GC might
+    // happen when forwarding objects.
+    from_untagged = nullptr;
+    to_untagged = nullptr;
+
+    if (!needs_rehashing) {
+      Base::ForwardCompressedPointer(from, to,
+                                     OFFSET_OF(UntaggedLinkedHashBase, index_));
+      Base::StoreCompressedPointersNoBarrier(
+          from, to, OFFSET_OF(UntaggedLinkedHashBase, hash_mask_),
+          OFFSET_OF(UntaggedLinkedHashBase, hash_mask_));
+    }
+    Base::ForwardCompressedPointer(from, to,
+                                   OFFSET_OF(UntaggedLinkedHashBase, data_));
+    Base::StoreCompressedPointersNoBarrier(
+        from, to, OFFSET_OF(UntaggedLinkedHashBase, used_data_),
+        OFFSET_OF(UntaggedLinkedHashBase, used_data_));
+    Base::StoreCompressedPointersNoBarrier(
+        from, to, OFFSET_OF(UntaggedLinkedHashMap, deleted_keys_),
+        OFFSET_OF(UntaggedLinkedHashMap, deleted_keys_));
+  }
+
+  void CopyLinkedHashMap(typename Types::LinkedHashMap from,
+                         typename Types::LinkedHashMap to) {
+    CopyLinkedHashBase<2, typename Types::LinkedHashMap>(
+        from, to, UntagLinkedHashMap(from), UntagLinkedHashMap(to));
+  }
+  void CopyLinkedHashSet(typename Types::LinkedHashSet from,
+                         typename Types::LinkedHashSet to) {
+    CopyLinkedHashBase<1, typename Types::LinkedHashSet>(
+        from, to, UntagLinkedHashSet(from), UntagLinkedHashSet(to));
+  }
+
+  void CopyDouble(typename Types::Double from, typename Types::Double to) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    auto raw_from = UntagDouble(from);
+    auto raw_to = UntagDouble(to);
+    raw_to->value_ = raw_from->value_;
+#else
+    // Will be shared and not copied.
+    UNREACHABLE();
+#endif
+  }
+
+  void CopyFloat32x4(typename Types::Float32x4 from,
+                     typename Types::Float32x4 to) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    auto raw_from = UntagFloat32x4(from);
+    auto raw_to = UntagFloat32x4(to);
+    raw_to->value_[0] = raw_from->value_[0];
+    raw_to->value_[1] = raw_from->value_[1];
+    raw_to->value_[2] = raw_from->value_[2];
+    raw_to->value_[3] = raw_from->value_[3];
+#else
+    // Will be shared and not copied.
+    UNREACHABLE();
+#endif
+  }
+
+  void CopyFloat64x2(typename Types::Float64x2 from,
+                     typename Types::Float64x2 to) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    auto raw_from = UntagFloat64x2(from);
+    auto raw_to = UntagFloat64x2(to);
+    raw_to->value_[0] = raw_from->value_[0];
+    raw_to->value_[1] = raw_from->value_[1];
+#else
+    // Will be shared and not copied.
+    UNREACHABLE();
+#endif
+  }
+
+  void CopyTypedData(typename Types::TypedData from,
+                     typename Types::TypedData to) {
+    auto raw_from = UntagTypedData(from);
+    auto raw_to = UntagTypedData(to);
+    const intptr_t cid = Types::GetTypedDataPtr(from)->GetClassId();
+    raw_to->length_ = raw_from->length_;
+    raw_to->RecomputeDataField();
+    const intptr_t length =
+        TypedData::ElementSizeInBytes(cid) * Smi::Value(raw_from->length_);
+    memmove(raw_to->data_, raw_from->data_, length);
+  }
+
+  void CopyTypedDataView(typename Types::TypedDataView from,
+                         typename Types::TypedDataView to) {
+    // This will forward & initialize the typed data.
+    Base::ForwardCompressedPointer(
+        from, to, OFFSET_OF(UntaggedTypedDataView, typed_data_));
+
+    auto raw_from = UntagTypedDataView(from);
+    auto raw_to = UntagTypedDataView(to);
+    raw_to->length_ = raw_from->length_;
+    raw_to->offset_in_bytes_ = raw_from->offset_in_bytes_;
+    raw_to->data_ = nullptr;
+
+    if (raw_to->typed_data_.Decompress(Base::heap_base_) == Object::null()) {
+      ASSERT(Base::exception_msg_ != nullptr);
+      return;
+    }
+
+    const bool is_external =
+        raw_from->data_ != raw_from->DataFieldForInternalTypedData();
+    if (is_external) {
+      // The raw_to is fully initialized at this point (see handling of external
+      // typed data in [ForwardCompressedPointer])
+      raw_to->RecomputeDataField();
+    } else {
+      // The raw_to isn't initialized yet, but it's address is valid, so we can
+      // compute the data field it would use.
+      raw_to->RecomputeDataFieldForInternalTypedData();
+    }
+    const bool is_external2 =
+        raw_to->data_ != raw_to->DataFieldForInternalTypedData();
+    ASSERT(is_external == is_external2);
+  }
+
+  void CopyExternalTypedData(typename Types::ExternalTypedData from,
+                             typename Types::ExternalTypedData to) {
+    // The external typed data is initialized on the forwarding pass (where
+    // normally allocation but not initialization happens), so views on it
+    // can be initialized immediately.
+#if defined(DEBUG)
+    auto raw_from = UntagExternalTypedData(from);
+    auto raw_to = UntagExternalTypedData(to);
+    ASSERT(raw_to->data_ != nullptr);
+    ASSERT(raw_to->length_ == raw_from->length_);
+#endif
+  }
+
+  void CopyTransferableTypedData(typename Types::TransferableTypedData from,
+                                 typename Types::TransferableTypedData to) {
+    // The [TransferableTypedData] is an empty object with an associated heap
+    // peer object.
+    // -> We'll validate that there's a peer and enqueue the transferable to be
+    // transferred if the transitive copy is successful.
+    auto fpeer = static_cast<TransferableTypedDataPeer*>(
+        Base::heap_->GetPeer(Types::GetTransferableTypedDataPtr(from)));
+    ASSERT(fpeer != nullptr);
+    if (fpeer->data() == nullptr) {
+      Base::exception_msg_ =
+          "Illegal argument in isolate message"
+          " : (TransferableTypedData has been transferred already)";
+      return;
+    }
+    Base::EnqueueTransferable(from, to);
+  }
+
+#define DEFINE_UNSUPPORTED(clazz)                                              \
+  void Copy##clazz(typename Types::clazz from, typename Types::clazz to) {     \
+    FATAL("Objects of type " #clazz " should not occur in object graphs");     \
+  }
+
+  FOR_UNSUPPORTED_CLASSES(DEFINE_UNSUPPORTED)
+
+#undef DEFINE_UNSUPPORTED
+
+  UntaggedObject* UntagObject(typename Types::Object obj) {
+    return Types::GetObjectPtr(obj).Decompress(Base::heap_base_).untag();
+  }
+
+#define DO(V)                                                                  \
+  DART_FORCE_INLINE                                                            \
+  Untagged##V* Untag##V(typename Types::V obj) {                               \
+    return Types::Get##V##Ptr(obj).Decompress(Base::heap_base_).untag();       \
+  }
+  CLASS_LIST_FOR_HANDLES(DO)
+#undef DO
+};
+
+class FastObjectCopy : public ObjectCopy<FastObjectCopyBase> {
+ public:
+  explicit FastObjectCopy(Thread* thread) : ObjectCopy(thread) {}
+  ~FastObjectCopy() {}
+
+  ObjectPtr TryCopyGraphFast(ObjectPtr root) {
+    NoSafepointScope no_safepoint_scope;
+
+    ObjectPtr root_copy = Forward(TagsFromUntaggedObject(root.untag()), root);
+    if (root_copy == Marker()) {
+      return root_copy;
+    }
+    while (fast_forward_map_.fill_cursor_ <
+           fast_forward_map_.raw_from_to_.length()) {
+      const intptr_t index = fast_forward_map_.fill_cursor_;
+      ObjectPtr from = fast_forward_map_.raw_from_to_[index];
+      ObjectPtr to = fast_forward_map_.raw_from_to_[index + 1];
+      FastCopyObject(from, to);
+      if (exception_msg_ != nullptr) {
+        return root_copy;
+      }
+      fast_forward_map_.fill_cursor_ += 2;
+    }
+    if (root_copy != Marker()) {
+      TryBuildArrayOfObjectsToRehash();
+    }
+    return root_copy;
+  }
+
+  void TryBuildArrayOfObjectsToRehash() {
+    const auto& objects_to_rehash = fast_forward_map_.raw_objects_to_rehash_;
+    const intptr_t length = objects_to_rehash.length();
+    if (length == 0) return;
+
+    const intptr_t size = Array::InstanceSize(length);
+    const uword array_addr = new_space_->TryAllocate(thread_, size);
+    if (array_addr == 0) {
+      exception_msg_ = kFastAllocationFailed;
+      return;
+    }
+
+    const uword header_size =
+        UntaggedObject::SizeTag::SizeFits(size) ? size : 0;
+    ArrayPtr array(reinterpret_cast<UntaggedArray*>(array_addr));
+    SetNewSpaceTaggingWord(array, kArrayCid, header_size);
+    StoreCompressedPointerNoBarrier(array, OFFSET_OF(UntaggedArray, length_),
+                                    Smi::New(length));
+    StoreCompressedPointerNoBarrier(array,
+                                    OFFSET_OF(UntaggedArray, type_arguments_),
+                                    TypeArguments::null());
+    auto array_data = array.untag()->data();
+    for (intptr_t i = 0; i < length; ++i) {
+      array_data[i] = objects_to_rehash[i];
+    }
+    raw_objects_to_rehash_ = array;
+  }
+
+ private:
+  friend class ObjectGraphCopier;
+
+  void FastCopyObject(ObjectPtr from, ObjectPtr to) {
+    const uword tags = TagsFromUntaggedObject(from.untag());
+    const intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
+    const intptr_t size = UntaggedObject::SizeTag::decode(tags);
+
+    // Ensure the last word is GC-safe (our heap objects are 2-word aligned, the
+    // object header stores the size in multiples of kObjectAlignment, the GC
+    // uses the information from the header and therefore might visit one slot
+    // more than the actual size of the instance).
+    *reinterpret_cast<ObjectPtr*>(UntaggedObject::ToAddr(to) +
+                                  from.untag()->HeapSize() - kWordSize) = 0;
+    SetNewSpaceTaggingWord(to, cid, size);
+
+    // Fall back to virtual variant for predefined classes
+    if (cid < kNumPredefinedCids && cid != kInstanceCid) {
+      CopyPredefinedInstance(from, to, cid);
+      return;
+    }
+#if defined(DART_PRECOMPILED_RUNTIME)
+    const auto bitmap =
+        class_table_->shared_class_table()->GetUnboxedFieldsMapAt(cid);
+    CopyUserdefinedInstanceAOT(Instance::RawCast(from), Instance::RawCast(to),
+                               bitmap);
+#else
+    CopyUserdefinedInstance(Instance::RawCast(from), Instance::RawCast(to));
+#endif
+  }
+
+  ArrayPtr raw_objects_to_rehash_ = Array::null();
+};
+
+class SlowObjectCopy : public ObjectCopy<SlowObjectCopyBase> {
+ public:
+  explicit SlowObjectCopy(Thread* thread)
+      : ObjectCopy(thread), objects_to_rehash_(Array::Handle(thread->zone())) {}
+  ~SlowObjectCopy() {}
+
+  ObjectPtr ContinueCopyGraphSlow(const Object& root,
+                                  const Object& fast_root_copy) {
+    auto& root_copy = Object::Handle(Z, fast_root_copy.ptr());
+    if (root_copy.ptr() == Marker()) {
+      root_copy = Forward(TagsFromUntaggedObject(root.ptr().untag()), root);
+    }
+
+    Object& from = Object::Handle(Z);
+    Object& to = Object::Handle(Z);
+    while (slow_forward_map_.fill_cursor_ <
+           slow_forward_map_.from_to_.length()) {
+      const intptr_t index = slow_forward_map_.fill_cursor_;
+      from = slow_forward_map_.from_to_[index]->ptr();
+      to = slow_forward_map_.from_to_[index + 1]->ptr();
+      CopyObject(from, to);
+      slow_forward_map_.fill_cursor_ += 2;
+      if (exception_msg_ != nullptr) {
+        return Marker();
+      }
+    }
+    BuildArrayOfObjectsToRehash();
+    return root_copy.ptr();
+  }
+
+  void BuildArrayOfObjectsToRehash() {
+    const auto& objects_to_rehash = slow_forward_map_.objects_to_rehash_;
+    const intptr_t length = objects_to_rehash.length();
+    if (length == 0) return;
+
+    objects_to_rehash_ = Array::New(length);
+    for (intptr_t i = 0; i < length; ++i) {
+      objects_to_rehash_.SetAt(i, *objects_to_rehash[i]);
+    }
+  }
+
+ private:
+  friend class ObjectGraphCopier;
+
+  void CopyObject(const Object& from, const Object& to) {
+    const auto cid = from.GetClassId();
+
+    // Fall back to virtual variant for predefined classes
+    if (cid < kNumPredefinedCids && cid != kInstanceCid) {
+      CopyPredefinedInstance(from, to, cid);
+      return;
+    }
+#if defined(DART_PRECOMPILED_RUNTIME)
+    const auto bitmap =
+        class_table_->shared_class_table()->GetUnboxedFieldsMapAt(cid);
+    CopyUserdefinedInstanceAOT(from, to, bitmap);
+#else
+    CopyUserdefinedInstance(from, to);
+#endif
+  }
+
+  Array& objects_to_rehash_;
+};
+
+class ObjectGraphCopier {
+ public:
+  explicit ObjectGraphCopier(Thread* thread)
+      : thread_(thread),
+        zone_(thread->zone()),
+        fast_object_copy_(thread_),
+        slow_object_copy_(thread_) {
+    thread_->isolate()->set_forward_table_new(new WeakTable());
+    thread_->isolate()->set_forward_table_old(new WeakTable());
+  }
+  ~ObjectGraphCopier() {
+    thread_->isolate()->set_forward_table_new(nullptr);
+    thread_->isolate()->set_forward_table_old(nullptr);
+  }
+
+  // Result will be [<msg>, <objects-in-msg-to-rehash>]
+  ObjectPtr CopyObjectGraph(const Object& root) {
+    const char* volatile exception_msg = nullptr;
+    auto& result = Object::Handle(zone_);
+
+    {
+      LongJumpScope jump;  // e.g. for OOMs.
+      if (setjmp(*jump.Set()) == 0) {
+        result = CopyObjectGraphInternal(root, &exception_msg);
+        // Any allocated external typed data must have finalizers attached so
+        // memory will get free()ed.
+        slow_object_copy_.slow_forward_map_.FinalizeExternalTypedData();
+      } else {
+        // Any allocated external typed data must have finalizers attached so
+        // memory will get free()ed.
+        slow_object_copy_.slow_forward_map_.FinalizeExternalTypedData();
+
+        // The copy failed due to non-application error (e.g. OOM error),
+        // propagate this error.
+        result = thread_->StealStickyError();
+        RELEASE_ASSERT(result.IsError());
+      }
+    }
+
+    if (result.IsError()) {
+      Exceptions::PropagateError(Error::Cast(result));
+      UNREACHABLE();
+    }
+    if (result.ptr() == Marker()) {
+      ASSERT(exception_msg != nullptr);
+      ThrowException(exception_msg);
+      UNREACHABLE();
+    }
+
+    // The copy was successful, then detach transferable data from the sender
+    // and attach to the copied graph.
+    slow_object_copy_.slow_forward_map_.FinalizeTransferables();
+    return result.ptr();
+  }
+
+ private:
+  ObjectPtr CopyObjectGraphInternal(const Object& root,
+                                    const char* volatile* exception_msg) {
+    const auto& result_array = Array::Handle(zone_, Array::New(2));
+    if (!root.ptr()->IsHeapObject()) {
+      result_array.SetAt(0, root);
+      return result_array.ptr();
+    }
+    const uword tags = TagsFromUntaggedObject(root.ptr().untag());
+    if (CanShareObject(tags)) {
+      result_array.SetAt(0, root);
+      return result_array.ptr();
+    }
+    if (!fast_object_copy_.CanCopyObject(tags, root.ptr())) {
+      ASSERT(fast_object_copy_.exception_msg_ != nullptr);
+      *exception_msg = fast_object_copy_.exception_msg_;
+      return Marker();
+    }
+
+    // We try a fast new-space only copy first that will not use any barriers.
+    auto& result = Object::Handle(Z, Marker());
+
+    // All allocated but non-initialized heap objects have to be made GC-visible
+    // at this point.
+    if (FLAG_enable_fast_object_copy) {
+      {
+        NoSafepointScope no_safepoint_scope;
+
+        result = fast_object_copy_.TryCopyGraphFast(root.ptr());
+        if (result.ptr() != Marker()) {
+          if (fast_object_copy_.exception_msg_ == nullptr) {
+            result_array.SetAt(0, result);
+            fast_object_copy_.tmp_ = fast_object_copy_.raw_objects_to_rehash_;
+            result_array.SetAt(1, fast_object_copy_.tmp_);
+            HandlifyExternalTypedData();
+            HandlifyTransferables();
+            return result_array.ptr();
+          }
+
+          // There are left-over uninitialized objects we'll have to make GC
+          // visible.
+          SwitchToSlowFowardingList();
+        }
+      }
+
+      if (FLAG_gc_on_foc_slow_path) {
+        // We use kLowMemory to force the GC to compact, which is more likely to
+        // discover untracked pointers (and other issues, like incorrect class
+        // table).
+        thread_->heap()->CollectAllGarbage(Heap::kLowMemory);
+      }
+
+      // Fast copy failed due to
+      //   - either failure to allocate into new space
+      //   - or failure to copy object which we cannot copy
+      ASSERT(fast_object_copy_.exception_msg_ != nullptr);
+      if (fast_object_copy_.exception_msg_ != kFastAllocationFailed) {
+        *exception_msg = fast_object_copy_.exception_msg_;
+        return Marker();
+      }
+      ASSERT(fast_object_copy_.exception_msg_ == kFastAllocationFailed);
+    }
+
+    // Use the slow copy approach.
+    result = slow_object_copy_.ContinueCopyGraphSlow(root, result);
+    ASSERT((result.ptr() == Marker()) ==
+           (slow_object_copy_.exception_msg_ != nullptr));
+    if (result.ptr() == Marker()) {
+      *exception_msg = slow_object_copy_.exception_msg_;
+      return Marker();
+    }
+
+    result_array.SetAt(0, result);
+    result_array.SetAt(1, slow_object_copy_.objects_to_rehash_);
+    return result_array.ptr();
+  }
+
+  void SwitchToSlowFowardingList() {
+    auto& fast_forward_map = fast_object_copy_.fast_forward_map_;
+    auto& slow_forward_map = slow_object_copy_.slow_forward_map_;
+
+    MakeUninitializedNewSpaceObjectsGCSafe();
+    HandlifyTransferables();
+    HandlifyExternalTypedData();
+    HandlifyObjectsToReHash();
+    HandlifyFromToObjects();
+    slow_forward_map.fill_cursor_ = fast_forward_map.fill_cursor_;
+  }
+
+  void MakeUninitializedNewSpaceObjectsGCSafe() {
+    auto& fast_forward_map = fast_object_copy_.fast_forward_map_;
+    const auto length = fast_forward_map.raw_from_to_.length();
+    const auto cursor = fast_forward_map.fill_cursor_;
+    for (intptr_t i = cursor; i < length; i += 2) {
+      auto from = fast_forward_map.raw_from_to_[i];
+      auto to = fast_forward_map.raw_from_to_[i + 1];
+      const uword tags = TagsFromUntaggedObject(from.untag());
+      const intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
+      const intptr_t size = UntaggedObject::SizeTag::decode(tags);
+      // External typed data is already initialized.
+      if (!IsExternalTypedDataClassId(cid) && !IsTypedDataViewClassId(cid)) {
+        memset(reinterpret_cast<void*>(to.untag()), 0,
+               from.untag()->HeapSize());
+        SetNewSpaceTaggingWord(to, cid, size);
+        UpdateLengthField(cid, from, to);
+      }
+    }
+  }
+  void HandlifyTransferables() {
+    auto& raw_transferables =
+        fast_object_copy_.fast_forward_map_.raw_transferables_from_to_;
+    const auto length = raw_transferables.length();
+    if (length > 0) {
+      auto& transferables =
+          slow_object_copy_.slow_forward_map_.transferables_from_to_;
+      transferables.Resize(length);
+      for (intptr_t i = 0; i < length; i++) {
+        transferables[i] =
+            &TransferableTypedData::Handle(Z, raw_transferables[i]);
+      }
+      raw_transferables.Clear();
+    }
+  }
+  void HandlifyExternalTypedData() {
+    auto& raw_external_typed_data =
+        fast_object_copy_.fast_forward_map_.raw_external_typed_data_to_;
+    const auto length = raw_external_typed_data.length();
+    if (length > 0) {
+      auto& external_typed_data =
+          slow_object_copy_.slow_forward_map_.external_typed_data_;
+      external_typed_data.Resize(length);
+      for (intptr_t i = 0; i < length; i++) {
+        external_typed_data[i] =
+            &ExternalTypedData::Handle(Z, raw_external_typed_data[i]);
+      }
+      raw_external_typed_data.Clear();
+    }
+  }
+  void HandlifyObjectsToReHash() {
+    auto& fast_forward_map = fast_object_copy_.fast_forward_map_;
+    auto& slow_forward_map = slow_object_copy_.slow_forward_map_;
+    const auto length = fast_forward_map.raw_transferables_from_to_.length();
+    if (length > 0) {
+      slow_forward_map.objects_to_rehash_.Resize(length);
+      for (intptr_t i = 0; i < length; i++) {
+        slow_forward_map.objects_to_rehash_[i] =
+            &Object::Handle(Z, fast_forward_map.raw_objects_to_rehash_[i]);
+      }
+      fast_forward_map.raw_objects_to_rehash_.Clear();
+    }
+  }
+  void HandlifyFromToObjects() {
+    auto& fast_forward_map = fast_object_copy_.fast_forward_map_;
+    auto& slow_forward_map = slow_object_copy_.slow_forward_map_;
+
+    const intptr_t cursor = fast_forward_map.fill_cursor_;
+    const intptr_t length = fast_forward_map.raw_from_to_.length();
+
+    slow_forward_map.from_to_.Resize(length);
+    for (intptr_t i = 2; i < length; i += 2) {
+      slow_forward_map.from_to_[i] =
+          i < cursor ? nullptr
+                     : &Object::Handle(Z, fast_forward_map.raw_from_to_[i]);
+      slow_forward_map.from_to_[i + 1] =
+          &Object::Handle(Z, fast_forward_map.raw_from_to_[i + 1]);
+    }
+    fast_forward_map.raw_from_to_.Clear();
+  }
+  void ThrowException(const char* exception_msg) {
+    const auto& msg_obj = String::Handle(Z, String::New(exception_msg));
+    const auto& args = Array::Handle(Z, Array::New(1));
+    args.SetAt(0, msg_obj);
+    Exceptions::ThrowByType(Exceptions::kArgument, args);
+    UNREACHABLE();
+  }
+
+  Thread* thread_;
+  Zone* zone_;
+  FastObjectCopy fast_object_copy_;
+  SlowObjectCopy slow_object_copy_;
+};
+
+ObjectPtr CopyMutableObjectGraph(const Object& object) {
+  auto thread = Thread::Current();
+  ObjectGraphCopier copier(thread);
+  return copier.CopyObjectGraph(object);
+}
+
+}  // namespace dart
diff --git a/runtime/vm/object_graph_copy.h b/runtime/vm/object_graph_copy.h
new file mode 100644
index 0000000..b33c3e4
--- /dev/null
+++ b/runtime/vm/object_graph_copy.h
@@ -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.
+
+#ifndef RUNTIME_VM_OBJECT_GRAPH_COPY_H_
+#define RUNTIME_VM_OBJECT_GRAPH_COPY_H_
+
+namespace dart {
+
+class Object;
+class ObjectPtr;
+
+// Makes a transitive copy of the object graph referenced by [object]. Will not
+// copy objects that can be safely shared - due to being immutable.
+//
+// The result will be an array of length 2 of the format
+//
+//   [<copy-of-root>, <array-of-objects-to-rehash / null>]
+//
+// If the array of objects to rehash is not `null` the receiver should re-hash
+// those objects.
+ObjectPtr CopyMutableObjectGraph(const Object& root);
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_OBJECT_GRAPH_COPY_H_
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 2f404f5..7fe26f1 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -6,6 +6,7 @@
 
 #include "platform/unaligned.h"
 #include "vm/code_patcher.h"
+#include "vm/dart_entry.h"
 #include "vm/hash_table.h"
 #include "vm/isolate_reload.h"
 #include "vm/log.h"
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 2fa6cda..1685ebf 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -94,6 +94,15 @@
 
   jsobj.AddProperty("library", Object::Handle(library()));
 
+  const intptr_t num_type_params = NumTypeParameters();
+  if (num_type_params > 0) {
+    JSONArray jsarr(&jsobj, "typeParameters");
+    TypeParameter& type_param = TypeParameter::Handle();
+    for (intptr_t i = 0; i < num_type_params; ++i) {
+      type_param = TypeParameterAt(i);
+      jsarr.AddValue(type_param);
+    }
+  }
   if (ref) {
     return;
   }
@@ -172,8 +181,10 @@
 }
 
 void TypeParameters::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  // Consider making this type public if we decide to expose TypeParameters
+  // through the protocol.
   JSONObject jsobj(stream);
-  jsobj.AddProperty("kind", "TypeParameters");
+  jsobj.AddProperty("kind", "_TypeParameters");
   jsobj.AddProperty("flags", Array::Handle(flags()));
   jsobj.AddProperty("names", Array::Handle(names()));
   jsobj.AddProperty("bounds", TypeArguments::Handle(bounds()));
@@ -317,6 +328,7 @@
   jsobj.AddProperty("_kind", kind_string);
   jsobj.AddProperty("static", is_static());
   jsobj.AddProperty("const", is_const());
+  jsobj.AddProperty("implicit", IsImplicitGetterOrSetter());
   jsobj.AddProperty("_intrinsic", is_intrinsic());
   jsobj.AddProperty("_native", is_native());
 
@@ -328,6 +340,9 @@
   if (ref) {
     return;
   }
+  const FunctionType& sig = FunctionType::Handle(signature());
+  jsobj.AddProperty("signature", sig);
+
   Code& code = Code::Handle(CurrentCode());
   if (!code.IsNull()) {
     jsobj.AddProperty("code", code);
@@ -1178,7 +1193,38 @@
   JSONObject jsobj(stream);
   PrintSharedInstanceJSON(&jsobj, ref);
   jsobj.AddProperty("kind", "FunctionType");
-  // TODO(regis): Function types were not handled before, necessary now?
+  AbstractType& type = AbstractType::Handle(result_type());
+  jsobj.AddProperty("returnType", type);
+
+  const int type_params_count = NumTypeParameters();
+  if (type_params_count > 0) {
+    JSONArray arr(&jsobj, "typeParameters");
+    TypeParameter& type_param = TypeParameter::Handle();
+    for (intptr_t i = 0; i < type_params_count; ++i) {
+      type_param = TypeParameterAt(i);
+      arr.AddValue(type_param);
+    }
+  }
+
+  {
+    JSONArray jsarr(&jsobj, "parameters");
+    String& name = String::Handle();
+    const intptr_t param_count = NumParameters();
+    const intptr_t fixed_param_count = num_fixed_parameters();
+    const bool has_named = HasOptionalNamedParameters();
+    for (intptr_t i = 0; i < param_count; ++i) {
+      JSONObject param(&jsarr);
+      type = ParameterTypeAt(i);
+      param.AddProperty("parameterType", type);
+      bool fixed = i < fixed_param_count;
+      param.AddProperty("fixed", fixed);
+      if (!fixed && has_named) {
+        name = ParameterNameAt(i);
+        param.AddProperty("name", name.ToCString());
+        param.AddProperty("required", IsRequiredAt(i));
+      }
+    }
+  }
 }
 
 void TypeRef::PrintJSONImpl(JSONStream* stream, bool ref) const {
@@ -1390,6 +1436,41 @@
   }
 }
 
+void LinkedHashSet::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  JSONObject jsobj(stream);
+  PrintSharedInstanceJSON(&jsobj, ref);
+  jsobj.AddProperty("kind", "PlainInstance");
+  jsobj.AddServiceId(*this);
+  jsobj.AddProperty("length", Length());
+  if (ref) {
+    return;
+  }
+  intptr_t offset;
+  intptr_t count;
+  stream->ComputeOffsetAndCount(Length(), &offset, &count);
+  if (offset > 0) {
+    jsobj.AddProperty("offset", offset);
+  }
+  if (count < Length()) {
+    jsobj.AddProperty("count", count);
+  }
+  intptr_t limit = offset + count;
+  ASSERT(limit <= Length());
+  {
+    JSONArray jsarr(&jsobj, "elements");
+    Object& object = Object::Handle();
+    LinkedHashSet::Iterator iterator(*this);
+    int i = 0;
+    while (iterator.MoveNext() && i < limit) {
+      if (i >= offset) {
+        object = iterator.CurrentKey();
+        jsarr.AddValue(object);
+      }
+      i++;
+    }
+  }
+}
+
 void Float32x4::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   PrintSharedInstanceJSON(&jsobj, ref);
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 2ffb6ce..33bede3 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -91,7 +91,20 @@
   return Error::null();
 }
 
-ObjectStore::ObjectStore() {
+ObjectStore::ObjectStore()
+    :
+#define EMIT_FIELD_INIT(type, name) name##_(nullptr),
+      OBJECT_STORE_FIELD_LIST(EMIT_FIELD_INIT,
+                              EMIT_FIELD_INIT,
+                              EMIT_FIELD_INIT,
+                              EMIT_FIELD_INIT,
+                              EMIT_FIELD_INIT,
+                              EMIT_FIELD_INIT,
+                              EMIT_FIELD_INIT,
+                              EMIT_FIELD_INIT)
+#undef EMIT_FIELD_INIT
+          unused_field_(0)  // Just to prevent a trailing comma.
+{
   for (ObjectPtr* current = from(); current <= to(); current++) {
     *current = Object::null();
   }
@@ -121,8 +134,9 @@
     Object& value = Object::Handle();
     static const char* const names[] = {
 #define EMIT_FIELD_NAME(type, name) #name "_",
-        OBJECT_STORE_FIELD_LIST(EMIT_FIELD_NAME, EMIT_FIELD_NAME,
-                                EMIT_FIELD_NAME, EMIT_FIELD_NAME)
+        OBJECT_STORE_FIELD_LIST(
+            EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME,
+            EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME)
 #undef EMIT_FIELD_NAME
     };
     ObjectPtr* current = from();
@@ -270,10 +284,6 @@
     }
   }
 
-  const Library& internal_lib = Library::Handle(zone, _internal_library());
-  cls = internal_lib.LookupClass(Symbols::Symbol());
-  set_symbol_class(cls);
-
   const Library& core_lib = Library::Handle(zone, core_library());
   cls = core_lib.LookupClassAllowPrivate(Symbols::_CompileTimeError());
   ASSERT(!cls.IsNull());
@@ -282,11 +292,13 @@
   cls = core_lib.LookupClassAllowPrivate(Symbols::Pragma());
   ASSERT(!cls.IsNull());
   set_pragma_class(cls);
+  RELEASE_ASSERT(cls.EnsureIsFinalized(thread) == Error::null());
   set_pragma_name(Field::Handle(zone, cls.LookupField(Symbols::name())));
   set_pragma_options(Field::Handle(zone, cls.LookupField(Symbols::options())));
 
   cls = core_lib.LookupClassAllowPrivate(Symbols::_GrowableList());
   ASSERT(!cls.IsNull());
+  RELEASE_ASSERT(cls.EnsureIsFinalized(thread) == Error::null());
   growable_list_factory_ =
       cls.LookupFactoryAllowPrivate(Symbols::_GrowableListFactory());
   ASSERT(growable_list_factory_ != Function::null());
@@ -295,6 +307,10 @@
   ASSERT(!cls.IsNull());
   set_error_class(cls);
 
+  cls = core_lib.LookupClassAllowPrivate(Symbols::Expando());
+  ASSERT(!cls.IsNull());
+  set_expando_class(cls);
+
   // Cache the core private functions used for fast instance of checks.
   simple_instance_of_function_ =
       PrivateObjectLookup(Symbols::_simpleInstanceOf());
@@ -306,6 +322,7 @@
   // Ensure AddSmiSmiCheckForFastSmiStubs run by the background compiler
   // will not create new functions.
   const Class& smi_class = Class::Handle(zone, this->smi_class());
+  RELEASE_ASSERT(smi_class.EnsureIsFinalized(thread) == Error::null());
   function_name =
       Function::CreateDynamicInvocationForwarderName(Symbols::Plus());
   Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name);
@@ -333,41 +350,64 @@
 #endif
 }
 
-void ObjectStore::LazyInitCoreTypes() {
-  if (list_class_ == Type::null()) {
-    ASSERT(non_nullable_list_rare_type_ == Type::null());
-    ASSERT(non_nullable_map_rare_type_ == Type::null());
-    Thread* thread = Thread::Current();
-    Zone* zone = thread->zone();
-    const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
-    Class& cls = Class::Handle(zone, core_lib.LookupClass(Symbols::List()));
+void ObjectStore::LazyInitCoreMembers() {
+  auto* const thread = Thread::Current();
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
+  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(_object_equals_function_.load() == Function::null());
+    ASSERT(_object_hash_code_function_.load() == Function::null());
+    ASSERT(_object_to_string_function_.load() == Function::null());
+
+    auto* const zone = thread->zone();
+    const auto& core_lib = Library::Handle(zone, Library::CoreLibrary());
+    auto& cls = Class::Handle(zone);
+
+    cls = core_lib.LookupClass(Symbols::List());
     ASSERT(!cls.IsNull());
-    set_list_class(cls);
-    Type& type = Type::Handle(zone);
+    list_class_.store(cls.ptr());
+
+    auto& type = Type::Handle(zone);
     type ^= cls.RareType();
-    set_non_nullable_list_rare_type(type);
+    non_nullable_list_rare_type_.store(type.ptr());
+
     cls = core_lib.LookupClass(Symbols::Map());
     ASSERT(!cls.IsNull());
     type ^= cls.RareType();
-    set_non_nullable_map_rare_type(type);
+    non_nullable_map_rare_type_.store(type.ptr());
+
+    auto& function = Function::Handle(zone);
+
+    function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectHashCode());
+    ASSERT(!function.IsNull());
+    _object_hash_code_function_.store(function.ptr());
+
+    function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectEquals());
+    ASSERT(!function.IsNull());
+    _object_equals_function_.store(function.ptr());
+
+    function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectToString());
+    ASSERT(!function.IsNull());
+    _object_to_string_function_.store(function.ptr());
   }
 }
 
-void ObjectStore::LazyInitFutureTypes() {
-  if (non_nullable_future_rare_type_ == Type::null()) {
-    ASSERT(non_nullable_future_never_type_ == Type::null() &&
-           nullable_future_null_type_ == Type::null());
-    Thread* thread = Thread::Current();
-    Zone* zone = thread->zone();
-    Class& cls = Class::Handle(zone, future_class());
-    if (cls.IsNull()) {
-      const Library& async_lib = Library::Handle(zone, async_library());
-      ASSERT(!async_lib.IsNull());
-      cls = async_lib.LookupClass(Symbols::Future());
-      ASSERT(!cls.IsNull());
-    }
-    TypeArguments& type_args = TypeArguments::Handle(zone);
-    Type& type = Type::Handle(zone);
+void ObjectStore::LazyInitAsyncMembers() {
+  auto* const thread = Thread::Current();
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
+  if (non_nullable_future_rare_type_.load() == Type::null()) {
+    ASSERT(non_nullable_future_never_type_.load() == Type::null());
+    ASSERT(nullable_future_null_type_.load() == Type::null());
+
+    auto* const zone = thread->zone();
+    const auto& cls = Class::Handle(zone, future_class());
+    ASSERT(!cls.IsNull());
+
+    auto& type_args = TypeArguments::Handle(zone);
+    auto& type = Type::Handle(zone);
     type = never_type();
     ASSERT(!type.IsNull());
     type_args = TypeArguments::New(1);
@@ -375,7 +415,8 @@
     type = Type::New(cls, type_args, Nullability::kNonNullable);
     type.SetIsFinalized();
     type ^= type.Canonicalize(thread, nullptr);
-    set_non_nullable_future_never_type(type);
+    non_nullable_future_never_type_.store(type.ptr());
+
     type = null_type();
     ASSERT(!type.IsNull());
     type_args = TypeArguments::New(1);
@@ -383,9 +424,67 @@
     type = Type::New(cls, type_args, Nullability::kNullable);
     type.SetIsFinalized();
     type ^= type.Canonicalize(thread, nullptr);
-    set_nullable_future_null_type(type);
+    nullable_future_null_type_.store(type.ptr());
+
     type ^= cls.RareType();
-    set_non_nullable_future_rare_type(type);
+    non_nullable_future_rare_type_.store(type.ptr());
+  }
+}
+
+void ObjectStore::LazyInitIsolateMembers() {
+  auto* const thread = Thread::Current();
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
+  if (lookup_port_handler_.load() == Type::null()) {
+    ASSERT(lookup_open_ports_.load() == Type::null());
+    ASSERT(handle_message_function_.load() == Type::null());
+
+    auto* const zone = thread->zone();
+    const auto& isolate_lib = Library::Handle(zone, Library::IsolateLibrary());
+    auto& cls = Class::Handle(zone);
+    auto& function = Function::Handle(zone);
+
+    cls = isolate_lib.LookupClassAllowPrivate(Symbols::_RawReceivePortImpl());
+    ASSERT(!cls.IsNull());
+    const auto& error = cls.EnsureIsFinalized(thread);
+    ASSERT(error == Error::null());
+
+    function = cls.LookupFunctionAllowPrivate(Symbols::_lookupHandler());
+    ASSERT(!function.IsNull());
+    lookup_port_handler_.store(function.ptr());
+
+    function = cls.LookupFunctionAllowPrivate(Symbols::_lookupOpenPorts());
+    ASSERT(!function.IsNull());
+    lookup_open_ports_.store(function.ptr());
+
+    function = cls.LookupFunctionAllowPrivate(Symbols::_handleMessage());
+    ASSERT(!function.IsNull());
+    handle_message_function_.store(function.ptr());
+  }
+}
+
+void ObjectStore::LazyInitInternalMembers() {
+  auto* const thread = Thread::Current();
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
+  if (symbol_class_.load() == Type::null()) {
+    ASSERT(symbol_name_field_.load() == Field::null());
+
+    auto* const zone = thread->zone();
+    auto& cls = Class::Handle(zone);
+    auto& field = Field::Handle(zone);
+
+    const auto& internal_lib =
+        Library::Handle(zone, Library::InternalLibrary());
+    cls = internal_lib.LookupClass(Symbols::Symbol());
+    ASSERT(!cls.IsNull());
+    const auto& error = cls.EnsureIsFinalized(thread);
+    ASSERT(error == Error::null());
+    symbol_class_.store(cls.ptr());
+
+    field = cls.LookupInstanceFieldAllowPrivate(Symbols::_name());
+    ASSERT(!field.IsNull());
+    symbol_name_field_.store(field.ptr());
   }
 }
 
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index eec9974e..a944d89 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -36,9 +36,28 @@
 //
 // R_ - needs getter only
 // RW - needs getter and setter
-// CW - needs lazy Core init getter and setter
-// FW - needs lazy Future init getter and setter
-#define OBJECT_STORE_FIELD_LIST(R_, RW, CW, FW)                                \
+// ARW_RELAXED - needs getter and setter with relaxed atomic access
+// ARW_AR - needs getter and setter with acq/rel atomic access
+// LAZY_CORE - needs lazy init getter for a "dart:core" member
+// LAZY_ASYNC - needs lazy init getter for a "dart:async" member
+// LAZY_ISOLATE - needs lazy init getter for a "dart:isolate" member
+// LAZY_INTERNAL - needs lazy init getter for a "dart:_internal" member
+#define OBJECT_STORE_FIELD_LIST(R_, RW, ARW_RELAXED, ARW_AR, LAZY_CORE,        \
+                                LAZY_ASYNC, LAZY_ISOLATE, LAZY_INTERNAL)       \
+  LAZY_CORE(Class, list_class)                                                 \
+  LAZY_CORE(Type, non_nullable_list_rare_type)                                 \
+  LAZY_CORE(Type, non_nullable_map_rare_type)                                  \
+  LAZY_CORE(Function, _object_equals_function)                                 \
+  LAZY_CORE(Function, _object_hash_code_function)                              \
+  LAZY_CORE(Function, _object_to_string_function)                              \
+  LAZY_INTERNAL(Class, symbol_class)                                           \
+  LAZY_INTERNAL(Field, symbol_name_field)                                      \
+  LAZY_ASYNC(Type, non_nullable_future_rare_type)                              \
+  LAZY_ASYNC(Type, non_nullable_future_never_type)                             \
+  LAZY_ASYNC(Type, nullable_future_null_type)                                  \
+  LAZY_ISOLATE(Function, lookup_port_handler)                                  \
+  LAZY_ISOLATE(Function, lookup_open_ports)                                    \
+  LAZY_ISOLATE(Function, handle_message_function)                              \
   RW(Class, object_class)                                                      \
   RW(Type, object_type)                                                        \
   RW(Type, legacy_object_type)                                                 \
@@ -81,12 +100,6 @@
   RW(Type, string_type)                                                        \
   RW(Type, legacy_string_type)                                                 \
   RW(Type, non_nullable_string_type)                                           \
-  CW(Class, list_class)                    /* maybe be null, lazily built */   \
-  CW(Type, non_nullable_list_rare_type)    /* maybe be null, lazily built */   \
-  CW(Type, non_nullable_map_rare_type)     /* maybe be null, lazily built */   \
-  FW(Type, non_nullable_future_rare_type)  /* maybe be null, lazily built */   \
-  FW(Type, non_nullable_future_never_type) /* maybe be null, lazily built */   \
-  FW(Type, nullable_future_null_type)      /* maybe be null, lazily built */   \
   RW(TypeArguments, type_argument_int)                                         \
   RW(TypeArguments, type_argument_legacy_int)                                  \
   RW(TypeArguments, type_argument_non_nullable_int)                            \
@@ -108,7 +121,6 @@
   RW(Field, pragma_options)                                                    \
   RW(Class, future_class)                                                      \
   RW(Class, completer_class)                                                   \
-  RW(Class, symbol_class)                                                      \
   RW(Class, one_byte_string_class)                                             \
   RW(Class, two_byte_string_class)                                             \
   RW(Class, external_one_byte_string_class)                                    \
@@ -129,8 +141,9 @@
   RW(Class, int32x4_class)                                                     \
   RW(Class, float64x2_class)                                                   \
   RW(Class, error_class)                                                       \
+  RW(Class, expando_class)                                                     \
   RW(Class, weak_property_class)                                               \
-  RW(Array, symbol_table)                                                      \
+  ARW_AR(Array, symbol_table)                                                  \
   RW(Array, canonical_types)                                                   \
   RW(Array, canonical_function_types)                                          \
   RW(Array, canonical_type_parameters)                                         \
@@ -158,12 +171,6 @@
   RW(GrowableObjectArray, pending_classes)                                     \
   RW(Instance, stack_overflow)                                                 \
   RW(Instance, out_of_memory)                                                  \
-  RW(Function, _object_equals_function)                                        \
-  RW(Function, _object_hash_code_function)                                     \
-  RW(Function, _object_to_string_function)                                     \
-  RW(Function, lookup_port_handler)                                            \
-  RW(Function, lookup_open_ports)                                              \
-  RW(Function, handle_message_function)                                        \
   RW(Function, growable_list_factory)                                          \
   RW(Function, simple_instance_of_function)                                    \
   RW(Function, simple_instance_of_true_function)                               \
@@ -172,11 +179,14 @@
   RW(Function, complete_on_async_return)                                       \
   RW(Function, complete_on_async_error)                                        \
   RW(Class, async_star_stream_controller)                                      \
+  ARW_RELAXED(Smi, future_timeout_future_index)                                \
+  ARW_RELAXED(Smi, future_wait_future_index)                                   \
   RW(CompressedStackMaps, canonicalized_stack_map_entries)                     \
   RW(ObjectPool, global_object_pool)                                           \
   RW(Array, unique_dynamic_targets)                                            \
   RW(GrowableObjectArray, megamorphic_cache_table)                             \
-  RW(Code, build_method_extractor_code)                                        \
+  RW(Code, build_generic_method_extractor_code)                                \
+  RW(Code, build_nongeneric_method_extractor_code)                             \
   RW(Code, dispatch_table_null_error_stub)                                     \
   RW(Code, late_initialization_error_stub_with_fpu_regs_stub)                  \
   RW(Code, late_initialization_error_stub_without_fpu_regs_stub)               \
@@ -387,35 +397,62 @@
   ObjectStore();
   ~ObjectStore();
 
+#define DECLARE_OFFSET(name)                                                   \
+  static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
 #define DECLARE_GETTER(Type, name)                                             \
   Type##Ptr name() const { return name##_; }                                   \
-  static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
+  DECLARE_OFFSET(name)
 #define DECLARE_GETTER_AND_SETTER(Type, name)                                  \
   DECLARE_GETTER(Type, name)                                                   \
   void set_##name(const Type& value) { name##_ = value.ptr(); }
+#define DECLARE_RELAXED_ATOMIC_GETTER_AND_SETTER(Type, name)                   \
+  template <std::memory_order order = std::memory_order_relaxed>               \
+  Type##Ptr name() const {                                                     \
+    return name##_.load(order);                                                \
+  }                                                                            \
+  template <std::memory_order order = std::memory_order_relaxed>               \
+  void set_##name(const Type& value) {                                         \
+    name##_.store(value.ptr(), order);                                         \
+  }                                                                            \
+  DECLARE_OFFSET(name)
+#define DECLARE_ACQREL_ATOMIC_GETTER_AND_SETTER(Type, name)                    \
+  Type##Ptr name() const { return name##_.load(); }                            \
+  void set_##name(const Type& value) { name##_.store(value.ptr()); }           \
+  DECLARE_OFFSET(name)
 #define DECLARE_LAZY_INIT_GETTER(Type, name, init)                             \
   Type##Ptr name() {                                                           \
-    if (name##_ == Type::null()) {                                             \
+    if (name##_.load() == Type::null()) {                                      \
       init();                                                                  \
     }                                                                          \
-    return name##_;                                                            \
+    return name##_.load();                                                     \
   }                                                                            \
-  static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
-#define DECLARE_LAZY_INIT_CORE_GETTER_AND_SETTER(Type, name)                   \
-  DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitCoreTypes)                      \
-  void set_##name(const Type& value) { name##_ = value.ptr(); }
-#define DECLARE_LAZY_INIT_FUTURE_GETTER_AND_SETTER(Type, name)                 \
-  DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitFutureTypes)                    \
-  void set_##name(const Type& value) { name##_ = value.ptr(); }
+  DECLARE_OFFSET(name)
+#define DECLARE_LAZY_INIT_CORE_GETTER(Type, name)                              \
+  DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitCoreMembers)
+#define DECLARE_LAZY_INIT_ASYNC_GETTER(Type, name)                             \
+  DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitAsyncMembers)
+#define DECLARE_LAZY_INIT_ISOLATE_GETTER(Type, name)                           \
+  DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitIsolateMembers)
+#define DECLARE_LAZY_INIT_INTERNAL_GETTER(Type, name)                          \
+  DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitInternalMembers)
   OBJECT_STORE_FIELD_LIST(DECLARE_GETTER,
                           DECLARE_GETTER_AND_SETTER,
-                          DECLARE_LAZY_INIT_CORE_GETTER_AND_SETTER,
-                          DECLARE_LAZY_INIT_FUTURE_GETTER_AND_SETTER)
+                          DECLARE_RELAXED_ATOMIC_GETTER_AND_SETTER,
+                          DECLARE_ACQREL_ATOMIC_GETTER_AND_SETTER,
+                          DECLARE_LAZY_INIT_CORE_GETTER,
+                          DECLARE_LAZY_INIT_ASYNC_GETTER,
+                          DECLARE_LAZY_INIT_ISOLATE_GETTER,
+                          DECLARE_LAZY_INIT_INTERNAL_GETTER)
+#undef DECLARE_OFFSET
 #undef DECLARE_GETTER
 #undef DECLARE_GETTER_AND_SETTER
+#undef DECLARE_RELAXED_ATOMIC_GETTER_AND_SETTER
+#undef DECLARE_ACQREL_ATOMIC_GETTER_AND_SETTER
 #undef DECLARE_LAZY_INIT_GETTER
-#undef DECLARE_LAZY_INIT_CORE_GETTER_AND_SETTER
-#undef DECLARE_LAZY_INIT_FUTURE_GETTER_AND_SETTER
+#undef DECLARE_LAZY_INIT_CORE_GETTER
+#undef DECLARE_LAZY_INIT_ASYNC_GETTER
+#undef DECLARE_LAZY_INIT_ISOLATE_GETTER
+#undef DECLARE_LAZY_INIT_INTERNAL_GETTER
 
   LibraryPtr bootstrap_library(BootstrapLibraryId index) {
     switch (index) {
@@ -463,19 +500,31 @@
 #endif
 
  private:
-  void LazyInitCoreTypes();
-  void LazyInitFutureTypes();
+  void LazyInitCoreMembers();
+  void LazyInitAsyncMembers();
+  void LazyInitIsolateMembers();
+  void LazyInitInternalMembers();
 
   // Finds a core library private method in Object.
   FunctionPtr PrivateObjectLookup(const String& name);
 
-  ObjectPtr* from() { return reinterpret_cast<ObjectPtr*>(&object_class_); }
+  ObjectPtr* from() { return reinterpret_cast<ObjectPtr*>(&list_class_); }
 #define DECLARE_OBJECT_STORE_FIELD(type, name) type##Ptr name##_;
+#define DECLARE_ATOMIC_OBJECT_STORE_FIELD(type, name)                          \
+  std::atomic<type##Ptr> name##_;
+#define DECLARE_LAZY_OBJECT_STORE_FIELD(type, name)                            \
+  AcqRelAtomic<type##Ptr> name##_;
   OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
                           DECLARE_OBJECT_STORE_FIELD,
-                          DECLARE_OBJECT_STORE_FIELD,
-                          DECLARE_OBJECT_STORE_FIELD)
+                          DECLARE_ATOMIC_OBJECT_STORE_FIELD,
+                          DECLARE_LAZY_OBJECT_STORE_FIELD,
+                          DECLARE_LAZY_OBJECT_STORE_FIELD,
+                          DECLARE_LAZY_OBJECT_STORE_FIELD,
+                          DECLARE_LAZY_OBJECT_STORE_FIELD,
+                          DECLARE_LAZY_OBJECT_STORE_FIELD)
 #undef DECLARE_OBJECT_STORE_FIELD
+#undef DECLARE_ATOMIC_OBJECT_STORE_FIELD
+#undef DECLARE_LAZY_OBJECT_STORE_FIELD
   ObjectPtr* to() {
     return reinterpret_cast<ObjectPtr*>(&ffi_as_function_internal_);
   }
@@ -487,7 +536,6 @@
       case Snapshot::kFullJIT:
       case Snapshot::kFullAOT:
         return reinterpret_cast<ObjectPtr*>(&slow_tts_stub_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -495,6 +543,7 @@
     UNREACHABLE();
     return NULL;
   }
+  uword unused_field_;
 
   friend class ProgramSerializationRoots;
   friend class ProgramDeserializationRoots;
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 7e5c738..93cfc12 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2532,8 +2532,8 @@
   const VariableIndex first_local_index(-1);
   bool found_captured_vars = false;
   VariableIndex next_index = parent_scope->AllocateVariables(
-      first_parameter_index, num_parameters, first_local_index, NULL,
-      &found_captured_vars);
+      Function::null_function(), first_parameter_index, num_parameters,
+      first_local_index, NULL, &found_captured_vars);
   // Variables a, c and var_ta are captured, therefore are not allocated in
   // frame.
   EXPECT_EQ(0, next_index.value() -
@@ -4345,7 +4345,7 @@
 
 ISOLATE_UNIT_TEST_CASE(PrintJSONPrimitives) {
   // WARNING: This MUST be big enough for the serialised JSON string.
-  const int kBufferSize = 1024;
+  const int kBufferSize = 4096;
   char buffer[kBufferSize];
   Isolate* isolate = Isolate::Current();
 
@@ -4396,6 +4396,7 @@
         "\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
         "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
         "\"_kind\":\"RegularFunction\",\"static\":false,\"const\":false,"
+        "\"implicit\":false,"
         "\"_intrinsic\":false,\"_native\":false,"
         "\"location\":{\"type\":\"SourceLocation\","
         "\"script\":{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
@@ -4543,18 +4544,42 @@
     ElideJSONSubstring("objects", buffer, buffer);
     ElideJSONSubstring("libraries", buffer, buffer);
     ElideJSONSubstring("_List@", buffer, buffer);
-    StripTokenPositions(buffer);
-    EXPECT_STREQ(
+    ElideJSONSubstring("_TypeParameter@", buffer, buffer);
+    EXPECT_SUBSTRING(
         "{\"type\":\"@Instance\",\"_vmType\":\"Array\",\"class\":{\"type\":\"@"
         "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_List\",\"_vmName\":"
         "\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{\"type\":"
-        "\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
-        "patch\\/array.dart\",\"_kind\":\"kernel\"}"
-        "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+        "\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-patch\\/"
+        "array.dart\",\"_kind\":\"kernel\"},\"tokenPos\":248,\"endTokenPos\":"
+        "7758},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
+        "\"name\":\"dart.core\",\"uri\":\"dart:core\"},\"typeParameters\":[{"
+        "\"type\":\"@"
+        "Instance\",\"_vmType\":\"TypeParameter\",\"class\":{\"type\":\"@"
+        "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_TypeParameter\",\"_"
+        "vmName\":\"\",\"location\":{\"type\":"
+        "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
+        "\"id\":\"\",\"uri\":\"dart:core-patch\\/"
+        "type_patch.dart\",\"_kind\":\"kernel\"},\"tokenPos\":1584,"
+        "\"endTokenPos\":1729},\"library\":{\"type\":\"@Library\",\"fixedId\":"
         "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
+        "\"identityHashCode\":",
+        buffer);
+
+    EXPECT_SUBSTRING(
+        "\"kind\":\"TypeParameter\",\"id\":\"\",\"name\":\"X0\","
+        "\"parameterizedClass\":{\"type\":\"@Instance\",\"_vmType\":\"Class\","
+        "\"class\":{\"type\":\"@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\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
+        "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
+        "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}}]},"
         "\"identityHashCode\":0,\"kind\":\"List\",\"id\":\"\",\"length\":0}",
         buffer);
   }
+  OS::PrintErr("\n\n\n");
   // GrowableObjectArray reference
   {
     JSONStream js;
@@ -4568,16 +4593,40 @@
     ElideJSONSubstring("libraries", buffer, buffer);
     ElideJSONSubstring("_GrowableList@", buffer, buffer);
     StripTokenPositions(buffer);
-    EXPECT_STREQ(
+    ElideJSONSubstring("_TypeParameter@", buffer, buffer);
+    EXPECT_SUBSTRING(
         "{\"type\":\"@Instance\",\"_vmType\":\"GrowableObjectArray\",\"class\":"
         "{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_"
         "GrowableList\",\"_vmName\":\"\",\"location\":{\"type\":"
         "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
-        "\"id\":\"\",\"uri\":\"dart:core-patch\\/growable_array.dart\",\"_"
-        "kind\":\"kernel\"}},"
-        "\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
-        "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"identityHashCode\":0,"
-        "\"kind\":\"List\",\"id\":\"\",\"length\":0}",
+        "\"id\":\"\",\"uri\":\"dart:core-patch\\/"
+        "growable_array.dart\",\"_kind\":\"kernel\"}"
+        "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+        "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"},"
+        "\"typeParameters\":[{\"type\":\"@Instance\",\"_vmType\":"
+        "\"TypeParameter\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
+        "\"id\":\"\",\"name\":\"_TypeParameter\",\"_vmName\":\""
+        "\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
+        "\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
+        "patch\\/"
+        "type_patch.dart\",\"_kind\":\"kernel\"}"
+        "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+        "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
+        "\"identityHashCode\":",
+        buffer);
+
+    EXPECT_SUBSTRING(
+        "\"kind\":\"TypeParameter\",\"id\":"
+        "\"\",\"name\":\"X0\",\"parameterizedClass\":{\"type\":\"@Instance\","
+        "\"_vmType\":\"Class\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
+        "\"id\":\"\",\"name\":\"Null\",\"location\":{\"type\":"
+        "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
+        "\"id\":\"\",\"uri\":\"dart:core\\/"
+        "null.dart\",\"_kind\":\"kernel\"}"
+        "},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
+        "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
+        "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}}]},"
+        "\"identityHashCode\":0,\"kind\":\"List\",\"id\":\"\",\"length\":0}",
         buffer);
   }
   // LinkedHashMap reference
@@ -4593,15 +4642,61 @@
     ElideJSONSubstring("libraries", buffer, buffer);
     ElideJSONSubstring("_InternalLinkedHashMap@", buffer, buffer);
     StripTokenPositions(buffer);
-    EXPECT_STREQ(
+    ElideJSONSubstring("_TypeParameter@", buffer, buffer);
+    EXPECT_SUBSTRING(
         "{\"type\":\"@Instance\",\"_vmType\":\"LinkedHashMap\",\"class\":{"
         "\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_"
         "InternalLinkedHashMap\",\"_vmName\":\"\",\"location\":{\"type\":"
         "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
-        "\"id\":\"\",\"uri\":\"dart:collection-patch\\/compact_hash.dart\",\"_"
-        "kind\":\"kernel\"}},"
-        "\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
-        "\"name\":\"dart.collection\",\"uri\":\"dart:collection\"}},"
+        "\"id\":\"\",\"uri\":\"dart:collection-patch\\/"
+        "compact_hash.dart\",\"_kind\":\"kernel\"}"
+        "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+        "true,\"id\":\"\",\"name\":\"dart.collection\",\"uri\":\"dart:"
+        "collection\"},\"typeParameters\":[{\"type\":\"@Instance\",\"_vmType\":"
+        "\"TypeParameter\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
+        "\"id\":\"\",\"name\":\"_TypeParameter\",\"_vmName\":\""
+        "\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
+        "\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
+        "patch\\/"
+        "type_patch.dart\",\"_kind\":\"kernel\"}"
+        "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+        "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
+        "\"identityHashCode\":",
+        buffer);
+
+    EXPECT_SUBSTRING(
+        "\"kind\":\"TypeParameter\",\"id\":"
+        "\"\",\"name\":\"X0\",\"parameterizedClass\":{\"type\":\"@Instance\","
+        "\"_vmType\":\"Class\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
+        "\"id\":\"\",\"name\":\"Null\",\"location\":{\"type\":"
+        "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
+        "\"id\":\"\",\"uri\":\"dart:core\\/"
+        "null.dart\",\"_kind\":\"kernel\"}"
+        "},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
+        "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
+        "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}},{\"type\":"
+        "\"@Instance\",\"_vmType\":\"TypeParameter\",\"class\":{\"type\":\"@"
+        "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_TypeParameter\",\"_"
+        "vmName\":\"\",\"location\":{\"type\":"
+        "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
+        "\"id\":\"\",\"uri\":\"dart:core-patch\\/"
+        "type_patch.dart\",\"_kind\":\"kernel\"}"
+        "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+        "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
+        "\"identityHashCode\":",
+        buffer);
+
+    EXPECT_SUBSTRING(
+        "\"kind\":\"TypeParameter\",\"id\":"
+        "\"\",\"name\":\"X1\",\"parameterizedClass\":{\"type\":\"@Instance\","
+        "\"_vmType\":\"Class\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
+        "\"id\":\"\",\"name\":\"Null\",\"location\":{\"type\":"
+        "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
+        "\"id\":\"\",\"uri\":\"dart:core\\/"
+        "null.dart\",\"_kind\":\"kernel\"}"
+        "},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
+        "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
+        "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}}]},"
         "\"identityHashCode\":0,\"kind\":\"Map\",\"id\":\"\",\"length\":0}",
         buffer);
   }
@@ -4779,8 +4874,7 @@
     const char* value_script,
     uint32_t hashcode_canonicalize_vm = kCalculateCanonizalizeHash,
     bool check_identity = true,
-    bool check_hashcode = true,
-    bool print_failure = true) {
+    bool check_hashcode = true) {
   auto kScriptChars = Utils::CStringUniquePtr(
       OS::SCreate(nullptr,
                   "%s"
@@ -4834,7 +4928,7 @@
     success &= identity_hashcode_dart == hashcode_canonicalize_vm;
   }
 
-  if (!success && print_failure) {
+  if (!success) {
     LogBlock lb;
     THR_Print(
         "Dart hashCode or Dart identityHashCode does not equal VM "
@@ -4896,6 +4990,15 @@
   EXPECT(HashCodeEqualsCanonicalizeHash(kScript));
 }
 
+TEST_CASE(HashCode_Symbol) {
+  const char* kScript =
+      "value() {\n"
+      "  return #A;\n"
+      "}\n";
+  EXPECT(HashCodeEqualsCanonicalizeHash(kScript, kCalculateCanonizalizeHash,
+                                        /*check_identity=*/false));
+}
+
 TEST_CASE(HashCode_True) {
   const char* kScript =
       "value() {\n"
@@ -4926,6 +5029,64 @@
                                         /*check_identity=*/false));
 }
 
+// Because we want to reuse CanonicalizeHash for hashCode, we should not have
+// collisions.
+TEST_CASE(CanonicalizeHash_Const_Instances) {
+  const char* kScript =
+      "class A {\n"
+      "  final int n;\n"
+      "  \n"
+      "  const A(this.n);\n"
+      "}\n"
+      "\n"
+      "class B {\n"
+      "  final int n;\n"
+      "  \n"
+      "  const B(this.n);\n"
+      "}\n"
+      "\n"
+      "valueA() {\n"
+      "  return const A(5);\n"
+      "}\n"
+      "\n"
+      "valueB() {\n"
+      "  return const B(5);\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, nullptr);
+  EXPECT_VALID(lib);
+
+  Dart_Handle value_a_result =
+      Dart_Invoke(lib, NewString("valueA"), 0, nullptr);
+  EXPECT_VALID(value_a_result);
+  Dart_Handle value_b_result =
+      Dart_Invoke(lib, NewString("valueB"), 0, nullptr);
+  EXPECT_VALID(value_b_result);
+
+  TransitionNativeToVM transition(Thread::Current());
+
+  const auto& value_a_dart = Instance::CheckedHandle(
+      Thread::Current()->zone(), Api::UnwrapHandle(value_a_result));
+  const auto& value_b_dart = Instance::CheckedHandle(
+      Thread::Current()->zone(), Api::UnwrapHandle(value_b_result));
+
+  const uint32_t canonicalize_hash_a = value_a_dart.CanonicalizeHash();
+  const uint32_t canonicalize_hash_b = value_b_dart.CanonicalizeHash();
+
+  bool success = canonicalize_hash_a != canonicalize_hash_b;
+
+  if (!success) {
+    LogBlock lb;
+    THR_Print("Hash collision between %s and %s\n", value_a_dart.ToCString(),
+              value_b_dart.ToCString());
+    THR_Print("VM CanonicalizeHash a %" Px32 " %" Pd32 "\n",
+              canonicalize_hash_a, canonicalize_hash_a);
+    THR_Print("VM CanonicalizeHash b %" Px32 " %" Pd32 "\n",
+              canonicalize_hash_b, canonicalize_hash_b);
+  }
+  EXPECT(success);
+}
+
 TEST_CASE(LinkedHashMap_iteration) {
   const char* kScript =
       "makeMap() {\n"
@@ -4965,6 +5126,41 @@
   EXPECT(!iterator.MoveNext());
 }
 
+TEST_CASE(LinkedHashSet_iteration) {
+  const char* kScript =
+      "makeSet() {\n"
+      "  var set = {'x', 'y', 'z', 'w'};\n"
+      "  set.remove('y');\n"
+      "  set.remove('w');\n"
+      "  return set;\n"
+      "}";
+  Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(h_lib);
+  Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeSet"), 0, NULL);
+  EXPECT_VALID(h_result);
+
+  TransitionNativeToVM transition(thread);
+  Instance& dart_set = Instance::Handle();
+  dart_set ^= Api::UnwrapHandle(h_result);
+  ASSERT(dart_set.IsLinkedHashSet());
+  const LinkedHashSet& cc_set = LinkedHashSet::Cast(dart_set);
+
+  EXPECT_EQ(2, cc_set.Length());
+
+  LinkedHashSet::Iterator iterator(cc_set);
+  Object& object = Object::Handle();
+
+  EXPECT(iterator.MoveNext());
+  object = iterator.CurrentKey();
+  EXPECT_STREQ("x", object.ToCString());
+
+  EXPECT(iterator.MoveNext());
+  object = iterator.CurrentKey();
+  EXPECT_STREQ("z", object.ToCString());
+
+  EXPECT(!iterator.MoveNext());
+}
+
 static void CheckConcatAll(const String* data[], intptr_t n) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 866d0aa..7c6592f 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -287,7 +287,7 @@
   VariableIndex first_local_index =
       VariableIndex(parameter_index_start.value() > 0 ? 0 : -num_params);
   VariableIndex next_free_index = scope->AllocateVariables(
-      parameter_index_start, num_params, first_local_index, NULL,
+      function(), parameter_index_start, num_params, first_local_index, NULL,
       &found_captured_variables);
 
   num_stack_locals_ = -next_free_index.value();
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index c7312de..a671373 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -243,7 +243,9 @@
   MutexLocker ml(mutex_);
   auto it = ports_->TryLookup(receiver);
   if (it == ports_->end()) return false;
-  return (*it).handler->isolate()->group() == group;
+  auto isolate = (*it).handler->isolate();
+  if (isolate == nullptr) return false;
+  return isolate->group() == group;
 }
 
 void PortMap::Init() {
diff --git a/runtime/vm/port.h b/runtime/vm/port.h
index 1405362..4999ad4 100644
--- a/runtime/vm/port.h
+++ b/runtime/vm/port.h
@@ -63,6 +63,7 @@
   // Returns the owning Isolate for port 'id'.
   static Isolate* GetIsolate(Dart_Port id);
 
+  // Whether the destination port's isolate is a member of [isolate_group].
   static bool IsReceiverInThisIsolateGroup(Dart_Port receiver,
                                            IsolateGroup* group);
 
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 532eb63..2436574 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -19,6 +19,7 @@
 #include "vm/object.h"
 #include "vm/os.h"
 #include "vm/profiler.h"
+#include "vm/profiler_service.h"
 #include "vm/reusable_handles.h"
 #include "vm/signal_handler.h"
 #include "vm/simulator.h"
@@ -61,8 +62,8 @@
 #ifndef PRODUCT
 
 RelaxedAtomic<bool> Profiler::initialized_ = false;
-SampleBuffer* Profiler::sample_buffer_ = NULL;
-AllocationSampleBuffer* Profiler::allocation_sample_buffer_ = NULL;
+SampleBlockBuffer* Profiler::sample_block_buffer_ = nullptr;
+AllocationSampleBuffer* Profiler::allocation_sample_buffer_ = nullptr;
 ProfilerCounters Profiler::counters_ = {};
 
 void Profiler::Init() {
@@ -75,9 +76,9 @@
   SetSamplePeriod(FLAG_profile_period);
   // The profiler may have been shutdown previously, in which case the sample
   // buffer will have already been initialized.
-  if (sample_buffer_ == NULL) {
-    intptr_t capacity = CalculateSampleBufferCapacity();
-    sample_buffer_ = new SampleBuffer(capacity);
+  if (sample_block_buffer_ == nullptr) {
+    intptr_t num_blocks = CalculateSampleBufferCapacity();
+    sample_block_buffer_ = new SampleBlockBuffer(num_blocks);
     Profiler::InitAllocationSampleBuffer();
   }
   ThreadInterrupter::Init();
@@ -92,14 +93,28 @@
   }
 }
 
+class SampleBlockCleanupVisitor : public IsolateVisitor {
+ public:
+  SampleBlockCleanupVisitor() = default;
+  virtual ~SampleBlockCleanupVisitor() = default;
+
+  void VisitIsolate(Isolate* isolate) {
+    isolate->set_current_allocation_sample_block(nullptr);
+    {
+      MutexLocker ml(isolate->current_sample_block_lock());
+      isolate->set_current_sample_block(nullptr);
+    }
+  }
+};
+
 void Profiler::Cleanup() {
   if (!FLAG_profiler) {
     return;
   }
   ASSERT(initialized_);
   ThreadInterrupter::Cleanup();
-  delete sample_buffer_;
-  sample_buffer_ = NULL;
+  SampleBlockCleanupVisitor visitor;
+  Isolate::VisitIsolates(&visitor);
   initialized_ = false;
 }
 
@@ -130,16 +145,16 @@
 
 intptr_t Profiler::CalculateSampleBufferCapacity() {
   if (FLAG_sample_buffer_duration <= 0) {
-    return SampleBuffer::kDefaultBufferCapacity;
+    return SampleBlockBuffer::kDefaultBlockCount;
   }
   // Deeper stacks require more than a single Sample object to be represented
   // correctly. These samples are chained, so we need to determine the worst
   // case sample chain length for a single stack.
   const intptr_t max_sample_chain_length =
       FLAG_max_profile_depth / kMaxSamplesPerTick;
-  const intptr_t buffer_size = FLAG_sample_buffer_duration *
-                               SamplesPerSecond() * max_sample_chain_length;
-  return buffer_size;
+  const intptr_t sample_count = FLAG_sample_buffer_duration *
+                                SamplesPerSecond() * max_sample_chain_length;
+  return (sample_count / SampleBlock::kSamplesPerBlock) + 1;
 }
 
 void Profiler::SetSamplePeriod(intptr_t period) {
@@ -156,7 +171,171 @@
   SetSamplePeriod(FLAG_profile_period);
 }
 
-SampleBuffer::SampleBuffer(intptr_t capacity) {
+SampleBlockBuffer::SampleBlockBuffer(intptr_t blocks,
+                                     intptr_t samples_per_block) {
+  const intptr_t size = Utils::RoundUp(
+      blocks * samples_per_block * sizeof(Sample), VirtualMemory::PageSize());
+  const bool kNotExecutable = false;
+  memory_ = VirtualMemory::Allocate(size, kNotExecutable, "dart-profiler");
+  if (memory_ == NULL) {
+    OUT_OF_MEMORY();
+  }
+  sample_buffer_ = reinterpret_cast<Sample*>(memory_->address());
+  blocks_ = new SampleBlock[blocks];
+  for (intptr_t i = 0; i < blocks; ++i) {
+    blocks_[i].Init(&sample_buffer_[i * samples_per_block], samples_per_block);
+  }
+  capacity_ = blocks;
+  cursor_ = 0;
+  free_list_head_ = nullptr;
+  free_list_tail_ = nullptr;
+}
+
+SampleBlockBuffer::~SampleBlockBuffer() {
+  delete[] blocks_;
+  blocks_ = nullptr;
+  delete memory_;
+  memory_ = nullptr;
+  capacity_ = 0;
+  cursor_ = 0;
+}
+
+SampleBlock* SampleBlockBuffer::ReserveSampleBlock() {
+  // Don't increment right away to avoid unlikely wrap-around errors.
+  if (cursor_.load() < capacity_) {
+    intptr_t index = cursor_.fetch_add(1u);
+    // Check the index again to make sure the last block hasn't been snatched
+    // from underneath us.
+    if (index < capacity_) {
+      return &blocks_[index];
+    }
+  }
+  // Try to re-use a previously freed SampleBlock once we've handed out each
+  // block at least once. Freed blocks aren't cleared immediately and are still
+  // valid until they're re-allocated, similar to how a ring buffer would clear
+  // the oldest samples.
+  SampleBlock* block = GetFreeBlock();
+  if (block != nullptr) {
+    block->Clear();
+  }
+  return block;
+}
+
+void SampleBlockBuffer::ProcessCompletedBlocks() {
+  Thread* thread = Thread::Current();
+  int64_t start = Dart_TimelineGetMicros();
+  for (intptr_t i = 0; i < capacity_; ++i) {
+    SampleBlock* block = &blocks_[i];
+    if (block->is_full() && !block->evictable()) {
+      if (Service::profiler_stream.enabled()) {
+        Profile profile(block->owner());
+        profile.Build(thread, nullptr, block);
+        ServiceEvent event(block->owner(), ServiceEvent::kCpuSamples);
+        event.set_cpu_profile(&profile);
+        Service::HandleEvent(&event);
+      }
+      block->evictable_ = true;
+      FreeBlock(block);
+    }
+  }
+  int64_t end = Dart_TimelineGetMicros();
+  Dart_TimelineEvent("SampleBlockBuffer::ProcessCompletedBlocks", start, end,
+                     Dart_Timeline_Event_Duration, 0, nullptr, nullptr);
+}
+
+ProcessedSampleBuffer* SampleBlockBuffer::BuildProcessedSampleBuffer(
+    SampleFilter* filter,
+    ProcessedSampleBuffer* buffer) {
+  ASSERT(filter != NULL);
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+
+  if (buffer == nullptr) {
+    buffer = new (zone) ProcessedSampleBuffer();
+  }
+
+  for (intptr_t i = 0; i < capacity_; ++i) {
+    (&blocks_[i])->BuildProcessedSampleBuffer(filter, buffer);
+  }
+
+  return buffer;
+}
+
+Sample* SampleBlock::ReserveSample() {
+  if (full_.load()) {
+    return nullptr;
+  }
+  intptr_t slot = cursor_.fetch_add(1u);
+  if (slot + 1 == capacity_) {
+    full_ = true;
+  }
+  return (slot < capacity_) ? At(slot) : nullptr;
+}
+
+Sample* SampleBlock::ReserveSampleAndLink(Sample* previous) {
+  ASSERT(previous != nullptr);
+  SampleBlockBuffer* buffer = Profiler::sample_block_buffer();
+  Isolate* isolate = owner_;
+  ASSERT(isolate != nullptr);
+  Sample* next = previous->is_allocation_sample()
+                     ? buffer->ReserveAllocationSample(isolate)
+                     : buffer->ReserveCPUSample(isolate);
+  if (next == nullptr) {
+    return nullptr;  // No blocks left, so drop sample.
+  }
+  next->Init(previous->port(), previous->timestamp(), previous->tid());
+  next->set_head_sample(false);
+  // Mark that previous continues at next.
+  previous->SetContinuation(next);
+  return next;
+}
+
+Sample* SampleBlockBuffer::ReserveCPUSample(Isolate* isolate) {
+  return ReserveSampleImpl(isolate, false);
+}
+
+Sample* SampleBlockBuffer::ReserveAllocationSample(Isolate* isolate) {
+  return ReserveSampleImpl(isolate, true);
+}
+
+Sample* SampleBlockBuffer::ReserveSampleImpl(Isolate* isolate,
+                                             bool allocation_sample) {
+  SampleBlock* block = allocation_sample
+                           ? isolate->current_allocation_sample_block()
+                           : isolate->current_sample_block();
+  Sample* sample = nullptr;
+  if (block != nullptr) {
+    sample = block->ReserveSample();
+  }
+  if (sample != nullptr) {
+    return sample;
+  }
+  SampleBlock* next = nullptr;
+  if (allocation_sample) {
+    // We only need to be locked while accessing the CPU sample block since
+    // Dart allocations can only occur on the mutator thread.
+    next = ReserveSampleBlock();
+    if (next == nullptr) {
+      // We're out of blocks to reserve. Drop the sample.
+      return nullptr;
+    }
+    isolate->set_current_allocation_sample_block(next);
+  } else {
+    MutexLocker locker(isolate->current_sample_block_lock());
+    next = ReserveSampleBlock();
+    if (next == nullptr) {
+      // We're out of blocks to reserve. Drop the sample.
+      return nullptr;
+    }
+    isolate->set_current_sample_block(next);
+  }
+  next->set_is_allocation_block(allocation_sample);
+  can_process_block_.store(true);
+  isolate->mutator_thread()->ScheduleInterrupts(Thread::kVMInterrupt);
+  return ReserveSampleImpl(isolate, allocation_sample);
+}
+
+AllocationSampleBuffer::AllocationSampleBuffer(intptr_t capacity) {
   const intptr_t size =
       Utils::RoundUp(capacity * sizeof(Sample), VirtualMemory::PageSize());
   const bool kNotExecutable = false;
@@ -164,85 +343,24 @@
   if (memory_ == NULL) {
     OUT_OF_MEMORY();
   }
-
-  samples_ = reinterpret_cast<Sample*>(memory_->address());
-  capacity_ = capacity;
+  Init(reinterpret_cast<Sample*>(memory_->address()), capacity);
+  free_sample_list_ = nullptr;
   cursor_ = 0;
-
-  if (FLAG_trace_profiler) {
-    OS::PrintErr("Profiler holds %" Pd " samples\n", capacity);
-    OS::PrintErr("Profiler sample is %" Pd " bytes\n", sizeof(Sample));
-    OS::PrintErr("Profiler memory usage = %" Pd " bytes\n", size);
-  }
-  if (FLAG_sample_buffer_duration != 0) {
-    OS::PrintErr(
-        "** WARNING ** Custom sample buffer size provided via "
-        "--sample-buffer-duration\n");
-    OS::PrintErr(
-        "The sample buffer can hold at least %ds worth of "
-        "samples with stacks depths of up to %d, collected at "
-        "a sample rate of %" Pd "Hz.\n",
-        FLAG_sample_buffer_duration, FLAG_max_profile_depth,
-        SamplesPerSecond());
-    OS::PrintErr("The resulting sample buffer size is %" Pd " bytes.\n", size);
-  }
-}
-
-AllocationSampleBuffer::AllocationSampleBuffer(intptr_t capacity)
-    : SampleBuffer(capacity), mutex_(), free_sample_list_(NULL) {}
-
-SampleBuffer::~SampleBuffer() {
-  delete memory_;
 }
 
 AllocationSampleBuffer::~AllocationSampleBuffer() {
-}
-
-Sample* SampleBuffer::At(intptr_t idx) const {
-  ASSERT(idx >= 0);
-  ASSERT(idx < capacity_);
-  return &samples_[idx];
-}
-
-intptr_t SampleBuffer::ReserveSampleSlot() {
-  ASSERT(samples_ != NULL);
-  uintptr_t cursor = cursor_.fetch_add(1u);
-  // Map back into sample buffer range.
-  cursor = cursor % capacity_;
-  return cursor;
-}
-
-Sample* SampleBuffer::ReserveSample() {
-  return At(ReserveSampleSlot());
-}
-
-Sample* SampleBuffer::ReserveSampleAndLink(Sample* previous) {
-  ASSERT(previous != NULL);
-  intptr_t next_index = ReserveSampleSlot();
-  Sample* next = At(next_index);
-  next->Init(previous->port(), previous->timestamp(), previous->tid());
-  next->set_head_sample(false);
-  // Mark that previous continues at next.
-  previous->SetContinuationIndex(next_index);
-  return next;
+  delete memory_;
+  memory_ = nullptr;
 }
 
 void AllocationSampleBuffer::FreeAllocationSample(Sample* sample) {
   MutexLocker ml(&mutex_);
-  while (sample != NULL) {
-    intptr_t continuation_index = -1;
-    if (sample->is_continuation_sample()) {
-      continuation_index = sample->continuation_index();
-    }
+  while (sample != nullptr) {
+    Sample* next = sample->continuation_sample();
     sample->Clear();
     sample->set_next_free(free_sample_list_);
     free_sample_list_ = sample;
-
-    if (continuation_index != -1) {
-      sample = At(continuation_index);
-    } else {
-      sample = NULL;
-    }
+    sample = next;
   }
 }
 
@@ -255,7 +373,7 @@
     uint8_t* free_sample_ptr = reinterpret_cast<uint8_t*>(free_sample);
     return static_cast<intptr_t>((free_sample_ptr - samples_array_ptr) /
                                  sizeof(Sample));
-  } else if (cursor_ < static_cast<uintptr_t>(capacity_ - 1)) {
+  } else if (cursor_ < static_cast<intptr_t>(capacity_ - 1)) {
     return cursor_ += 1;
   } else {
     return -1;
@@ -277,7 +395,7 @@
       previous->native_allocation_size_bytes());
   next->set_head_sample(false);
   // Mark that previous continues at next.
-  previous->SetContinuationIndex(next_index);
+  previous->SetContinuation(next);
   return next;
 }
 
@@ -957,12 +1075,16 @@
 }
 
 static Sample* SetupSample(Thread* thread,
-                           SampleBuffer* sample_buffer,
+                           bool allocation_sample,
                            ThreadId tid) {
   ASSERT(thread != NULL);
   Isolate* isolate = thread->isolate();
-  ASSERT(sample_buffer != NULL);
-  Sample* sample = sample_buffer->ReserveSample();
+  SampleBlockBuffer* buffer = Profiler::sample_block_buffer();
+  Sample* sample = allocation_sample ? buffer->ReserveAllocationSample(isolate)
+                                     : buffer->ReserveCPUSample(isolate);
+  if (sample == nullptr) {
+    return nullptr;
+  }
   sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid);
   uword vm_tag = thread->vm_tag();
 #if defined(USING_SIMULATOR)
@@ -980,7 +1102,8 @@
   return sample;
 }
 
-static Sample* SetupSampleNative(SampleBuffer* sample_buffer, ThreadId tid) {
+static Sample* SetupSampleNative(AllocationSampleBuffer* sample_buffer,
+                                 ThreadId tid) {
   Sample* sample = sample_buffer->ReserveSample();
   if (sample == NULL) {
     return NULL;
@@ -1129,11 +1252,10 @@
   if (!CheckIsolate(isolate)) {
     return;
   }
-
   const bool exited_dart_code = thread->HasExitedDartCode();
 
-  SampleBuffer* sample_buffer = Profiler::sample_buffer();
-  if (sample_buffer == NULL) {
+  SampleBlockBuffer* buffer = Profiler::sample_block_buffer();
+  if (buffer == nullptr) {
     // Profiler not initialized.
     return;
   }
@@ -1157,24 +1279,30 @@
     return;
   }
 
-  Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
+  Sample* sample =
+      SetupSample(thread, /*allocation_block*/ true, os_thread->trace_id());
+  if (sample == nullptr) {
+    // We were unable to assign a sample for this allocation.
+    counters_.sample_allocation_failure++;
+    return;
+  }
   sample->SetAllocationCid(cid);
   sample->set_allocation_identity_hash(identity_hash);
 
   if (FLAG_profile_vm_allocation) {
     ProfilerNativeStackWalker native_stack_walker(
         &counters_, (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT,
-        sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
+        sample, isolate->current_allocation_sample_block(), stack_lower,
+        stack_upper, pc, fp, sp);
     native_stack_walker.walk();
   } else if (exited_dart_code) {
     ProfilerDartStackWalker dart_exit_stack_walker(
-        thread, sample, sample_buffer, pc, fp, /* allocation_sample*/ true);
+        thread, sample, isolate->current_allocation_sample_block(), pc, fp,
+        /* allocation_sample*/ true);
     dart_exit_stack_walker.walk();
   } else {
     // Fall back.
     uintptr_t pc = OS::GetProgramCounter();
-    Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
-    sample->SetAllocationCid(cid);
     sample->SetAt(0, pc);
   }
 }
@@ -1231,20 +1359,16 @@
   return sample;
 }
 
-void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) {
+void Profiler::SampleThreadSingleFrame(Thread* thread,
+                                       Sample* sample,
+                                       uintptr_t pc) {
   ASSERT(thread != NULL);
   OSThread* os_thread = thread->os_thread();
   ASSERT(os_thread != NULL);
   Isolate* isolate = thread->isolate();
 
-  SampleBuffer* sample_buffer = Profiler::sample_buffer();
-  if (sample_buffer == NULL) {
-    // Profiler not initialized.
-    return;
-  }
+  ASSERT(Profiler::sample_block_buffer() != nullptr);
 
-  // Setup sample.
-  Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
   // Increment counter for vm tag.
   VMTagCounters* counters = isolate->vm_tag_counters();
   ASSERT(counters != NULL);
@@ -1306,22 +1430,37 @@
     return;
   }
 
+  SampleBlockBuffer* sample_block_buffer = Profiler::sample_block_buffer();
+  if (sample_block_buffer == nullptr) {
+    // Profiler not initialized.
+    return;
+  }
+
+  // Setup sample.
+  Sample* sample =
+      SetupSample(thread, /*allocation_block*/ false, os_thread->trace_id());
+  if (sample == nullptr) {
+    // We were unable to assign a sample for this profiler tick.
+    counters_.sample_allocation_failure++;
+    return;
+  }
+
   if (thread->IsMutatorThread()) {
     if (isolate->IsDeoptimizing()) {
       counters_.single_frame_sample_deoptimizing.fetch_add(1);
-      SampleThreadSingleFrame(thread, pc);
+      SampleThreadSingleFrame(thread, sample, pc);
       return;
     }
     if (isolate->group()->compaction_in_progress()) {
       // The Dart stack isn't fully walkable.
-      SampleThreadSingleFrame(thread, pc);
+      SampleThreadSingleFrame(thread, sample, pc);
       return;
     }
   }
 
   if (!InitialRegisterCheck(pc, fp, sp)) {
     counters_.single_frame_sample_register_check.fetch_add(1);
-    SampleThreadSingleFrame(thread, pc);
+    SampleThreadSingleFrame(thread, sample, pc);
     return;
   }
 
@@ -1331,20 +1470,13 @@
                                        &stack_upper)) {
     counters_.single_frame_sample_get_and_validate_stack_bounds.fetch_add(1);
     // Could not get stack boundary.
-    SampleThreadSingleFrame(thread, pc);
+    SampleThreadSingleFrame(thread, sample, pc);
     return;
   }
 
   // At this point we have a valid stack boundary for this isolate and
   // know that our initial stack and frame pointers are within the boundary.
-  SampleBuffer* sample_buffer = Profiler::sample_buffer();
-  if (sample_buffer == NULL) {
-    // Profiler not initialized.
-    return;
-  }
 
-  // Setup sample.
-  Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
   // Increment counter for vm tag.
   VMTagCounters* counters = isolate->vm_tag_counters();
   ASSERT(counters != NULL);
@@ -1354,9 +1486,11 @@
 
   ProfilerNativeStackWalker native_stack_walker(
       &counters_, (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT,
-      sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
+      sample, isolate->current_sample_block(), stack_lower, stack_upper, pc, fp,
+      sp);
   const bool exited_dart_code = thread->HasExitedDartCode();
-  ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer, pc,
+  ProfilerDartStackWalker dart_stack_walker(thread, sample,
+                                            isolate->current_sample_block(), pc,
                                             fp, /* allocation_sample*/ false);
 
   // All memory access is done inside CollectSample.
@@ -1480,12 +1614,14 @@
 }
 
 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer(
-    SampleFilter* filter) {
-  ASSERT(filter != NULL);
+    SampleFilter* filter,
+    ProcessedSampleBuffer* buffer) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
 
-  ProcessedSampleBuffer* buffer = new (zone) ProcessedSampleBuffer();
+  if (buffer == nullptr) {
+    buffer = new (zone) ProcessedSampleBuffer();
+  }
 
   const intptr_t length = capacity();
   for (intptr_t i = 0; i < length; i++) {
@@ -1498,12 +1634,6 @@
       // An inner sample in a chain of samples.
       continue;
     }
-    // If we're requesting all the native allocation samples, we don't care
-    // whether or not we're in the same isolate as the sample.
-    if (sample->port() != filter->port()) {
-      // Another isolate.
-      continue;
-    }
     if (sample->timestamp() == 0) {
       // Empty.
       continue;
@@ -1512,17 +1642,25 @@
       // No frames.
       continue;
     }
-    if (!filter->TimeFilterSample(sample)) {
-      // Did not pass time filter.
-      continue;
-    }
-    if (!filter->TaskFilterSample(sample)) {
-      // Did not pass task filter.
-      continue;
-    }
-    if (!filter->FilterSample(sample)) {
-      // Did not pass filter.
-      continue;
+    if (filter != nullptr) {
+      // If we're requesting all the native allocation samples, we don't care
+      // whether or not we're in the same isolate as the sample.
+      if (sample->port() != filter->port()) {
+        // Another isolate.
+        continue;
+      }
+      if (!filter->TimeFilterSample(sample)) {
+        // Did not pass time filter.
+        continue;
+      }
+      if (!filter->TaskFilterSample(sample)) {
+        // Did not pass task filter.
+        continue;
+      }
+      if (!filter->FilterSample(sample)) {
+        // Did not pass filter.
+        continue;
+      }
     }
     buffer->Add(BuildProcessedSample(sample, buffer->code_lookup_table()));
   }
@@ -1577,7 +1715,7 @@
 
 Sample* SampleBuffer::Next(Sample* sample) {
   if (!sample->is_continuation_sample()) return NULL;
-  Sample* next_sample = At(sample->continuation_index());
+  Sample* next_sample = sample->continuation_sample();
   // Sanity check.
   ASSERT(sample != next_sample);
   // Detect invalid chaining.
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 2f9ea17..dd30bcc 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -29,7 +29,7 @@
 
 class Sample;
 class AllocationSampleBuffer;
-class SampleBuffer;
+class SampleBlock;
 class ProfileTrieNode;
 
 #define PROFILER_COUNTERS(V)                                                   \
@@ -46,7 +46,8 @@
   V(incomplete_sample_fp_bounds)                                               \
   V(incomplete_sample_fp_step)                                                 \
   V(incomplete_sample_bad_pc)                                                  \
-  V(failure_native_allocation_sample)
+  V(failure_native_allocation_sample)                                          \
+  V(sample_allocation_failure)
 
 struct ProfilerCounters {
 #define DECLARE_PROFILER_COUNTER(name) RelaxedAtomic<int64_t> name;
@@ -69,7 +70,9 @@
   // service protocol.
   static void UpdateRunningState();
 
-  static SampleBuffer* sample_buffer() { return sample_buffer_; }
+  static SampleBlockBuffer* sample_block_buffer() {
+    return sample_block_buffer_;
+  }
   static AllocationSampleBuffer* allocation_sample_buffer() {
     return allocation_sample_buffer_;
   }
@@ -111,10 +114,12 @@
   static intptr_t CalculateSampleBufferCapacity();
 
   // Does not walk the thread's stack.
-  static void SampleThreadSingleFrame(Thread* thread, uintptr_t pc);
+  static void SampleThreadSingleFrame(Thread* thread,
+                                      Sample* sample,
+                                      uintptr_t pc);
   static RelaxedAtomic<bool> initialized_;
 
-  static SampleBuffer* sample_buffer_;
+  static SampleBlockBuffer* sample_block_buffer_;
   static AllocationSampleBuffer* allocation_sample_buffer_;
 
   static ProfilerCounters counters_;
@@ -129,6 +134,8 @@
 
   virtual void VisitSample(Sample* sample) = 0;
 
+  virtual void Reset() { visited_ = 0; }
+
   intptr_t visited() const { return visited_; }
 
   void IncrementVisited() { visited_++; }
@@ -189,11 +196,14 @@
 // Each Sample holds a stack trace from an isolate.
 class Sample {
  public:
+  Sample() = default;
+
   void Init(Dart_Port port, int64_t timestamp, ThreadId tid) {
     Clear();
     timestamp_ = timestamp;
     tid_ = tid;
     port_ = port;
+    next_ = nullptr;
   }
 
   Dart_Port port() const { return port_; }
@@ -214,7 +224,7 @@
     vm_tag_ = VMTag::kInvalidTagId;
     user_tag_ = UserTags::kDefaultUserTag;
     state_ = 0;
-    continuation_index_ = -1;
+    next_ = nullptr;
     allocation_identity_hash_ = 0;
 #if defined(DART_USE_TCMALLOC) && defined(DEBUG)
     native_allocation_address_ = 0;
@@ -352,18 +362,14 @@
     return ContinuationSampleBit::decode(state_);
   }
 
-  void SetContinuationIndex(intptr_t index) {
+  void SetContinuation(Sample* next) {
     ASSERT(!is_continuation_sample());
-    ASSERT(continuation_index_ == -1);
+    ASSERT(next_ == nullptr);
     state_ = ContinuationSampleBit::update(true, state_);
-    continuation_index_ = index;
-    ASSERT(is_continuation_sample());
+    next_ = next;
   }
 
-  intptr_t continuation_index() const {
-    ASSERT(is_continuation_sample());
-    return continuation_index_;
-  }
+  Sample* continuation_sample() const { return next_; }
 
   intptr_t allocation_cid() const {
     ASSERT(is_allocation_sample());
@@ -431,7 +437,7 @@
   uword vm_tag_;
   uword user_tag_;
   uint32_t state_;
-  int32_t continuation_index_;
+  Sample* next_;
   uint32_t allocation_identity_hash_;
 
 #if defined(DART_USE_TCMALLOC) && defined(DEBUG)
@@ -623,21 +629,26 @@
   DISALLOW_COPY_AND_ASSIGN(CodeLookupTable);
 };
 
-// Ring buffer of Samples that is (usually) shared by many isolates.
-class SampleBuffer {
+// Interface for a class that can create a ProcessedSampleBuffer.
+class ProcessedSampleBufferBuilder {
  public:
-  // Up to 1 minute @ 1000Hz, less if samples are deep.
-  static const intptr_t kDefaultBufferCapacity = 60000;
+  virtual ~ProcessedSampleBufferBuilder() = default;
+  virtual ProcessedSampleBuffer* BuildProcessedSampleBuffer(
+      SampleFilter* filter,
+      ProcessedSampleBuffer* buffer = nullptr) = 0;
+};
 
-  explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity);
-  virtual ~SampleBuffer();
+class SampleBuffer : public ProcessedSampleBufferBuilder {
+ public:
+  SampleBuffer() = default;
+  virtual ~SampleBuffer() = default;
 
-  intptr_t capacity() const { return capacity_; }
-
-  Sample* At(intptr_t idx) const;
-  intptr_t ReserveSampleSlot();
-  virtual Sample* ReserveSample();
-  virtual Sample* ReserveSampleAndLink(Sample* previous);
+  virtual void Init(Sample* samples, intptr_t capacity) {
+    ASSERT(samples != nullptr);
+    ASSERT(capacity > 0);
+    samples_ = samples;
+    capacity_ = capacity;
+  }
 
   void VisitSamples(SampleVisitor* visitor) {
     ASSERT(visitor != NULL);
@@ -669,45 +680,218 @@
     }
   }
 
-  ProcessedSampleBuffer* BuildProcessedSampleBuffer(SampleFilter* filter);
+  virtual Sample* ReserveSample() = 0;
+  virtual Sample* ReserveSampleAndLink(Sample* previous) = 0;
 
-  intptr_t Size() { return memory_->size(); }
+  Sample* At(intptr_t idx) const {
+    ASSERT(idx >= 0);
+    ASSERT(idx < capacity_);
+    return &samples_[idx];
+  }
+
+  intptr_t capacity() const { return capacity_; }
+
+  virtual ProcessedSampleBuffer* BuildProcessedSampleBuffer(
+      SampleFilter* filter,
+      ProcessedSampleBuffer* buffer = nullptr);
 
  protected:
-  ProcessedSample* BuildProcessedSample(Sample* sample,
-                                        const CodeLookupTable& clt);
   Sample* Next(Sample* sample);
 
-  VirtualMemory* memory_;
+  ProcessedSample* BuildProcessedSample(Sample* sample,
+                                        const CodeLookupTable& clt);
+
   Sample* samples_;
   intptr_t capacity_;
-  RelaxedAtomic<uintptr_t> cursor_;
+
+  DISALLOW_COPY_AND_ASSIGN(SampleBuffer);
+};
+
+class SampleBlock : public SampleBuffer {
+ public:
+  // The default number of samples per block. Overridden by some tests.
+  static const intptr_t kSamplesPerBlock = 1000;
+
+  SampleBlock() = default;
+  virtual ~SampleBlock() = default;
+
+  void Clear() {
+    allocation_block_ = false;
+    cursor_ = 0;
+    full_ = false;
+    evictable_ = false;
+    next_free_ = nullptr;
+  }
+
+  // Returns the number of samples contained within this block.
+  intptr_t capacity() const { return capacity_; }
+
+  // Specify whether or not this block is used for assigning allocation
+  // samples.
+  void set_is_allocation_block(bool is_allocation_block) {
+    allocation_block_ = is_allocation_block;
+  }
+
+  Isolate* owner() const { return owner_; }
+  void set_owner(Isolate* isolate) { owner_ = isolate; }
+
+  // Manually marks the block as full so it can be processed and added back to
+  // the pool of available blocks.
+  void release_block() { full_.store(true); }
+
+  // When true, this sample block is considered complete and will no longer be
+  // used to assign new Samples. This block is **not** available for
+  // re-allocation simply because it's full. It must be processed by
+  // SampleBlockBuffer::ProcessCompletedBlocks before it can be considered
+  // evictable and available for re-allocation.
+  bool is_full() const { return full_.load(); }
+
+  // When true, this sample block is available for re-allocation.
+  bool evictable() const { return evictable_.load(); }
+
+  virtual Sample* ReserveSample();
+  virtual Sample* ReserveSampleAndLink(Sample* previous);
+
+ protected:
+  Isolate* owner_ = nullptr;
+  bool allocation_block_ = false;
+
+  intptr_t index_;
+  RelaxedAtomic<int> cursor_ = 0;
+  RelaxedAtomic<bool> full_ = false;
+  RelaxedAtomic<bool> evictable_ = false;
+
+  SampleBlock* next_free_ = nullptr;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(SampleBuffer);
+  friend class SampleBlockBuffer;
+
+  DISALLOW_COPY_AND_ASSIGN(SampleBlock);
+};
+
+class SampleBlockBuffer : public ProcessedSampleBufferBuilder {
+ public:
+  static const intptr_t kDefaultBlockCount = 60;
+
+  // Creates a SampleBlockBuffer with a predetermined number of blocks.
+  //
+  // Defaults to kDefaultBlockCount blocks. Block size is fixed to
+  // SampleBlock::kSamplesPerBlock samples per block, except for in tests.
+  explicit SampleBlockBuffer(
+      intptr_t blocks = kDefaultBlockCount,
+      intptr_t samples_per_block = SampleBlock::kSamplesPerBlock);
+
+  virtual ~SampleBlockBuffer();
+
+  void VisitSamples(SampleVisitor* visitor) {
+    ASSERT(visitor != NULL);
+    for (intptr_t i = 0; i < cursor_.load(); ++i) {
+      (&blocks_[i])->VisitSamples(visitor);
+    }
+  }
+
+  // Returns true when there is at least a single block that needs to be
+  // processed.
+  //
+  // NOTE: this should only be called from the interrupt handler as
+  // invocation will have the side effect of clearing the underlying flag.
+  bool process_blocks() { return can_process_block_.exchange(false); }
+
+  // Iterates over the blocks in the buffer and processes blocks marked as
+  // full. Processing consists of sending a service event with the samples from
+  // completed, unprocessed blocks and marking these blocks are evictable
+  // (i.e., safe to be re-allocated and re-used).
+  void ProcessCompletedBlocks();
+
+  // Reserves a sample for a CPU profile.
+  //
+  // Returns nullptr when a sample can't be reserved.
+  Sample* ReserveCPUSample(Isolate* isolate);
+
+  // Reserves a sample for a Dart object allocation profile.
+  //
+  // Returns nullptr when a sample can't be reserved.
+  Sample* ReserveAllocationSample(Isolate* isolate);
+
+  intptr_t Size() const { return memory_->size(); }
+
+  virtual ProcessedSampleBuffer* BuildProcessedSampleBuffer(
+      SampleFilter* filter,
+      ProcessedSampleBuffer* buffer = nullptr);
+
+ private:
+  Sample* ReserveSampleImpl(Isolate* isolate, bool allocation_sample);
+
+  // Returns nullptr if there are no available blocks.
+  SampleBlock* ReserveSampleBlock();
+
+  void FreeBlock(SampleBlock* block) {
+    ASSERT(block->next_free_ == nullptr);
+    MutexLocker ml(&free_block_lock_);
+    if (free_list_head_ == nullptr) {
+      free_list_head_ = block;
+      free_list_tail_ = block;
+      return;
+    }
+    free_list_tail_->next_free_ = block;
+    free_list_tail_ = block;
+  }
+
+  SampleBlock* GetFreeBlock() {
+    MutexLocker ml(&free_block_lock_);
+    if (free_list_head_ == nullptr) {
+      return nullptr;
+    }
+    SampleBlock* block = free_list_head_;
+    free_list_head_ = block->next_free_;
+    if (free_list_head_ == nullptr) {
+      free_list_tail_ = nullptr;
+    }
+    block->next_free_ = nullptr;
+    return block;
+  }
+
+  Mutex free_block_lock_;
+  RelaxedAtomic<bool> can_process_block_ = false;
+
+  // Sample block management.
+  RelaxedAtomic<int> cursor_;
+  SampleBlock* blocks_;
+  intptr_t capacity_;
+  SampleBlock* free_list_head_;
+  SampleBlock* free_list_tail_;
+
+  // Sample buffer management.
+  VirtualMemory* memory_;
+  Sample* sample_buffer_;
+  DISALLOW_COPY_AND_ASSIGN(SampleBlockBuffer);
 };
 
 class AllocationSampleBuffer : public SampleBuffer {
  public:
-  explicit AllocationSampleBuffer(intptr_t capacity = kDefaultBufferCapacity);
+  explicit AllocationSampleBuffer(intptr_t capacity = 60000);
   virtual ~AllocationSampleBuffer();
 
-  intptr_t ReserveSampleSlotLocked();
   virtual Sample* ReserveSample();
   virtual Sample* ReserveSampleAndLink(Sample* previous);
   void FreeAllocationSample(Sample* sample);
 
+  intptr_t Size() { return memory_->size(); }
+
  private:
+  intptr_t ReserveSampleSlotLocked();
+
   Mutex mutex_;
   Sample* free_sample_list_;
-
+  VirtualMemory* memory_;
+  RelaxedAtomic<int> cursor_ = 0;
   DISALLOW_COPY_AND_ASSIGN(AllocationSampleBuffer);
 };
 
 intptr_t Profiler::Size() {
   intptr_t size = 0;
-  if (sample_buffer_ != nullptr) {
-    size += sample_buffer_->Size();
+  if (sample_block_buffer_ != nullptr) {
+    size += sample_block_buffer_->Size();
   }
   if (allocation_sample_buffer_ != nullptr) {
     size += allocation_sample_buffer_->Size();
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index a61fb94..e9f333e 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -7,6 +7,7 @@
 #include "platform/text_buffer.h"
 #include "vm/growable_array.h"
 #include "vm/hash_map.h"
+#include "vm/heap/safepoint.h"
 #include "vm/log.h"
 #include "vm/malloc_hooks.h"
 #include "vm/native_symbol.h"
@@ -15,6 +16,8 @@
 #include "vm/profiler.h"
 #include "vm/reusable_handles.h"
 #include "vm/scope_timer.h"
+#include "vm/service.h"
+#include "vm/service_event.h"
 #include "vm/timeline.h"
 
 namespace dart {
@@ -919,7 +922,7 @@
 
   ProfileBuilder(Thread* thread,
                  SampleFilter* filter,
-                 SampleBuffer* sample_buffer,
+                 ProcessedSampleBufferBuilder* sample_buffer,
                  Profile* profile)
       : thread_(thread),
         vm_isolate_(Dart::vm_isolate()),
@@ -932,8 +935,6 @@
         inlined_functions_cache_(new ProfileCodeInlinedFunctionsCache()),
         samples_(NULL),
         info_kind_(kNone) {
-    ASSERT((sample_buffer_ == Profiler::sample_buffer()) ||
-           (sample_buffer_ == Profiler::allocation_sample_buffer()));
     ASSERT(profile_ != NULL);
   }
 
@@ -975,7 +976,7 @@
 
   bool FilterSamples() {
     ScopeTimer sw("ProfileBuilder::FilterSamples", FLAG_trace_profiler);
-    ASSERT(sample_buffer_ != NULL);
+    ASSERT(sample_buffer_ != nullptr);
     samples_ = sample_buffer_->BuildProcessedSampleBuffer(filter_);
     profile_->samples_ = samples_;
     profile_->sample_count_ = samples_->length();
@@ -1439,7 +1440,7 @@
   Thread* thread_;
   Isolate* vm_isolate_;
   SampleFilter* filter_;
-  SampleBuffer* sample_buffer_;
+  ProcessedSampleBufferBuilder* sample_buffer_;
   Profile* profile_;
   const AbstractCode null_code_;
   const Function& null_function_;
@@ -1466,11 +1467,10 @@
 
 void Profile::Build(Thread* thread,
                     SampleFilter* filter,
-                    SampleBuffer* sample_buffer) {
+                    ProcessedSampleBufferBuilder* sample_buffer) {
   // Disable thread interrupts while processing the buffer.
   DisableThreadInterruptsScope dtis(thread);
   ThreadInterrupter::SampleBufferReaderScope scope;
-
   ProfileBuilder builder(thread, filter, sample_buffer, this);
   builder.Build();
 }
@@ -1722,12 +1722,16 @@
 }
 
 void Profile::PrintProfileJSON(JSONStream* stream, bool include_code_samples) {
-  ScopeTimer sw("Profile::PrintProfileJSON", FLAG_trace_profiler);
   JSONObject obj(stream);
-  obj.AddProperty("type", "CpuSamples");
-  PrintHeaderJSON(&obj);
+  PrintProfileJSON(&obj, include_code_samples);
+}
+
+void Profile::PrintProfileJSON(JSONObject* obj, bool include_code_samples) {
+  ScopeTimer sw("Profile::PrintProfileJSON", FLAG_trace_profiler);
+  obj->AddProperty("type", "CpuSamples");
+  PrintHeaderJSON(obj);
   if (include_code_samples) {
-    JSONArray codes(&obj, "_codes");
+    JSONArray codes(obj, "_codes");
     for (intptr_t i = 0; i < live_code_->length(); i++) {
       ProfileCode* code = live_code_->At(i);
       ASSERT(code != NULL);
@@ -1746,30 +1750,30 @@
   }
 
   {
-    JSONArray functions(&obj, "functions");
+    JSONArray functions(obj, "functions");
     for (intptr_t i = 0; i < functions_->length(); i++) {
       ProfileFunction* function = functions_->At(i);
       ASSERT(function != NULL);
       function->PrintToJSONArray(&functions);
     }
   }
-  PrintSamplesJSON(&obj, include_code_samples);
+  PrintSamplesJSON(obj, include_code_samples);
 }
 
 void ProfilerService::PrintJSONImpl(Thread* thread,
                                     JSONStream* stream,
                                     SampleFilter* filter,
-                                    SampleBuffer* sample_buffer,
+                                    ProcessedSampleBufferBuilder* buffer,
                                     bool include_code_samples) {
   Isolate* isolate = thread->isolate();
 
   // We should bail out in service.cc if the profiler is disabled.
-  ASSERT(sample_buffer != NULL);
+  ASSERT(buffer != nullptr);
 
   StackZone zone(thread);
   HANDLESCOPE(thread);
   Profile profile(isolate);
-  profile.Build(thread, filter, sample_buffer);
+  profile.Build(thread, filter, buffer);
   profile.PrintProfileJSON(stream, include_code_samples);
 }
 
@@ -1795,7 +1799,7 @@
   Isolate* isolate = thread->isolate();
   NoAllocationSampleFilter filter(isolate->main_port(), Thread::kMutatorTask,
                                   time_origin_micros, time_extent_micros);
-  PrintJSONImpl(thread, stream, &filter, Profiler::sample_buffer(),
+  PrintJSONImpl(thread, stream, &filter, Profiler::sample_block_buffer(),
                 include_code_samples);
 }
 
@@ -1820,7 +1824,7 @@
   Isolate* isolate = thread->isolate();
   AllocationSampleFilter filter(isolate->main_port(), Thread::kMutatorTask,
                                 time_origin_micros, time_extent_micros);
-  PrintJSONImpl(thread, stream, &filter, Profiler::sample_buffer(), true);
+  PrintJSONImpl(thread, stream, &filter, Profiler::sample_block_buffer(), true);
 }
 
 class ClassAllocationSampleFilter : public SampleFilter {
@@ -1856,7 +1860,7 @@
   ClassAllocationSampleFilter filter(isolate->main_port(), cls,
                                      Thread::kMutatorTask, time_origin_micros,
                                      time_extent_micros);
-  PrintJSONImpl(thread, stream, &filter, Profiler::sample_buffer(), true);
+  PrintJSONImpl(thread, stream, &filter, Profiler::sample_block_buffer(), true);
 }
 
 void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream,
@@ -1870,8 +1874,8 @@
 }
 
 void ProfilerService::ClearSamples() {
-  SampleBuffer* sample_buffer = Profiler::sample_buffer();
-  if (sample_buffer == NULL) {
+  SampleBlockBuffer* sample_block_buffer = Profiler::sample_block_buffer();
+  if (sample_block_buffer == nullptr) {
     return;
   }
 
@@ -1883,7 +1887,7 @@
   ThreadInterrupter::SampleBufferReaderScope scope;
 
   ClearProfileVisitor clear_profile(isolate);
-  sample_buffer->VisitSamples(&clear_profile);
+  sample_block_buffer->VisitSamples(&clear_profile);
 }
 
 #endif  // !PRODUCT
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index 8009207..1c02db3 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -367,7 +367,9 @@
   explicit Profile(Isolate* isolate);
 
   // Build a filtered model using |filter|.
-  void Build(Thread* thread, SampleFilter* filter, SampleBuffer* sample_buffer);
+  void Build(Thread* thread,
+             SampleFilter* filter,
+             ProcessedSampleBufferBuilder* sample_block_buffer);
 
   // After building:
   int64_t min_time() const { return min_time_; }
@@ -383,6 +385,7 @@
   ProfileCode* GetCodeFromPC(uword pc, int64_t timestamp);
 
   void PrintProfileJSON(JSONStream* stream, bool include_code_samples);
+  void PrintProfileJSON(JSONObject* obj, bool include_code_samples);
 
   ProfileFunction* FindFunction(const Function& function);
 
@@ -445,7 +448,7 @@
   static void PrintJSONImpl(Thread* thread,
                             JSONStream* stream,
                             SampleFilter* filter,
-                            SampleBuffer* sample_buffer,
+                            ProcessedSampleBufferBuilder* buffer,
                             bool include_code_samples);
 };
 
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 1829169..1171458 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -22,6 +22,12 @@
 DECLARE_FLAG(int, max_profile_depth);
 DECLARE_FLAG(int, optimization_counter_threshold);
 
+// SampleVisitor ignores samples with timestamp == 0.
+const int64_t kValidTimeStamp = 1;
+
+// SampleVisitor ignores samples with pc == 0.
+const uword kValidPc = 0xFF;
+
 // Some tests are written assuming native stack trace profiling is disabled.
 class DisableNativeProfileScope : public ValueObject {
  public:
@@ -71,87 +77,123 @@
   const intptr_t FLAG_max_profile_depth_;
 };
 
-class ProfileSampleBufferTestHelper {
+class ProfileSampleBufferTestHelper : public SampleVisitor {
  public:
-  static intptr_t IterateCount(const Dart_Port port,
-                               const SampleBuffer& sample_buffer) {
-    intptr_t c = 0;
-    for (intptr_t i = 0; i < sample_buffer.capacity(); i++) {
-      Sample* sample = sample_buffer.At(i);
-      if (sample->port() != port) {
-        continue;
-      }
-      c++;
-    }
-    return c;
+  explicit ProfileSampleBufferTestHelper(Dart_Port port)
+      : SampleVisitor(port) {}
+
+  void VisitSample(Sample* sample) { sum_ += sample->At(0); }
+
+  void Reset() {
+    sum_ = 0;
+    SampleVisitor::Reset();
   }
 
-  static intptr_t IterateSumPC(const Dart_Port port,
-                               const SampleBuffer& sample_buffer) {
-    intptr_t c = 0;
-    for (intptr_t i = 0; i < sample_buffer.capacity(); i++) {
-      Sample* sample = sample_buffer.At(i);
-      if (sample->port() != port) {
-        continue;
-      }
-      c += sample->At(0);
-    }
-    return c;
-  }
+  intptr_t sum() const { return sum_; }
+
+ private:
+  intptr_t sum_ = 0;
 };
 
+void VisitSamples(SampleBlockBuffer* buffer, SampleVisitor* visitor) {
+  // Mark the completed blocks as free so they can be re-used.
+  buffer->ProcessCompletedBlocks();
+  visitor->Reset();
+  buffer->VisitSamples(visitor);
+}
+
 TEST_CASE(Profiler_SampleBufferWrapTest) {
-  SampleBuffer* sample_buffer = new SampleBuffer(3);
+  Isolate* isolate = Isolate::Current();
+  SampleBlockBuffer* sample_buffer = new SampleBlockBuffer(3, 1);
   Dart_Port i = 123;
-  EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
+  ProfileSampleBufferTestHelper visitor(i);
+
+  VisitSamples(sample_buffer, &visitor);
+  EXPECT_EQ(0, visitor.sum());
   Sample* s;
-  s = sample_buffer->ReserveSample();
-  s->Init(i, 0, 0);
+
+  s = sample_buffer->ReserveCPUSample(isolate);
+  s->Init(i, kValidTimeStamp, 0);
   s->SetAt(0, 2);
-  EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
-  s = sample_buffer->ReserveSample();
-  s->Init(i, 0, 0);
+  VisitSamples(sample_buffer, &visitor);
+  EXPECT_EQ(2, visitor.sum());
+
+  s = sample_buffer->ReserveCPUSample(isolate);
+  s->Init(i, kValidTimeStamp, 0);
   s->SetAt(0, 4);
-  EXPECT_EQ(6, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
-  s = sample_buffer->ReserveSample();
-  s->Init(i, 0, 0);
+  VisitSamples(sample_buffer, &visitor);
+  EXPECT_EQ(6, visitor.sum());
+
+  s = sample_buffer->ReserveCPUSample(isolate);
+  s->Init(i, kValidTimeStamp, 0);
   s->SetAt(0, 6);
-  EXPECT_EQ(12, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
-  s = sample_buffer->ReserveSample();
-  s->Init(i, 0, 0);
+  VisitSamples(sample_buffer, &visitor);
+  EXPECT_EQ(12, visitor.sum());
+
+  // Mark the completed blocks as free so they can be re-used.
+  sample_buffer->ProcessCompletedBlocks();
+
+  s = sample_buffer->ReserveCPUSample(isolate);
+  s->Init(i, kValidTimeStamp, 0);
   s->SetAt(0, 8);
-  EXPECT_EQ(18, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
+  VisitSamples(sample_buffer, &visitor);
+  EXPECT_EQ(18, visitor.sum());
+  {
+    MutexLocker ml(isolate->current_sample_block_lock());
+    isolate->set_current_sample_block(nullptr);
+  }
   delete sample_buffer;
 }
 
 TEST_CASE(Profiler_SampleBufferIterateTest) {
-  SampleBuffer* sample_buffer = new SampleBuffer(3);
+  Isolate* isolate = Isolate::Current();
+  SampleBlockBuffer* sample_buffer = new SampleBlockBuffer(3, 1);
   Dart_Port i = 123;
-  EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
+  ProfileSampleBufferTestHelper visitor(i);
+
+  sample_buffer->VisitSamples(&visitor);
+  EXPECT_EQ(0, visitor.visited());
   Sample* s;
-  s = sample_buffer->ReserveSample();
-  s->Init(i, 0, 0);
-  EXPECT_EQ(1, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
-  s = sample_buffer->ReserveSample();
-  s->Init(i, 0, 0);
-  EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
-  s = sample_buffer->ReserveSample();
-  s->Init(i, 0, 0);
-  EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
-  s = sample_buffer->ReserveSample();
-  s->Init(i, 0, 0);
-  EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
+  s = sample_buffer->ReserveCPUSample(isolate);
+  s->Init(i, kValidTimeStamp, 0);
+  s->SetAt(0, kValidPc);
+  VisitSamples(sample_buffer, &visitor);
+  EXPECT_EQ(1, visitor.visited());
+
+  s = sample_buffer->ReserveCPUSample(isolate);
+  s->Init(i, kValidTimeStamp, 0);
+  s->SetAt(0, kValidPc);
+  VisitSamples(sample_buffer, &visitor);
+  EXPECT_EQ(2, visitor.visited());
+
+  s = sample_buffer->ReserveCPUSample(isolate);
+  s->Init(i, kValidTimeStamp, 0);
+  s->SetAt(0, kValidPc);
+  VisitSamples(sample_buffer, &visitor);
+  EXPECT_EQ(3, visitor.visited());
+
+  s = sample_buffer->ReserveCPUSample(isolate);
+  s->Init(i, kValidTimeStamp, 0);
+  s->SetAt(0, kValidPc);
+  VisitSamples(sample_buffer, &visitor);
+  EXPECT_EQ(3, visitor.visited());
+
+  {
+    MutexLocker ml(isolate->current_sample_block_lock());
+    isolate->set_current_sample_block(nullptr);
+  }
   delete sample_buffer;
 }
 
 TEST_CASE(Profiler_AllocationSampleTest) {
   Isolate* isolate = Isolate::Current();
-  SampleBuffer* sample_buffer = new SampleBuffer(3);
-  Sample* sample = sample_buffer->ReserveSample();
+  SampleBlockBuffer* sample_buffer = new SampleBlockBuffer(1, 1);
+  Sample* sample = sample_buffer->ReserveAllocationSample(isolate);
   sample->Init(isolate->main_port(), 0, 0);
   sample->set_metadata(99);
   sample->set_is_allocation_sample(true);
   EXPECT_EQ(99, sample->allocation_cid());
+  isolate->set_current_allocation_sample_block(nullptr);
   delete sample_buffer;
 }
 
@@ -443,7 +485,7 @@
     AllocationFilter filter(isolate->main_port(), class_a.id(),
                             before_allocations_micros,
                             allocation_extent_micros);
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have 1 allocation sample.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -471,7 +513,7 @@
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id(),
                             Dart_TimelineGetMicros(), 16000);
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples because none occured within
     // the specified time range.
     EXPECT_EQ(0, profile.sample_count());
@@ -561,7 +603,7 @@
     // Filter for the class in the time range.
     NativeAllocationSampleFilter filter(before_allocations_micros,
                                         allocation_extent_micros);
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have 0 allocation samples since we freed the memory.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -574,7 +616,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     NativeAllocationSampleFilter filter(Dart_TimelineGetMicros(), 16000);
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples because none occured within
     // the specified time range.
     EXPECT_EQ(0, profile.sample_count());
@@ -620,7 +662,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -637,7 +679,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -667,7 +709,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should still only have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
   }
@@ -705,7 +747,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -725,7 +767,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have three allocation samples.
     EXPECT_EQ(3, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -780,7 +822,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -800,7 +842,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have three allocation samples.
     EXPECT_EQ(3, profile.sample_count());
     ProfileStackWalker walker(&profile, true);
@@ -850,7 +892,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), double_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -863,7 +905,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), double_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -885,7 +927,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), double_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should still only have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
   }
@@ -912,7 +954,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), array_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -925,7 +967,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), array_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -947,7 +989,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), array_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should still only have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
   }
@@ -969,7 +1011,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), array_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples, since empty
     // growable lists use a shared backing.
     EXPECT_EQ(0, profile.sample_count());
@@ -999,7 +1041,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), context_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -1012,7 +1054,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), context_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -1032,7 +1074,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), context_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should still only have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
   }
@@ -1073,7 +1115,7 @@
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), closure_class.id());
     filter.set_enable_vm_ticks(true);
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -1097,7 +1139,7 @@
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), closure_class.id());
     filter.set_enable_vm_ticks(true);
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should still only have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
   }
@@ -1127,7 +1169,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), float32_list_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -1140,7 +1182,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), float32_list_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -1162,7 +1204,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), float32_list_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should still only have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
   }
@@ -1175,7 +1217,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), float32_list_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should now have two allocation samples.
     EXPECT_EQ(2, profile.sample_count());
   }
@@ -1207,7 +1249,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -1220,7 +1262,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should still only have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -1240,7 +1282,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should still only have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
   }
@@ -1253,7 +1295,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should now have two allocation samples.
     EXPECT_EQ(2, profile.sample_count());
   }
@@ -1285,7 +1327,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -1298,7 +1340,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should still only have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -1324,7 +1366,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should still only have one allocation sample.
     EXPECT_EQ(1, profile.sample_count());
   }
@@ -1337,7 +1379,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should now have two allocation samples.
     EXPECT_EQ(2, profile.sample_count());
   }
@@ -1393,7 +1435,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -1411,7 +1453,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have 50,000 allocation samples.
     EXPECT_EQ(50000, profile.sample_count());
     {
@@ -1540,7 +1582,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have no allocation samples.
     EXPECT_EQ(0, profile.sample_count());
   }
@@ -1557,7 +1599,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile, true);
 
@@ -1633,7 +1675,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have 1 allocation sample.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
@@ -1728,7 +1770,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation samples.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile, true);
@@ -1810,7 +1852,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation samples.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile, true);
@@ -1888,7 +1930,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation samples.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile, true);
@@ -1998,7 +2040,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation samples.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile, true);
@@ -2093,7 +2135,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation samples.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile, true);
@@ -2211,7 +2253,7 @@
     HANDLESCOPE(thread);
     Profile profile(isolate);
     AllocationFilter filter(isolate->main_port(), class_a.id());
-    profile.Build(thread, &filter, Profiler::sample_buffer());
+    profile.Build(thread, &filter, Profiler::sample_block_buffer());
     // We should have one allocation samples.
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile, true);
@@ -2256,10 +2298,10 @@
   }
 }
 
-static void InsertFakeSample(SampleBuffer* sample_buffer, uword* pc_offsets) {
-  ASSERT(sample_buffer != NULL);
+static void InsertFakeSample(uword* pc_offsets) {
   Isolate* isolate = Isolate::Current();
-  Sample* sample = sample_buffer->ReserveSample();
+  ASSERT(Profiler::sample_block_buffer() != nullptr);
+  Sample* sample = Profiler::sample_block_buffer()->ReserveCPUSample(isolate);
   ASSERT(sample != NULL);
   sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(),
                OSThread::Current()->trace_id());
@@ -2319,8 +2361,8 @@
 
   DisableBackgroundCompilationScope dbcs;
 
-  SampleBuffer* sample_buffer = Profiler::sample_buffer();
-  EXPECT(sample_buffer != NULL);
+  SampleBlockBuffer* sample_block_buffer = Profiler::sample_block_buffer();
+  ASSERT(sample_block_buffer != nullptr);
 
   const Library& root_library = Library::Handle(LoadTestScript(kScript));
 
@@ -2330,7 +2372,7 @@
   {
     // Clear the profile for this isolate.
     ClearProfileVisitor cpv(Isolate::Current());
-    sample_buffer->VisitSamples(&cpv);
+    sample_block_buffer->VisitSamples(&cpv);
   }
 
   // Query the code object for main and determine the PC at some token
@@ -2390,9 +2432,9 @@
                      callPositionPc,  // main.
                      0};
 
-  InsertFakeSample(sample_buffer, &sample1[0]);
-  InsertFakeSample(sample_buffer, &sample2[0]);
-  InsertFakeSample(sample_buffer, &sample3[0]);
+  InsertFakeSample(&sample1[0]);
+  InsertFakeSample(&sample2[0]);
+  InsertFakeSample(&sample3[0]);
 
   // Generate source report for main.
   JSONStream js;
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 3020106b..6eb0c25 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -1436,7 +1436,7 @@
   ObjectPtr* from = object_store->from();
   ObjectPtr* to = object_store->to_snapshot(Snapshot::kFullAOT);
   for (ObjectPtr* p = from; p <= to; p++) {
-    if ((*p)->IsCode()) {
+    if ((*p)->IsHeapObject() && (*p)->IsCode()) {
       code ^= *p;
       inst = code.instructions();
       thread->heap()->SetLoadingUnit(inst.ptr(), LoadingUnit::kRootId);
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index d7a1beb..b79c6b9 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -562,6 +562,7 @@
 COMPRESSED_VISITOR(ExternalTwoByteString)
 COMPRESSED_VISITOR(GrowableObjectArray)
 COMPRESSED_VISITOR(LinkedHashMap)
+COMPRESSED_VISITOR(LinkedHashSet)
 COMPRESSED_VISITOR(ExternalTypedData)
 TYPED_DATA_VIEW_VISITOR(TypedDataView)
 COMPRESSED_VISITOR(ReceivePort)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 4d0bfbb..3d442b2 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -18,8 +18,10 @@
 #include "vm/pointer_tagging.h"
 #include "vm/snapshot.h"
 #include "vm/tagged_pointer.h"
+#include "vm/thread.h"
 #include "vm/token.h"
 #include "vm/token_position.h"
+#include "vm/visitor.h"
 
 // Currently we have two different axes for offset generation:
 //
@@ -118,17 +120,10 @@
 #undef V
 };
 
-#define SNAPSHOT_WRITER_SUPPORT()                                              \
-  void WriteTo(SnapshotWriter* writer, intptr_t object_id,                     \
-               Snapshot::Kind kind, bool as_reference);                        \
-  friend class SnapshotWriter;
-
 #define VISITOR_SUPPORT(object)                                                \
   static intptr_t Visit##object##Pointers(object##Ptr raw_obj,                 \
                                           ObjectPointerVisitor* visitor);
 
-#define HEAP_PROFILER_SUPPORT() friend class HeapProfiler;
-
 #define RAW_OBJECT_IMPLEMENTATION(object)                                      \
  private: /* NOLINT */                                                         \
   VISITOR_SUPPORT(object)                                                      \
@@ -144,12 +139,14 @@
 #define RAW_HEAP_OBJECT_IMPLEMENTATION(object)                                 \
  private:                                                                      \
   RAW_OBJECT_IMPLEMENTATION(object);                                           \
-  SNAPSHOT_WRITER_SUPPORT()                                                    \
-  HEAP_PROFILER_SUPPORT()                                                      \
   friend class object##SerializationCluster;                                   \
   friend class object##DeserializationCluster;                                 \
+  friend class object##MessageSerializationCluster;                            \
+  friend class object##MessageDeserializationCluster;                          \
   friend class Serializer;                                                     \
   friend class Deserializer;                                                   \
+  template <typename Base>                                                     \
+  friend class ObjectCopy;                                                     \
   friend class Pass2Visitor;
 
 // RawObject is the base class of all raw objects; even though it carries the
@@ -540,11 +537,13 @@
   void StorePointer(type const* addr, type value) {
     reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
         ->store(value, order);
-    if (value->IsHeapObject()) {
+    if (value.IsHeapObject()) {
       CheckHeapPointerStore(value, Thread::Current());
     }
   }
 
+  friend class MessageDeserializer;  // bogus
+
   template <typename type,
             typename compressed_type,
             std::memory_order order = std::memory_order_relaxed>
@@ -552,7 +551,7 @@
     reinterpret_cast<std::atomic<compressed_type>*>(
         const_cast<compressed_type*>(addr))
         ->store(static_cast<compressed_type>(value), order);
-    if (value->IsHeapObject()) {
+    if (value.IsHeapObject()) {
       CheckHeapPointerStore(value, Thread::Current());
     }
   }
@@ -560,7 +559,7 @@
   template <typename type>
   void StorePointer(type const* addr, type value, Thread* thread) {
     *const_cast<type*>(addr) = value;
-    if (value->IsHeapObject()) {
+    if (value.IsHeapObject()) {
       CheckHeapPointerStore(value, thread);
     }
   }
@@ -570,7 +569,7 @@
                               type value,
                               Thread* thread) {
     *const_cast<compressed_type*>(addr) = value;
-    if (value->IsHeapObject()) {
+    if (value.IsHeapObject()) {
       CheckHeapPointerStore(value, thread);
     }
   }
@@ -758,9 +757,7 @@
   friend class ImageWriter;
   friend class AssemblyImageWriter;
   friend class BlobImageWriter;
-  friend class SnapshotReader;
   friend class Deserializer;
-  friend class SnapshotWriter;
   friend class String;
   friend class WeakProperty;            // StorePointer
   friend class Instance;                // StorePointer
@@ -772,6 +769,9 @@
   friend class WriteBarrierUpdateVisitor;  // CheckHeapPointerStore
   friend class OffsetsTable;
   friend class Object;
+  friend uword TagsFromUntaggedObject(UntaggedObject*);                // tags_
+  friend void SetNewSpaceTaggingWord(ObjectPtr, classid_t, uint32_t);  // tags_
+  friend class ObjectCopyBase;  // LoadPointer/StorePointer
   friend void ReportImpossibleNullError(intptr_t cid,
                                         StackFrame* caller_frame,
                                         Thread* thread);
@@ -835,8 +835,8 @@
   }                                                                            \
   template <std::memory_order order = std::memory_order_relaxed>               \
   void set_##name(type value) {                                                \
-    StoreArrayPointer<Compressed##type, order>(&name##_,                       \
-                                               Compressed##type(value));       \
+    StoreCompressedArrayPointer<type, Compressed##type, order>(&name##_,       \
+                                                               value);         \
   }                                                                            \
                                                                                \
  protected:                                                                    \
@@ -1010,7 +1010,6 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
         return reinterpret_cast<CompressedObjectPtr*>(&dependent_code_);
 #endif
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1057,7 +1056,7 @@
   friend class UntaggedInstance;
   friend class UntaggedInstructions;
   friend class UntaggedTypeArguments;
-  friend class SnapshotReader;
+  friend class MessageSerializer;
   friend class InstanceSerializationCluster;
   friend class TypeSerializationCluster;
   friend class CidRewriteVisitor;
@@ -1083,7 +1082,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&library_kernel_data_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1267,7 +1265,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&data_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1412,7 +1409,6 @@
       case Snapshot::kFullJIT:
       case Snapshot::kFullAOT:
         return reinterpret_cast<CompressedObjectPtr*>(&initializer_function_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1486,7 +1482,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&kernel_program_info_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1578,7 +1573,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&kernel_data_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1631,7 +1625,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&owner_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -2186,7 +2179,6 @@
   VARIABLE_POINTER_FIELDS(ObjectPtr, element, data)
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 class UntaggedContextScope : public UntaggedObject {
@@ -2262,7 +2254,6 @@
 
   friend class Object;
   friend class UntaggedClosureData;
-  friend class SnapshotReader;
 };
 
 class UntaggedSentinel : public UntaggedObject {
@@ -2328,7 +2319,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return to();
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -2423,7 +2413,6 @@
 class UntaggedInstance : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Instance);
   friend class Object;
-  friend class SnapshotReader;
 
  public:
 #if defined(DART_COMPRESSED_POINTERS)
@@ -2452,7 +2441,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&importer_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -2479,7 +2467,6 @@
   COMPRESSED_VARIABLE_POINTER_FIELDS(AbstractTypePtr, element, types)
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 class UntaggedTypeParameters : public UntaggedObject {
@@ -2498,7 +2485,6 @@
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 class UntaggedAbstractType : public UntaggedInstance {
@@ -2517,6 +2503,9 @@
 
   // Accessed from generated code.
   std::atomic<uword> type_test_stub_entry_point_;
+#if defined(DART_COMPRESSED_POINTERS)
+  uint32_t padding_;  // Makes Windows and Posix agree on layout.
+#endif
   COMPRESSED_POINTER_FIELD(CodePtr, type_test_stub)
   VISIT_FROM(type_test_stub)
 
@@ -2707,7 +2696,6 @@
   friend class Api;
   friend class Class;
   friend class Integer;
-  friend class SnapshotReader;
 };
 COMPILE_ASSERT(sizeof(UntaggedMint) == 16);
 
@@ -2718,7 +2706,6 @@
   ALIGN8 double value_;
 
   friend class Api;
-  friend class SnapshotReader;
   friend class Class;
 };
 COMPILE_ASSERT(sizeof(UntaggedDouble) == 16);
@@ -2754,9 +2741,7 @@
   uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
   const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
 
-  friend class ApiMessageReader;
   friend class RODataSerializationCluster;
-  friend class SnapshotReader;
   friend class String;
 };
 
@@ -2769,7 +2754,6 @@
   const uint16_t* data() const { OPEN_ARRAY_START(uint16_t, uint16_t); }
 
   friend class RODataSerializationCluster;
-  friend class SnapshotReader;
   friend class String;
 };
 
@@ -2800,6 +2784,9 @@
 // Abstract base class for RawTypedData/RawExternalTypedData/RawTypedDataView.
 class UntaggedTypedDataBase : public UntaggedPointerBase {
  protected:
+#if defined(DART_COMPRESSED_POINTERS)
+  uint32_t padding_;  // Makes Windows and Posix agree on layout.
+#endif
   // The length of the view in element sizes (obtainable via
   // [TypedDataBase::ElementSizeInBytes]).
   COMPRESSED_SMI_FIELD(SmiPtr, length);
@@ -2808,6 +2795,12 @@
 
  private:
   friend class UntaggedTypedDataView;
+  friend void UpdateLengthField(intptr_t, ObjectPtr, ObjectPtr);  // length_
+  friend void InitializeExternalTypedData(
+      intptr_t,
+      ExternalTypedDataPtr,
+      ExternalTypedDataPtr);  // initialize fields.
+
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypedDataBase);
 };
 
@@ -2844,7 +2837,6 @@
   friend class ObjectPoolDeserializationCluster;
   friend class ObjectPoolSerializationCluster;
   friend class UntaggedObjectPool;
-  friend class SnapshotReader;
 };
 
 // All _*ArrayView/_ByteDataView classes share the same layout.
@@ -2899,6 +2891,7 @@
   VISIT_TO(offset_in_bytes)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
+  friend void InitializeTypedDataView(TypedDataViewPtr);
   friend class Api;
   friend class Object;
   friend class ObjectPoolDeserializationCluster;
@@ -2907,7 +2900,6 @@
   friend class GCCompactor;
   template <bool>
   friend class ScavengerVisitorBase;
-  friend class SnapshotReader;
 };
 
 class UntaggedExternalOneByteString : public UntaggedString {
@@ -2953,7 +2945,6 @@
   friend class Deserializer;
   friend class UntaggedCode;
   friend class UntaggedImmutableArray;
-  friend class SnapshotReader;
   friend class GrowableObjectArray;
   friend class LinkedHashMap;
   friend class UntaggedLinkedHashMap;
@@ -2964,12 +2955,12 @@
   template <typename Table, bool kAllCanonicalObjectsAreIncludedIntoSet>
   friend class CanonicalSetDeserializationCluster;
   friend class OldPage;
+  friend class FastObjectCopy;  // For initializing fields.
+  friend void UpdateLengthField(intptr_t, ObjectPtr, ObjectPtr);  // length_
 };
 
 class UntaggedImmutableArray : public UntaggedArray {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ImmutableArray);
-
-  friend class SnapshotReader;
 };
 
 class UntaggedGrowableObjectArray : public UntaggedInstance {
@@ -2982,7 +2973,6 @@
   VISIT_TO(data)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
-  friend class SnapshotReader;
   friend class ReversePc;
 };
 
@@ -2991,19 +2981,25 @@
 
   COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_arguments)
   VISIT_FROM(type_arguments)
-  COMPRESSED_POINTER_FIELD(TypedDataPtr, index)
   COMPRESSED_POINTER_FIELD(SmiPtr, hash_mask)
   COMPRESSED_POINTER_FIELD(ArrayPtr, data)
   COMPRESSED_POINTER_FIELD(SmiPtr, used_data)
   COMPRESSED_POINTER_FIELD(SmiPtr, deleted_keys)
-  VISIT_TO(deleted_keys)
-  CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
+  COMPRESSED_POINTER_FIELD(TypedDataPtr, index)
+  VISIT_TO(index)
+
+  CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) {
+    // Do not serialize index.
+    return reinterpret_cast<CompressedObjectPtr*>(&deleted_keys_);
+  }
 };
 
 class UntaggedLinkedHashMap : public UntaggedLinkedHashBase {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashMap);
+};
 
-  friend class SnapshotReader;
+class UntaggedLinkedHashSet : public UntaggedLinkedHashBase {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashSet);
 };
 
 class UntaggedFloat32x4 : public UntaggedInstance {
@@ -3012,7 +3008,6 @@
 
   ALIGN8 float value_[4];
 
-  friend class SnapshotReader;
   friend class Class;
 
  public:
@@ -3029,7 +3024,6 @@
 
   ALIGN8 int32_t value_[4];
 
-  friend class SnapshotReader;
 
  public:
   int32_t x() const { return value_[0]; }
@@ -3045,7 +3039,6 @@
 
   ALIGN8 double value_[2];
 
-  friend class SnapshotReader;
   friend class Class;
 
  public:
@@ -3234,7 +3227,6 @@
   // Isolate unique tag.
   uword tag_;
 
-  friend class SnapshotReader;
   friend class Object;
 
  public:
@@ -3247,8 +3239,6 @@
   COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_arguments)
   VISIT_FROM(type_arguments)
   VISIT_TO(type_arguments)
-
-  friend class SnapshotReader;
 };
 
 #undef WSR_COMPRESSED_POINTER_FIELD
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index 9c0d887a..0c64af6 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -231,8 +231,7 @@
 #define NON_HEADER_HASH_CLASSES_AND_FIELDS(F) F(String, hash_)
 
 OffsetsTable::OffsetsTable(Zone* zone) : cached_offsets_(zone) {
-  for (intptr_t i = 0; offsets_table[i].class_id != -1; ++i) {
-    OffsetsTableEntry entry = offsets_table[i];
+  for (const OffsetsTableEntry& entry : OffsetsTable::offsets_table()) {
     cached_offsets_.Insert({{entry.class_id, entry.offset}, entry.field_name});
   }
 }
@@ -242,37 +241,46 @@
   return cached_offsets_.LookupValue({class_id, offset});
 }
 
-#define DEFINE_OFFSETS_TABLE_ENTRY(class_name, field_name)                     \
-  {class_name::kClassId, #field_name,                                          \
-   OFFSET_OF(Untagged##class_name, field_name)},
+static MallocGrowableArray<OffsetsTable::OffsetsTableEntry> field_offsets_table;
 
-// clang-format off
-const OffsetsTable::OffsetsTableEntry OffsetsTable::offsets_table[] = {
-    COMMON_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+const MallocGrowableArray<OffsetsTable::OffsetsTableEntry>&
+OffsetsTable::offsets_table() {
+  ASSERT(field_offsets_table.length() > 0);  // Initialized.
+  return field_offsets_table;
+}
+
+void OffsetsTable::Init() {
+#define DEFINE_OFFSETS_TABLE_ENTRY(class_name, field_name)                     \
+  field_offsets_table.Add({class_name::kClassId, #field_name,                  \
+                           OFFSET_OF(Untagged##class_name, field_name)});
+
+  COMMON_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
 #if !defined(PRODUCT)
-    NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+  NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
 #endif
 
 #if !defined(HASH_IN_OBJECT_HEADER)
-    NON_HEADER_HASH_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+  NON_HEADER_HASH_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
 #endif
 
 #if defined(DART_PRECOMPILED_RUNTIME)
-    AOT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+  AOT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
 #if !defined(PRODUCT)
-    AOT_NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+  AOT_NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
 #endif
 #else
-    JIT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+  JIT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
 #if !defined(PRODUCT)
-    JIT_NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+  JIT_NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
 #endif
 #endif
-    {-1, nullptr, -1}
-};
-// clang-format on
 
 #undef DEFINE_OFFSETS_TABLE_ENTRY
+}
+
+void OffsetsTable::Cleanup() {
+  field_offsets_table.Clear();
+}
 
 #endif
 
diff --git a/runtime/vm/raw_object_fields.h b/runtime/vm/raw_object_fields.h
index 6a4f572..be56a51 100644
--- a/runtime/vm/raw_object_fields.h
+++ b/runtime/vm/raw_object_fields.h
@@ -30,12 +30,14 @@
   const char* FieldNameForOffset(intptr_t cid, intptr_t offset);
 
   struct OffsetsTableEntry {
-    const intptr_t class_id;
-    const char* const field_name;
-    const intptr_t offset;
+    intptr_t class_id;
+    const char* field_name;
+    intptr_t offset;
   };
 
-  static const OffsetsTableEntry offsets_table[];
+  static const MallocGrowableArray<OffsetsTableEntry>& offsets_table();
+  static void Init();
+  static void Cleanup();
 
  private:
   struct IntAndIntToStringMapTraits {
@@ -71,6 +73,9 @@
   const char* FieldNameForOffset(intptr_t cid, intptr_t offset) {
     return nullptr;
   }
+
+  static void Init() {}
+  static void Cleanup() {}
 };
 
 #endif
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
deleted file mode 100644
index 7e6df08..0000000
--- a/runtime/vm/raw_object_snapshot.cc
+++ /dev/null
@@ -1,1833 +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/dart_api_state.h"
-#include "vm/message.h"
-#include "vm/native_entry.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/regexp.h"
-#include "vm/snapshot.h"
-#include "vm/stub_code.h"
-#include "vm/symbols.h"
-#include "vm/type_testing_stubs.h"
-#include "vm/visitor.h"
-
-namespace dart {
-
-// TODO(dartbug.com/34796): enable or remove this optimization.
-DEFINE_FLAG(
-    uint64_t,
-    externalize_typed_data_threshold,
-    kMaxUint64,
-    "Convert TypedData to ExternalTypedData when sending through a message"
-    " port after it exceeds certain size in bytes.");
-
-#define OFFSET_OF_FROM(obj)                                                    \
-  obj.ptr()->from() - reinterpret_cast<ObjectPtr*>(obj.ptr()->untag())
-
-#define READ_OBJECT_FIELDS(object, from, to, as_reference)                     \
-  intptr_t num_flds = (to) - (from);                                           \
-  for (intptr_t i = 0; i <= num_flds; i++) {                                   \
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(as_reference);   \
-    object.StorePointer(((from) + i), reader->PassiveObjectHandle()->ptr());   \
-  }
-
-#define READ_COMPRESSED_OBJECT_FIELDS(object, from, to, as_reference)          \
-  intptr_t num_flds = (to) - (from);                                           \
-  for (intptr_t i = 0; i <= num_flds; i++) {                                   \
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(as_reference);   \
-    object.StoreCompressedPointer(((from) + i),                                \
-                                  reader->PassiveObjectHandle()->ptr());       \
-  }
-
-ClassPtr Class::ReadFrom(SnapshotReader* reader,
-                         intptr_t object_id,
-                         intptr_t tags,
-                         Snapshot::Kind kind,
-                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  Class& cls = Class::ZoneHandle(reader->zone(), Class::null());
-  cls = reader->ReadClassId(object_id);
-  return cls.ptr();
-}
-
-void UntaggedClass::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kClassCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  if (writer->can_send_any_object() ||
-      writer->AllowObjectsInDartLibrary(library())) {
-    writer->WriteClassId(this);
-  } else {
-    // We do not allow regular dart instances in isolate messages.
-    writer->SetWriteException(Exceptions::kArgument,
-                              "Illegal argument in isolate message"
-                              " : (object is a regular Dart Instance)");
-  }
-}
-
-TypePtr Type::ReadFrom(SnapshotReader* reader,
-                       intptr_t object_id,
-                       intptr_t tags,
-                       Snapshot::Kind kind,
-                       bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Determine if the type class of this type is in the full snapshot.
-  reader->Read<bool>();
-
-  // Allocate type object.
-  Type& type = Type::ZoneHandle(reader->zone(), Type::New());
-  bool is_canonical = UntaggedObject::IsCanonical(tags);
-  reader->AddBackRef(object_id, &type, kIsDeserialized);
-
-  // Set all non object fields.
-  const uint8_t combined = reader->Read<uint8_t>();
-  type.set_type_state(combined >> 4);
-  type.set_nullability(static_cast<Nullability>(combined & 0xf));
-
-  // Read the code object for the type testing stub and set its entrypoint.
-  reader->EnqueueTypePostprocessing(type);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(type, type.ptr()->untag()->from(),
-                                type.ptr()->untag()->to(), as_reference);
-
-  // Read in the type class.
-  (*reader->ClassHandle()) =
-      Class::RawCast(reader->ReadObjectImpl(as_reference));
-  type.set_type_class(*reader->ClassHandle());
-
-  // Fill in the type testing stub.
-  Code& code = *reader->CodeHandle();
-  code = TypeTestingStubGenerator::DefaultCodeForType(type);
-  type.InitializeTypeTestingStubNonAtomic(code);
-
-  if (is_canonical) {
-    type ^= type.Canonicalize(Thread::Current(), nullptr);
-  }
-
-  return type.ptr();
-}
-
-void UntaggedType::WriteTo(SnapshotWriter* writer,
-                           intptr_t object_id,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Only resolved and finalized types should be written to a snapshot.
-  ASSERT((type_state_ == UntaggedType::kFinalizedInstantiated) ||
-         (type_state_ == UntaggedType::kFinalizedUninstantiated));
-  ASSERT(type_class_id() != Object::null());
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kTypeCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  if (type_class_id()->IsHeapObject()) {
-    // Type class is still an unresolved class.
-    UNREACHABLE();
-  }
-
-  // Lookup the type class.
-  SmiPtr raw_type_class_id = Smi::RawCast(type_class_id());
-  ClassPtr type_class =
-      writer->isolate_group()->class_table()->At(Smi::Value(raw_type_class_id));
-
-  // Write out typeclass_is_in_fullsnapshot first as this will
-  // help the reader decide on how to canonicalize the type object.
-  intptr_t tags = writer->GetObjectTags(type_class);
-  bool typeclass_is_in_fullsnapshot =
-      (ClassIdTag::decode(tags) == kClassCid) &&
-      Class::IsInFullSnapshot(static_cast<ClassPtr>(type_class));
-  writer->Write<bool>(typeclass_is_in_fullsnapshot);
-
-  // Write out all the non object pointer fields.
-  const uint8_t combined = (type_state_ << 4) | nullability_;
-  ASSERT(type_state_ == (combined >> 4));
-  ASSERT(nullability_ == (combined & 0xf));
-  writer->Write<uint8_t>(combined);
-
-  // Write out all the object pointer fields.
-  ASSERT(type_class_id() != Object::null());
-  SnapshotWriterVisitor visitor(writer, as_reference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-
-  // Write out the type class.
-  writer->WriteObjectImpl(type_class, as_reference);
-}
-
-TypeRefPtr TypeRef::ReadFrom(SnapshotReader* reader,
-                             intptr_t object_id,
-                             intptr_t tags,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate type ref object.
-  TypeRef& type_ref = TypeRef::ZoneHandle(reader->zone(), TypeRef::New());
-  reader->AddBackRef(object_id, &type_ref, kIsDeserialized);
-
-  // Read the code object for the type testing stub and set its entrypoint.
-  reader->EnqueueTypePostprocessing(type_ref);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(type_ref, type_ref.ptr()->untag()->from(),
-                                type_ref.ptr()->untag()->to(), kAsReference);
-
-  // Fill in the type testing stub.
-  Code& code = *reader->CodeHandle();
-  code = TypeTestingStubGenerator::DefaultCodeForType(type_ref);
-  type_ref.InitializeTypeTestingStubNonAtomic(code);
-
-  return type_ref.ptr();
-}
-
-void UntaggedTypeRef::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kTypeRefCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-TypeParameterPtr TypeParameter::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate type parameter object.
-  TypeParameter& type_parameter =
-      TypeParameter::ZoneHandle(reader->zone(), TypeParameter::New());
-  bool is_canonical = UntaggedObject::IsCanonical(tags);
-  reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
-
-  // Set all non object fields.
-  type_parameter.set_base(reader->Read<uint8_t>());
-  type_parameter.set_index(reader->Read<uint8_t>());
-  const uint8_t combined = reader->Read<uint8_t>();
-  type_parameter.set_flags(combined >> 4);
-  type_parameter.set_nullability(static_cast<Nullability>(combined & 0xf));
-
-  // Read the code object for the type testing stub and set its entrypoint.
-  reader->EnqueueTypePostprocessing(type_parameter);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(
-      type_parameter, type_parameter.ptr()->untag()->from(),
-      type_parameter.ptr()->untag()->to(), kAsReference);
-
-  // Read in the parameterized class.
-  (*reader->ClassHandle()) =
-      Class::RawCast(reader->ReadObjectImpl(kAsReference));
-  if (reader->ClassHandle()->id() == kFunctionCid) {
-    (*reader->ClassHandle()) = Class::null();
-  }
-  type_parameter.set_parameterized_class(*reader->ClassHandle());
-
-  // Fill in the type testing stub.
-  Code& code = *reader->CodeHandle();
-  code = TypeTestingStubGenerator::DefaultCodeForType(type_parameter);
-  type_parameter.InitializeTypeTestingStubNonAtomic(code);
-
-  if (is_canonical) {
-    type_parameter ^= type_parameter.Canonicalize(Thread::Current(), nullptr);
-  }
-
-  return type_parameter.ptr();
-}
-
-void UntaggedTypeParameter::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Only finalized type parameters should be written to a snapshot.
-  ASSERT(FinalizedBit::decode(flags_));
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kTypeParameterCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the non object pointer fields.
-  writer->Write<uint8_t>(base_);
-  writer->Write<uint8_t>(index_);
-  const uint8_t combined = (flags_ << 4) | nullability_;
-  ASSERT(flags_ == (combined >> 4));
-  ASSERT(nullability_ == (combined & 0xf));
-  writer->Write<uint8_t>(combined);
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-
-  // Write out the parameterized class (or Function if cid == kFunctionCid).
-  ClassPtr param_class =
-      writer->isolate_group()->class_table()->At(parameterized_class_id_);
-  writer->WriteObjectImpl(param_class, kAsReference);
-}
-
-TypeParametersPtr TypeParameters::ReadFrom(SnapshotReader* reader,
-                                           intptr_t object_id,
-                                           intptr_t tags,
-                                           Snapshot::Kind kind,
-                                           bool as_reference) {
-  ASSERT(reader != NULL);
-
-  TypeParameters& type_parameters =
-      TypeParameters::ZoneHandle(reader->zone(), TypeParameters::New());
-  reader->AddBackRef(object_id, &type_parameters, kIsDeserialized);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(
-      type_parameters, type_parameters.ptr()->untag()->from(),
-      type_parameters.ptr()->untag()->to(), kAsReference);
-
-  return type_parameters.ptr();
-}
-
-void UntaggedTypeParameters::WriteTo(SnapshotWriter* writer,
-                                     intptr_t object_id,
-                                     Snapshot::Kind kind,
-                                     bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kTypeParametersCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-TypeArgumentsPtr TypeArguments::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Read the length so that we can determine instance size to allocate.
-  intptr_t len = reader->ReadSmiValue();
-
-  TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(reader->zone(), TypeArguments::New(len));
-  bool is_canonical = UntaggedObject::IsCanonical(tags);
-  reader->AddBackRef(object_id, &type_arguments, kIsDeserialized);
-
-  // Set the instantiations field, which is only read from a full snapshot.
-  type_arguments.set_instantiations(Object::zero_array());
-
-  // Now set all the type fields.
-  for (intptr_t i = 0; i < len; i++) {
-    *reader->TypeHandle() ^= reader->ReadObjectImpl(as_reference);
-    type_arguments.SetTypeAt(i, *reader->TypeHandle());
-  }
-
-  // Set the canonical bit.
-  if (is_canonical) {
-    type_arguments = type_arguments.Canonicalize(Thread::Current(), nullptr);
-  }
-
-  return type_arguments.ptr();
-}
-
-void UntaggedTypeArguments::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kTypeArgumentsCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the length field.
-  writer->Write<ObjectPtr>(length());
-
-  // Write out the individual types.
-  intptr_t len = Smi::Value(length());
-  for (intptr_t i = 0; i < len; i++) {
-    // The Dart VM reuses type argument lists across instances in order
-    // to reduce memory footprint, this can sometimes lead to a type from
-    // such a shared type argument list being sent over to another isolate.
-    // In such scenarios where it is not appropriate to send the types
-    // across (isolates spawned using spawnURI) we send them as dynamic.
-    if (!writer->can_send_any_object()) {
-      // Lookup the type class.
-      TypePtr raw_type = Type::RawCast(element(i));
-      SmiPtr raw_type_class_id =
-          Smi::RawCast(raw_type->untag()->type_class_id());
-      ClassPtr type_class = writer->isolate_group()->class_table()->At(
-          Smi::Value(raw_type_class_id));
-      if (!writer->AllowObjectsInDartLibrary(type_class->untag()->library())) {
-        writer->WriteVMIsolateObject(kDynamicType);
-      } else {
-        writer->WriteObjectImpl(element(i), as_reference);
-      }
-    } else {
-      writer->WriteObjectImpl(element(i), as_reference);
-    }
-  }
-}
-
-ClosurePtr Closure::ReadFrom(SnapshotReader* reader,
-                             intptr_t object_id,
-                             intptr_t tags,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  UNREACHABLE();
-  return Closure::null();
-}
-
-void UntaggedClosure::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  ASSERT(writer != NULL);
-  ASSERT(kind == Snapshot::kMessage);
-
-  // Check if closure is serializable, throw an exception otherwise.
-  FunctionPtr func = writer->IsSerializableClosure(ClosurePtr(this));
-  if (func != Function::null()) {
-    writer->WriteStaticImplicitClosure(
-        object_id, func, writer->GetObjectTags(this), delayed_type_arguments());
-    return;
-  }
-
-  UNREACHABLE();
-}
-
-ContextPtr Context::ReadFrom(SnapshotReader* reader,
-                             intptr_t object_id,
-                             intptr_t tags,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate context object.
-  int32_t num_vars = reader->Read<int32_t>();
-  Context& context = Context::ZoneHandle(reader->zone());
-  reader->AddBackRef(object_id, &context, kIsDeserialized);
-  if (num_vars != 0) {
-    context = Context::New(num_vars);
-
-    // Set all the object fields.
-    // TODO(5411462): Need to assert No GC can happen here, even though
-    // allocations may happen.
-    intptr_t num_flds =
-        (context.ptr()->untag()->to(num_vars) - context.ptr()->untag()->from());
-    for (intptr_t i = 0; i <= num_flds; i++) {
-      (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
-      context.StorePointer((context.ptr()->untag()->from() + i),
-                           reader->PassiveObjectHandle()->ptr());
-    }
-  }
-  return context.ptr();
-}
-
-void UntaggedContext::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kContextCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out num of variables in the context.
-  const int32_t num_variables = num_variables_;
-  writer->Write<int32_t>(num_variables);
-  if (num_variables != 0) {
-    // Write out all the object pointer fields.
-    SnapshotWriterVisitor visitor(writer, kAsReference);
-    visitor.VisitPointers(from(), to(num_variables));
-  }
-}
-
-ContextScopePtr ContextScope::ReadFrom(SnapshotReader* reader,
-                                       intptr_t object_id,
-                                       intptr_t tags,
-                                       Snapshot::Kind kind,
-                                       bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate context object.
-  bool is_implicit = reader->Read<bool>();
-  if (is_implicit) {
-    ContextScope& context_scope = ContextScope::ZoneHandle(reader->zone());
-    context_scope = ContextScope::New(1, true);
-    reader->AddBackRef(object_id, &context_scope, kIsDeserialized);
-
-    *reader->TypeHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-
-    // Create a descriptor for 'this' variable.
-    context_scope.SetTokenIndexAt(0, TokenPosition::kMinSource);
-    context_scope.SetDeclarationTokenIndexAt(0, TokenPosition::kMinSource);
-    context_scope.SetNameAt(0, Symbols::This());
-    context_scope.SetIsFinalAt(0, true);
-    context_scope.SetIsConstAt(0, false);
-    context_scope.SetTypeAt(0, *reader->TypeHandle());
-    context_scope.SetContextIndexAt(0, 0);
-    context_scope.SetContextLevelAt(0, 0);
-    return context_scope.ptr();
-  }
-  UNREACHABLE();
-  return NULL;
-}
-
-void UntaggedContextScope::WriteTo(SnapshotWriter* writer,
-                                   intptr_t object_id,
-                                   Snapshot::Kind kind,
-                                   bool as_reference) {
-  ASSERT(writer != NULL);
-
-  if (is_implicit_) {
-    ASSERT(num_variables_ == 1);
-    const VariableDesc* var = VariableDescAddr(0);
-
-    // Write out the serialization header value for this object.
-    writer->WriteInlinedObjectHeader(object_id);
-
-    // Write out the class and tags information.
-    writer->WriteVMIsolateObject(kContextScopeCid);
-    writer->WriteTags(writer->GetObjectTags(this));
-
-    // Write out is_implicit flag for the context scope.
-    writer->Write<bool>(true);
-
-    // Write out the type of 'this' the variable.
-    writer->WriteObjectImpl(var->type.Decompress(heap_base()),
-                            kAsInlinedObject);
-
-    return;
-  }
-  UNREACHABLE();
-}
-
-#define MESSAGE_SNAPSHOT_UNREACHABLE(type)                                     \
-  type##Ptr type::ReadFrom(SnapshotReader* reader, intptr_t object_id,         \
-                           intptr_t tags, Snapshot::Kind kind,                 \
-                           bool as_reference) {                                \
-    UNREACHABLE();                                                             \
-    return type::null();                                                       \
-  }                                                                            \
-  void Untagged##type::WriteTo(SnapshotWriter* writer, intptr_t object_id,     \
-                               Snapshot::Kind kind, bool as_reference) {       \
-    UNREACHABLE();                                                             \
-  }
-
-#define MESSAGE_SNAPSHOT_ILLEGAL(type)                                         \
-  type##Ptr type::ReadFrom(SnapshotReader* reader, intptr_t object_id,         \
-                           intptr_t tags, Snapshot::Kind kind,                 \
-                           bool as_reference) {                                \
-    UNREACHABLE();                                                             \
-    return type::null();                                                       \
-  }                                                                            \
-  void Untagged##type::WriteTo(SnapshotWriter* writer, intptr_t object_id,     \
-                               Snapshot::Kind kind, bool as_reference) {       \
-    writer->SetWriteException(Exceptions::kArgument,                           \
-                              "Illegal argument in isolate message"            \
-                              " : (object is a " #type ")");                   \
-  }
-
-MESSAGE_SNAPSHOT_UNREACHABLE(AbstractType);
-MESSAGE_SNAPSHOT_UNREACHABLE(Bool);
-MESSAGE_SNAPSHOT_UNREACHABLE(ClosureData);
-MESSAGE_SNAPSHOT_UNREACHABLE(Code);
-MESSAGE_SNAPSHOT_UNREACHABLE(CodeSourceMap);
-MESSAGE_SNAPSHOT_UNREACHABLE(CompressedStackMaps);
-MESSAGE_SNAPSHOT_UNREACHABLE(Error);
-MESSAGE_SNAPSHOT_UNREACHABLE(ExceptionHandlers);
-MESSAGE_SNAPSHOT_UNREACHABLE(FfiTrampolineData);
-MESSAGE_SNAPSHOT_UNREACHABLE(Field);
-MESSAGE_SNAPSHOT_UNREACHABLE(Function);
-MESSAGE_SNAPSHOT_UNREACHABLE(CallSiteData);
-MESSAGE_SNAPSHOT_UNREACHABLE(ICData);
-MESSAGE_SNAPSHOT_UNREACHABLE(Instructions);
-MESSAGE_SNAPSHOT_UNREACHABLE(InstructionsSection);
-MESSAGE_SNAPSHOT_UNREACHABLE(InstructionsTable);
-MESSAGE_SNAPSHOT_UNREACHABLE(KernelProgramInfo);
-MESSAGE_SNAPSHOT_UNREACHABLE(Library);
-MESSAGE_SNAPSHOT_UNREACHABLE(LibraryPrefix);
-MESSAGE_SNAPSHOT_UNREACHABLE(LocalVarDescriptors);
-MESSAGE_SNAPSHOT_UNREACHABLE(MegamorphicCache);
-MESSAGE_SNAPSHOT_UNREACHABLE(Namespace);
-MESSAGE_SNAPSHOT_UNREACHABLE(ObjectPool);
-MESSAGE_SNAPSHOT_UNREACHABLE(PatchClass);
-MESSAGE_SNAPSHOT_UNREACHABLE(PcDescriptors);
-MESSAGE_SNAPSHOT_UNREACHABLE(Script);
-MESSAGE_SNAPSHOT_UNREACHABLE(Sentinel);
-MESSAGE_SNAPSHOT_UNREACHABLE(SingleTargetCache);
-MESSAGE_SNAPSHOT_UNREACHABLE(String);
-MESSAGE_SNAPSHOT_UNREACHABLE(SubtypeTestCache);
-MESSAGE_SNAPSHOT_UNREACHABLE(LoadingUnit);
-MESSAGE_SNAPSHOT_UNREACHABLE(TypedDataBase);
-MESSAGE_SNAPSHOT_UNREACHABLE(UnlinkedCall);
-MESSAGE_SNAPSHOT_UNREACHABLE(MonomorphicSmiableCall);
-MESSAGE_SNAPSHOT_UNREACHABLE(UnwindError);
-MESSAGE_SNAPSHOT_UNREACHABLE(FutureOr);
-MESSAGE_SNAPSHOT_UNREACHABLE(WeakSerializationReference);
-
-MESSAGE_SNAPSHOT_ILLEGAL(FunctionType)
-MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
-MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
-MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
-MESSAGE_SNAPSHOT_ILLEGAL(ReceivePort);
-MESSAGE_SNAPSHOT_ILLEGAL(StackTrace);
-MESSAGE_SNAPSHOT_ILLEGAL(UserTag);
-
-ApiErrorPtr ApiError::ReadFrom(SnapshotReader* reader,
-                               intptr_t object_id,
-                               intptr_t tags,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate ApiError object.
-  ApiError& api_error = ApiError::ZoneHandle(reader->zone(), ApiError::New());
-  reader->AddBackRef(object_id, &api_error, kIsDeserialized);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(api_error, api_error.ptr()->untag()->from(),
-                                api_error.ptr()->untag()->to(), kAsReference);
-
-  return api_error.ptr();
-}
-
-void UntaggedApiError::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kApiErrorCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-LanguageErrorPtr LanguageError::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate LanguageError object.
-  LanguageError& language_error =
-      LanguageError::ZoneHandle(reader->zone(), LanguageError::New());
-  reader->AddBackRef(object_id, &language_error, kIsDeserialized);
-
-  // Set all non object fields.
-  language_error.set_token_pos(
-      TokenPosition::Deserialize(reader->Read<int32_t>()));
-  language_error.set_report_after_token(reader->Read<bool>());
-  language_error.set_kind(reader->Read<uint8_t>());
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(
-      language_error, language_error.ptr()->untag()->from(),
-      language_error.ptr()->untag()->to(), kAsReference);
-
-  return language_error.ptr();
-}
-
-void UntaggedLanguageError::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kLanguageErrorCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the non object fields.
-  writer->Write<int32_t>(token_pos_.Serialize());
-  writer->Write<bool>(report_after_token_);
-  writer->Write<uint8_t>(kind_);
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-UnhandledExceptionPtr UnhandledException::ReadFrom(SnapshotReader* reader,
-                                                   intptr_t object_id,
-                                                   intptr_t tags,
-                                                   Snapshot::Kind kind,
-                                                   bool as_reference) {
-  UnhandledException& result =
-      UnhandledException::ZoneHandle(reader->zone(), UnhandledException::New());
-  reader->AddBackRef(object_id, &result, kIsDeserialized);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(result, result.ptr()->untag()->from(),
-                                result.ptr()->untag()->to(), kAsReference);
-
-  return result.ptr();
-}
-
-void UntaggedUnhandledException::WriteTo(SnapshotWriter* writer,
-                                         intptr_t object_id,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kUnhandledExceptionCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-InstancePtr Instance::ReadFrom(SnapshotReader* reader,
-                               intptr_t object_id,
-                               intptr_t tags,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Create an Instance object or get canonical one if it is a canonical
-  // constant.
-  Instance& obj = Instance::ZoneHandle(reader->zone(), Instance::null());
-  obj ^= Object::Allocate(kInstanceCid, Instance::InstanceSize(), Heap::kNew,
-                          Instance::ContainsCompressedPointers());
-  if (UntaggedObject::IsCanonical(tags)) {
-    obj = obj.Canonicalize(reader->thread());
-  }
-  reader->AddBackRef(object_id, &obj, kIsDeserialized);
-
-  return obj.ptr();
-}
-
-void UntaggedInstance::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kInstanceCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-}
-
-IntegerPtr Mint::ReadFrom(SnapshotReader* reader,
-                          intptr_t object_id,
-                          intptr_t tags,
-                          Snapshot::Kind kind,
-                          bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Read the 64 bit value for the object.
-  int64_t value = reader->Read<int64_t>();
-
-  // Check if the value could potentially fit in a Smi in our current
-  // architecture, if so return the object as a Smi.
-  if (Smi::IsValid(value)) {
-    Smi& smi =
-        Smi::ZoneHandle(reader->zone(), Smi::New(static_cast<intptr_t>(value)));
-    reader->AddBackRef(object_id, &smi, kIsDeserialized);
-    return smi.ptr();
-  }
-
-  // Create a Mint object or get canonical one if it is a canonical constant.
-  Mint& mint = Mint::ZoneHandle(reader->zone(), Mint::null());
-  // When reading a script snapshot we need to canonicalize only those object
-  // references that are objects from the core library (loaded from a
-  // full snapshot). Objects that are only in the script need not be
-  // canonicalized as they are already canonical.
-  // When reading a message snapshot we always have to canonicalize.
-  if (UntaggedObject::IsCanonical(tags)) {
-    mint = Mint::NewCanonical(value);
-    ASSERT(mint.IsCanonical());
-  } else {
-    mint = Mint::New(value);
-  }
-  reader->AddBackRef(object_id, &mint, kIsDeserialized);
-  return mint.ptr();
-}
-
-void UntaggedMint::WriteTo(SnapshotWriter* writer,
-                           intptr_t object_id,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kMintCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the 64 bit value.
-  writer->Write<int64_t>(value_);
-}
-
-DoublePtr Double::ReadFrom(SnapshotReader* reader,
-                           intptr_t object_id,
-                           intptr_t tags,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
-  ASSERT(reader != NULL);
-  ASSERT(kind != Snapshot::kMessage);
-  // Read the double value for the object.
-  double value = reader->ReadDouble();
-
-  // Create a Double object or get canonical one if it is a canonical constant.
-  Double& dbl = Double::ZoneHandle(reader->zone(), Double::null());
-  // When reading a script snapshot we need to canonicalize only those object
-  // references that are objects from the core library (loaded from a
-  // full snapshot). Objects that are only in the script need not be
-  // canonicalized as they are already canonical.
-  if (UntaggedObject::IsCanonical(tags)) {
-    dbl = Double::NewCanonical(value);
-    ASSERT(dbl.IsCanonical());
-  } else {
-    dbl = Double::New(value);
-  }
-  reader->AddBackRef(object_id, &dbl, kIsDeserialized);
-  return dbl.ptr();
-}
-
-void UntaggedDouble::WriteTo(SnapshotWriter* writer,
-                             intptr_t object_id,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kDoubleCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the double value.
-  writer->WriteDouble(value_);
-}
-
-template <typename StringType, typename CharacterType, typename CallbackType>
-void String::ReadFromImpl(SnapshotReader* reader,
-                          String* str_obj,
-                          intptr_t len,
-                          intptr_t tags,
-                          CallbackType new_symbol,
-                          Snapshot::Kind kind) {
-  ASSERT(reader != NULL);
-  if (UntaggedObject::IsCanonical(tags)) {
-    // Set up canonical string object.
-    ASSERT(reader != NULL);
-    CharacterType* ptr = reader->zone()->Alloc<CharacterType>(len);
-    for (intptr_t i = 0; i < len; i++) {
-      ptr[i] = reader->Read<CharacterType>();
-    }
-    *str_obj = (*new_symbol)(reader->thread(), ptr, len);
-  } else {
-    // Set up the string object.
-    *str_obj = StringType::New(len, Heap::kNew);
-    str_obj->SetHash(0);  // Will get computed when needed.
-    if (len == 0) {
-      return;
-    }
-    NoSafepointScope no_safepoint;
-    CharacterType* str_addr = StringType::DataStart(*str_obj);
-    for (intptr_t i = 0; i < len; i++) {
-      *str_addr = reader->Read<CharacterType>();
-      str_addr++;
-    }
-  }
-}
-
-OneByteStringPtr OneByteString::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  // Read the length so that we can determine instance size to allocate.
-  ASSERT(reader != NULL);
-  intptr_t len = reader->ReadSmiValue();
-  String& str_obj = String::ZoneHandle(reader->zone(), String::null());
-
-  String::ReadFromImpl<OneByteString, uint8_t>(reader, &str_obj, len, tags,
-                                               Symbols::FromLatin1, kind);
-  reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
-  return raw(str_obj);
-}
-
-TwoByteStringPtr TwoByteString::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  // Read the length so that we can determine instance size to allocate.
-  ASSERT(reader != NULL);
-  intptr_t len = reader->ReadSmiValue();
-  String& str_obj = String::ZoneHandle(reader->zone(), String::null());
-
-  String::ReadFromImpl<TwoByteString, uint16_t>(reader, &str_obj, len, tags,
-                                                Symbols::FromUTF16, kind);
-  reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
-  return raw(str_obj);
-}
-
-template <typename T>
-static void StringWriteTo(SnapshotWriter* writer,
-                          intptr_t object_id,
-                          Snapshot::Kind kind,
-                          intptr_t class_id,
-                          intptr_t tags,
-                          SmiPtr length,
-                          T* data) {
-  ASSERT(writer != NULL);
-  intptr_t len = Smi::Value(length);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(class_id);
-  writer->WriteTags(tags);
-
-  // Write out the length field.
-  writer->Write<ObjectPtr>(length);
-
-  // Write out the string.
-  if (len > 0) {
-    if (class_id == kOneByteStringCid) {
-      writer->WriteBytes(reinterpret_cast<const uint8_t*>(data), len);
-    } else {
-      for (intptr_t i = 0; i < len; i++) {
-        writer->Write(data[i]);
-      }
-    }
-  }
-}
-
-void UntaggedOneByteString::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  StringWriteTo(writer, object_id, kind, kOneByteStringCid,
-                writer->GetObjectTags(this), length(), data());
-}
-
-void UntaggedTwoByteString::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  StringWriteTo(writer, object_id, kind, kTwoByteStringCid,
-                writer->GetObjectTags(this), length(), data());
-}
-
-ExternalOneByteStringPtr ExternalOneByteString::ReadFrom(SnapshotReader* reader,
-                                                         intptr_t object_id,
-                                                         intptr_t tags,
-                                                         Snapshot::Kind kind,
-                                                         bool as_reference) {
-  UNREACHABLE();
-  return ExternalOneByteString::null();
-}
-
-ExternalTwoByteStringPtr ExternalTwoByteString::ReadFrom(SnapshotReader* reader,
-                                                         intptr_t object_id,
-                                                         intptr_t tags,
-                                                         Snapshot::Kind kind,
-                                                         bool as_reference) {
-  UNREACHABLE();
-  return ExternalTwoByteString::null();
-}
-
-void UntaggedExternalOneByteString::WriteTo(SnapshotWriter* writer,
-                                            intptr_t object_id,
-                                            Snapshot::Kind kind,
-                                            bool as_reference) {
-  // Serialize as a non-external one byte string.
-  StringWriteTo(writer, object_id, kind, kOneByteStringCid,
-                writer->GetObjectTags(this), length(), external_data_);
-}
-
-void UntaggedExternalTwoByteString::WriteTo(SnapshotWriter* writer,
-                                            intptr_t object_id,
-                                            Snapshot::Kind kind,
-                                            bool as_reference) {
-  // Serialize as a non-external two byte string.
-  StringWriteTo(writer, object_id, kind, kTwoByteStringCid,
-                writer->GetObjectTags(this), length(), external_data_);
-}
-
-ArrayPtr Array::ReadFrom(SnapshotReader* reader,
-                         intptr_t object_id,
-                         intptr_t tags,
-                         Snapshot::Kind kind,
-                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Read the length so that we can determine instance size to allocate.
-  intptr_t len = reader->ReadSmiValue();
-  Array* array = NULL;
-  DeserializeState state;
-  if (!as_reference) {
-    array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
-    state = kIsDeserialized;
-  } else {
-    state = kIsNotDeserialized;
-  }
-  if (array == NULL) {
-    array = &(Array::ZoneHandle(reader->zone(), Array::New(len)));
-    reader->AddBackRef(object_id, array, state);
-  }
-  if (!as_reference) {
-    // Read all the individual elements for inlined objects.
-    ASSERT(!UntaggedObject::IsCanonical(tags));
-    reader->ArrayReadFrom(object_id, *array, len, tags);
-  }
-  return array->ptr();
-}
-
-ImmutableArrayPtr ImmutableArray::ReadFrom(SnapshotReader* reader,
-                                           intptr_t object_id,
-                                           intptr_t tags,
-                                           Snapshot::Kind kind,
-                                           bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Read the length so that we can determine instance size to allocate.
-  intptr_t len = reader->ReadSmiValue();
-  Array* array = NULL;
-  DeserializeState state;
-  if (!as_reference) {
-    array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
-    state = kIsDeserialized;
-  } else {
-    state = kIsNotDeserialized;
-  }
-  if (array == NULL) {
-    array = &(Array::ZoneHandle(reader->zone(), ImmutableArray::New(len)));
-    reader->AddBackRef(object_id, array, state);
-  }
-  if (!as_reference) {
-    // Read all the individual elements for inlined objects.
-    reader->ArrayReadFrom(object_id, *array, len, tags);
-    if (UntaggedObject::IsCanonical(tags)) {
-      *array ^= array->Canonicalize(reader->thread());
-    }
-  }
-  return raw(*array);
-}
-
-void UntaggedArray::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
-  ASSERT(!this->IsCanonical());
-  writer->ArrayWriteTo(object_id, kArrayCid, writer->GetObjectTags(this),
-                       length(), type_arguments(), data(), as_reference);
-}
-
-void UntaggedImmutableArray::WriteTo(SnapshotWriter* writer,
-                                     intptr_t object_id,
-                                     Snapshot::Kind kind,
-                                     bool as_reference) {
-  writer->ArrayWriteTo(object_id, kImmutableArrayCid,
-                       writer->GetObjectTags(this), length(), type_arguments(),
-                       data(), as_reference);
-}
-
-GrowableObjectArrayPtr GrowableObjectArray::ReadFrom(SnapshotReader* reader,
-                                                     intptr_t object_id,
-                                                     intptr_t tags,
-                                                     Snapshot::Kind kind,
-                                                     bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Read the length so that we can determine instance size to allocate.
-  GrowableObjectArray& array = GrowableObjectArray::ZoneHandle(
-      reader->zone(), GrowableObjectArray::null());
-  array = GrowableObjectArray::New(0);
-  reader->AddBackRef(object_id, &array, kIsDeserialized);
-
-  // Read type arguments of growable array object.
-  *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-  array.StoreCompressedPointer(&array.untag()->type_arguments_,
-                               reader->TypeArgumentsHandle()->ptr());
-
-  // Read length of growable array object.
-  array.SetLength(reader->ReadSmiValue());
-
-  // Read the backing array of growable array object.
-  *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference);
-  array.SetData(*(reader->ArrayHandle()));
-
-  return array.ptr();
-}
-
-void UntaggedGrowableObjectArray::WriteTo(SnapshotWriter* writer,
-                                          intptr_t object_id,
-                                          Snapshot::Kind kind,
-                                          bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kGrowableObjectArrayCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the type arguments field.
-  writer->WriteObjectImpl(type_arguments(), kAsInlinedObject);
-
-  // Write out the used length field.
-  writer->Write<ObjectPtr>(length());
-
-  // Write out the Array object.
-  writer->WriteObjectImpl(data(), kAsReference);
-}
-
-LinkedHashMapPtr LinkedHashMap::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  LinkedHashMap& map =
-      LinkedHashMap::ZoneHandle(reader->zone(), LinkedHashMap::null());
-  // Since the map might contain itself as a key or value, allocate first.
-  map = LinkedHashMap::NewUninitialized();
-  reader->AddBackRef(object_id, &map, kIsDeserialized);
-
-  // Read the type arguments.
-  *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-  map.SetTypeArguments(*reader->TypeArgumentsHandle());
-
-  // Read the number of key/value pairs.
-  intptr_t len = reader->ReadSmiValue();
-  intptr_t used_data = (len << 1);
-  map.SetUsedData(used_data);
-
-  // Allocate the data array.
-  intptr_t data_size =
-      Utils::Maximum(Utils::RoundUpToPowerOfTwo(used_data),
-                     static_cast<uintptr_t>(LinkedHashMap::kInitialIndexSize));
-  Array& data = Array::ZoneHandle(reader->zone(), Array::New(data_size));
-  map.SetData(data);
-  map.SetDeletedKeys(0);
-
-  // The index and hashMask is regenerated by the maps themselves on demand.
-  // Thus, the index will probably be allocated in new space (unless it's huge).
-  // TODO(koda): Eagerly rehash here when no keys have user-defined '==', and
-  // in particular, if/when (const) maps are needed in the VM isolate snapshot.
-  ASSERT(reader->isolate_group() != Dart::vm_isolate_group());
-  map.SetHashMask(0);  // Prefer sentinel 0 over null for better type feedback.
-
-  reader->EnqueueRehashingOfMap(map);
-
-  // Read the keys and values.
-  bool read_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-  for (intptr_t i = 0; i < used_data; i++) {
-    *reader->PassiveObjectHandle() = reader->ReadObjectImpl(read_as_reference);
-    data.SetAt(i, *reader->PassiveObjectHandle());
-  }
-  return map.ptr();
-}
-
-void UntaggedLinkedHashMap::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kLinkedHashMapCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the type arguments.
-  writer->WriteObjectImpl(type_arguments(), kAsInlinedObject);
-
-  const intptr_t num_used_data = Smi::Value(used_data());
-  ASSERT((num_used_data & 1) == 0);  // Keys + values, so must be even.
-  const intptr_t num_deleted_keys = Smi::Value(deleted_keys());
-
-  // Write out the number of (not deleted) key/value pairs that will follow.
-  writer->Write<ObjectPtr>(Smi::New((num_used_data >> 1) - num_deleted_keys));
-
-  // Write out the keys and values.
-  const bool write_as_reference = this->IsCanonical() ? false : true;
-  ArrayPtr data_array = data();
-  ASSERT(num_used_data <= Smi::Value(data_array->untag()->length()));
-#if defined(DEBUG)
-  intptr_t deleted_keys_found = 0;
-#endif  // DEBUG
-  for (intptr_t i = 0; i < num_used_data; i += 2) {
-    ObjectPtr key = data_array->untag()->element(i);
-    if (key == data_array) {
-#if defined(DEBUG)
-      ++deleted_keys_found;
-#endif  // DEBUG
-      continue;
-    }
-    ObjectPtr value = data_array->untag()->element(i + 1);
-    writer->WriteObjectImpl(key, write_as_reference);
-    writer->WriteObjectImpl(value, write_as_reference);
-  }
-  DEBUG_ASSERT(deleted_keys_found == num_deleted_keys);
-}
-
-Float32x4Ptr Float32x4::ReadFrom(SnapshotReader* reader,
-                                 intptr_t object_id,
-                                 intptr_t tags,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  ASSERT(reader != NULL);
-  // Read the values.
-  float value0 = reader->Read<float>();
-  float value1 = reader->Read<float>();
-  float value2 = reader->Read<float>();
-  float value3 = reader->Read<float>();
-
-  // Create a Float32x4 object.
-  Float32x4& simd = Float32x4::ZoneHandle(reader->zone(), Float32x4::null());
-  simd = Float32x4::New(value0, value1, value2, value3);
-  reader->AddBackRef(object_id, &simd, kIsDeserialized);
-  return simd.ptr();
-}
-
-void UntaggedFloat32x4::WriteTo(SnapshotWriter* writer,
-                                intptr_t object_id,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kFloat32x4Cid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the float values.
-  writer->Write<float>(value_[0]);
-  writer->Write<float>(value_[1]);
-  writer->Write<float>(value_[2]);
-  writer->Write<float>(value_[3]);
-}
-
-Int32x4Ptr Int32x4::ReadFrom(SnapshotReader* reader,
-                             intptr_t object_id,
-                             intptr_t tags,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  ASSERT(reader != NULL);
-  // Read the values.
-  uint32_t value0 = reader->Read<uint32_t>();
-  uint32_t value1 = reader->Read<uint32_t>();
-  uint32_t value2 = reader->Read<uint32_t>();
-  uint32_t value3 = reader->Read<uint32_t>();
-
-  // Create a Float32x4 object.
-  Int32x4& simd = Int32x4::ZoneHandle(reader->zone(), Int32x4::null());
-  simd = Int32x4::New(value0, value1, value2, value3);
-  reader->AddBackRef(object_id, &simd, kIsDeserialized);
-  return simd.ptr();
-}
-
-void UntaggedInt32x4::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kInt32x4Cid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the mask values.
-  writer->Write<uint32_t>(value_[0]);
-  writer->Write<uint32_t>(value_[1]);
-  writer->Write<uint32_t>(value_[2]);
-  writer->Write<uint32_t>(value_[3]);
-}
-
-Float64x2Ptr Float64x2::ReadFrom(SnapshotReader* reader,
-                                 intptr_t object_id,
-                                 intptr_t tags,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  ASSERT(reader != NULL);
-  // Read the values.
-  double value0 = reader->Read<double>();
-  double value1 = reader->Read<double>();
-
-  // Create a Float64x2 object.
-  Float64x2& simd = Float64x2::ZoneHandle(reader->zone(), Float64x2::null());
-  simd = Float64x2::New(value0, value1);
-  reader->AddBackRef(object_id, &simd, kIsDeserialized);
-  return simd.ptr();
-}
-
-void UntaggedFloat64x2::WriteTo(SnapshotWriter* writer,
-                                intptr_t object_id,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kFloat64x2Cid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the float values.
-  writer->Write<double>(value_[0]);
-  writer->Write<double>(value_[1]);
-}
-
-TypedDataPtr TypedData::ReadFrom(SnapshotReader* reader,
-                                 intptr_t object_id,
-                                 intptr_t tags,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  ASSERT(reader != NULL);
-
-  intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
-  intptr_t len = reader->ReadSmiValue();
-  TypedData& result =
-      TypedData::ZoneHandle(reader->zone(), TypedData::New(cid, len));
-  reader->AddBackRef(object_id, &result, kIsDeserialized);
-
-  // Setup the array elements.
-  intptr_t element_size = ElementSizeInBytes(cid);
-  intptr_t length_in_bytes = len * element_size;
-  NoSafepointScope no_safepoint;
-  uint8_t* data = reinterpret_cast<uint8_t*>(result.DataAddr(0));
-  reader->Align(Zone::kAlignment);
-  reader->ReadBytes(data, length_in_bytes);
-
-  // If it is a canonical constant make it one.
-  // When reading a full snapshot we don't need to canonicalize the object
-  // as it would already be a canonical object.
-  // When reading a script snapshot or a message snapshot we always have
-  // to canonicalize the object.
-  if (UntaggedObject::IsCanonical(tags)) {
-    result ^= result.Canonicalize(reader->thread());
-    ASSERT(!result.IsNull());
-    ASSERT(result.IsCanonical());
-  }
-  return result.ptr();
-}
-
-ExternalTypedDataPtr ExternalTypedData::ReadFrom(SnapshotReader* reader,
-                                                 intptr_t object_id,
-                                                 intptr_t tags,
-                                                 Snapshot::Kind kind,
-                                                 bool as_reference) {
-  ASSERT(!Snapshot::IsFull(kind));
-  intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
-  intptr_t length = reader->ReadSmiValue();
-
-  FinalizableData finalizable_data =
-      static_cast<MessageSnapshotReader*>(reader)->finalizable_data()->Take();
-  uint8_t* data = reinterpret_cast<uint8_t*>(finalizable_data.data);
-  ExternalTypedData& obj =
-      ExternalTypedData::ZoneHandle(ExternalTypedData::New(cid, data, length));
-  reader->AddBackRef(object_id, &obj, kIsDeserialized);
-  intptr_t external_size = obj.LengthInBytes();
-  obj.AddFinalizer(finalizable_data.peer, finalizable_data.callback,
-                   external_size);
-  return obj.ptr();
-}
-
-// This function's name can appear in Observatory.
-static void IsolateMessageTypedDataFinalizer(void* isolate_callback_data,
-                                             void* buffer) {
-  free(buffer);
-}
-
-void UntaggedTypedData::WriteTo(SnapshotWriter* writer,
-                                intptr_t object_id,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
-  ASSERT(writer != NULL);
-  intptr_t cid = this->GetClassId();
-  intptr_t length = Smi::Value(this->length());  // In elements.
-  intptr_t external_cid;
-  intptr_t bytes;
-  switch (cid) {
-    case kTypedDataInt8ArrayCid:
-      external_cid = kExternalTypedDataInt8ArrayCid;
-      bytes = length * sizeof(int8_t);
-      break;
-    case kTypedDataUint8ArrayCid:
-      external_cid = kExternalTypedDataUint8ArrayCid;
-      bytes = length * sizeof(uint8_t);
-      break;
-    case kTypedDataUint8ClampedArrayCid:
-      external_cid = kExternalTypedDataUint8ClampedArrayCid;
-      bytes = length * sizeof(uint8_t);
-      break;
-    case kTypedDataInt16ArrayCid:
-      external_cid = kExternalTypedDataInt16ArrayCid;
-      bytes = length * sizeof(int16_t);
-      break;
-    case kTypedDataUint16ArrayCid:
-      external_cid = kExternalTypedDataUint16ArrayCid;
-      bytes = length * sizeof(uint16_t);
-      break;
-    case kTypedDataInt32ArrayCid:
-      external_cid = kExternalTypedDataInt32ArrayCid;
-      bytes = length * sizeof(int32_t);
-      break;
-    case kTypedDataUint32ArrayCid:
-      external_cid = kExternalTypedDataUint32ArrayCid;
-      bytes = length * sizeof(uint32_t);
-      break;
-    case kTypedDataInt64ArrayCid:
-      external_cid = kExternalTypedDataInt64ArrayCid;
-      bytes = length * sizeof(int64_t);
-      break;
-    case kTypedDataUint64ArrayCid:
-      external_cid = kExternalTypedDataUint64ArrayCid;
-      bytes = length * sizeof(uint64_t);
-      break;
-    case kTypedDataFloat32ArrayCid:
-      external_cid = kExternalTypedDataFloat32ArrayCid;
-      bytes = length * sizeof(float);
-      break;
-    case kTypedDataFloat64ArrayCid:
-      external_cid = kExternalTypedDataFloat64ArrayCid;
-      bytes = length * sizeof(double);
-      break;
-    case kTypedDataInt32x4ArrayCid:
-      external_cid = kExternalTypedDataInt32x4ArrayCid;
-      bytes = length * sizeof(int32_t) * 4;
-      break;
-    case kTypedDataFloat32x4ArrayCid:
-      external_cid = kExternalTypedDataFloat32x4ArrayCid;
-      bytes = length * sizeof(float) * 4;
-      break;
-    case kTypedDataFloat64x2ArrayCid:
-      external_cid = kExternalTypedDataFloat64x2ArrayCid;
-      bytes = length * sizeof(double) * 2;
-      break;
-    default:
-      external_cid = kIllegalCid;
-      bytes = 0;
-      UNREACHABLE();
-  }
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  if ((kind == Snapshot::kMessage) &&
-      (static_cast<uint64_t>(bytes) >= FLAG_externalize_typed_data_threshold)) {
-    // Write as external.
-    writer->WriteIndexedObject(external_cid);
-    writer->WriteTags(writer->GetObjectTags(this));
-    writer->Write<ObjectPtr>(this->length());
-    uint8_t* data = reinterpret_cast<uint8_t*>(this->data());
-    void* passed_data = malloc(bytes);
-    memmove(passed_data, data, bytes);
-    static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
-        bytes,
-        passed_data,  // data
-        passed_data,  // peer,
-        IsolateMessageTypedDataFinalizer);
-  } else {
-    // Write as internal.
-    writer->WriteIndexedObject(cid);
-    writer->WriteTags(writer->GetObjectTags(this));
-    writer->Write<ObjectPtr>(this->length());
-    uint8_t* data = reinterpret_cast<uint8_t*>(this->data());
-    writer->Align(Zone::kAlignment);
-    writer->WriteBytes(data, bytes);
-  }
-}
-
-void UntaggedExternalTypedData::WriteTo(SnapshotWriter* writer,
-                                        intptr_t object_id,
-                                        Snapshot::Kind kind,
-                                        bool as_reference) {
-  ASSERT(writer != NULL);
-  intptr_t cid = this->GetClassId();
-  intptr_t length = Smi::Value(this->length());  // In elements.
-  intptr_t bytes;
-  switch (cid) {
-    case kExternalTypedDataInt8ArrayCid:
-      bytes = length * sizeof(int8_t);
-      break;
-    case kExternalTypedDataUint8ArrayCid:
-      bytes = length * sizeof(uint8_t);
-      break;
-    case kExternalTypedDataUint8ClampedArrayCid:
-      bytes = length * sizeof(uint8_t);
-      break;
-    case kExternalTypedDataInt16ArrayCid:
-      bytes = length * sizeof(int16_t);
-      break;
-    case kExternalTypedDataUint16ArrayCid:
-      bytes = length * sizeof(uint16_t);
-      break;
-    case kExternalTypedDataInt32ArrayCid:
-      bytes = length * sizeof(int32_t);
-      break;
-    case kExternalTypedDataUint32ArrayCid:
-      bytes = length * sizeof(uint32_t);
-      break;
-    case kExternalTypedDataInt64ArrayCid:
-      bytes = length * sizeof(int64_t);
-      break;
-    case kExternalTypedDataUint64ArrayCid:
-      bytes = length * sizeof(uint64_t);
-      break;
-    case kExternalTypedDataFloat32ArrayCid:
-      bytes = length * sizeof(float);  // NOLINT.
-      break;
-    case kExternalTypedDataFloat64ArrayCid:
-      bytes = length * sizeof(double);  // NOLINT.
-      break;
-    case kExternalTypedDataInt32x4ArrayCid:
-      bytes = length * sizeof(int32_t) * 4;
-      break;
-    case kExternalTypedDataFloat32x4ArrayCid:
-      bytes = length * sizeof(float) * 4;
-      break;
-    case kExternalTypedDataFloat64x2ArrayCid:
-      bytes = length * sizeof(double) * 2;
-      break;
-    default:
-      bytes = 0;
-      UNREACHABLE();
-  }
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write as external.
-  writer->WriteIndexedObject(cid);
-  writer->WriteTags(writer->GetObjectTags(this));
-  writer->Write<ObjectPtr>(this->length());
-  uint8_t* data = reinterpret_cast<uint8_t*>(data_);
-  void* passed_data = malloc(bytes);
-  memmove(passed_data, data, bytes);
-  static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
-      bytes,
-      passed_data,  // data
-      passed_data,  // peer,
-      IsolateMessageTypedDataFinalizer);
-}
-
-void UntaggedTypedDataView::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  // Views have always a backing store.
-  ASSERT(typed_data() != Object::null());
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(GetClassId());
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write members.
-  writer->Write<ObjectPtr>(offset_in_bytes());
-  writer->Write<ObjectPtr>(length());
-  writer->WriteObjectImpl(typed_data(), as_reference);
-}
-
-TypedDataViewPtr TypedDataView::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  auto& typed_data = *reader->TypedDataBaseHandle();
-  const classid_t cid = UntaggedObject::ClassIdTag::decode(tags);
-
-  auto& view = *reader->TypedDataViewHandle();
-  view = TypedDataView::New(cid);
-  reader->AddBackRef(object_id, &view, kIsDeserialized);
-
-  const intptr_t offset_in_bytes = reader->ReadSmiValue();
-  const intptr_t length = reader->ReadSmiValue();
-  typed_data ^= reader->ReadObjectImpl(as_reference);
-  view.InitializeWith(typed_data, offset_in_bytes, length);
-
-  return view.ptr();
-}
-
-CapabilityPtr Capability::ReadFrom(SnapshotReader* reader,
-                                   intptr_t object_id,
-                                   intptr_t tags,
-                                   Snapshot::Kind kind,
-                                   bool as_reference) {
-  uint64_t id = reader->Read<uint64_t>();
-
-  Capability& result =
-      Capability::ZoneHandle(reader->zone(), Capability::New(id));
-  reader->AddBackRef(object_id, &result, kIsDeserialized);
-  return result.ptr();
-}
-
-void UntaggedCapability::WriteTo(SnapshotWriter* writer,
-                                 intptr_t object_id,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kCapabilityCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  writer->Write<uint64_t>(id_);
-}
-
-SendPortPtr SendPort::ReadFrom(SnapshotReader* reader,
-                               intptr_t object_id,
-                               intptr_t tags,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  ASSERT(kind == Snapshot::kMessage);
-
-  uint64_t id = reader->Read<uint64_t>();
-  uint64_t origin_id = reader->Read<uint64_t>();
-
-  SendPort& result =
-      SendPort::ZoneHandle(reader->zone(), SendPort::New(id, origin_id));
-  reader->AddBackRef(object_id, &result, kIsDeserialized);
-  return result.ptr();
-}
-
-void UntaggedSendPort::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kSendPortCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  writer->Write<uint64_t>(id_);
-  writer->Write<uint64_t>(origin_id_);
-}
-
-TransferableTypedDataPtr TransferableTypedData::ReadFrom(SnapshotReader* reader,
-                                                         intptr_t object_id,
-                                                         intptr_t tags,
-                                                         Snapshot::Kind kind,
-                                                         bool as_reference) {
-  ASSERT(reader != nullptr);
-
-  ASSERT(!Snapshot::IsFull(kind));
-  const intptr_t length = reader->Read<int64_t>();
-
-  const FinalizableData finalizable_data =
-      static_cast<MessageSnapshotReader*>(reader)->finalizable_data()->Take();
-  uint8_t* data = reinterpret_cast<uint8_t*>(finalizable_data.data);
-  auto& transferableTypedData = TransferableTypedData::ZoneHandle(
-      reader->zone(), TransferableTypedData::New(data, length));
-  reader->AddBackRef(object_id, &transferableTypedData, kIsDeserialized);
-  return transferableTypedData.ptr();
-}
-
-void UntaggedTransferableTypedData::WriteTo(SnapshotWriter* writer,
-                                            intptr_t object_id,
-                                            Snapshot::Kind kind,
-                                            bool as_reference) {
-  ASSERT(writer != nullptr);
-  ASSERT(GetClassId() == kTransferableTypedDataCid);
-  void* peer = writer->thread()->heap()->GetPeer(ObjectPtr(this));
-  // Assume that object's Peer is only used to track transferrability state.
-  ASSERT(peer != nullptr);
-  TransferableTypedDataPeer* tpeer =
-      reinterpret_cast<TransferableTypedDataPeer*>(peer);
-  intptr_t length = tpeer->length();  // In bytes.
-  void* data = tpeer->data();
-  if (data == nullptr) {
-    writer->SetWriteException(
-        Exceptions::kArgument,
-        "Illegal argument in isolate message"
-        " : (TransferableTypedData has been transferred already)");
-    return;
-  }
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  writer->WriteIndexedObject(GetClassId());
-  writer->WriteTags(writer->GetObjectTags(this));
-  writer->Write<int64_t>(length);
-
-  static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
-      length, data, tpeer,
-      // Finalizer does nothing - in case of failure to serialize,
-      // [data] remains wrapped in sender's [TransferableTypedData].
-      [](void* data, void* peer) {},
-      // This is invoked on successful serialization of the message
-      [](void* data, void* peer) {
-        TransferableTypedDataPeer* tpeer =
-            reinterpret_cast<TransferableTypedDataPeer*>(peer);
-        tpeer->handle()->EnsureFreedExternal(IsolateGroup::Current());
-        tpeer->ClearData();
-      });
-}
-
-RegExpPtr RegExp::ReadFrom(SnapshotReader* reader,
-                           intptr_t object_id,
-                           intptr_t tags,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
-  ASSERT(reader != NULL);
-  // Allocate RegExp object.
-  RegExp& regex =
-      RegExp::ZoneHandle(reader->zone(), RegExp::New(reader->zone()));
-  reader->AddBackRef(object_id, &regex, kIsDeserialized);
-
-  // Read and Set all the other fields.
-  *reader->ArrayHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-  regex.set_capture_name_map(*reader->ArrayHandle());
-  *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-  regex.set_pattern(*reader->StringHandle());
-
-  regex.StoreNonPointer(&regex.untag()->num_bracket_expressions_,
-                        reader->Read<int32_t>());
-  regex.StoreNonPointer(&regex.untag()->num_one_byte_registers_,
-                        reader->Read<int32_t>());
-  regex.StoreNonPointer(&regex.untag()->num_two_byte_registers_,
-                        reader->Read<int32_t>());
-  regex.StoreNonPointer(&regex.untag()->type_flags_, reader->Read<int8_t>());
-  return regex.ptr();
-}
-
-void UntaggedRegExp::WriteTo(SnapshotWriter* writer,
-                             intptr_t object_id,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kRegExpCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the other fields.
-  writer->WriteObjectImpl(capture_name_map(), kAsInlinedObject);
-  writer->WriteObjectImpl(pattern(), kAsInlinedObject);
-  writer->Write<int32_t>(num_bracket_expressions_);
-  writer->Write<int32_t>(num_one_byte_registers_);
-  writer->Write<int32_t>(num_two_byte_registers_);
-  writer->Write<int8_t>(type_flags_);
-}
-
-WeakPropertyPtr WeakProperty::ReadFrom(SnapshotReader* reader,
-                                       intptr_t object_id,
-                                       intptr_t tags,
-                                       Snapshot::Kind kind,
-                                       bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate the weak property object.
-  WeakProperty& weak_property =
-      WeakProperty::ZoneHandle(reader->zone(), WeakProperty::New());
-  reader->AddBackRef(object_id, &weak_property, kIsDeserialized);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(
-      weak_property, weak_property.ptr()->untag()->from(),
-      weak_property.ptr()->untag()->to(), kAsReference);
-
-  return weak_property.ptr();
-}
-
-void UntaggedWeakProperty::WriteTo(SnapshotWriter* writer,
-                                   intptr_t object_id,
-                                   Snapshot::Kind kind,
-                                   bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kWeakPropertyCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-}  // namespace dart
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 856d43f..b23182e 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -4,6 +4,7 @@
 
 #include "vm/runtime_entry.h"
 
+#include "platform/thread_sanitizer.h"
 #include "vm/code_descriptors.h"
 #include "vm/code_patcher.h"
 #include "vm/compiler/api/deopt_id.h"
@@ -757,8 +758,9 @@
   auto& instance_delayed_type_arguments = TypeArguments::Handle(zone);
   if (instance_class.IsClosureClass()) {
     const auto& closure = Closure::Cast(instance);
-    const auto& closure_function = Function::Handle(zone, closure.function());
-    instance_class_id_or_signature = closure_function.signature();
+    const auto& function = Function::Handle(zone, closure.function());
+    instance_class_id_or_signature = function.signature();
+    ASSERT(instance_class_id_or_signature.IsFunctionType());
     instance_type_arguments = closure.instantiator_type_arguments();
     instance_parent_function_type_arguments = closure.function_type_arguments();
     instance_delayed_type_arguments = closure.delayed_type_arguments();
@@ -827,7 +829,7 @@
         new_cache.WriteEntryToBuffer(zone, &buffer, colliding_index, "      ");
         OS::PrintErr("%s\n", buffer.buffer());
       }
-      if (!IsolateGroup::AreIsolateGroupsEnabled()) {
+      if (!FLAG_enable_isolate_groups) {
         FATAL("Duplicate subtype test cache entry");
       }
       if (old_result.ptr() != result.ptr()) {
@@ -1190,7 +1192,7 @@
   const Code& target_code = Code::Handle(zone, target_function.EnsureHasCode());
   // Before patching verify that we are not repeatedly patching to the same
   // target.
-  ASSERT(IsolateGroup::AreIsolateGroupsEnabled() ||
+  ASSERT(FLAG_enable_isolate_groups ||
          target_code.ptr() != CodePatcher::GetStaticCallTargetAt(
                                   caller_frame->pc(), caller_code));
   if (target_code.ptr() !=
@@ -1613,6 +1615,7 @@
 enum class MissHandler {
   kInlineCacheMiss,
   kSwitchableCallMiss,
+  kFixCallersTargetMonomorphic,
 };
 
 // Handles updating of type feedback and possible patching of instance calls.
@@ -2132,12 +2135,21 @@
                                      const Function& target) {
   // In JIT we can have two different miss handlers to which we return slightly
   // differently.
-  if (miss_handler_ == MissHandler::kSwitchableCallMiss) {
-    arguments_.SetArgAt(0, stub);  // Second return value.
-    arguments_.SetReturn(data);
-  } else {
-    ASSERT(miss_handler_ == MissHandler::kInlineCacheMiss);
-    arguments_.SetReturn(target);
+  switch (miss_handler_) {
+    case MissHandler::kSwitchableCallMiss: {
+      arguments_.SetArgAt(0, stub);  // Second return value.
+      arguments_.SetReturn(data);
+      break;
+    }
+    case MissHandler::kFixCallersTargetMonomorphic: {
+      arguments_.SetArgAt(1, data);  // Second return value.
+      arguments_.SetReturn(stub);
+      break;
+    }
+    case MissHandler::kInlineCacheMiss: {
+      arguments_.SetReturn(target);
+      break;
+    }
   }
 }
 
@@ -2954,8 +2966,7 @@
   // With isolate groups enabled, it is possible that the target code
   // has been deactivated just now(as a result of re-optimizatin for example),
   // which will result in another run through FixCallersTarget.
-  ASSERT(!current_target_code.IsDisabled() ||
-         IsolateGroup::AreIsolateGroupsEnabled());
+  ASSERT(!current_target_code.IsDisabled() || FLAG_enable_isolate_groups);
   arguments.SetReturn(current_target_code);
 #else
   UNREACHABLE();
@@ -2964,49 +2975,25 @@
 
 // The caller must be a monomorphic call from unoptimized code.
 // Patch call to point to new target.
-DEFINE_RUNTIME_ENTRY(FixCallersTargetMonomorphic, 0) {
+DEFINE_RUNTIME_ENTRY(FixCallersTargetMonomorphic, 2) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames, thread,
-                              StackFrameIterator::kNoCrossThreadIteration);
-  StackFrame* frame = iterator.NextFrame();
-  ASSERT(frame != NULL);
-  while (frame->IsStubFrame() || frame->IsExitFrame()) {
-    frame = iterator.NextFrame();
-    ASSERT(frame != NULL);
-  }
-  if (frame->IsEntryFrame()) {
-    // Since function's current code is always unpatched, the entry frame always
-    // calls to unpatched code.
-    UNREACHABLE();
-  }
-  ASSERT(frame->IsDartFrame());
-  const Code& caller_code = Code::Handle(zone, frame->LookupDartCode());
-  RELEASE_ASSERT(!caller_code.is_optimized());
+  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+  const Array& switchable_call_data =
+      Array::CheckedHandle(zone, arguments.ArgAt(1));
 
-  Object& cache = Object::Handle(zone);
-  const Code& old_target_code = Code::Handle(
-      zone, CodePatcher::GetInstanceCallAt(frame->pc(), caller_code, &cache));
-  const Function& target_function =
-      Function::Handle(zone, old_target_code.function());
-  const Code& current_target_code =
-      Code::Handle(zone, target_function.EnsureHasCode());
-  CodePatcher::PatchInstanceCallAt(frame->pc(), caller_code, cache,
-                                   current_target_code);
-  if (FLAG_trace_patching) {
-    OS::PrintErr(
-        "FixCallersTargetMonomorphic: caller %#" Px
-        " "
-        "target '%s' -> %#" Px " (%s)\n",
-        frame->pc(), target_function.ToFullyQualifiedCString(),
-        current_target_code.EntryPoint(),
-        current_target_code.is_optimized() ? "optimized" : "unoptimized");
-  }
-  // With isolate groups enabled, it is possible that the target code
-  // has been deactivated just now(as a result of re-optimizatin for example),
-  // which will result in another run through FixCallersTarget.
-  ASSERT(!current_target_code.IsDisabled() ||
-         IsolateGroup::AreIsolateGroupsEnabled());
-  arguments.SetReturn(current_target_code);
+  DartFrameIterator iterator(thread,
+                             StackFrameIterator::kNoCrossThreadIteration);
+  StackFrame* caller_frame = iterator.NextFrame();
+  const auto& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
+  const auto& caller_function =
+      Function::Handle(zone, caller_frame->LookupDartFunction());
+
+  GrowableArray<const Instance*> caller_arguments(1);
+  caller_arguments.Add(&receiver);
+  PatchableCallHandler handler(
+      thread, caller_arguments, MissHandler::kFixCallersTargetMonomorphic,
+      arguments, caller_frame, caller_code, caller_function);
+  handler.ResolveSwitchAndReturn(switchable_call_data);
 #else
   UNREACHABLE();
 #endif
@@ -3679,10 +3666,29 @@
   TRACE_RUNTIME_CALL("AllocateHandle returning %p", return_value);
   return return_value;
 }
+
 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
     AllocateHandle,
     1,
     false /* is_float */,
     reinterpret_cast<RuntimeFunction>(&DLRT_AllocateHandle));
 
+#if defined(USING_THREAD_SANITIZER)
+#define TSAN_ACQUIRE reinterpret_cast<RuntimeFunction>(&__tsan_acquire)
+#define TSAN_RELEASE reinterpret_cast<RuntimeFunction>(&__tsan_release)
+#else
+#define TSAN_ACQUIRE nullptr
+#define TSAN_RELEASE nullptr
+#endif
+
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(TsanLoadAcquire,
+                              /*argument_count=*/1,
+                              /*is_float=*/false,
+                              TSAN_ACQUIRE);
+
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(TsanStoreRelease,
+                              /*argument_count=*/1,
+                              /*is_float=*/false,
+                              TSAN_RELEASE);
+
 }  // namespace dart
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index 69b2872..f22572c 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -96,7 +96,9 @@
   V(void, ExitSafepoint)                                                       \
   V(ApiLocalScope*, EnterHandleScope, Thread*)                                 \
   V(void, ExitHandleScope, Thread*)                                            \
-  V(LocalHandle*, AllocateHandle, ApiLocalScope*)
+  V(LocalHandle*, AllocateHandle, ApiLocalScope*)                              \
+  V(void, TsanLoadAcquire, uword /* address */)                                \
+  V(void, TsanStoreRelease, uword /* address */)
 
 }  // namespace dart
 
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index c643b46..b2545cf 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -7,6 +7,7 @@
 
 #include "vm/compiler/backend/slot.h"
 #include "vm/object.h"
+#include "vm/object_store.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
 
@@ -194,7 +195,8 @@
       &Slot::GetContextVariableSlotFor(Thread::Current(), *variable));
 }
 
-VariableIndex LocalScope::AllocateVariables(VariableIndex first_parameter_index,
+VariableIndex LocalScope::AllocateVariables(const Function& function,
+                                            VariableIndex first_parameter_index,
                                             int num_parameters,
                                             VariableIndex first_local_index,
                                             LocalScope* context_owner,
@@ -252,8 +254,30 @@
   if (chained_future != nullptr) {
     AllocateContextVariable(chained_future, &context_owner);
     *found_captured_variables = true;
-    ASSERT(chained_future->index().value() ==
-           chained_future->expected_context_index());
+    // Remember context indices of _future variables in _Future.timeout and
+    // Future.wait. They are used while collecting async stack traces.
+    if (function.recognized_kind() == MethodRecognizer::kFutureTimeout) {
+#ifdef DEBUG
+      auto old_value = IsolateGroup::Current()
+                           ->object_store()
+                           ->future_timeout_future_index();
+      ASSERT(old_value == Object::null() ||
+             Smi::Value(old_value) == chained_future->index().value());
+#endif  // DEBUG
+      IsolateGroup::Current()->object_store()->set_future_timeout_future_index(
+          Smi::Handle(Smi::New(chained_future->index().value())));
+    } else if (function.recognized_kind() == MethodRecognizer::kFutureWait) {
+#ifdef DEBUG
+      auto old_value =
+          IsolateGroup::Current()->object_store()->future_wait_future_index();
+      ASSERT(old_value == Object::null() ||
+             Smi::Value(old_value) == chained_future->index().value());
+#endif  // DEBUG
+      IsolateGroup::Current()->object_store()->set_future_wait_future_index(
+          Smi::Handle(Smi::New(chained_future->index().value())));
+    } else {
+      UNREACHABLE();
+    }
   }
   if (is_sync != nullptr) {
     AllocateContextVariable(is_sync, &context_owner);
@@ -312,7 +336,7 @@
     // No parameters in children scopes.
     const int num_parameters_in_child = 0;
     VariableIndex child_next_index = child->AllocateVariables(
-        dummy_parameter_index, num_parameters_in_child, next_index,
+        function, dummy_parameter_index, num_parameters_in_child, next_index,
         context_owner, found_captured_variables);
     if (child_next_index.value() < min_index.value()) {
       min_index = child_next_index;
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index 593e186..ff80167 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -94,7 +94,6 @@
         covariance_mode_(kNotCovariant),
         is_late_(false),
         is_chained_future_(false),
-        expected_context_index_(-1),
         late_init_offset_(0),
         type_check_mode_(kDoTypeCheck),
         index_() {
@@ -136,11 +135,6 @@
   bool is_chained_future() const { return is_chained_future_; }
   void set_is_chained_future() { is_chained_future_ = true; }
 
-  intptr_t expected_context_index() const { return expected_context_index_; }
-  void set_expected_context_index(int index) {
-    expected_context_index_ = index;
-  }
-
   intptr_t late_init_offset() const { return late_init_offset_; }
   void set_late_init_offset(intptr_t late_init_offset) {
     late_init_offset_ = late_init_offset;
@@ -244,7 +238,6 @@
   CovarianceMode covariance_mode_;
   bool is_late_;
   bool is_chained_future_;
-  intptr_t expected_context_index_;
   intptr_t late_init_offset_;
   TypeCheckMode type_check_mode_;
   VariableIndex index_;
@@ -476,7 +469,8 @@
   // Two locals in different sibling scopes may share the same frame slot.
   //
   // Return the index of the next available frame slot.
-  VariableIndex AllocateVariables(VariableIndex first_parameter_index,
+  VariableIndex AllocateVariables(const Function& function,
+                                  VariableIndex first_parameter_index,
                                   int num_parameters,
                                   VariableIndex first_local_index,
                                   LocalScope* context_owner,
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 238bc27..b9552b5 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -30,6 +30,7 @@
 #include "vm/malloc_hooks.h"
 #include "vm/message.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/native_arguments.h"
 #include "vm/native_entry.h"
 #include "vm/native_symbol.h"
@@ -1018,9 +1019,9 @@
     message.value.as_array.length = 2;
     message.value.as_array.values = elements;
 
-    ApiMessageWriter writer;
-    std::unique_ptr<Message> msg = writer.WriteCMessage(
-        &message, ServiceIsolate::Port(), Message::kNormalPriority);
+    std::unique_ptr<Message> msg =
+        WriteApiMessage(thread->zone(), &message, ServiceIsolate::Port(),
+                        Message::kNormalPriority);
     if (msg == nullptr) {
       result = false;
     } else {
@@ -1188,9 +1189,10 @@
   json_cobj.value.as_string = const_cast<char*>(event->ToCString());
   list_values[1] = &json_cobj;
 
-  ApiMessageWriter writer;
-  std::unique_ptr<Message> msg = writer.WriteCMessage(
-      &list_cobj, ServiceIsolate::Port(), Message::kNormalPriority);
+  AllocOnlyStackZone zone;
+  std::unique_ptr<Message> msg =
+      WriteApiMessage(zone.GetZone(), &list_cobj, ServiceIsolate::Port(),
+                      Message::kNormalPriority);
   if (msg != nullptr) {
     PortMap::PostMessage(std::move(msg));
   }
@@ -2017,8 +2019,7 @@
   if (message->IsRaw()) {
     return message->raw_obj();
   } else {
-    MessageSnapshotReader reader(message, thread);
-    return reader.ReadObject();
+    return ReadMessage(thread, message);
   }
 }
 
@@ -5211,7 +5212,12 @@
   }
   {
     JSONArray internals(&map, "Map");
-    DEFINE_ADD_VALUE_F_CID(LinkedHashMap)
+    CLASS_LIST_MAPS(DEFINE_ADD_VALUE_F_CID)
+  }
+
+  {
+    JSONArray internals(&map, "Set");
+    CLASS_LIST_SETS(DEFINE_ADD_VALUE_F_CID)
   }
 #define DEFINE_ADD_MAP_KEY(clazz)                                              \
   {                                                                            \
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index e178c6a..4c87d36 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 48
+#define SERVICE_PROTOCOL_MINOR_VERSION 50
 
 class Array;
 class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 708f581..6e29e0f 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.48
+# Dart VM Service Protocol 3.49
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.48_ of the Dart VM Service Protocol. This
+This document describes of _version 3.49_ 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.
@@ -117,6 +117,7 @@
   - [NativeFunction](#nativefunction)
   - [Null](#null)
   - [Object](#object)
+  - [Parameter](#parameter)[
   - [PortList](#portlist)
   - [ReloadReport](#reloadreport)
   - [Response](#response)
@@ -139,6 +140,7 @@
   - [TimelineFlags](#timelineflags)
   - [Timestamp](#timestamp)
   - [TypeArguments](#typearguments)
+  - [TypeParameters](#typeparameters)[
   - [UresolvedSourceLocation](#unresolvedsourcelocation)
   - [Version](#version)
   - [VM](#vm)
@@ -1477,7 +1479,7 @@
 VM | VMUpdate, VMFlagUpdate
 Isolate | IsolateStart, IsolateRunnable, IsolateExit, IsolateUpdate, IsolateReload, ServiceExtensionAdded
 Debug | PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted, PauseException, PausePostRequest, Resume, BreakpointAdded, BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
-Profiler | UserTagChanged
+Profiler | CpuSamples, UserTagChanged
 GC | GC
 Extension | Extension
 Timeline | TimelineEvents, TimelineStreamsSubscriptionUpdate
@@ -1694,6 +1696,11 @@
 
   // The library which contains this class.
   @Library library;
+
+  // The type parameters for the class.
+  //
+  // Provided if the class is generic.
+  @Instance[] typeParameters [optional];
 }
 ```
 
@@ -1710,6 +1717,11 @@
   // The library which contains this class.
   @Library library;
 
+  // The type parameters for the class.
+  //
+  // Provided if the class is generic.
+  @Instance[] typeParameters [optional];
+
   // The error which occurred during class finalization, if it exists.
   @Error error [optional];
 
@@ -2161,6 +2173,9 @@
 
   // The previous UserTag label.
   string previousTag [optional];
+
+  // A CPU profile containing recent samples.
+  CpuSamples cpuSamples [optional];
 }
 ```
 
@@ -2274,6 +2289,9 @@
 
   // Notification that the UserTag for an isolate has been changed.
   UserTagChanged,
+
+  // A block of recently collected CPU samples.
+  CpuSamples,
 }
 ```
 
@@ -2421,6 +2439,9 @@
   // Is this function const?
   bool const;
 
+  // Is this function implicitly defined (e.g., implicit getter/setter)?
+  bool implicit;
+
   // The location of this function in the source code.
   SourceLocation location [optional];
 }
@@ -2443,9 +2464,15 @@
   // Is this function const?
   bool const;
 
+  // Is this function implicitly defined (e.g., implicit getter/setter)?
+  bool implicit;
+
   // The location of this function in the source code.
   SourceLocation location [optional];
 
+  // The signature of the function.
+  @Instance signature;
+
   // The compiled code associated with this function.
   @Code code [optional];
 }
@@ -2523,12 +2550,29 @@
   //   Type
   @Class typeClass [optional];
 
-  // The parameterized class of a type parameter:
+  // The parameterized class of a type parameter.
   //
   // Provided for instance kinds:
   //   TypeParameter
   @Class parameterizedClass [optional];
 
+  // The return type of a function.
+  //
+  // Provided for instance kinds:
+  //   FunctionType
+  @Instance returnType [optional];
+
+  // The list of parameter types for a function.
+  //
+  // Provided for instance kinds:
+  //   FunctionType
+  Parameter[] parameters [optional];
+
+  // The type parameters for a function.
+  //
+  // Provided for instance kinds:
+  //   FunctionType
+  @Instance[] typeParameters [optional];
 
   // The pattern of a RegExp instance.
   //
@@ -2688,6 +2732,24 @@
   //   TypeParameter
   @Class parameterizedClass [optional];
 
+  // The return type of a function.
+  //
+  // Provided for instance kinds:
+  //   FunctionType
+  @Instance returnType [optional];
+
+  // The list of parameter types for a function.
+  //
+  // Provided for instance kinds:
+  //   FunctionType
+  Parameter[] parameters [optional];
+
+  // The type parameters for a function.
+  //
+  // Provided for instance kinds:
+  //   FunctionType
+  @Instance[] typeParameters [optional];
+
   // The fields of this Instance.
   BoundField[] fields [optional];
 
@@ -2905,6 +2967,9 @@
   // An instance of the Dart class TypeRef.
   TypeRef,
 
+  // An instance of the Dart class FunctionType.
+  FunctionType,
+
   // An instance of the Dart class BoundedType.
   BoundedType,
 
@@ -3356,7 +3421,29 @@
 }
 ```
 
-An _Object_ is a  persistent object that is owned by some isolate.
+An _Object_ is a persistent object that is owned by some isolate.
+
+### Parameter
+
+```
+class Parameter {
+  // The type of the parameter.
+  @Instance parameterType;
+
+  // Represents whether or not this parameter is fixed or optional.
+  bool fixed;
+
+  // The name of a named optional parameter.
+  string name [optional];
+
+  // Whether or not this named optional parameter is marked as required.
+  bool required [optional];
+}
+```
+
+A _Parameter_ is a representation of a function parameter.
+
+See [Instance](#instance).
 
 ### PortList
 
@@ -3908,6 +3995,24 @@
 A _TypeArguments_ object represents the type argument vector for some
 instantiated generic type.
 
+### TypeParameters
+
+```
+class TypeParameters {
+  // The names of the type parameters.
+  string[] names;
+
+  // The bounds set on each type parameter.
+  @TypeArguments bounds;
+
+  // The default types for each type parameter.
+  @TypeArguments defaults;
+}
+```
+
+A _TypeParameters_ object represents the type argument vector for some
+uninstantiated generic type.
+
 ### UnresolvedSourceLocation
 
 ```
@@ -4069,5 +4174,7 @@
 3.46 | Moved `sourceLocation` property into reference types for `Class`, `Field`, and `Function`.
 3.47 | Added `shows` and `hides` properties to `LibraryDependency`.
 3.48 | Added `Profiler` stream, `UserTagChanged` event kind, and `updatedTag` and `previousTag` properties to `Event`.
+3.49 | Added `CpuSamples` event kind, and `cpuSamples` property to `Event`.
+3.50 | Added `returnType`, `parameters`, and `typeParameters` to `@Instance`, and `implicit` to `@Function`. Added `Parameter` type.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index f8ab174..85740cf 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -64,7 +64,8 @@
            event_kind == ServiceEvent::kNone ||
            // VM service can print Observatory information to Stdout or Stderr
            // which are embedder streams.
-           event_kind == ServiceEvent::kEmbedder)));
+           event_kind == ServiceEvent::kEmbedder ||
+           event_kind == ServiceEvent::kCpuSamples)));
 
   if ((event_kind == ServiceEvent::kPauseStart) ||
       (event_kind == ServiceEvent::kPauseExit)) {
@@ -141,6 +142,8 @@
       return "TimelineStreamSubscriptionsUpdate";
     case kUserTagChanged:
       return "UserTagChanged";
+    case kCpuSamples:
+      return "CpuSamples";
     default:
       UNREACHABLE();
       return "Unknown";
@@ -193,6 +196,7 @@
     case kEmbedder:
       return nullptr;
 
+    case kCpuSamples:
     case kUserTagChanged:
       return &Service::profiler_stream;
 
@@ -300,6 +304,11 @@
     js->AppendSerializedObject("extensionData",
                                extension_event_.event_data->ToCString());
   }
+
+  if (kind() == kCpuSamples) {
+    JSONObject cpu_profile(&jsobj, "cpuSamples");
+    cpu_profile_->PrintProfileJSON(&cpu_profile, false);
+  }
 }
 
 void ServiceEvent::PrintJSONHeader(JSONObject* jsobj) const {
diff --git a/runtime/vm/service_event.h b/runtime/vm/service_event.h
index 3b8de0e..4c0efdd 100644
--- a/runtime/vm/service_event.h
+++ b/runtime/vm/service_event.h
@@ -7,6 +7,7 @@
 
 #include "vm/globals.h"
 #include "vm/heap/heap.h"
+#include "vm/profiler_service.h"
 
 namespace dart {
 
@@ -62,6 +63,8 @@
 
     kUserTagChanged,
 
+    kCpuSamples,
+
     kIllegal,
   };
 
@@ -213,6 +216,9 @@
     timeline_event_block_ = block;
   }
 
+  Profile* cpu_profile() const { return cpu_profile_; }
+  void set_cpu_profile(Profile* profile) { cpu_profile_ = profile; }
+
   void PrintJSON(JSONStream* js) const;
 
   void PrintJSONHeader(JSONObject* jsobj) const;
@@ -246,6 +252,7 @@
   intptr_t bytes_length_;
   LogRecord log_record_;
   ExtensionEvent extension_event_;
+  Profile* cpu_profile_;
   int64_t timestamp_;
 };
 
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index c243b02b..d840e7b 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -12,6 +12,7 @@
 #include "vm/lockers.h"
 #include "vm/message.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/native_arguments.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
@@ -91,9 +92,8 @@
       sp, VM_SERVICE_SERVER_INFO_MESSAGE_ID, false /* ignored */,
       Bool::Handle() /* ignored */));
   ASSERT(!message.IsNull());
-  MessageWriter writer(false);
-  PortMap::PostMessage(
-      writer.WriteMessage(message, port_, Message::kNormalPriority));
+  PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, message,
+                                    port_, Message::kNormalPriority));
 }
 
 void ServiceIsolate::ControlWebServer(const SendPort& sp,
@@ -102,9 +102,8 @@
   const Array& message = Array::Handle(MakeServerControlMessage(
       sp, VM_SERVICE_WEB_SERVER_CONTROL_MESSAGE_ID, enable, silenceOutput));
   ASSERT(!message.IsNull());
-  MessageWriter writer(false);
-  PortMap::PostMessage(
-      writer.WriteMessage(message, port_, Message::kNormalPriority));
+  PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, message,
+                                    port_, Message::kNormalPriority));
 }
 
 void ServiceIsolate::SetServerAddress(const char* address) {
@@ -223,14 +222,13 @@
   const Array& list = Array::Handle(MakeServiceControlMessage(
       Dart_GetMainPortId(), VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID, name));
   ASSERT(!list.IsNull());
-  MessageWriter writer(false);
   if (FLAG_trace_service) {
     OS::PrintErr(DART_VM_SERVICE_ISOLATE_NAME ": Isolate %s %" Pd64
                                               " registered.\n",
                  name.ToCString(), Dart_GetMainPortId());
   }
-  return PortMap::PostMessage(
-      writer.WriteMessage(list, port_, Message::kNormalPriority));
+  return PortMap::PostMessage(WriteMessage(
+      /* can_send_any_object */ false, list, port_, Message::kNormalPriority));
 }
 
 bool ServiceIsolate::SendIsolateShutdownMessage() {
@@ -249,14 +247,13 @@
   const Array& list = Array::Handle(MakeServiceControlMessage(
       Dart_GetMainPortId(), VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID, name));
   ASSERT(!list.IsNull());
-  MessageWriter writer(false);
   if (FLAG_trace_service) {
     OS::PrintErr(DART_VM_SERVICE_ISOLATE_NAME ": Isolate %s %" Pd64
                                               " deregistered.\n",
                  name.ToCString(), Dart_GetMainPortId());
   }
-  return PortMap::PostMessage(
-      writer.WriteMessage(list, port_, Message::kNormalPriority));
+  return PortMap::PostMessage(WriteMessage(
+      /* can_send_any_object */ false, list, port_, Message::kNormalPriority));
 }
 
 void ServiceIsolate::SendServiceExitMessage() {
@@ -278,9 +275,9 @@
   message.value.as_array.length = 1;
   message.value.as_array.values = values;
 
-  ApiMessageWriter writer;
-  PortMap::PostMessage(
-      writer.WriteCMessage(&message, port_, Message::kNormalPriority));
+  AllocOnlyStackZone zone;
+  PortMap::PostMessage(WriteApiMessage(zone.GetZone(), &message, port_,
+                                       Message::kNormalPriority));
 }
 
 void ServiceIsolate::SetServicePort(Dart_Port port) {
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 7dec0a8..2800565 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -14,6 +14,7 @@
 #include "vm/globals.h"
 #include "vm/heap/safepoint.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/object_id_ring.h"
 #include "vm/os.h"
 #include "vm/port.h"
@@ -50,8 +51,7 @@
       response_obj = message->raw_obj();
     } else {
       Thread* thread = Thread::Current();
-      MessageSnapshotReader reader(message.get(), thread);
-      response_obj = reader.ReadObject();
+      response_obj = ReadMessage(thread, message.get());
     }
     if (response_obj.IsString()) {
       String& response = String::Handle();
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index f849156..f9b3cdc 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -5,228 +5,10 @@
 #include "vm/snapshot.h"
 
 #include "platform/assert.h"
-#include "vm/bootstrap.h"
-#include "vm/class_finalizer.h"
 #include "vm/dart.h"
-#include "vm/exceptions.h"
-#include "vm/heap/heap.h"
-#include "vm/longjump.h"
-#include "vm/message.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/snapshot_ids.h"
-#include "vm/stub_code.h"
-#include "vm/symbols.h"
-#include "vm/timeline.h"
-#include "vm/type_testing_stubs.h"
-#include "vm/version.h"
-
-// We currently only expect the Dart mutator to read snapshots.
-#define ASSERT_NO_SAFEPOINT_SCOPE()                                            \
-  isolate()->AssertCurrentThreadIsMutator();                                   \
-  ASSERT(thread()->no_safepoint_scope_depth() != 0)
 
 namespace dart {
 
-static const int kNumInitialReferences = 32;
-
-static bool IsSingletonClassId(intptr_t class_id) {
-  // Check if this is a singleton object class which is shared by all isolates.
-  return ((class_id >= kClassCid && class_id <= kUnwindErrorCid) ||
-          (class_id == kTypeArgumentsCid) ||
-          (class_id >= kNullCid && class_id <= kVoidCid));
-}
-
-static bool IsBootstrapedClassId(intptr_t class_id) {
-  // Check if this is a class which is created during bootstrapping.
-  return (class_id == kObjectCid ||
-          (class_id >= kInstanceCid && class_id <= kUserTagCid) ||
-          class_id == kArrayCid || class_id == kImmutableArrayCid ||
-          IsStringClassId(class_id) || IsTypedDataClassId(class_id) ||
-          IsExternalTypedDataClassId(class_id) ||
-          IsTypedDataViewClassId(class_id) || class_id == kNullCid ||
-          class_id == kNeverCid || class_id == kTransferableTypedDataCid);
-}
-
-static bool IsObjectStoreTypeId(intptr_t index) {
-  // Check if this is a type which is stored in the object store.
-  static_assert(kFirstTypeArgumentsSnapshotId == kLastTypeSnapshotId + 1,
-                "Type and type arguments snapshot ids should be adjacent");
-  return index >= kFirstTypeSnapshotId && index <= kLastTypeArgumentsSnapshotId;
-}
-
-static bool IsSplitClassId(intptr_t class_id) {
-  // Return whether this class is serialized in two steps: first a reference,
-  // with sufficient information to allocate a correctly sized object, and then
-  // later inline with complete contents.
-  return class_id >= kNumPredefinedCids || class_id == kArrayCid ||
-         class_id == kImmutableArrayCid || class_id == kObjectPoolCid ||
-         IsImplicitFieldClassId(class_id);
-}
-
-static intptr_t ClassIdFromObjectId(intptr_t object_id) {
-  ASSERT(object_id > kClassIdsOffset);
-  intptr_t class_id = (object_id - kClassIdsOffset);
-  return class_id;
-}
-
-static intptr_t ObjectIdFromClassId(intptr_t class_id) {
-  ASSERT((class_id > kIllegalCid) && (class_id < kNumPredefinedCids));
-  return (class_id + kClassIdsOffset);
-}
-
-static ObjectPtr GetType(ObjectStore* object_store, intptr_t index) {
-  switch (index) {
-    case kLegacyObjectType:
-      return object_store->legacy_object_type();
-    case kNullableObjectType:
-      return object_store->nullable_object_type();
-    case kNullType:
-      return object_store->null_type();
-    case kNeverType:
-      return object_store->never_type();
-    case kLegacyFunctionType:
-      return object_store->legacy_function_type();
-    case kLegacyNumberType:
-      return object_store->legacy_number_type();
-    case kLegacySmiType:
-      return object_store->legacy_smi_type();
-    case kLegacyMintType:
-      return object_store->legacy_mint_type();
-    case kLegacyDoubleType:
-      return object_store->legacy_double_type();
-    case kLegacyIntType:
-      return object_store->legacy_int_type();
-    case kLegacyBoolType:
-      return object_store->legacy_bool_type();
-    case kLegacyStringType:
-      return object_store->legacy_string_type();
-    case kLegacyArrayType:
-      return object_store->legacy_array_type();
-    case kLegacyIntTypeArguments:
-      return object_store->type_argument_legacy_int();
-    case kLegacyDoubleTypeArguments:
-      return object_store->type_argument_legacy_double();
-    case kLegacyStringTypeArguments:
-      return object_store->type_argument_legacy_string();
-    case kLegacyStringDynamicTypeArguments:
-      return object_store->type_argument_legacy_string_dynamic();
-    case kLegacyStringLegacyStringTypeArguments:
-      return object_store->type_argument_legacy_string_legacy_string();
-    case kNonNullableObjectType:
-      return object_store->non_nullable_object_type();
-    case kNonNullableFunctionType:
-      return object_store->non_nullable_function_type();
-    case kNonNullableNumberType:
-      return object_store->non_nullable_number_type();
-    case kNonNullableSmiType:
-      return object_store->non_nullable_smi_type();
-    case kNonNullableMintType:
-      return object_store->non_nullable_mint_type();
-    case kNonNullableDoubleType:
-      return object_store->non_nullable_double_type();
-    case kNonNullableIntType:
-      return object_store->non_nullable_int_type();
-    case kNonNullableBoolType:
-      return object_store->non_nullable_bool_type();
-    case kNonNullableStringType:
-      return object_store->non_nullable_string_type();
-    case kNonNullableArrayType:
-      return object_store->non_nullable_array_type();
-    case kNonNullableIntTypeArguments:
-      return object_store->type_argument_non_nullable_int();
-    case kNonNullableDoubleTypeArguments:
-      return object_store->type_argument_non_nullable_double();
-    case kNonNullableStringTypeArguments:
-      return object_store->type_argument_non_nullable_string();
-    case kNonNullableStringDynamicTypeArguments:
-      return object_store->type_argument_non_nullable_string_dynamic();
-    case kNonNullableStringNonNullableStringTypeArguments:
-      return object_store
-          ->type_argument_non_nullable_string_non_nullable_string();
-    default:
-      break;
-  }
-  UNREACHABLE();
-  return Type::null();
-}
-
-static intptr_t GetTypeIndex(ObjectStore* object_store,
-                             const ObjectPtr raw_type) {
-  if (raw_type == object_store->legacy_object_type()) {
-    return kLegacyObjectType;
-  } else if (raw_type == object_store->nullable_object_type()) {
-    return kNullableObjectType;
-  } else if (raw_type == object_store->null_type()) {
-    return kNullType;
-  } else if (raw_type == object_store->never_type()) {
-    return kNeverType;
-  } else if (raw_type == object_store->legacy_function_type()) {
-    return kLegacyFunctionType;
-  } else if (raw_type == object_store->legacy_number_type()) {
-    return kLegacyNumberType;
-  } else if (raw_type == object_store->legacy_smi_type()) {
-    return kLegacySmiType;
-  } else if (raw_type == object_store->legacy_mint_type()) {
-    return kLegacyMintType;
-  } else if (raw_type == object_store->legacy_double_type()) {
-    return kLegacyDoubleType;
-  } else if (raw_type == object_store->legacy_int_type()) {
-    return kLegacyIntType;
-  } else if (raw_type == object_store->legacy_bool_type()) {
-    return kLegacyBoolType;
-  } else if (raw_type == object_store->legacy_string_type()) {
-    return kLegacyStringType;
-  } else if (raw_type == object_store->legacy_array_type()) {
-    return kLegacyArrayType;
-  } else if (raw_type == object_store->type_argument_legacy_int()) {
-    return kLegacyIntTypeArguments;
-  } else if (raw_type == object_store->type_argument_legacy_double()) {
-    return kLegacyDoubleTypeArguments;
-  } else if (raw_type == object_store->type_argument_legacy_string()) {
-    return kLegacyStringTypeArguments;
-  } else if (raw_type == object_store->type_argument_legacy_string_dynamic()) {
-    return kLegacyStringDynamicTypeArguments;
-  } else if (raw_type ==
-             object_store->type_argument_legacy_string_legacy_string()) {
-    return kLegacyStringLegacyStringTypeArguments;
-  } else if (raw_type == object_store->non_nullable_object_type()) {
-    return kNonNullableObjectType;
-  } else if (raw_type == object_store->non_nullable_function_type()) {
-    return kNonNullableFunctionType;
-  } else if (raw_type == object_store->non_nullable_number_type()) {
-    return kNonNullableNumberType;
-  } else if (raw_type == object_store->non_nullable_smi_type()) {
-    return kNonNullableSmiType;
-  } else if (raw_type == object_store->non_nullable_mint_type()) {
-    return kNonNullableMintType;
-  } else if (raw_type == object_store->non_nullable_double_type()) {
-    return kNonNullableDoubleType;
-  } else if (raw_type == object_store->non_nullable_int_type()) {
-    return kNonNullableIntType;
-  } else if (raw_type == object_store->non_nullable_bool_type()) {
-    return kNonNullableBoolType;
-  } else if (raw_type == object_store->non_nullable_string_type()) {
-    return kNonNullableStringType;
-  } else if (raw_type == object_store->non_nullable_array_type()) {
-    return kNonNullableArrayType;
-  } else if (raw_type == object_store->type_argument_non_nullable_int()) {
-    return kNonNullableIntTypeArguments;
-  } else if (raw_type == object_store->type_argument_non_nullable_double()) {
-    return kNonNullableDoubleTypeArguments;
-  } else if (raw_type == object_store->type_argument_non_nullable_string()) {
-    return kNonNullableStringTypeArguments;
-  } else if (raw_type ==
-             object_store->type_argument_non_nullable_string_dynamic()) {
-    return kNonNullableStringDynamicTypeArguments;
-  } else if (raw_type ==
-             object_store
-                 ->type_argument_non_nullable_string_non_nullable_string()) {
-    return kNonNullableStringNonNullableStringTypeArguments;
-  }
-  return kInvalidIndex;
-}
-
 const char* Snapshot::KindToCString(Kind kind) {
   switch (kind) {
     case kFull:
@@ -237,8 +19,6 @@
       return "full-jit";
     case kFullAOT:
       return "full-aot";
-    case kMessage:
-      return "message";
     case kNone:
       return "none";
     case kInvalid:
@@ -262,96 +42,7 @@
   return snapshot;
 }
 
-SmiPtr BaseReader::ReadAsSmi() {
-  SmiPtr value = static_cast<SmiPtr>(Read<intptr_t>());
-  ASSERT((static_cast<uword>(value) & kSmiTagMask) == kSmiTag);
-  return value;
-}
-
-intptr_t BaseReader::ReadSmiValue() {
-  return Smi::Value(ReadAsSmi());
-}
-
-SnapshotReader::SnapshotReader(const uint8_t* buffer,
-                               intptr_t size,
-                               Snapshot::Kind kind,
-                               ZoneGrowableArray<BackRefNode>* backward_refs,
-                               Thread* thread)
-    : BaseReader(buffer, size),
-      kind_(kind),
-      thread_(thread),
-      zone_(thread->zone()),
-      heap_(isolate_group()->heap()),
-      old_space_(isolate_group()->heap()->old_space()),
-      cls_(Class::Handle(zone_)),
-      code_(Code::Handle(zone_)),
-      instance_(Instance::Handle(zone_)),
-      instructions_(Instructions::Handle(zone_)),
-      obj_(Object::Handle(zone_)),
-      pobj_(PassiveObject::Handle(zone_)),
-      array_(Array::Handle(zone_)),
-      field_(Field::Handle(zone_)),
-      str_(String::Handle(zone_)),
-      library_(Library::Handle(zone_)),
-      type_(AbstractType::Handle(zone_)),
-      type_arguments_(TypeArguments::Handle(zone_)),
-      tokens_(GrowableObjectArray::Handle(zone_)),
-      data_(ExternalTypedData::Handle(zone_)),
-      typed_data_base_(TypedDataBase::Handle(zone_)),
-      typed_data_(TypedData::Handle(zone_)),
-      typed_data_view_(TypedDataView::Handle(zone_)),
-      function_(Function::Handle(zone_)),
-      smi_(Smi::Handle(zone_)),
-      error_(UnhandledException::Handle(zone_)),
-      set_class_(Class::ZoneHandle(
-          zone_,
-          thread_->isolate_group()->object_store()->linked_hash_set_class())),
-      max_vm_isolate_object_id_(
-          (Snapshot::IsFull(kind))
-              ? Object::vm_isolate_snapshot_object_table().Length()
-              : 0),
-      backward_references_(backward_refs),
-      types_to_postprocess_(GrowableObjectArray::Handle(zone_)),
-      objects_to_rehash_(GrowableObjectArray::Handle(zone_)) {}
-
-ObjectPtr SnapshotReader::ReadObject() {
-  // Setup for long jump in case there is an exception while reading.
-  LongJumpScope jump;
-  if (setjmp(*jump.Set()) == 0) {
-    PassiveObject& obj =
-        PassiveObject::Handle(zone(), ReadObjectImpl(kAsInlinedObject));
-    for (intptr_t i = 0; i < backward_references_->length(); i++) {
-      if (!(*backward_references_)[i].is_deserialized()) {
-        ReadObjectImpl(kAsInlinedObject);
-        (*backward_references_)[i].set_state(kIsDeserialized);
-      }
-    }
-    Object& result = Object::Handle(zone_);
-    if (backward_references_->length() > 0) {
-      result = (*backward_references_)[0].reference()->ptr();
-    } else {
-      result = obj.ptr();
-    }
-    RunDelayedTypePostprocessing();
-    const Object& ok = Object::Handle(zone_, RunDelayedRehashingOfMaps());
-    objects_to_rehash_ = GrowableObjectArray::null();
-    if (!ok.IsNull()) {
-      return ok.ptr();
-    }
-    return result.ptr();
-  } else {
-    // An error occurred while reading, return the error object.
-    return Thread::Current()->StealStickyError();
-  }
-}
-
-void SnapshotReader::EnqueueTypePostprocessing(const AbstractType& type) {
-  if (types_to_postprocess_.IsNull()) {
-    types_to_postprocess_ = GrowableObjectArray::New();
-  }
-  types_to_postprocess_.Add(type);
-}
-
+#if 0
 void SnapshotReader::RunDelayedTypePostprocessing() {
   if (types_to_postprocess_.IsNull()) {
     return;
@@ -365,1283 +56,6 @@
     type.InitializeTypeTestingStubNonAtomic(code);
   }
 }
-
-void SnapshotReader::EnqueueRehashingOfMap(const LinkedHashMap& map) {
-  if (objects_to_rehash_.IsNull()) {
-    objects_to_rehash_ = GrowableObjectArray::New();
-  }
-  objects_to_rehash_.Add(map);
-}
-
-ObjectPtr SnapshotReader::RunDelayedRehashingOfMaps() {
-  if (!objects_to_rehash_.IsNull()) {
-    return DartLibraryCalls::RehashObjects(thread(), objects_to_rehash_);
-  }
-  return Object::null();
-}
-
-ClassPtr SnapshotReader::ReadClassId(intptr_t object_id) {
-  ASSERT(!Snapshot::IsFull(kind_));
-  // Read the class header information and lookup the class.
-  intptr_t class_header = Read<int32_t>();
-  ASSERT((class_header & kSmiTagMask) != kSmiTag);
-  ASSERT(!IsVMIsolateObject(class_header) ||
-         !IsSingletonClassId(GetVMIsolateObjectId(class_header)));
-  ASSERT((SerializedHeaderTag::decode(class_header) != kObjectId) ||
-         !IsBootstrapedClassId(SerializedHeaderData::decode(class_header)));
-  Class& cls = Class::ZoneHandle(zone(), Class::null());
-  AddBackRef(object_id, &cls, kIsDeserialized);
-  // Read the library/class information and lookup the class.
-  str_ ^= ReadObjectImpl(class_header, kAsInlinedObject);
-  library_ = Library::LookupLibrary(thread(), str_);
-  if (library_.IsNull() || !library_.Loaded()) {
-    SetReadException(
-        "Invalid object found in message: library is not found or loaded.");
-  }
-  str_ ^= ReadObjectImpl(kAsInlinedObject);
-  if (str_.ptr() == Symbols::TopLevel().ptr()) {
-    cls = library_.toplevel_class();
-  } else {
-    str_ = String::New(String::ScrubName(str_));
-    cls = library_.LookupClassAllowPrivate(str_);
-  }
-  if (cls.IsNull()) {
-    SetReadException("Invalid object found in message: class not found");
-  }
-  cls.EnsureIsFinalized(thread());
-  return cls.ptr();
-}
-
-ObjectPtr SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id,
-                                                    intptr_t class_header) {
-  ASSERT(!Snapshot::IsFull(kind_));
-
-  // First create a function object and associate it with the specified
-  // 'object_id'.
-  Function& func = Function::Handle(zone(), Function::null());
-  Instance& obj = Instance::ZoneHandle(zone(), Instance::null());
-  AddBackRef(object_id, &obj, kIsDeserialized);
-
-  // Read the library/class/function information and lookup the function.
-  // Note: WriteStaticImplicitClosure is *not* scrubbing the names before
-  // writing them into the snapshot, because scrubbing requires allocation.
-  // This means that names we read here might be mangled with private
-  // keys. These keys need to be scrubbed before performing lookups
-  // otherwise lookups might fail.
-  str_ ^= ReadObjectImpl(kAsInlinedObject);
-  library_ = Library::LookupLibrary(thread(), str_);
-  if (library_.IsNull() || !library_.Loaded()) {
-    SetReadException("Invalid Library object found in message.");
-  }
-  str_ ^= ReadObjectImpl(kAsInlinedObject);
-  if (str_.Equals(Symbols::TopLevel())) {
-    str_ ^= ReadObjectImpl(kAsInlinedObject);
-    str_ = String::New(String::ScrubName(str_));
-    func = library_.LookupFunctionAllowPrivate(str_);
-  } else {
-    str_ = String::New(String::ScrubName(str_));
-    cls_ = library_.LookupClassAllowPrivate(str_);
-    if (cls_.IsNull()) {
-      OS::PrintErr("Name of class not found %s\n", str_.ToCString());
-      SetReadException("Invalid Class object found in message.");
-    }
-    cls_.EnsureIsFinalized(thread());
-    str_ ^= ReadObjectImpl(kAsInlinedObject);
-    str_ = String::New(String::ScrubName(str_));
-    func = cls_.LookupFunctionAllowPrivate(str_);
-  }
-  if (func.IsNull()) {
-    SetReadException("Invalid function object found in message.");
-  }
-  TypeArguments& delayed_type_arguments = TypeArguments::Handle(zone());
-  delayed_type_arguments ^= ReadObjectImpl(kAsInlinedObject);
-
-  func = func.ImplicitClosureFunction();
-  ASSERT(!func.IsNull());
-
-  // If delayedtype arguments were provided, create and return new closure with
-  // those, otherwise return associated implicit static closure.
-  // Note that static closures can't have instantiator or function types since
-  // statics can't refer to class type arguments, don't have outer functions.
-  if (!delayed_type_arguments.IsNull()) {
-    const Context& context = Context::Handle(zone());
-    obj = Closure::New(
-        /*instantiator_type_arguments=*/Object::null_type_arguments(),
-        /*function_type_arguments=*/Object::null_type_arguments(),
-        delayed_type_arguments, func, context, Heap::kOld);
-  } else {
-    obj = func.ImplicitStaticClosure();
-  }
-  return obj.ptr();
-}
-
-intptr_t SnapshotReader::NextAvailableObjectId() const {
-  return backward_references_->length() + kMaxPredefinedObjectIds +
-         max_vm_isolate_object_id_;
-}
-
-void SnapshotReader::SetReadException(const char* msg) {
-  const String& error_str = String::Handle(zone(), String::New(msg));
-  const Array& args = Array::Handle(zone(), Array::New(1));
-  args.SetAt(0, error_str);
-  Object& result = Object::Handle(zone());
-  const Library& library = Library::Handle(zone(), Library::CoreLibrary());
-  result = DartLibraryCalls::InstanceCreate(library, Symbols::ArgumentError(),
-                                            Symbols::Dot(), args);
-  const StackTrace& stacktrace = StackTrace::Handle(zone());
-  const UnhandledException& error = UnhandledException::Handle(
-      zone(), UnhandledException::New(Instance::Cast(result), stacktrace));
-  thread()->long_jump_base()->Jump(1, error);
-}
-
-ObjectPtr SnapshotReader::VmIsolateSnapshotObject(intptr_t index) const {
-  return Object::vm_isolate_snapshot_object_table().At(index);
-}
-
-bool SnapshotReader::is_vm_isolate() const {
-  return isolate_group() == Dart::vm_isolate_group();
-}
-
-ObjectPtr SnapshotReader::ReadObjectImpl(bool as_reference) {
-  int64_t header_value = Read<int64_t>();
-  if ((header_value & kSmiTagMask) == kSmiTag) {
-    return NewInteger(header_value);
-  }
-  ASSERT((header_value <= kIntptrMax) && (header_value >= kIntptrMin));
-  return ReadObjectImpl(static_cast<intptr_t>(header_value), as_reference);
-}
-
-ObjectPtr SnapshotReader::ReadObjectImpl(intptr_t header_value,
-                                         bool as_reference) {
-  if (IsVMIsolateObject(header_value)) {
-    return ReadVMIsolateObject(header_value);
-  }
-  if (SerializedHeaderTag::decode(header_value) == kObjectId) {
-    return ReadIndexedObject(SerializedHeaderData::decode(header_value));
-  }
-  ASSERT(SerializedHeaderTag::decode(header_value) == kInlined);
-  intptr_t object_id = SerializedHeaderData::decode(header_value);
-  if (object_id == kOmittedObjectId) {
-    object_id = NextAvailableObjectId();
-  }
-
-  // Read the class header information.
-  intptr_t class_header = Read<int32_t>();
-  intptr_t tags = ReadTags();
-  bool read_as_reference = as_reference && !UntaggedObject::IsCanonical(tags);
-  intptr_t header_id = SerializedHeaderData::decode(class_header);
-  if (header_id == kInstanceObjectId) {
-    return ReadInstance(object_id, tags, read_as_reference);
-  } else if (header_id == kStaticImplicitClosureObjectId) {
-    // We skip the tags that have been written as the implicit static
-    // closure is going to be created in this isolate or the canonical
-    // version already created in the isolate will be used.
-    return ReadStaticImplicitClosure(object_id, class_header);
-  }
-  ASSERT((class_header & kSmiTagMask) != kSmiTag);
-
-  intptr_t class_id = LookupInternalClass(class_header);
-  switch (class_id) {
-#define SNAPSHOT_READ(clazz)                                                   \
-  case clazz::kClassId: {                                                      \
-    pobj_ = clazz::ReadFrom(this, object_id, tags, kind_, read_as_reference);  \
-    break;                                                                     \
-  }
-    CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kTypedData##clazz##Cid:
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-      tags = UntaggedObject::ClassIdTag::update(class_id, tags);
-      pobj_ =
-          TypedData::ReadFrom(this, object_id, tags, kind_, read_as_reference);
-      break;
-    }
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kExternalTypedData##clazz##Cid:
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-      tags = UntaggedObject::ClassIdTag::update(class_id, tags);
-      pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_, true);
-      break;
-    }
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kTypedData##clazz##ViewCid:
-
-    case kByteDataViewCid:
-      CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-        tags = UntaggedObject::ClassIdTag::update(class_id, tags);
-        pobj_ = TypedDataView::ReadFrom(this, object_id, tags, kind_, true);
-        break;
-      }
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kFfi##clazz##Cid:
-
-    CLASS_LIST_FFI(SNAPSHOT_READ) { UNREACHABLE(); }
-#undef SNAPSHOT_READ
-    default:
-      UNREACHABLE();
-      break;
-  }
-  return pobj_.ptr();
-}
-
-void SnapshotReader::EnqueueRehashingOfSet(const Object& set) {
-  if (objects_to_rehash_.IsNull()) {
-    objects_to_rehash_ = GrowableObjectArray::New();
-  }
-  objects_to_rehash_.Add(set);
-}
-
-ObjectPtr SnapshotReader::ReadInstance(intptr_t object_id,
-                                       intptr_t tags,
-                                       bool as_reference) {
-  // Object is regular dart instance.
-  intptr_t instance_size = 0;
-  Instance* result = NULL;
-  DeserializeState state;
-  if (!as_reference) {
-    result = reinterpret_cast<Instance*>(GetBackRef(object_id));
-    state = kIsDeserialized;
-  } else {
-    state = kIsNotDeserialized;
-  }
-  if (result == NULL) {
-    result = &(Instance::ZoneHandle(zone(), Instance::null()));
-    AddBackRef(object_id, result, state);
-    cls_ ^= ReadObjectImpl(kAsInlinedObject);
-    ASSERT(!cls_.IsNull());
-    // Closure instances are handled by Closure::ReadFrom().
-    ASSERT(!cls_.IsClosureClass());
-    instance_size = cls_.host_instance_size();
-    ASSERT(instance_size > 0);
-    // Allocate the instance and read in all the fields for the object.
-    *result ^= Object::Allocate(cls_.id(), instance_size, Heap::kNew,
-                                Instance::ContainsCompressedPointers());
-  } else {
-    cls_ ^= ReadObjectImpl(kAsInlinedObject);
-    ASSERT(!cls_.IsNull());
-    instance_size = cls_.host_instance_size();
-  }
-  if (cls_.id() == set_class_.id()) {
-    EnqueueRehashingOfSet(*result);
-  }
-  if (!as_reference) {
-    // Read all the individual fields for inlined objects.
-    intptr_t next_field_offset = cls_.host_next_field_offset();
-
-    intptr_t type_argument_field_offset =
-        cls_.host_type_arguments_field_offset();
-    ASSERT(next_field_offset > 0);
-    // Instance::NextFieldOffset() returns the offset of the first field in
-    // a Dart object.
-    bool read_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-    intptr_t offset = Instance::NextFieldOffset();
-    intptr_t result_cid = result->GetClassId();
-
-    const auto unboxed_fields =
-        isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            result_cid);
-
-    while (offset < next_field_offset) {
-      if (unboxed_fields.Get(offset / kCompressedWordSize)) {
-        uword* p = reinterpret_cast<uword*>(result->raw_value() -
-                                            kHeapObjectTag + offset);
-        // Reads 32 bits of the unboxed value at a time
-        *p = ReadWordWith32BitReads();
-      } else {
-        pobj_ = ReadObjectImpl(read_as_reference);
-        result->SetFieldAtOffset(offset, pobj_);
-        if ((offset != type_argument_field_offset) &&
-            (kind_ == Snapshot::kMessage) &&
-            isolate_group()->use_field_guards() &&
-            (pobj_.ptr() != Object::sentinel().ptr())) {
-          // TODO(fschneider): Consider hoisting these lookups out of the loop.
-          // This would involve creating a handle, since cls_ can't be reused
-          // across the call to ReadObjectImpl.
-          cls_ = isolate_group()->class_table()->At(result_cid);
-          array_ = cls_.OffsetToFieldMap();
-          field_ ^= array_.At(offset >> kCompressedWordSizeLog2);
-          ASSERT(!field_.IsNull());
-          ASSERT(field_.HostOffset() == offset);
-          obj_ = pobj_.ptr();
-          field_.RecordStore(obj_);
-        }
-        // TODO(fschneider): Verify the guarded cid and length for other kinds
-        // of snapshot (kFull, kScript) with asserts.
-      }
-      offset += kCompressedWordSize;
-    }
-    if (UntaggedObject::IsCanonical(tags)) {
-      *result = result->Canonicalize(thread());
-      ASSERT(!result->IsNull());
-    }
-  }
-  return result->ptr();
-}
-
-void SnapshotReader::AddBackRef(intptr_t id,
-                                Object* obj,
-                                DeserializeState state) {
-  intptr_t index = (id - kMaxPredefinedObjectIds);
-  ASSERT(index >= max_vm_isolate_object_id_);
-  index -= max_vm_isolate_object_id_;
-  ASSERT(index == backward_references_->length());
-  BackRefNode node(obj, state);
-  backward_references_->Add(node);
-}
-
-Object* SnapshotReader::GetBackRef(intptr_t id) {
-  ASSERT(id >= kMaxPredefinedObjectIds);
-  intptr_t index = (id - kMaxPredefinedObjectIds);
-  ASSERT(index >= max_vm_isolate_object_id_);
-  index -= max_vm_isolate_object_id_;
-  if (index < backward_references_->length()) {
-    return (*backward_references_)[index].reference();
-  }
-  return NULL;
-}
-
-ApiErrorPtr SnapshotReader::VerifyVersionAndFeatures(
-    IsolateGroup* isolate_group) {
-  // If the version string doesn't match, return an error.
-  // Note: New things are allocated only if we're going to return an error.
-
-  const char* expected_version = Version::SnapshotString();
-  ASSERT(expected_version != NULL);
-  const intptr_t version_len = strlen(expected_version);
-  if (PendingBytes() < version_len) {
-    const intptr_t kMessageBufferSize = 128;
-    char message_buffer[kMessageBufferSize];
-    Utils::SNPrint(message_buffer, kMessageBufferSize,
-                   "No full snapshot version found, expected '%s'",
-                   expected_version);
-    // This can also fail while bringing up the VM isolate, so make sure to
-    // allocate the error message in old space.
-    const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
-    return ApiError::New(msg, Heap::kOld);
-  }
-
-  const char* version = reinterpret_cast<const char*>(CurrentBufferAddress());
-  ASSERT(version != NULL);
-  if (strncmp(version, expected_version, version_len) != 0) {
-    const intptr_t kMessageBufferSize = 256;
-    char message_buffer[kMessageBufferSize];
-    char* actual_version = Utils::StrNDup(version, version_len);
-    Utils::SNPrint(message_buffer, kMessageBufferSize,
-                   "Wrong %s snapshot version, expected '%s' found '%s'",
-                   (Snapshot::IsFull(kind_)) ? "full" : "script",
-                   expected_version, actual_version);
-    free(actual_version);
-    // This can also fail while bringing up the VM isolate, so make sure to
-    // allocate the error message in old space.
-    const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
-    return ApiError::New(msg, Heap::kOld);
-  }
-  Advance(version_len);
-
-  const char* expected_features =
-      Dart::FeaturesString(isolate_group, false, kind_);
-  ASSERT(expected_features != NULL);
-  const intptr_t expected_len = strlen(expected_features);
-
-  const char* features = reinterpret_cast<const char*>(CurrentBufferAddress());
-  ASSERT(features != NULL);
-  intptr_t buffer_len = Utils::StrNLen(features, PendingBytes());
-  if ((buffer_len != expected_len) ||
-      (strncmp(features, expected_features, expected_len) != 0)) {
-    const intptr_t kMessageBufferSize = 256;
-    char message_buffer[kMessageBufferSize];
-    char* actual_features =
-        Utils::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
-    Utils::SNPrint(message_buffer, kMessageBufferSize,
-                   "Snapshot not compatible with the current VM configuration: "
-                   "the snapshot requires '%s' but the VM has '%s'",
-                   actual_features, expected_features);
-    free(const_cast<char*>(expected_features));
-    free(actual_features);
-    // This can also fail while bringing up the VM isolate, so make sure to
-    // allocate the error message in old space.
-    const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
-    return ApiError::New(msg, Heap::kOld);
-  }
-  free(const_cast<char*>(expected_features));
-  Advance(expected_len + 1);
-  return ApiError::null();
-}
-
-ObjectPtr SnapshotReader::NewInteger(int64_t value) {
-  ASSERT((value & kSmiTagMask) == kSmiTag);
-  value = value >> kSmiTagShift;
-  if (Smi::IsValid(value)) {
-    return Smi::New(static_cast<intptr_t>(value));
-  }
-  return Mint::NewCanonical(value);
-}
-
-intptr_t SnapshotReader::LookupInternalClass(intptr_t class_header) {
-  // If the header is an object Id, lookup singleton VM classes or classes
-  // stored in the object store.
-  if (IsVMIsolateObject(class_header)) {
-    intptr_t class_id = GetVMIsolateObjectId(class_header);
-    ASSERT(IsSingletonClassId(class_id));
-    return class_id;
-  }
-  ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
-  intptr_t class_id = SerializedHeaderData::decode(class_header);
-  ASSERT(IsBootstrapedClassId(class_id) || IsSingletonClassId(class_id));
-  return class_id;
-}
-
-#define READ_VM_SINGLETON_OBJ(id, obj)                                         \
-  if (object_id == id) {                                                       \
-    return obj;                                                                \
-  }
-
-ObjectPtr SnapshotReader::ReadVMIsolateObject(intptr_t header_value) {
-  intptr_t object_id = GetVMIsolateObjectId(header_value);
-
-  // First check if it is one of the singleton objects.
-  READ_VM_SINGLETON_OBJ(kNullObject, Object::null());
-  READ_VM_SINGLETON_OBJ(kSentinelObject, Object::sentinel().ptr());
-  READ_VM_SINGLETON_OBJ(kTransitionSentinelObject,
-                        Object::transition_sentinel().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyArrayObject, Object::empty_array().ptr());
-  READ_VM_SINGLETON_OBJ(kZeroArrayObject, Object::zero_array().ptr());
-  READ_VM_SINGLETON_OBJ(kDynamicType, Object::dynamic_type().ptr());
-  READ_VM_SINGLETON_OBJ(kVoidType, Object::void_type().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyTypeArguments,
-                        Object::empty_type_arguments().ptr());
-  READ_VM_SINGLETON_OBJ(kTrueValue, Bool::True().ptr());
-  READ_VM_SINGLETON_OBJ(kFalseValue, Bool::False().ptr());
-  READ_VM_SINGLETON_OBJ(kExtractorParameterTypes,
-                        Object::extractor_parameter_types().ptr());
-  READ_VM_SINGLETON_OBJ(kExtractorParameterNames,
-                        Object::extractor_parameter_names().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyContextScopeObject,
-                        Object::empty_context_scope().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyObjectPool, Object::empty_object_pool().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyDescriptors, Object::empty_descriptors().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyVarDescriptors,
-                        Object::empty_var_descriptors().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyExceptionHandlers,
-                        Object::empty_exception_handlers().ptr());
-
-  // Check if it is a double.
-  if (object_id == kDoubleObject) {
-    ASSERT(kind_ == Snapshot::kMessage);
-    return Double::New(ReadDouble());
-  }
-
-  // Check it is a singleton class object.
-  intptr_t class_id = ClassIdFromObjectId(object_id);
-  if (IsSingletonClassId(class_id)) {
-    return isolate_group()->class_table()->At(
-        class_id);  // get singleton class.
-  }
-
-  // Check if it is a singleton Argument descriptor object.
-  for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
-    if (object_id == (kCachedArgumentsDescriptor0 + i)) {
-      return ArgumentsDescriptor::cached_args_descriptors_[i];
-    }
-  }
-
-  // Check if it is a singleton ICData array object.
-  for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
-    if (object_id == (kCachedICDataArray0 + i)) {
-      return ICData::cached_icdata_arrays_[i];
-    }
-  }
-
-  ASSERT(Symbols::IsPredefinedSymbolId(object_id));
-  return Symbols::GetPredefinedSymbol(object_id);  // return VM symbol.
-}
-
-ObjectPtr SnapshotReader::ReadIndexedObject(intptr_t object_id) {
-  intptr_t class_id = ClassIdFromObjectId(object_id);
-  if (IsBootstrapedClassId(class_id)) {
-    return isolate_group()->class_table()->At(
-        class_id);  // get singleton class.
-  }
-  if (IsObjectStoreTypeId(object_id)) {
-    return GetType(object_store(), object_id);  // return type obj.
-  }
-  ASSERT(object_id >= kMaxPredefinedObjectIds);
-  intptr_t index = (object_id - kMaxPredefinedObjectIds);
-  if (index < max_vm_isolate_object_id_) {
-    return VmIsolateSnapshotObject(index);
-  }
-  return GetBackRef(object_id)->ptr();
-}
-
-void SnapshotReader::ArrayReadFrom(intptr_t object_id,
-                                   const Array& result,
-                                   intptr_t len,
-                                   intptr_t tags) {
-  // Setup the object fields.
-  *TypeArgumentsHandle() ^= ReadObjectImpl(kAsInlinedObject);
-  result.SetTypeArguments(*TypeArgumentsHandle());
-
-  bool as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-  for (intptr_t i = 0; i < len; i++) {
-    *PassiveObjectHandle() = ReadObjectImpl(as_reference);
-    result.SetAt(i, *PassiveObjectHandle());
-  }
-}
-
-MessageSnapshotReader::MessageSnapshotReader(Message* message, Thread* thread)
-    : SnapshotReader(message->snapshot(),
-                     message->snapshot_length(),
-                     Snapshot::kMessage,
-                     new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
-                     thread),
-      finalizable_data_(message->finalizable_data()) {}
-
-MessageSnapshotReader::~MessageSnapshotReader() {
-  ResetBackwardReferenceTable();
-}
-
-SnapshotWriter::SnapshotWriter(Thread* thread,
-                               Snapshot::Kind kind,
-                               intptr_t initial_size,
-                               ForwardList* forward_list,
-                               bool can_send_any_object)
-    : BaseWriter(initial_size),
-      thread_(thread),
-      kind_(kind),
-      object_store_(isolate_group()->object_store()),
-      class_table_(isolate_group()->class_table()),
-      forward_list_(forward_list),
-      exception_type_(Exceptions::kNone),
-      exception_msg_(NULL),
-      can_send_any_object_(can_send_any_object) {
-  ASSERT(forward_list_ != NULL);
-}
-
-void SnapshotWriter::WriteObject(ObjectPtr rawobj) {
-  WriteObjectImpl(rawobj, kAsInlinedObject);
-  WriteForwardedObjects();
-}
-
-uint32_t SnapshotWriter::GetObjectTags(ObjectPtr raw) {
-  uword tags = raw->untag()->tags_;
-#if defined(HASH_IN_OBJECT_HEADER)
-  // Clear hash to make the narrowing cast safe / appease UBSAN.
-  tags = UntaggedObject::HashTag::update(0, tags);
 #endif
-  return tags;
-}
-
-uint32_t SnapshotWriter::GetObjectTags(UntaggedObject* raw) {
-  uword tags = raw->tags_;
-#if defined(HASH_IN_OBJECT_HEADER)
-  // Clear hash to make the narrowing cast safe / appease UBSAN.
-  tags = UntaggedObject::HashTag::update(0, tags);
-#endif
-  return tags;
-}
-
-uword SnapshotWriter::GetObjectTagsAndHash(ObjectPtr raw) {
-  return raw->untag()->tags_;
-}
-
-#define VM_OBJECT_CLASS_LIST(V)                                                \
-  V(OneByteString)                                                             \
-  V(TwoByteString)                                                             \
-  V(Mint)                                                                      \
-  V(Double)                                                                    \
-  V(ImmutableArray)
-
-#define VM_OBJECT_WRITE(clazz)                                                 \
-  case clazz::kClassId: {                                                      \
-    object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);       \
-    clazz##Ptr raw_obj = static_cast<clazz##Ptr>(rawobj);                      \
-    raw_obj->untag()->WriteTo(this, object_id, kind(), false);                 \
-    return true;                                                               \
-  }
-
-#define WRITE_VM_SINGLETON_OBJ(obj, id)                                        \
-  if (rawobj == obj) {                                                         \
-    WriteVMIsolateObject(id);                                                  \
-    return true;                                                               \
-  }
-
-bool SnapshotWriter::HandleVMIsolateObject(ObjectPtr rawobj) {
-  // Check if it is one of the singleton VM objects.
-  WRITE_VM_SINGLETON_OBJ(Object::null(), kNullObject);
-  WRITE_VM_SINGLETON_OBJ(Object::sentinel().ptr(), kSentinelObject);
-  WRITE_VM_SINGLETON_OBJ(Object::transition_sentinel().ptr(),
-                         kTransitionSentinelObject);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_array().ptr(), kEmptyArrayObject);
-  WRITE_VM_SINGLETON_OBJ(Object::zero_array().ptr(), kZeroArrayObject);
-  WRITE_VM_SINGLETON_OBJ(Object::dynamic_type().ptr(), kDynamicType);
-  WRITE_VM_SINGLETON_OBJ(Object::void_type().ptr(), kVoidType);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_type_arguments().ptr(),
-                         kEmptyTypeArguments);
-  WRITE_VM_SINGLETON_OBJ(Bool::True().ptr(), kTrueValue);
-  WRITE_VM_SINGLETON_OBJ(Bool::False().ptr(), kFalseValue);
-  WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_types().ptr(),
-                         kExtractorParameterTypes);
-  WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_names().ptr(),
-                         kExtractorParameterNames);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_context_scope().ptr(),
-                         kEmptyContextScopeObject);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_object_pool().ptr(), kEmptyObjectPool);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_descriptors().ptr(), kEmptyDescriptors);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_var_descriptors().ptr(),
-                         kEmptyVarDescriptors);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_exception_handlers().ptr(),
-                         kEmptyExceptionHandlers);
-
-  // Check if it is a singleton class object which is shared by
-  // all isolates.
-  intptr_t id = rawobj->GetClassId();
-  if (id == kClassCid) {
-    ClassPtr raw_class = static_cast<ClassPtr>(rawobj);
-    intptr_t class_id = raw_class->untag()->id_;
-    if (IsSingletonClassId(class_id)) {
-      intptr_t object_id = ObjectIdFromClassId(class_id);
-      WriteVMIsolateObject(object_id);
-      return true;
-    }
-  }
-
-  // Check if it is a singleton Argument descriptor object.
-  for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
-    if (rawobj == ArgumentsDescriptor::cached_args_descriptors_[i]) {
-      WriteVMIsolateObject(kCachedArgumentsDescriptor0 + i);
-      return true;
-    }
-  }
-
-  // Check if it is a singleton ICData array object.
-  for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
-    if (rawobj == ICData::cached_icdata_arrays_[i]) {
-      WriteVMIsolateObject(kCachedICDataArray0 + i);
-      return true;
-    }
-  }
-
-  // In the case of script snapshots or for messages we do not use
-  // the index into the vm isolate snapshot object table, instead we
-  // explicitly write the object out.
-  intptr_t object_id = forward_list_->FindObject(rawobj);
-  if (object_id != -1) {
-    WriteIndexedObject(object_id);
-    return true;
-  } else {
-    // We do this check down here, because it's quite expensive.
-    if (!rawobj->untag()->InVMIsolateHeap()) {
-      return false;
-    }
-
-    switch (id) {
-      VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE)
-      case kTypedDataUint32ArrayCid: {
-        object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);
-        TypedDataPtr raw_obj = static_cast<TypedDataPtr>(rawobj);
-        raw_obj->untag()->WriteTo(this, object_id, kind(), false);
-        return true;
-      }
-      default:
-        OS::PrintErr("class id = %" Pd "\n", id);
-        break;
-    }
-  }
-
-  const Object& obj = Object::Handle(rawobj);
-  FATAL1("Unexpected reference to object in VM isolate: %s\n", obj.ToCString());
-  return false;
-}
-
-#undef VM_OBJECT_WRITE
-
-ForwardList::ForwardList(Thread* thread, intptr_t first_object_id)
-    : thread_(thread),
-      first_object_id_(first_object_id),
-      nodes_(),
-      first_unprocessed_object_id_(first_object_id) {
-  ASSERT(first_object_id > 0);
-  isolate()->set_forward_table_new(new WeakTable());
-  isolate()->set_forward_table_old(new WeakTable());
-}
-
-ForwardList::~ForwardList() {
-  isolate()->set_forward_table_new(nullptr);
-  isolate()->set_forward_table_old(nullptr);
-}
-
-intptr_t ForwardList::AddObject(Zone* zone,
-                                ObjectPtr raw,
-                                SerializeState state) {
-  NoSafepointScope no_safepoint;
-  intptr_t object_id = next_object_id();
-  ASSERT(object_id > 0 && object_id <= kMaxObjectId);
-  const Object& obj = Object::ZoneHandle(zone, raw);
-  Node* node = new Node(&obj, state);
-  ASSERT(node != NULL);
-  nodes_.Add(node);
-  ASSERT(object_id != 0);
-  SetObjectId(raw, object_id);
-  return object_id;
-}
-
-intptr_t ForwardList::FindObject(ObjectPtr raw) {
-  NoSafepointScope no_safepoint;
-  intptr_t id = GetObjectId(raw);
-  ASSERT(id == 0 || NodeForObjectId(id)->obj()->ptr() == raw);
-  return (id == 0) ? static_cast<intptr_t>(kInvalidIndex) : id;
-}
-
-void ForwardList::SetObjectId(ObjectPtr object, intptr_t id) {
-  if (object->IsNewObject()) {
-    isolate()->forward_table_new()->SetValueExclusive(object, id);
-  } else {
-    isolate()->forward_table_old()->SetValueExclusive(object, id);
-  }
-}
-
-intptr_t ForwardList::GetObjectId(ObjectPtr object) {
-  if (object->IsNewObject()) {
-    return isolate()->forward_table_new()->GetValueExclusive(object);
-  } else {
-    return isolate()->forward_table_old()->GetValueExclusive(object);
-  }
-}
-
-bool SnapshotWriter::CheckAndWritePredefinedObject(ObjectPtr rawobj) {
-  // Check if object can be written in one of the following ways:
-  // - Smi: the Smi value is written as is (last bit is not tagged).
-  // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3)
-  // - Object that has already been written: (negative id in stream | 0x3)
-
-  NoSafepointScope no_safepoint;
-
-  // First check if it is a Smi (i.e not a heap object).
-  if (!rawobj->IsHeapObject()) {
-#if !defined(DART_COMPRESSED_POINTERS)
-    Write<int64_t>(static_cast<intptr_t>(rawobj));
-#else
-    // One might expect this to be unnecessary because the reader will just
-    // ignore the upper bits, but the upper bits affect the variable-length
-    // encoding and can change lower bits in the variable-length reader.
-    Write<int64_t>(static_cast<intptr_t>(rawobj) << 32 >> 32);
-#endif
-    return true;
-  }
-
-  intptr_t cid = rawobj->GetClassId();
-
-  if ((kind_ == Snapshot::kMessage) && (cid == kDoubleCid)) {
-    WriteVMIsolateObject(kDoubleObject);
-    DoublePtr rd = static_cast<DoublePtr>(rawobj);
-    WriteDouble(rd->untag()->value_);
-    return true;
-  }
-
-  // Check if object has already been serialized, in that case just write
-  // the object id out.
-  intptr_t object_id = forward_list_->FindObject(rawobj);
-  if (object_id != kInvalidIndex) {
-    WriteIndexedObject(object_id);
-    return true;
-  }
-
-  // Check if it is a code object in that case just write a Null object
-  // as we do not want code objects in the snapshot.
-  if (cid == kCodeCid) {
-    WriteVMIsolateObject(kNullObject);
-    return true;
-  }
-
-  // Now check if it is an object from the VM isolate. These objects are shared
-  // by all isolates.
-  if (HandleVMIsolateObject(rawobj)) {
-    return true;
-  }
-
-  // Check if classes are not being serialized and it is preinitialized type
-  // or a predefined internal VM class in the object store.
-  // Check if it is an internal VM class which is in the object store.
-  if (cid == kClassCid) {
-    ClassPtr raw_class = static_cast<ClassPtr>(rawobj);
-    intptr_t class_id = raw_class->untag()->id_;
-    if (IsBootstrapedClassId(class_id)) {
-      intptr_t object_id = ObjectIdFromClassId(class_id);
-      WriteIndexedObject(object_id);
-      return true;
-    }
-  }
-
-  // Now check it is a preinitialized type object.
-  intptr_t index = GetTypeIndex(object_store(), rawobj);
-  if (index != kInvalidIndex) {
-    WriteIndexedObject(index);
-    return true;
-  }
-
-  return false;
-}
-
-void SnapshotWriter::WriteObjectImpl(ObjectPtr raw, bool as_reference) {
-  // First check if object can be written as a simple predefined type.
-  if (CheckAndWritePredefinedObject(raw)) {
-    return;
-  }
-
-  // When we know that we are dealing with leaf or shallow objects we write
-  // these objects inline even when 'as_reference' is true.
-  const bool write_as_reference = as_reference && !raw->untag()->IsCanonical();
-  uintptr_t tags = GetObjectTagsAndHash(raw);
-
-  // Add object to the forward ref list and mark it so that future references
-  // to this object in the snapshot will use this object id. Mark the
-  // serialization state so that we do the right thing when we go through
-  // the forward list.
-  intptr_t class_id = raw->GetClassId();
-  intptr_t object_id;
-  if (write_as_reference && IsSplitClassId(class_id)) {
-    object_id = forward_list_->AddObject(zone(), raw, kIsNotSerialized);
-  } else {
-    object_id = forward_list_->AddObject(zone(), raw, kIsSerialized);
-  }
-  if (write_as_reference || !IsSplitClassId(class_id)) {
-    object_id = kOmittedObjectId;
-  }
-  WriteMarkedObjectImpl(raw, tags, object_id, write_as_reference);
-}
-
-void SnapshotWriter::WriteMarkedObjectImpl(ObjectPtr raw,
-                                           intptr_t tags,
-                                           intptr_t object_id,
-                                           bool as_reference) {
-  NoSafepointScope no_safepoint;
-  ClassPtr cls = class_table_->At(UntaggedObject::ClassIdTag::decode(tags));
-  intptr_t class_id = cls->untag()->id_;
-  ASSERT(class_id == UntaggedObject::ClassIdTag::decode(tags));
-  if (class_id >= kNumPredefinedCids || IsImplicitFieldClassId(class_id)) {
-    WriteInstance(raw, cls, tags, object_id, as_reference);
-    return;
-  }
-  switch (class_id) {
-#define SNAPSHOT_WRITE(clazz)                                                  \
-  case clazz::kClassId: {                                                      \
-    clazz##Ptr raw_obj = static_cast<clazz##Ptr>(raw);                         \
-    raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);           \
-    return;                                                                    \
-  }
-
-    CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz) case kTypedData##clazz##Cid:
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
-      TypedDataPtr raw_obj = static_cast<TypedDataPtr>(raw);
-      raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
-      return;
-    }
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz) case kExternalTypedData##clazz##Cid:
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
-      ExternalTypedDataPtr raw_obj = static_cast<ExternalTypedDataPtr>(raw);
-      raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
-      return;
-    }
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz) case kTypedData##clazz##ViewCid:
-
-    case kByteDataViewCid:
-      CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
-        auto raw_obj = static_cast<TypedDataViewPtr>(raw);
-        raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
-        return;
-      }
-#undef SNAPSHOT_WRITE
-
-#define SNAPSHOT_WRITE(clazz) case kFfi##clazz##Cid:
-
-      CLASS_LIST_FFI(SNAPSHOT_WRITE) {
-        SetWriteException(Exceptions::kArgument,
-                          "Native objects (from dart:ffi) such as Pointers and "
-                          "Structs cannot be passed between isolates.");
-        UNREACHABLE();
-      }
-#undef SNAPSHOT_WRITE
-    default:
-      break;
-  }
-
-  const Object& obj = Object::Handle(raw);
-  FATAL1("Unexpected object: %s\n", obj.ToCString());
-}
-
-class WriteInlinedObjectVisitor : public ObjectVisitor {
- public:
-  explicit WriteInlinedObjectVisitor(SnapshotWriter* writer)
-      : writer_(writer) {}
-
-  virtual void VisitObject(ObjectPtr obj) {
-    intptr_t object_id = writer_->forward_list_->FindObject(obj);
-    ASSERT(object_id != kInvalidIndex);
-    intptr_t tags = MessageWriter::GetObjectTagsAndHash(ObjectPtr(obj));
-    writer_->WriteMarkedObjectImpl(obj, tags, object_id, kAsInlinedObject);
-  }
-
- private:
-  SnapshotWriter* writer_;
-};
-
-void SnapshotWriter::WriteForwardedObjects() {
-  WriteInlinedObjectVisitor visitor(this);
-  forward_list_->SerializeAll(&visitor);
-}
-
-void ForwardList::SerializeAll(ObjectVisitor* writer) {
-// Write out all objects that were added to the forward list and have
-// not been serialized yet. These would typically be fields of instance
-// objects, arrays or immutable arrays (this is done in order to avoid
-// deep recursive calls to WriteObjectImpl).
-// NOTE: The forward list might grow as we process the list.
-#ifdef DEBUG
-  for (intptr_t i = first_object_id(); i < first_unprocessed_object_id_; ++i) {
-    ASSERT(NodeForObjectId(i)->is_serialized());
-  }
-#endif  // DEBUG
-  for (intptr_t id = first_unprocessed_object_id_; id < next_object_id();
-       ++id) {
-    if (!NodeForObjectId(id)->is_serialized()) {
-      // Write the object out in the stream.
-      ObjectPtr raw = NodeForObjectId(id)->obj()->ptr();
-      writer->VisitObject(raw);
-
-      // Mark object as serialized.
-      NodeForObjectId(id)->set_state(kIsSerialized);
-    }
-  }
-  first_unprocessed_object_id_ = next_object_id();
-}
-
-void SnapshotWriter::WriteClassId(UntaggedClass* cls) {
-  ASSERT(!Snapshot::IsFull(kind_));
-  int class_id = cls->id_;
-  ASSERT(!IsSingletonClassId(class_id) && !IsBootstrapedClassId(class_id));
-
-  // Write out the library url and class name.
-  LibraryPtr library = cls->library();
-  ASSERT(library != Library::null());
-  WriteObjectImpl(library->untag()->url(), kAsInlinedObject);
-  WriteObjectImpl(cls->name(), kAsInlinedObject);
-}
-
-void SnapshotWriter::WriteStaticImplicitClosure(
-    intptr_t object_id,
-    FunctionPtr func,
-    intptr_t tags,
-    TypeArgumentsPtr delayed_type_arguments) {
-  // Write out the serialization header value for this object.
-  WriteInlinedObjectHeader(object_id);
-
-  // Indicate this is a static implicit closure object.
-  Write<int32_t>(SerializedHeaderData::encode(kStaticImplicitClosureObjectId));
-
-  // Write out the tags.
-  WriteTags(tags);
-
-  // Write out the library url, class name and signature function name.
-  ClassPtr cls = GetFunctionOwner(func);
-  ASSERT(cls != Class::null());
-  LibraryPtr library = cls->untag()->library();
-  ASSERT(library != Library::null());
-  WriteObjectImpl(library->untag()->url(), kAsInlinedObject);
-  WriteObjectImpl(cls->untag()->name(), kAsInlinedObject);
-  WriteObjectImpl(func->untag()->name(), kAsInlinedObject);
-  WriteObjectImpl(delayed_type_arguments, kAsInlinedObject);
-}
-
-void SnapshotWriter::ArrayWriteTo(intptr_t object_id,
-                                  intptr_t array_kind,
-                                  intptr_t tags,
-                                  SmiPtr length,
-                                  TypeArgumentsPtr type_arguments,
-                                  CompressedObjectPtr data[],
-                                  bool as_reference) {
-  if (as_reference) {
-    // Write out the serialization header value for this object.
-    WriteInlinedObjectHeader(kOmittedObjectId);
-
-    // Write out the class information.
-    WriteIndexedObject(array_kind);
-    WriteTags(tags);
-
-    // Write out the length field.
-    Write<ObjectPtr>(length);
-  } else {
-    intptr_t len = Smi::Value(length);
-
-    // Write out the serialization header value for this object.
-    WriteInlinedObjectHeader(object_id);
-
-    // Write out the class and tags information.
-    WriteIndexedObject(array_kind);
-    WriteTags(tags);
-
-    // Write out the length field.
-    Write<ObjectPtr>(length);
-
-    // Write out the type arguments.
-    WriteObjectImpl(type_arguments, kAsInlinedObject);
-
-    // Write out the individual object ids.
-    bool write_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-    uword heap_base = type_arguments.heap_base();
-    for (intptr_t i = 0; i < len; i++) {
-      WriteObjectImpl(data[i].Decompress(heap_base), write_as_reference);
-    }
-  }
-}
-
-FunctionPtr SnapshotWriter::IsSerializableClosure(ClosurePtr closure) {
-  // Extract the function object to check if this closure
-  // can be sent in an isolate message.
-  FunctionPtr func = closure->untag()->function();
-  // We only allow closure of top level methods or static functions in a
-  // class to be sent in isolate messages.
-  if (can_send_any_object() &&
-      Function::IsImplicitStaticClosureFunction(func)) {
-    return func;
-  }
-  // Not a closure of a top level method or static function, throw an
-  // exception as we do not allow these objects to be serialized.
-  HANDLESCOPE(thread());
-
-  const Function& errorFunc = Function::Handle(zone(), func);
-  ASSERT(!errorFunc.IsNull());
-
-  // All other closures are errors.
-  char* chars = OS::SCreate(
-      thread()->zone(),
-      "Illegal argument in isolate message : (object is a closure - %s)",
-      errorFunc.ToCString());
-  SetWriteException(Exceptions::kArgument, chars);
-  return Function::null();
-}
-
-ClassPtr SnapshotWriter::GetFunctionOwner(FunctionPtr func) {
-  ObjectPtr owner = func->untag()->owner();
-  uword tags = GetObjectTags(owner);
-  intptr_t class_id = UntaggedObject::ClassIdTag::decode(tags);
-  if (class_id == kClassCid) {
-    return static_cast<ClassPtr>(owner);
-  }
-  ASSERT(class_id == kPatchClassCid);
-  return static_cast<PatchClassPtr>(owner)->untag()->patched_class();
-}
-
-void SnapshotWriter::CheckForNativeFields(ClassPtr cls) {
-  if (cls->untag()->num_native_fields_ != 0) {
-    // We do not allow objects with native fields in an isolate message.
-    HANDLESCOPE(thread());
-    const Class& clazz = Class::Handle(zone(), cls);
-    char* chars = OS::SCreate(thread()->zone(),
-                              "Illegal argument in isolate message"
-                              " : (object extends NativeWrapper - %s)",
-                              clazz.ToCString());
-    SetWriteException(Exceptions::kArgument, chars);
-  }
-}
-
-void SnapshotWriter::SetWriteException(Exceptions::ExceptionType type,
-                                       const char* msg) {
-  set_exception_type(type);
-  set_exception_msg(msg);
-  // The more specific error is set up in SnapshotWriter::ThrowException().
-  thread()->long_jump_base()->Jump(1, Object::snapshot_writer_error());
-}
-
-void SnapshotWriter::WriteInstance(ObjectPtr raw,
-                                   ClassPtr cls,
-                                   intptr_t tags,
-                                   intptr_t object_id,
-                                   bool as_reference) {
-  // Closure instances are handled by UntaggedClosure::WriteTo().
-  ASSERT(!Class::IsClosureClass(cls));
-
-  // Check if the instance has native fields and throw an exception if it does.
-  CheckForNativeFields(cls);
-
-  // Object is regular dart instance.
-  if (as_reference) {
-    // Write out the serialization header value for this object.
-    WriteInlinedObjectHeader(kOmittedObjectId);
-
-    // Indicate this is an instance object.
-    Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId));
-    WriteTags(tags);
-
-    // Write out the class information for this object.
-    WriteObjectImpl(cls, kAsInlinedObject);
-  } else {
-    intptr_t next_field_offset = Class::host_next_field_offset_in_words(cls)
-                                 << kCompressedWordSizeLog2;
-    ASSERT(next_field_offset > 0);
-
-    // Write out the serialization header value for this object.
-    WriteInlinedObjectHeader(object_id);
-
-    // Indicate this is an instance object.
-    Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId));
-
-    // Write out the tags.
-    WriteTags(tags);
-
-    // Write out the class information for this object.
-    WriteObjectImpl(cls, kAsInlinedObject);
-
-    const auto unboxed_fields =
-        isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            cls->untag()->id_);
-
-    // Write out all the fields for the object.
-    // Instance::NextFieldOffset() returns the offset of the first field in
-    // a Dart object.
-    bool write_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-
-    intptr_t offset = Instance::NextFieldOffset();
-    uword heap_base = raw->heap_base();
-    while (offset < next_field_offset) {
-      if (unboxed_fields.Get(offset / kCompressedWordSize)) {
-        // Writes 32 bits of the unboxed value at a time
-        const uword value = *reinterpret_cast<compressed_uword*>(
-            reinterpret_cast<uword>(raw->untag()) + offset);
-        WriteWordWith32BitWrites(value);
-      } else {
-        ObjectPtr raw_obj = reinterpret_cast<CompressedObjectPtr*>(
-                                reinterpret_cast<uword>(raw->untag()) + offset)
-                                ->Decompress(heap_base);
-        WriteObjectImpl(raw_obj, write_as_reference);
-      }
-      offset += kCompressedWordSize;
-    }
-  }
-  return;
-}
-
-bool SnapshotWriter::AllowObjectsInDartLibrary(LibraryPtr library) {
-  return (library == object_store()->collection_library() ||
-          library == object_store()->core_library() ||
-          library == object_store()->typed_data_library());
-}
-
-intptr_t SnapshotWriter::FindVmSnapshotObject(ObjectPtr rawobj) {
-  intptr_t length = Object::vm_isolate_snapshot_object_table().Length();
-  for (intptr_t i = 0; i < length; i++) {
-    if (Object::vm_isolate_snapshot_object_table().At(i) == rawobj) {
-      return (i + kMaxPredefinedObjectIds);
-    }
-  }
-  return kInvalidIndex;
-}
-
-void SnapshotWriter::ThrowException(Exceptions::ExceptionType type,
-                                    const char* msg) {
-  {
-    NoSafepointScope no_safepoint;
-    ErrorPtr error = thread()->StealStickyError();
-    ASSERT(error == Object::snapshot_writer_error().ptr());
-  }
-
-  if (msg != NULL) {
-    const String& msg_obj = String::Handle(String::New(msg));
-    const Array& args = Array::Handle(Array::New(1));
-    args.SetAt(0, msg_obj);
-    Exceptions::ThrowByType(type, args);
-  } else {
-    Exceptions::ThrowByType(type, Object::empty_array());
-  }
-  UNREACHABLE();
-}
-
-void SnapshotWriter::WriteVersionAndFeatures() {
-  const char* expected_version = Version::SnapshotString();
-  ASSERT(expected_version != NULL);
-  const intptr_t version_len = strlen(expected_version);
-  WriteBytes(reinterpret_cast<const uint8_t*>(expected_version), version_len);
-
-  const char* expected_features =
-      Dart::FeaturesString(IsolateGroup::Current(), false, kind_);
-  ASSERT(expected_features != NULL);
-  const intptr_t features_len = strlen(expected_features);
-  WriteBytes(reinterpret_cast<const uint8_t*>(expected_features),
-             features_len + 1);
-  free(const_cast<char*>(expected_features));
-}
-
-void SnapshotWriterVisitor::VisitPointers(ObjectPtr* first, ObjectPtr* last) {
-  ASSERT(Utils::IsAligned(first, sizeof(*first)));
-  ASSERT(Utils::IsAligned(last, sizeof(*last)));
-  for (ObjectPtr* current = first; current <= last; current++) {
-    ObjectPtr raw_obj = *current;
-    writer_->WriteObjectImpl(raw_obj, as_references_);
-  }
-}
-
-void SnapshotWriterVisitor::VisitCompressedPointers(uword heap_base,
-                                                    CompressedObjectPtr* first,
-                                                    CompressedObjectPtr* last) {
-  ASSERT(Utils::IsAligned(first, sizeof(*first)));
-  ASSERT(Utils::IsAligned(last, sizeof(*last)));
-  for (CompressedObjectPtr* current = first; current <= last; current++) {
-    ObjectPtr raw_obj = current->Decompress(heap_base);
-    writer_->WriteObjectImpl(raw_obj, as_references_);
-  }
-}
-
-MessageWriter::MessageWriter(bool can_send_any_object)
-    : SnapshotWriter(Thread::Current(),
-                     Snapshot::kMessage,
-                     kInitialSize,
-                     &forward_list_,
-                     can_send_any_object),
-      forward_list_(thread(), kMaxPredefinedObjectIds),
-      finalizable_data_(new MessageFinalizableData()) {}
-
-MessageWriter::~MessageWriter() {
-  delete finalizable_data_;
-}
-
-std::unique_ptr<Message> MessageWriter::WriteMessage(
-    const Object& obj,
-    Dart_Port dest_port,
-    Message::Priority priority) {
-  ASSERT(kind() == Snapshot::kMessage);
-  ASSERT(isolate() != NULL);
-
-  // Setup for long jump in case there is an exception while writing
-  // the message.
-  volatile bool has_exception = false;
-  {
-    LongJumpScope jump;
-    if (setjmp(*jump.Set()) == 0) {
-      NoSafepointScope no_safepoint;
-      WriteObject(obj.ptr());
-    } else {
-      FreeBuffer();
-      has_exception = true;
-    }
-  }
-  if (has_exception) {
-    ThrowException(exception_type(), exception_msg());
-  } else {
-    finalizable_data_->SerializationSucceeded();
-  }
-
-  MessageFinalizableData* finalizable_data = finalizable_data_;
-  finalizable_data_ = nullptr;
-  intptr_t size;
-  uint8_t* buffer = Steal(&size);
-  return Message::New(dest_port, buffer, size, finalizable_data, priority);
-}
 
 }  // namespace dart
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 60da2b3..63d61a8 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -9,83 +9,14 @@
 #include <utility>
 
 #include "platform/assert.h"
+#include "platform/unaligned.h"
 #include "vm/allocation.h"
-#include "vm/bitfield.h"
-#include "vm/datastream.h"
-#include "vm/finalizable_data.h"
 #include "vm/globals.h"
-#include "vm/growable_array.h"
-#include "vm/isolate.h"
 #include "vm/message.h"
-#include "vm/visitor.h"
+#include "vm/thread.h"
 
 namespace dart {
 
-// Forward declarations.
-class AbstractType;
-class Array;
-class Class;
-class ClassTable;
-class Closure;
-class Code;
-class ExternalTypedData;
-class TypedDataBase;
-class GrowableObjectArray;
-class Heap;
-class Instance;
-class Instructions;
-class LanguageError;
-class Library;
-class LinkedHashMap;
-class Object;
-class PassiveObject;
-class ObjectStore;
-class MegamorphicCache;
-class PageSpace;
-class TypedDataView;
-class String;
-class TypeArguments;
-class TypedData;
-class UnhandledException;
-
-// Serialized object header encoding is as follows:
-// - Smi: the Smi value is written as is (last bit is not tagged).
-// - VM object (from VM isolate): (object id in vm isolate | 0x3)
-//   This value is serialized as a negative number.
-//   (note VM objects are never serialized, they are expected to be found
-//    using ths unique ID assigned to them).
-// - Reference to object that has already been written: (object id | 0x3)
-//   This valus is serialized as a positive number.
-// - Object that is seen for the first time (inlined in the stream):
-//   (a unique id for this object | 0x1)
-enum SerializedHeaderType {
-  kInlined = 0x1,
-  kObjectId = 0x3,
-};
-static const int8_t kHeaderTagBits = 2;
-static const int8_t kObjectIdBits = (kBitsPerInt32 - (kHeaderTagBits + 1));
-static const intptr_t kMaxObjectId = (kMaxUint32 >> (kHeaderTagBits + 1));
-static const bool kAsReference = true;
-static const bool kAsInlinedObject = false;
-static const intptr_t kInvalidPatchIndex = -1;
-
-class SerializedHeaderTag
-    : public BitField<intptr_t, enum SerializedHeaderType, 0, kHeaderTagBits> {
-};
-
-class SerializedHeaderData
-    : public BitField<intptr_t, intptr_t, kHeaderTagBits, kObjectIdBits> {};
-
-enum DeserializeState {
-  kIsDeserialized = 0,
-  kIsNotDeserialized = 1,
-};
-
-enum SerializeState {
-  kIsSerialized = 0,
-  kIsNotSerialized = 1,
-};
-
 // Structure capturing the raw snapshot.
 //
 class Snapshot {
@@ -95,7 +26,6 @@
     kFullCore,  // Full snapshot of core libraries. Agnostic to null safety.
     kFullJIT,   // Full + JIT code
     kFullAOT,   // Full + AOT code
-    kMessage,   // A partial snapshot used only for isolate messaging.
     kNone,      // gen_snapshot
     kInvalid
   };
@@ -185,529 +115,6 @@
   return Snapshot::IsFull(isolate_kind);
 }
 
-class BaseReader {
- public:
-  BaseReader(const uint8_t* buffer, intptr_t size) : stream_(buffer, size) {}
-  // Reads raw data (for basic types).
-  // sizeof(T) must be in {1,2,4,8}.
-  template <typename T>
-  T Read() {
-    return ReadStream::Raw<sizeof(T), T>::Read(&stream_);
-  }
-
-  classid_t ReadClassIDValue() {
-    uint32_t value = Read<uint32_t>();
-    return static_cast<classid_t>(value);
-  }
-  COMPILE_ASSERT(sizeof(uint32_t) >= sizeof(classid_t));
-
-  void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); }
-
-  double ReadDouble() {
-    double result;
-    stream_.ReadBytes(reinterpret_cast<uint8_t*>(&result), sizeof(result));
-    return result;
-  }
-
-  intptr_t ReadTags() {
-    const intptr_t tags = static_cast<intptr_t>(Read<int8_t>()) & 0xff;
-    return tags;
-  }
-
-  const uint8_t* CurrentBufferAddress() const {
-    return stream_.AddressOfCurrentPosition();
-  }
-
-  void Align(intptr_t value) { stream_.Align(value); }
-  void Advance(intptr_t value) { stream_.Advance(value); }
-
-  intptr_t PendingBytes() const { return stream_.PendingBytes(); }
-
-  SmiPtr ReadAsSmi();
-  intptr_t ReadSmiValue();
-
-  // Negative header value indicates VM isolate object id.
-  bool IsVMIsolateObject(intptr_t header_value) { return (header_value < 0); }
-  intptr_t GetVMIsolateObjectId(intptr_t header_val) {
-    ASSERT(IsVMIsolateObject(header_val));
-    intptr_t value = -header_val;  // Header is negative for VM isolate objects.
-    ASSERT(SerializedHeaderTag::decode(value) == kObjectId);
-    return SerializedHeaderData::decode(value);
-  }
-
-  uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); }
-
- private:
-  ReadStream stream_;  // input stream.
-};
-
-class BackRefNode : public ValueObject {
- public:
-  BackRefNode(Object* reference, DeserializeState state)
-      : reference_(reference), state_(state) {}
-  Object* reference() const { return reference_; }
-  bool is_deserialized() const { return state_ == kIsDeserialized; }
-  void set_state(DeserializeState state) { state_ = state; }
-
-  BackRefNode& operator=(const BackRefNode& other) {
-    reference_ = other.reference_;
-    state_ = other.state_;
-    return *this;
-  }
-
- private:
-  Object* reference_;
-  DeserializeState state_;
-};
-
-// Reads a snapshot into objects.
-class SnapshotReader : public BaseReader {
- public:
-  Thread* thread() const { return thread_; }
-  Zone* zone() const { return zone_; }
-  Isolate* isolate() const { return thread_->isolate(); }
-  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
-  Heap* heap() const { return heap_; }
-  ObjectStore* object_store() const { return isolate_group()->object_store(); }
-  ClassTable* class_table() const { return isolate_group()->class_table(); }
-  PassiveObject* PassiveObjectHandle() { return &pobj_; }
-  Array* ArrayHandle() { return &array_; }
-  Class* ClassHandle() { return &cls_; }
-  Code* CodeHandle() { return &code_; }
-  Instance* InstanceHandle() { return &instance_; }
-  Instructions* InstructionsHandle() { return &instructions_; }
-  String* StringHandle() { return &str_; }
-  AbstractType* TypeHandle() { return &type_; }
-  TypeArguments* TypeArgumentsHandle() { return &type_arguments_; }
-  GrowableObjectArray* TokensHandle() { return &tokens_; }
-  ExternalTypedData* DataHandle() { return &data_; }
-  TypedDataBase* TypedDataBaseHandle() { return &typed_data_base_; }
-  TypedData* TypedDataHandle() { return &typed_data_; }
-  TypedDataView* TypedDataViewHandle() { return &typed_data_view_; }
-  Function* FunctionHandle() { return &function_; }
-  Smi* SmiHandle() { return &smi_; }
-  Snapshot::Kind kind() const { return kind_; }
-
-  // Reads an object.
-  ObjectPtr ReadObject();
-
-  // Add object to backward references.
-  void AddBackRef(intptr_t id, Object* obj, DeserializeState state);
-
-  // Get an object from the backward references list.
-  Object* GetBackRef(intptr_t id);
-
-  // Read version number of snapshot and verify.
-  ApiErrorPtr VerifyVersionAndFeatures(IsolateGroup* isolate_group);
-
-  ObjectPtr NewInteger(int64_t value);
-
- protected:
-  SnapshotReader(const uint8_t* buffer,
-                 intptr_t size,
-                 Snapshot::Kind kind,
-                 ZoneGrowableArray<BackRefNode>* backward_references,
-                 Thread* thread);
-  ~SnapshotReader() {}
-
-  ZoneGrowableArray<BackRefNode>* GetBackwardReferenceTable() const {
-    return backward_references_;
-  }
-  void ResetBackwardReferenceTable() { backward_references_ = NULL; }
-  PageSpace* old_space() const { return old_space_; }
-
- private:
-  void EnqueueTypePostprocessing(const AbstractType& type);
-  void RunDelayedTypePostprocessing();
-
-  void EnqueueRehashingOfMap(const LinkedHashMap& map);
-  void EnqueueRehashingOfSet(const Object& set);
-  ObjectPtr RunDelayedRehashingOfMaps();
-
-  ClassPtr ReadClassId(intptr_t object_id);
-  ObjectPtr ReadStaticImplicitClosure(intptr_t object_id, intptr_t cls_header);
-
-  // Implementation to read an object.
-  ObjectPtr ReadObjectImpl(bool as_reference);
-  ObjectPtr ReadObjectImpl(intptr_t header, bool as_reference);
-
-  // Read a Dart Instance object.
-  ObjectPtr ReadInstance(intptr_t object_id, intptr_t tags, bool as_reference);
-
-  // Read a VM isolate object that was serialized as an Id.
-  ObjectPtr ReadVMIsolateObject(intptr_t object_id);
-
-  // Read an object that was serialized as an Id (singleton in object store,
-  // or an object that was already serialized before).
-  ObjectPtr ReadIndexedObject(intptr_t object_id);
-
-  // Decode class id from the header field.
-  intptr_t LookupInternalClass(intptr_t class_header);
-
-  void ArrayReadFrom(intptr_t object_id,
-                     const Array& result,
-                     intptr_t len,
-                     intptr_t tags);
-
-  intptr_t NextAvailableObjectId() const;
-
-  void SetReadException(const char* msg);
-
-  ObjectPtr VmIsolateSnapshotObject(intptr_t index) const;
-
-  bool is_vm_isolate() const;
-
-  Snapshot::Kind kind_;            // Indicates type of the snapshot.
-  Thread* thread_;                 // Current thread.
-  Zone* zone_;                     // Zone for allocations while reading.
-  Heap* heap_;                     // Heap of the current isolate.
-  PageSpace* old_space_;           // Old space of the current isolate.
-  Class& cls_;                     // Temporary Class handle.
-  Code& code_;                     // Temporary Code handle.
-  Instance& instance_;             // Temporary Instance handle
-  Instructions& instructions_;     // Temporary Instructions handle
-  Object& obj_;                    // Temporary Object handle.
-  PassiveObject& pobj_;            // Temporary PassiveObject handle.
-  Array& array_;                   // Temporary Array handle.
-  Field& field_;                   // Temporary Field handle.
-  String& str_;                    // Temporary String handle.
-  Library& library_;               // Temporary library handle.
-  AbstractType& type_;             // Temporary type handle.
-  TypeArguments& type_arguments_;  // Temporary type argument handle.
-  GrowableObjectArray& tokens_;    // Temporary tokens handle.
-  ExternalTypedData& data_;        // Temporary stream data handle.
-  TypedDataBase& typed_data_base_;  // Temporary typed data base handle.
-  TypedData& typed_data_;          // Temporary typed data handle.
-  TypedDataView& typed_data_view_;  // Temporary typed data view handle.
-  Function& function_;             // Temporary function handle.
-  Smi& smi_;                       // Temporary Smi handle.
-  UnhandledException& error_;      // Error handle.
-  const Class& set_class_;         // The LinkedHashSet class.
-  intptr_t max_vm_isolate_object_id_;
-  ZoneGrowableArray<BackRefNode>* backward_references_;
-  GrowableObjectArray& types_to_postprocess_;
-  GrowableObjectArray& objects_to_rehash_;
-
-  friend class ApiError;
-  friend class Array;
-  friend class Class;
-  friend class Closure;
-  friend class ClosureData;
-  friend class Context;
-  friend class ContextScope;
-  friend class ExceptionHandlers;
-  friend class Field;
-  friend class Function;
-  friend class GrowableObjectArray;
-  friend class ICData;
-  friend class ImmutableArray;
-  friend class KernelProgramInfo;
-  friend class LanguageError;
-  friend class Library;
-  friend class LibraryPrefix;
-  friend class LinkedHashMap;
-  friend class MirrorReference;
-  friend class Namespace;
-  friend class PatchClass;
-  friend class RegExp;
-  friend class Script;
-  friend class SubtypeTestCache;
-  friend class TransferableTypedData;
-  friend class Type;
-  friend class FunctionType;
-  friend class TypedDataView;
-  friend class TypeParameters;
-  friend class TypeArguments;
-  friend class TypeParameter;
-  friend class TypeRef;
-  friend class UnhandledException;
-  friend class WeakProperty;
-  friend class WeakSerializationReference;
-  DISALLOW_COPY_AND_ASSIGN(SnapshotReader);
-};
-
-class MessageSnapshotReader : public SnapshotReader {
- public:
-  MessageSnapshotReader(Message* message, Thread* thread);
-  ~MessageSnapshotReader();
-
-  MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
-
- private:
-  MessageFinalizableData* finalizable_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageSnapshotReader);
-};
-
-class BaseWriter : public StackResource {
- public:
-  uint8_t* Steal(intptr_t* length) { return stream_.Steal(length); }
-  intptr_t BytesWritten() const { return stream_.bytes_written(); }
-
-  // Writes raw data to the stream (basic type).
-  // sizeof(T) must be in {1,2,4,8}.
-  template <typename T>
-  void Write(T value) {
-    MallocWriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
-  }
-
-  void WriteClassIDValue(classid_t value) { Write<uint32_t>(value); }
-  COMPILE_ASSERT(sizeof(uint32_t) >= sizeof(classid_t));
-
-  // Write an object that is serialized as an Id (singleton in object store,
-  // or an object that was already serialized before).
-  void WriteIndexedObject(intptr_t object_id) {
-    ASSERT(object_id <= kMaxObjectId);
-    intptr_t value = 0;
-    value = SerializedHeaderTag::update(kObjectId, value);
-    value = SerializedHeaderData::update(object_id, value);
-    Write<int32_t>(value);
-  }
-
-  // Write a VM Isolateobject that is serialized as an Id.
-  void WriteVMIsolateObject(intptr_t object_id) {
-    ASSERT(object_id <= kMaxObjectId);
-    intptr_t value = 0;
-    value = SerializedHeaderTag::update(kObjectId, value);
-    value = SerializedHeaderData::update(object_id, value);
-    Write<int32_t>(-value);  // Write as a negative value.
-  }
-
-  // Write serialization header information for an object.
-  void WriteInlinedObjectHeader(intptr_t id) {
-    ASSERT(id <= kMaxObjectId);
-    intptr_t value = 0;
-    value = SerializedHeaderTag::update(kInlined, value);
-    value = SerializedHeaderData::update(id, value);
-    Write<int32_t>(value);
-  }
-
-  void WriteTags(intptr_t tags) {
-    const intptr_t flags = tags & 0xff;
-    Write<int8_t>(static_cast<int8_t>(flags));
-  }
-
-  void Align(intptr_t value) { stream_.Align(value); }
-
-  // Write out a buffer of bytes.
-  void WriteBytes(const uint8_t* addr, intptr_t len) {
-    stream_.WriteBytes(addr, len);
-  }
-
-  void WriteDouble(double value) {
-    stream_.WriteBytes(reinterpret_cast<const uint8_t*>(&value), sizeof(value));
-  }
-
-  void WriteWordWith32BitWrites(uword value) {
-    stream_.WriteWordWith32BitWrites(value);
-  }
-
- protected:
-  explicit BaseWriter(intptr_t initial_size)
-      : StackResource(Thread::Current()), stream_(initial_size) {}
-  ~BaseWriter() {}
-
-  void ReserveHeader() {
-    // Make room for recording snapshot buffer size.
-    stream_.SetPosition(Snapshot::kHeaderSize);
-  }
-
-  void FillHeader(Snapshot::Kind kind) {
-    intptr_t length;
-    Snapshot* header = reinterpret_cast<Snapshot*>(Steal(&length));
-    header->set_magic();
-    header->set_length(length);
-    header->set_kind(kind);
-  }
-
-  void FreeBuffer() {
-    intptr_t unused;
-    free(Steal(&unused));
-  }
-
- private:
-  MallocWriteStream stream_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(BaseWriter);
-};
-
-class ForwardList {
- public:
-  explicit ForwardList(Thread* thread, intptr_t first_object_id);
-  ~ForwardList();
-
-  class Node : public ZoneAllocated {
-   public:
-    Node(const Object* obj, SerializeState state) : obj_(obj), state_(state) {}
-    const Object* obj() const { return obj_; }
-    bool is_serialized() const { return state_ == kIsSerialized; }
-
-   private:
-    // Private to ensure the invariant of first_unprocessed_object_id_.
-    void set_state(SerializeState value) { state_ = value; }
-
-    const Object* obj_;
-    SerializeState state_;
-
-    friend class ForwardList;
-    DISALLOW_COPY_AND_ASSIGN(Node);
-  };
-
-  Node* NodeForObjectId(intptr_t object_id) const {
-    return nodes_[object_id - first_object_id_];
-  }
-
-  // Returns the id for the added object.
-  intptr_t AddObject(Zone* zone, ObjectPtr raw, SerializeState state);
-
-  // Returns the id for the object it it exists in the list.
-  intptr_t FindObject(ObjectPtr raw);
-
-  // Exhaustively processes all unserialized objects in this list. 'writer' may
-  // concurrently add more objects.
-  void SerializeAll(ObjectVisitor* writer);
-
-  // Set state of object in forward list.
-  void SetState(intptr_t object_id, SerializeState state) {
-    NodeForObjectId(object_id)->set_state(state);
-  }
-
- private:
-  intptr_t first_object_id() const { return first_object_id_; }
-  intptr_t next_object_id() const { return nodes_.length() + first_object_id_; }
-  Isolate* isolate() const { return thread_->isolate(); }
-
-  Thread* thread_;
-  const intptr_t first_object_id_;
-  GrowableArray<Node*> nodes_;
-  intptr_t first_unprocessed_object_id_;
-
-  void SetObjectId(ObjectPtr object, intptr_t id);
-  intptr_t GetObjectId(ObjectPtr object);
-
-  DISALLOW_COPY_AND_ASSIGN(ForwardList);
-};
-
-class SnapshotWriter : public BaseWriter {
- protected:
-  SnapshotWriter(Thread* thread,
-                 Snapshot::Kind kind,
-                 intptr_t initial_size,
-                 ForwardList* forward_list,
-                 bool can_send_any_object);
-
- public:
-  // Snapshot kind.
-  Snapshot::Kind kind() const { return kind_; }
-  Thread* thread() const { return thread_; }
-  Zone* zone() const { return thread_->zone(); }
-  Isolate* isolate() const { return thread_->isolate(); }
-  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
-  Heap* heap() const { return isolate_group()->heap(); }
-
-  // Serialize an object into the buffer.
-  void WriteObject(ObjectPtr raw);
-
-  static uint32_t GetObjectTags(ObjectPtr raw);
-  static uint32_t GetObjectTags(UntaggedObject* raw);
-  static uword GetObjectTagsAndHash(ObjectPtr raw);
-
-  Exceptions::ExceptionType exception_type() const { return exception_type_; }
-  void set_exception_type(Exceptions::ExceptionType type) {
-    exception_type_ = type;
-  }
-  const char* exception_msg() const { return exception_msg_; }
-  void set_exception_msg(const char* msg) { exception_msg_ = msg; }
-  bool can_send_any_object() const { return can_send_any_object_; }
-  void ThrowException(Exceptions::ExceptionType type, const char* msg);
-
-  // Write a version string for the snapshot.
-  void WriteVersionAndFeatures();
-
-  FunctionPtr IsSerializableClosure(ClosurePtr closure);
-
-  void WriteStaticImplicitClosure(intptr_t object_id,
-                                  FunctionPtr func,
-                                  intptr_t tags,
-                                  TypeArgumentsPtr delayed_type_arguments);
-
- protected:
-  bool CheckAndWritePredefinedObject(ObjectPtr raw);
-  bool HandleVMIsolateObject(ObjectPtr raw);
-
-  void WriteClassId(UntaggedClass* cls);
-  void WriteObjectImpl(ObjectPtr raw, bool as_reference);
-  void WriteMarkedObjectImpl(ObjectPtr raw,
-                             intptr_t tags,
-                             intptr_t object_id,
-                             bool as_reference);
-  void WriteForwardedObjects();
-  void ArrayWriteTo(intptr_t object_id,
-                    intptr_t array_kind,
-                    intptr_t tags,
-                    SmiPtr length,
-                    TypeArgumentsPtr type_arguments,
-                    CompressedObjectPtr data[],
-                    bool as_reference);
-  ClassPtr GetFunctionOwner(FunctionPtr func);
-  void CheckForNativeFields(ClassPtr cls);
-  void SetWriteException(Exceptions::ExceptionType type, const char* msg);
-  void WriteInstance(ObjectPtr raw,
-                     ClassPtr cls,
-                     intptr_t tags,
-                     intptr_t object_id,
-                     bool as_reference);
-  bool AllowObjectsInDartLibrary(LibraryPtr library);
-  intptr_t FindVmSnapshotObject(ObjectPtr rawobj);
-
-  ObjectStore* object_store() const { return object_store_; }
-
- private:
-  Thread* thread_;
-  Snapshot::Kind kind_;
-  ObjectStore* object_store_;  // Object store for common classes.
-  ClassTable* class_table_;  // Class table for the class index to class lookup.
-  ForwardList* forward_list_;
-  Exceptions::ExceptionType exception_type_;  // Exception type.
-  const char* exception_msg_;  // Message associated with exception.
-  bool can_send_any_object_;   // True if any Dart instance can be sent.
-
-  friend class UntaggedArray;
-  friend class UntaggedClass;
-  friend class UntaggedCode;
-  friend class UntaggedContextScope;
-  friend class UntaggedDynamicLibrary;
-  friend class UntaggedExceptionHandlers;
-  friend class UntaggedField;
-  friend class UntaggedFunction;
-  friend class UntaggedFunctionType;
-  friend class UntaggedGrowableObjectArray;
-  friend class UntaggedImmutableArray;
-  friend class UntaggedInstructions;
-  friend class UntaggedLibrary;
-  friend class UntaggedLinkedHashMap;
-  friend class UntaggedLocalVarDescriptors;
-  friend class UntaggedMirrorReference;
-  friend class UntaggedObjectPool;
-  friend class UntaggedPointer;
-  friend class UntaggedReceivePort;
-  friend class UntaggedRegExp;
-  friend class UntaggedScript;
-  friend class UntaggedStackTrace;
-  friend class UntaggedSubtypeTestCache;
-  friend class UntaggedTransferableTypedData;
-  friend class UntaggedType;
-  friend class UntaggedTypeArguments;
-  friend class UntaggedTypeParameter;
-  friend class UntaggedTypeRef;
-  friend class UntaggedTypedDataView;
-  friend class UntaggedUserTag;
-  friend class UntaggedWeakSerializationReference;
-  friend class SnapshotWriterVisitor;
-  friend class WriteInlinedObjectVisitor;
-  DISALLOW_COPY_AND_ASSIGN(SnapshotWriter);
-};
-
 class SerializedObjectBuffer : public StackResource {
  public:
   SerializedObjectBuffer()
@@ -723,46 +130,6 @@
   std::unique_ptr<Message> message_;
 };
 
-class MessageWriter : public SnapshotWriter {
- public:
-  static const intptr_t kInitialSize = 512;
-  explicit MessageWriter(bool can_send_any_object);
-  ~MessageWriter();
-
-  std::unique_ptr<Message> WriteMessage(const Object& obj,
-                                        Dart_Port dest_port,
-                                        Message::Priority priority);
-
-  MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
-
- private:
-  ForwardList forward_list_;
-  MessageFinalizableData* finalizable_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageWriter);
-};
-
-// An object pointer visitor implementation which writes out
-// objects to a snapshot.
-class SnapshotWriterVisitor : public ObjectPointerVisitor {
- public:
-  SnapshotWriterVisitor(SnapshotWriter* writer, bool as_references)
-      : ObjectPointerVisitor(Isolate::Current()->group()),
-        writer_(writer),
-        as_references_(as_references) {}
-
-  void VisitPointers(ObjectPtr* first, ObjectPtr* last);
-  void VisitCompressedPointers(uword heap_base,
-                               CompressedObjectPtr* first,
-                               CompressedObjectPtr* last);
-
- private:
-  SnapshotWriter* writer_;
-  bool as_references_;
-
-  DISALLOW_COPY_AND_ASSIGN(SnapshotWriterVisitor);
-};
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_SNAPSHOT_H_
diff --git a/runtime/vm/snapshot_ids.h b/runtime/vm/snapshot_ids.h
deleted file mode 100644
index b38bf1b..0000000
--- a/runtime/vm/snapshot_ids.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#ifndef RUNTIME_VM_SNAPSHOT_IDS_H_
-#define RUNTIME_VM_SNAPSHOT_IDS_H_
-
-#include "vm/dart_entry.h"
-#include "vm/raw_object.h"
-
-namespace dart {
-
-// Index for predefined singleton objects used in a snapshot.
-enum {
-  kNullObject = 0,
-  kSentinelObject,
-  kTransitionSentinelObject,
-  kEmptyArrayObject,
-  kZeroArrayObject,
-  kTrueValue,
-  kFalseValue,
-  // Marker for special encoding of double objects in message snapshots.
-  kDoubleObject,
-  // Object id has been optimized away; reader should use next available id.
-  kOmittedObjectId,
-
-  kClassIdsOffset = kOmittedObjectId,
-
-  // The class ids of predefined classes are included in this list
-  // at an offset of kClassIdsOffset.
-
-  kFirstTypeSnapshotId = (kNumPredefinedCids + kClassIdsOffset),
-  kLegacyObjectType = kFirstTypeSnapshotId,
-  kNullableObjectType,
-  kNullType,
-  kDynamicType,
-  kVoidType,
-  kNeverType,
-  kLegacyFunctionType,
-  kLegacyNumberType,
-  kLegacySmiType,
-  kLegacyMintType,
-  kLegacyDoubleType,
-  kLegacyIntType,
-  kLegacyBoolType,
-  kLegacyStringType,
-  kLegacyArrayType,
-  kNonNullableObjectType,
-  kNonNullableFunctionType,
-  kNonNullableNumberType,
-  kNonNullableSmiType,
-  kNonNullableMintType,
-  kNonNullableDoubleType,
-  kNonNullableIntType,
-  kNonNullableBoolType,
-  kNonNullableStringType,
-  kNonNullableArrayType,
-  kLastTypeSnapshotId = kNonNullableArrayType,
-
-  kFirstTypeArgumentsSnapshotId = kLastTypeSnapshotId + 1,
-  kLegacyIntTypeArguments = kFirstTypeArgumentsSnapshotId,
-  kLegacyDoubleTypeArguments,
-  kLegacyStringTypeArguments,
-  kLegacyStringDynamicTypeArguments,
-  kLegacyStringLegacyStringTypeArguments,
-  kNonNullableIntTypeArguments,
-  kNonNullableDoubleTypeArguments,
-  kNonNullableStringTypeArguments,
-  kNonNullableStringDynamicTypeArguments,
-  kNonNullableStringNonNullableStringTypeArguments,
-  kEmptyTypeArguments,
-  kLastTypeArgumentsSnapshotId = kEmptyTypeArguments,
-
-  kExtractorParameterTypes,
-  kExtractorParameterNames,
-  kEmptyContextScopeObject,
-  kImplicitClosureScopeObject,
-  kEmptyObjectPool,
-  kEmptyDescriptors,
-  kEmptyVarDescriptors,
-  kEmptyExceptionHandlers,
-  kCachedArgumentsDescriptor0,
-  kCachedArgumentsDescriptorN =
-      (kCachedArgumentsDescriptor0 +
-       ArgumentsDescriptor::kCachedDescriptorCount - 1),
-  kCachedICDataArray0,
-  kCachedICDataArrayN =
-      (kCachedICDataArray0 + ICData::kCachedICDataArrayCount - 1),
-
-  kInstanceObjectId,
-  kStaticImplicitClosureObjectId,
-  kMaxPredefinedObjectIds,
-  kInvalidIndex = -1,
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_SNAPSHOT_IDS_H_
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 944124f..8affadb 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -15,6 +15,7 @@
 #include "vm/debugger_api_impl_test.h"
 #include "vm/flags.h"
 #include "vm/malloc_hooks.h"
+#include "vm/message_snapshot.h"
 #include "vm/snapshot.h"
 #include "vm/symbols.h"
 #include "vm/timer.h"
@@ -59,7 +60,6 @@
   // Return immediately if entering a cycle.
   if (second->type == Dart_CObject_kNumberOfTypes) return;
 
-  EXPECT_NE(first, second);
   EXPECT_EQ(first->type, second->type);
   switch (first->type) {
     case Dart_CObject_kNull:
@@ -106,23 +106,20 @@
   }
 }
 
-static void CheckEncodeDecodeMessage(Dart_CObject* root) {
+static void CheckEncodeDecodeMessage(Zone* zone, Dart_CObject* root) {
   // Encode and decode the message.
-  ApiMessageWriter writer;
   std::unique_ptr<Message> message =
-      writer.WriteCMessage(root, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteApiMessage(zone, root, ILLEGAL_PORT, Message::kNormalPriority);
 
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* new_root = api_reader.ReadMessage();
+  Dart_CObject* new_root = ReadApiMessage(zone, message.get());
 
   // Check that the two messages are the same.
   CompareDartCObjects(root, new_root);
 }
 
-static void ExpectEncodeFail(Dart_CObject* root) {
-  ApiMessageWriter writer;
+static void ExpectEncodeFail(Zone* zone, Dart_CObject* root) {
   std::unique_ptr<Message> message =
-      writer.WriteCMessage(root, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteApiMessage(zone, root, ILLEGAL_PORT, Message::kNormalPriority);
   EXPECT(message == nullptr);
 }
 
@@ -131,22 +128,21 @@
 
   // Write snapshot with object content.
   const Object& null_object = Object::Handle();
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(null_object, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, null_object, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   EXPECT(Equals(null_object, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kNull, root->type);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeSmi1) {
@@ -154,23 +150,22 @@
 
   // Write snapshot with object content.
   const Smi& smi = Smi::Handle(Smi::New(124));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, smi, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   EXPECT(Equals(smi, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kInt32, root->type);
   EXPECT_EQ(smi.Value(), root->value.as_int32);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeSmi2) {
@@ -178,46 +173,44 @@
 
   // Write snapshot with object content.
   const Smi& smi = Smi::Handle(Smi::New(-1));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, smi, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   EXPECT(Equals(smi, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kInt32, root->type);
   EXPECT_EQ(smi.Value(), root->value.as_int32);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
-Dart_CObject* SerializeAndDeserializeMint(const Mint& mint) {
+Dart_CObject* SerializeAndDeserializeMint(Zone* zone, const Mint& mint) {
   // Write snapshot with object content.
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(mint, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, mint, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   {
     // Switch to a regular zone, where VM handle allocation is allowed.
     Thread* thread = Thread::Current();
     StackZone zone(thread);
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message.get(), thread);
-    const Object& serialized_object = Object::Handle(reader.ReadObject());
+    const Object& serialized_object =
+        Object::Handle(ReadMessage(thread, message.get()));
     EXPECT(serialized_object.IsMint());
   }
 
   // Read object back from the snapshot into a C structure.
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(zone, message.get());
   EXPECT_NOTNULL(root);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(zone, root);
   return root;
 }
 
@@ -227,7 +220,8 @@
 
   Mint& mint = Mint::Handle();
   mint ^= Integer::New(value);
-  Dart_CObject* mint_cobject = SerializeAndDeserializeMint(mint);
+  Dart_CObject* mint_cobject =
+      SerializeAndDeserializeMint(zone.GetZone(), mint);
 // On 64-bit platforms mints always require 64-bits as the smi range
 // here covers most of the 64-bit range. On 32-bit platforms the smi
 // range covers most of the 32-bit range and values outside that
@@ -270,23 +264,22 @@
 
   // Write snapshot with object content.
   const Double& dbl = Double::Handle(Double::New(101.29));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(dbl, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, dbl, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   EXPECT(Equals(dbl, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kDouble, root->type);
   EXPECT_EQ(dbl.value(), root->value.as_double);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeTrue) {
@@ -294,25 +287,24 @@
 
   // Write snapshot with true object.
   const Bool& bl = Bool::True();
-  MessageWriter writer(true);
-  std::unique_ptr<Message> message =
-      writer.WriteMessage(bl, ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* can_send_any_object */ true, bl, ILLEGAL_PORT,
+      Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   fprintf(stderr, "%s / %s\n", bl.ToCString(), serialized_object.ToCString());
 
   EXPECT(Equals(bl, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kBool, root->type);
   EXPECT_EQ(true, root->value.as_bool);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeFalse) {
@@ -320,57 +312,55 @@
 
   // Write snapshot with false object.
   const Bool& bl = Bool::False();
-  MessageWriter writer(true);
-  std::unique_ptr<Message> message =
-      writer.WriteMessage(bl, ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* can_send_any_object */ true, bl, ILLEGAL_PORT,
+      Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   EXPECT(Equals(bl, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kBool, root->type);
   EXPECT_EQ(false, root->value.as_bool);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeCapability) {
   // Write snapshot with object content.
   const Capability& capability = Capability::Handle(Capability::New(12345));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(capability, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, capability, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   Capability& obj = Capability::Handle();
-  obj ^= reader.ReadObject();
+  obj ^= ReadMessage(thread, message.get());
 
   EXPECT_EQ(static_cast<uint64_t>(12345), obj.Id());
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kCapability, root->type);
   int64_t id = root->value.as_capability.id;
   EXPECT_EQ(12345, id);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 #define TEST_ROUND_TRIP_IDENTICAL(object)                                      \
   {                                                                            \
-    MessageWriter writer(true);                                                \
-    std::unique_ptr<Message> message = writer.WriteMessage(                    \
-        Object::Handle(object), ILLEGAL_PORT, Message::kNormalPriority);       \
-    MessageSnapshotReader reader(message.get(), thread);                       \
-    EXPECT(reader.ReadObject() == object);                                     \
+    const Object& before = Object::Handle(object);                             \
+    std::unique_ptr<Message> message =                                         \
+        WriteMessage(/* can_send_any_object */ true, before, ILLEGAL_PORT,     \
+                     Message::kNormalPriority);                                \
+    const Object& after = Object::Handle(ReadMessage(thread, message.get()));  \
+    EXPECT(before.ptr() == after.ptr());                                       \
   }
 
 ISOLATE_UNIT_TEST_CASE(SerializeSingletons) {
@@ -393,23 +383,21 @@
   EXPECT(Utf8::IsValid(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr)));
   // Write snapshot with object content.
   String& str = String::Handle(String::New(cstr));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, str, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   String& serialized_str = String::Handle();
-  serialized_str ^= reader.ReadObject();
+  serialized_str ^= ReadMessage(thread, message.get());
   EXPECT(str.Equals(serialized_str));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kString, root->type);
   EXPECT_STREQ(cstr, root->value.as_string);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeString) {
@@ -436,20 +424,18 @@
     smi ^= Smi::New(i);
     array.SetAt(i, smi);
   }
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   Array& serialized_array = Array::Handle();
-  serialized_array ^= reader.ReadObject();
+  serialized_array ^= ReadMessage(thread, message.get());
   EXPECT(array.CanonicalizeEquals(serialized_array));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kArray, root->type);
   EXPECT_EQ(kArrayLength, root->value.as_array.length);
   for (int i = 0; i < kArrayLength; i++) {
@@ -457,7 +443,7 @@
     EXPECT_EQ(Dart_CObject_kInt32, element->type);
     EXPECT_EQ(i, element->value.as_int32);
   }
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeArrayWithTypeArgument) {
@@ -471,20 +457,18 @@
     smi ^= Smi::New(i);
     array.SetAt(i, smi);
   }
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   Array& serialized_array = Array::Handle();
-  serialized_array ^= reader.ReadObject();
+  serialized_array ^= ReadMessage(thread, message.get());
   EXPECT(array.CanonicalizeEquals(serialized_array));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kArray, root->type);
   EXPECT_EQ(kArrayLength, root->value.as_array.length);
   for (int i = 0; i < kArrayLength; i++) {
@@ -492,7 +476,7 @@
     EXPECT_EQ(Dart_CObject_kInt32, element->type);
     EXPECT_EQ(i, element->value.as_int32);
   }
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 TEST_CASE(FailSerializeLargeArray) {
@@ -500,7 +484,8 @@
   root.type = Dart_CObject_kArray;
   root.value.as_array.length = Array::kMaxElements + 1;
   root.value.as_array.values = NULL;
-  ExpectEncodeFail(&root);
+  ApiNativeScope scope;
+  ExpectEncodeFail(scope.zone(), &root);
 }
 
 TEST_CASE(FailSerializeLargeNestedArray) {
@@ -513,7 +498,8 @@
   parent.value.as_array.values = values;
   child.type = Dart_CObject_kArray;
   child.value.as_array.length = Array::kMaxElements + 1;
-  ExpectEncodeFail(&parent);
+  ApiNativeScope scope;
+  ExpectEncodeFail(scope.zone(), &parent);
 }
 
 TEST_CASE(FailSerializeLargeTypedDataInt8) {
@@ -522,7 +508,8 @@
   root.value.as_typed_data.type = Dart_TypedData_kInt8;
   root.value.as_typed_data.length =
       TypedData::MaxElements(kTypedDataInt8ArrayCid) + 1;
-  ExpectEncodeFail(&root);
+  ApiNativeScope scope;
+  ExpectEncodeFail(scope.zone(), &root);
 }
 
 TEST_CASE(FailSerializeLargeTypedDataUint8) {
@@ -531,39 +518,40 @@
   root.value.as_typed_data.type = Dart_TypedData_kUint8;
   root.value.as_typed_data.length =
       TypedData::MaxElements(kTypedDataUint8ArrayCid) + 1;
-  ExpectEncodeFail(&root);
+  ApiNativeScope scope;
+  ExpectEncodeFail(scope.zone(), &root);
 }
 
 TEST_CASE(FailSerializeLargeExternalTypedData) {
   Dart_CObject root;
   root.type = Dart_CObject_kExternalTypedData;
-  root.value.as_typed_data.length =
+  root.value.as_external_typed_data.type = Dart_TypedData_kUint8;
+  root.value.as_external_typed_data.length =
       ExternalTypedData::MaxElements(kExternalTypedDataUint8ArrayCid) + 1;
-  ExpectEncodeFail(&root);
+  ApiNativeScope scope;
+  ExpectEncodeFail(scope.zone(), &root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeEmptyArray) {
   // Write snapshot with object content.
   const int kArrayLength = 0;
   Array& array = Array::Handle(Array::New(kArrayLength));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   Array& serialized_array = Array::Handle();
-  serialized_array ^= reader.ReadObject();
+  serialized_array ^= ReadMessage(thread, message.get());
   EXPECT(array.CanonicalizeEquals(serialized_array));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kArray, root->type);
   EXPECT_EQ(kArrayLength, root->value.as_array.length);
   EXPECT(root->value.as_array.values == NULL);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeByteArray) {
@@ -574,26 +562,24 @@
   for (int i = 0; i < kTypedDataLength; i++) {
     typed_data.SetUint8(i, i);
   }
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(typed_data, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, typed_data, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   TypedData& serialized_typed_data = TypedData::Handle();
-  serialized_typed_data ^= reader.ReadObject();
+  serialized_typed_data ^= ReadMessage(thread, message.get());
   EXPECT(serialized_typed_data.IsTypedData());
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kTypedData, root->type);
   EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
   for (int i = 0; i < kTypedDataLength; i++) {
     EXPECT(root->value.as_typed_data.values[i] == i);
   }
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 #define TEST_TYPED_ARRAY(darttype, ctype)                                      \
@@ -606,12 +592,11 @@
     for (int i = 0; i < kArrayLength; i++) {                                   \
       array.Set##darttype((i * scale), i);                                     \
     }                                                                          \
-    MessageWriter writer(true);                                                \
     std::unique_ptr<Message> message =                                         \
-        writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);    \
-    MessageSnapshotReader reader(message.get(), thread);                       \
+        WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,      \
+                     Message::kNormalPriority);                                \
     TypedData& serialized_array = TypedData::Handle();                         \
-    serialized_array ^= reader.ReadObject();                                   \
+    serialized_array ^= ReadMessage(thread, message.get());                    \
     for (int i = 0; i < kArrayLength; i++) {                                   \
       EXPECT_EQ(static_cast<ctype>(i),                                         \
                 serialized_array.Get##darttype(i* scale));                     \
@@ -627,12 +612,11 @@
         ExternalTypedData::New(kExternalTypedData##darttype##ArrayCid,         \
                                reinterpret_cast<uint8_t*>(data), length));     \
     intptr_t scale = array.ElementSizeInBytes();                               \
-    MessageWriter writer(true);                                                \
     std::unique_ptr<Message> message =                                         \
-        writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);    \
-    MessageSnapshotReader reader(message.get(), thread);                       \
+        WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,      \
+                     Message::kNormalPriority);                                \
     ExternalTypedData& serialized_array = ExternalTypedData::Handle();         \
-    serialized_array ^= reader.ReadObject();                                   \
+    serialized_array ^= ReadMessage(thread, message.get());                    \
     for (int i = 0; i < length; i++) {                                         \
       EXPECT_EQ(static_cast<ctype>(data[i]),                                   \
                 serialized_array.Get##darttype(i* scale));                     \
@@ -670,25 +654,23 @@
   const int kTypedDataLength = 0;
   TypedData& typed_data = TypedData::Handle(
       TypedData::New(kTypedDataUint8ArrayCid, kTypedDataLength));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(typed_data, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, typed_data, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   TypedData& serialized_typed_data = TypedData::Handle();
-  serialized_typed_data ^= reader.ReadObject();
+  serialized_typed_data ^= ReadMessage(thread, message.get());
   EXPECT(serialized_typed_data.IsTypedData());
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kTypedData, root->type);
   EXPECT_EQ(Dart_TypedData_kUint8, root->value.as_typed_data.type);
   EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
   EXPECT(root->value.as_typed_data.values == NULL);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 VM_UNIT_TEST_CASE(FullSnapshot) {
@@ -790,47 +772,38 @@
   Object& obj = Object::Handle(Api::UnwrapHandle(result));
 
   // Serialize the object into a message.
-  MessageWriter writer(false);
-  return writer.WriteMessage(obj, ILLEGAL_PORT, Message::kNormalPriority);
-}
-
-// Helper function to deserialize the result into a Dart_CObject structure.
-static Dart_CObject* GetDeserialized(Message* message) {
-  // Read object back from the snapshot into a C structure.
-  ApiMessageReader api_reader(message);
-  return api_reader.ReadMessage();
+  return WriteMessage(/* can_send_any_object */ false, obj, ILLEGAL_PORT,
+                      Message::kNormalPriority);
 }
 
 static void CheckString(Dart_Handle dart_string, const char* expected) {
   StackZone zone(Thread::Current());
   String& str = String::Handle();
   str ^= Api::UnwrapHandle(dart_string);
-  MessageWriter writer(false);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ false, str, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(zone.GetZone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kString, root->type);
   EXPECT_STREQ(expected, root->value.as_string);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(zone.GetZone(), root);
 }
 
 static void CheckStringInvalid(Dart_Handle dart_string) {
   StackZone zone(Thread::Current());
   String& str = String::Handle();
   str ^= Api::UnwrapHandle(dart_string);
-  MessageWriter writer(false);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ false, str, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(zone.GetZone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kUnsupported, root->type);
 }
@@ -928,18 +901,17 @@
       StackZone zone(thread);
       Smi& smi = Smi::Handle();
       smi ^= Api::UnwrapHandle(smi_result);
-      MessageWriter writer(false);
       std::unique_ptr<Message> message =
-          writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
+          WriteMessage(/* can_send_any_object */ false, smi, ILLEGAL_PORT,
+                       Message::kNormalPriority);
 
       // Read object back from the snapshot into a C structure.
       ApiNativeScope scope;
-      ApiMessageReader api_reader(message.get());
-      Dart_CObject* root = api_reader.ReadMessage();
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kInt32, root->type);
       EXPECT_EQ(42, root->value.as_int32);
-      CheckEncodeDecodeMessage(root);
+      CheckEncodeDecodeMessage(scope.zone(), root);
     }
     CheckString(ascii_string_result, "Hello, world!");
     CheckString(non_ascii_string_result, "Blåbærgrød");
@@ -1000,20 +972,20 @@
       // Generate a list of nulls from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
       for (int i = 0; i < kArrayLength; i++) {
         EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
       }
-      CheckEncodeDecodeMessage(root);
+      CheckEncodeDecodeMessage(scope.zone(), root);
     }
     {
       // Generate a list of ints from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1021,13 +993,13 @@
         EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[i]->type);
         EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
       }
-      CheckEncodeDecodeMessage(root);
+      CheckEncodeDecodeMessage(scope.zone(), root);
     }
     {
       // Generate a list of strings from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1042,7 +1014,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1124,20 +1096,20 @@
       // Generate a list of nulls from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
       for (int i = 0; i < kArrayLength; i++) {
         EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
       }
-      CheckEncodeDecodeMessage(root);
+      CheckEncodeDecodeMessage(scope.zone(), root);
     }
     {
       // Generate a list of ints from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1145,13 +1117,13 @@
         EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[i]->type);
         EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
       }
-      CheckEncodeDecodeMessage(root);
+      CheckEncodeDecodeMessage(scope.zone(), root);
     }
     {
       // Generate a list of strings from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1166,7 +1138,7 @@
       // Generate a list of lists from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getListList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1185,7 +1157,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1357,7 +1329,7 @@
       // Generate a list of strings from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1372,7 +1344,7 @@
       // Generate a list of medium ints from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1387,7 +1359,7 @@
       // Generate a list of doubles from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1396,8 +1368,6 @@
       EXPECT_EQ(3.14, element->value.as_double);
       for (int i = 1; i < kArrayLength; i++) {
         element = root->value.as_array.values[i];
-        // Double values are expected to not be canonicalized in messages.
-        EXPECT_NE(root->value.as_array.values[0], element);
         EXPECT_EQ(Dart_CObject_kDouble, element->type);
         EXPECT_EQ(3.14, element->value.as_double);
       }
@@ -1406,7 +1376,7 @@
       // Generate a list of Uint8Lists from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1423,7 +1393,7 @@
       std::unique_ptr<Message> message =
           GetSerialized(lib, "getTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1441,7 +1411,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1458,8 +1428,6 @@
           EXPECT_EQ(Dart_CObject_kString, element->type);
           EXPECT_STREQ("A", element->value.as_string);
         } else {
-          // Double values are expected to not be canonicalized in messages.
-          EXPECT_NE(root->value.as_array.values[1], element);
           EXPECT_EQ(Dart_CObject_kDouble, element->type);
           EXPECT_EQ(2.72, element->value.as_double);
         }
@@ -1469,7 +1437,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1560,7 +1528,7 @@
       // Generate a list of strings from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1575,7 +1543,7 @@
       // Generate a list of medium ints from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1590,18 +1558,15 @@
       // Generate a list of doubles from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
       Dart_CObject* element = root->value.as_array.values[0];
-      // Double values are expected to not be canonicalized in messages.
       EXPECT_EQ(Dart_CObject_kDouble, element->type);
       EXPECT_EQ(3.14, element->value.as_double);
       for (int i = 1; i < kArrayLength; i++) {
         element = root->value.as_array.values[i];
-        // Double values are expected to not be canonicalized in messages.
-        EXPECT_NE(root->value.as_array.values[0], element);
         EXPECT_EQ(Dart_CObject_kDouble, element->type);
         EXPECT_EQ(3.14, element->value.as_double);
       }
@@ -1610,7 +1575,7 @@
       // Generate a list of Uint8Lists from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1627,7 +1592,7 @@
       std::unique_ptr<Message> message =
           GetSerialized(lib, "getTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1645,7 +1610,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1662,8 +1627,6 @@
           EXPECT_EQ(Dart_CObject_kString, element->type);
           EXPECT_STREQ(".", element->value.as_string);
         } else {
-          // Double values are expected to not be canonicalized in messages.
-          EXPECT_NE(root->value.as_array.values[1], element);
           EXPECT_EQ(Dart_CObject_kDouble, element->type);
           EXPECT_EQ(2.72, element->value.as_double);
         }
@@ -1673,7 +1636,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1806,7 +1769,7 @@
       // Generate a list of Uint8Lists from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -1834,7 +1797,7 @@
       std::unique_ptr<Message> message =
           GetSerialized(lib, "getTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -1882,7 +1845,7 @@
       std::unique_ptr<Message> message =
           GetSerialized(lib, "getMultipleTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -2009,15 +1972,6 @@
   Dart_ExitScope();
 }
 
-ISOLATE_UNIT_TEST_CASE(OmittedObjectEncodingLength) {
-  StackZone zone(Thread::Current());
-  MessageWriter writer(true);
-  writer.WriteInlinedObjectHeader(kOmittedObjectId);
-  // For performance, we'd like single-byte headers when ids are omitted.
-  // If this starts failing, consider renumbering the snapshot ids.
-  EXPECT_EQ(1, writer.BytesWritten());
-}
-
 TEST_CASE(IsKernelNegative) {
   EXPECT(!Dart_IsKernel(NULL, 0));
 
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 03eaf12..f999c81 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -59,7 +59,7 @@
     // Build the profile.
     SampleFilter samplesForIsolate(thread_->isolate()->main_port(),
                                    Thread::kMutatorTask, -1, -1);
-    profile_.Build(thread, &samplesForIsolate, Profiler::sample_buffer());
+    profile_.Build(thread, &samplesForIsolate, Profiler::sample_block_buffer());
   }
 }
 
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
index ad8c574..5934703 100644
--- a/runtime/vm/source_report_test.cc
+++ b/runtime/vm/source_report_test.cc
@@ -497,7 +497,7 @@
 
 ISOLATE_UNIT_TEST_CASE(SourceReport_CallSites_SimpleCall) {
   // WARNING: This MUST be big enough for the serialised JSON string.
-  const int kBufferSize = 1024;
+  const int kBufferSize = 2048;
   char buffer[kBufferSize];
   const char* kScript =
       "helper0() {}\n"
@@ -537,6 +537,7 @@
       "\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},"
       "\"_kind\":\"RegularFunction\",\"static\":true,\"const\":false,"
+      "\"implicit\":false,"
       "\"_intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
       "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
       "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
@@ -617,7 +618,8 @@
       "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
       "},\"_kind\":\"RegularFunction\","
-      "\"static\":false,\"const\":false,\"_intrinsic\":false,"
+      "\"static\":false,\"const\":false,\"implicit\":false,\"_intrinsic\":"
+      "false,"
       "\"_native\":false,"
       "\"location\":{\"type\":\"SourceLocation\","
       "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
@@ -649,7 +651,8 @@
       "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
       "},\"_kind\":\"RegularFunction\","
-      "\"static\":false,\"const\":false,\"_intrinsic\":false,"
+      "\"static\":false,\"const\":false,\"implicit\":false,\"_intrinsic\":"
+      "false,"
       "\"_native\":false,"
       "\"location\":{\"type\":\"SourceLocation\","
       "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
@@ -705,7 +708,8 @@
       "\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
       "\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},\"_"
-      "kind\":\"RegularFunction\",\"static\":true,\"const\":false,\"_"
+      "kind\":\"RegularFunction\",\"static\":true,\"const\":false,\"implicit\":"
+      "false,\"_"
       "intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
       "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
       "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 74fa21a..1f29e90 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -5,6 +5,7 @@
 #include "vm/stack_trace.h"
 
 #include "vm/dart_api_impl.h"
+#include "vm/object_store.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
 
@@ -242,14 +243,26 @@
     parent_function_ = receiver_function_.parent_function();
     if (parent_function_.recognized_kind() ==
         MethodRecognizer::kFutureTimeout) {
-      context_entry_ = receiver_context_.At(Context::kFutureTimeoutFutureIndex);
+      ASSERT(IsolateGroup::Current()
+                 ->object_store()
+                 ->future_timeout_future_index() != Object::null());
+      const intptr_t future_index =
+          Smi::Value(IsolateGroup::Current()
+                         ->object_store()
+                         ->future_timeout_future_index());
+      context_entry_ = receiver_context_.At(future_index);
       return GetCallerInFutureImpl(context_entry_);
     }
 
     if (parent_function_.recognized_kind() == MethodRecognizer::kFutureWait) {
       receiver_context_ = receiver_context_.parent();
       ASSERT(!receiver_context_.IsNull());
-      context_entry_ = receiver_context_.At(Context::kFutureWaitFutureIndex);
+      ASSERT(
+          IsolateGroup::Current()->object_store()->future_wait_future_index() !=
+          Object::null());
+      const intptr_t future_index = Smi::Value(
+          IsolateGroup::Current()->object_store()->future_wait_future_index());
+      context_entry_ = receiver_context_.At(future_index);
       return GetCallerInFutureImpl(context_entry_);
     }
   }
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 91474a0..8a54e72 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -299,8 +299,8 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 #if !defined(TARGET_ARCH_IA32)
-CodePtr StubCode::GetBuildMethodExtractorStub(
-    compiler::ObjectPoolBuilder* pool) {
+CodePtr StubCode::GetBuildMethodExtractorStub(compiler::ObjectPoolBuilder* pool,
+                                              bool generic) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
   auto thread = Thread::Current();
   auto Z = thread->zone();
@@ -314,9 +314,10 @@
   compiler::ObjectPoolBuilder object_pool_builder;
   compiler::Assembler assembler(pool != nullptr ? pool : &object_pool_builder);
   compiler::StubCodeCompiler::GenerateBuildMethodExtractorStub(
-      &assembler, closure_allocation_stub, context_allocation_stub);
+      &assembler, closure_allocation_stub, context_allocation_stub, generic);
 
-  const char* name = "BuildMethodExtractor";
+  const char* name = generic ? "BuildGenericMethodExtractor"
+                             : "BuildNonGenericMethodExtractor";
   const Code& stub = Code::Handle(Code::FinalizeCodeAndNotify(
       name, nullptr, &assembler, Code::PoolAttachment::kNotAttachPool,
       /*optimized=*/false));
@@ -368,7 +369,8 @@
     return "_iso_stub_" #name "Stub";                                          \
   }
   OBJECT_STORE_STUB_CODE_LIST(MATCH)
-  MATCH(build_method_extractor_code, BuildMethodExtractor)
+  MATCH(build_generic_method_extractor_code, BuildGenericMethodExtractor)
+  MATCH(build_nongeneric_method_extractor_code, BuildNonGenericMethodExtractor)
 #undef MATCH
   return nullptr;
 }
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index ae39cae..3eac0b6 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -21,8 +21,6 @@
 class Code;
 class Isolate;
 class ObjectPointerVisitor;
-class SnapshotReader;
-class SnapshotWriter;
 
 DECLARE_FLAG(bool, disassemble_stubs);
 
@@ -72,7 +70,14 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 #if !defined(TARGET_ARCH_IA32)
-  static CodePtr GetBuildMethodExtractorStub(compiler::ObjectPoolBuilder* pool);
+  static CodePtr GetBuildGenericMethodExtractorStub(
+      compiler::ObjectPoolBuilder* pool) {
+    return GetBuildMethodExtractorStub(pool, /*generic=*/true);
+  }
+  static CodePtr GetBuildNonGenericMethodExtractorStub(
+      compiler::ObjectPoolBuilder* pool) {
+    return GetBuildMethodExtractorStub(pool, /*generic=*/false);
+  }
 #endif
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -110,6 +115,9 @@
  private:
   friend class MegamorphicCacheTable;
 
+  static CodePtr GetBuildMethodExtractorStub(compiler::ObjectPoolBuilder* pool,
+                                             bool generic);
+
   enum {
 #define STUB_CODE_ENTRY(name) k##name##Index,
     VM_STUB_CODE_LIST(STUB_CODE_ENTRY)
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index c6819b0..673f26e 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -14,7 +14,6 @@
 #include "vm/object_store.h"
 #include "vm/raw_object.h"
 #include "vm/reusable_handles.h"
-#include "vm/snapshot_ids.h"
 #include "vm/visitor.h"
 
 namespace dart {
@@ -357,7 +356,9 @@
 
     // Most common case: The symbol is already in the table.
     {
-      SafepointReadRwLocker sl(thread, group->symbols_lock());
+      // We do allow lock-free concurrent read access to the symbol table.
+      // Both, the array in the ObjectStore as well as elements in the array
+      // are accessed via store-release/load-acquire barriers.
       data = object_store->symbol_table();
       CanonicalStringSet table(&key, &value, &data);
       symbol ^= table.GetOrNull(str);
@@ -365,7 +366,7 @@
     }
     // Otherwise we'll have to get exclusive access and get-or-insert it.
     if (symbol.IsNull()) {
-      SafepointWriteRwLocker sl(thread, group->symbols_lock());
+      SafepointMutexLocker ml(group->symbols_mutex());
       data = object_store->symbol_table();
       CanonicalStringSet table(&key, &value, &data);
       symbol ^= table.InsertNewOrGet(str);
@@ -403,14 +404,13 @@
       // In DEBUG mode the snapshot writer also calls this method inside a
       // safepoint.
 #if !defined(DEBUG)
-      RELEASE_ASSERT(IsolateGroup::AreIsolateGroupsEnabled() || !USING_PRODUCT);
+      RELEASE_ASSERT(FLAG_enable_isolate_groups || !USING_PRODUCT);
 #endif
       data = object_store->symbol_table();
       CanonicalStringSet table(&key, &value, &data);
       symbol ^= table.GetOrNull(str);
       table.Release();
     } else {
-      SafepointReadRwLocker sl(thread, group->symbols_lock());
       data = object_store->symbol_table();
       CanonicalStringSet table(&key, &value, &data);
       symbol ^= table.GetOrNull(str);
@@ -513,22 +513,4 @@
   table.Release();
 }
 
-intptr_t Symbols::LookupPredefinedSymbol(ObjectPtr obj) {
-  for (intptr_t i = 1; i < Symbols::kMaxPredefinedId; i++) {
-    if (symbol_handles_[i]->ptr() == obj) {
-      return (i + kMaxPredefinedObjectIds);
-    }
-  }
-  return kInvalidIndex;
-}
-
-ObjectPtr Symbols::GetPredefinedSymbol(intptr_t object_id) {
-  ASSERT(IsPredefinedSymbolId(object_id));
-  intptr_t i = (object_id - kMaxPredefinedObjectIds);
-  if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) {
-    return symbol_handles_[i]->ptr();
-  }
-  return Object::null();
-}
-
 }  // namespace dart
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 533119d..76d0070 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -7,7 +7,6 @@
 
 #include "vm/growable_array.h"
 #include "vm/object.h"
-#include "vm/snapshot_ids.h"
 
 namespace dart {
 
@@ -105,6 +104,7 @@
   V(ExceptionHandlers, "ExceptionHandlers")                                    \
   V(ExceptionParameter, ":exception")                                          \
   V(ExceptionVar, ":exception_var")                                            \
+  V(Expando, "Expando")                                                        \
   V(ExprTemp, ":expr_temp")                                                    \
   V(ExternalName, "ExternalName")                                              \
   V(ExternalOneByteString, "_ExternalOneByteString")                           \
@@ -415,6 +415,7 @@
   V(_objectNoSuchMethod, "_objectNoSuchMethod")                                \
   V(_objectToString, "_objectToString")                                        \
   V(_onData, "_onData")                                                        \
+  V(_rehash, "_rehash")                                                        \
   V(_rehashObjects, "_rehashObjects")                                          \
   V(_resultOrListeners, "_resultOrListeners")                                  \
   V(_runExtension, "_runExtension")                                            \
@@ -698,13 +699,6 @@
   template <typename StringType>
   static StringPtr NewSymbol(Thread* thread, const StringType& str);
 
-  static intptr_t LookupPredefinedSymbol(ObjectPtr obj);
-  static ObjectPtr GetPredefinedSymbol(intptr_t object_id);
-  static bool IsPredefinedSymbolId(intptr_t object_id) {
-    return (object_id >= kMaxPredefinedObjectIds &&
-            object_id < (kMaxPredefinedObjectIds + kMaxPredefinedId));
-  }
-
   // List of Latin1 characters stored in the vm isolate as symbols
   // in order to make Symbols::FromCharCode fast. This structure is
   // used in generated dart code for direct access to these objects.
@@ -715,11 +709,8 @@
 
   friend class Dart;
   friend class String;
-  friend class SnapshotReader;
-  friend class SnapshotWriter;
   friend class Serializer;
   friend class Deserializer;
-  friend class ApiMessageReader;
 
   DISALLOW_COPY_AND_ASSIGN(Symbols);
 };
diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h
index 4f3b1f6..ffd7d32 100644
--- a/runtime/vm/tagged_pointer.h
+++ b/runtime/vm/tagged_pointer.h
@@ -396,6 +396,7 @@
 DEFINE_TAGGED_POINTER(GrowableObjectArray, Instance)
 DEFINE_TAGGED_POINTER(LinkedHashBase, Instance)
 DEFINE_TAGGED_POINTER(LinkedHashMap, LinkedHashBase)
+DEFINE_TAGGED_POINTER(LinkedHashSet, LinkedHashBase)
 DEFINE_TAGGED_POINTER(Float32x4, Instance)
 DEFINE_TAGGED_POINTER(Int32x4, Instance)
 DEFINE_TAGGED_POINTER(Float64x2, Instance)
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 16a1f8f..09a3b25 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -91,9 +91,6 @@
       no_safepoint_scope_depth_(0),
 #endif
       reusable_handles_(),
-      defer_oob_messages_count_(0),
-      deferred_interrupts_mask_(0),
-      deferred_interrupts_(0),
       stack_overflow_count_(0),
       hierarchy_info_(NULL),
       type_usage_info_(NULL),
@@ -398,7 +395,7 @@
   MonitorLocker ml(&thread_lock_);
   if (!HasScheduledInterrupts()) {
     // No interrupt pending, set stack_limit_ too.
-    stack_limit_ = limit;
+    stack_limit_.store(limit);
   }
   saved_stack_limit_ = limit;
 }
@@ -407,96 +404,40 @@
   SetStackLimit(~static_cast<uword>(0));
 }
 
-void Thread::ScheduleInterrupts(uword interrupt_bits) {
-  MonitorLocker ml(&thread_lock_);
-  ScheduleInterruptsLocked(interrupt_bits);
+static bool IsInterruptLimit(uword limit) {
+  return (limit & ~Thread::kInterruptsMask) ==
+         (kInterruptStackLimit & ~Thread::kInterruptsMask);
 }
 
-void Thread::ScheduleInterruptsLocked(uword interrupt_bits) {
-  ASSERT(thread_lock_.IsOwnedByCurrentThread());
+void Thread::ScheduleInterrupts(uword interrupt_bits) {
   ASSERT((interrupt_bits & ~kInterruptsMask) == 0);  // Must fit in mask.
 
-  // Check to see if any of the requested interrupts should be deferred.
-  uword defer_bits = interrupt_bits & deferred_interrupts_mask_;
-  if (defer_bits != 0) {
-    deferred_interrupts_ |= defer_bits;
-    interrupt_bits &= ~deferred_interrupts_mask_;
-    if (interrupt_bits == 0) {
-      return;
+  uword old_limit = stack_limit_.load();
+  uword new_limit;
+  do {
+    if (IsInterruptLimit(old_limit)) {
+      new_limit = old_limit | interrupt_bits;
+    } else {
+      new_limit = (kInterruptStackLimit & ~kInterruptsMask) | interrupt_bits;
     }
-  }
-
-  if (stack_limit_ == saved_stack_limit_) {
-    stack_limit_ = (kInterruptStackLimit & ~kInterruptsMask) | interrupt_bits;
-  } else {
-    stack_limit_ = stack_limit_ | interrupt_bits;
-  }
+  } while (!stack_limit_.compare_exchange_weak(old_limit, new_limit));
 }
 
 uword Thread::GetAndClearInterrupts() {
-  MonitorLocker ml(&thread_lock_);
-  if (stack_limit_ == saved_stack_limit_) {
-    return 0;  // No interrupt was requested.
-  }
-  uword interrupt_bits = stack_limit_ & kInterruptsMask;
-  stack_limit_ = saved_stack_limit_;
+  uword interrupt_bits = 0;
+  uword old_limit = stack_limit_.load();
+  uword new_limit = saved_stack_limit_;
+  do {
+    if (IsInterruptLimit(old_limit)) {
+      interrupt_bits = interrupt_bits | (old_limit & kInterruptsMask);
+    } else {
+      return interrupt_bits;
+    }
+  } while (!stack_limit_.compare_exchange_weak(old_limit, new_limit));
+
   return interrupt_bits;
 }
 
-void Thread::DeferOOBMessageInterrupts() {
-  MonitorLocker ml(&thread_lock_);
-  defer_oob_messages_count_++;
-  if (defer_oob_messages_count_ > 1) {
-    // OOB message interrupts are already deferred.
-    return;
-  }
-  ASSERT(deferred_interrupts_mask_ == 0);
-  deferred_interrupts_mask_ = kMessageInterrupt;
-
-  if (stack_limit_ != saved_stack_limit_) {
-    // Defer any interrupts which are currently pending.
-    deferred_interrupts_ = stack_limit_ & deferred_interrupts_mask_;
-
-    // Clear deferrable interrupts, if present.
-    stack_limit_ = stack_limit_ & ~deferred_interrupts_mask_;
-
-    if ((stack_limit_ & kInterruptsMask) == 0) {
-      // No other pending interrupts.  Restore normal stack limit.
-      stack_limit_ = saved_stack_limit_;
-    }
-  }
-#if !defined(PRODUCT)
-  if (FLAG_trace_service && FLAG_trace_service_verbose) {
-    OS::PrintErr("[+%" Pd64 "ms] Isolate %s deferring OOB interrupts\n",
-                 Dart::UptimeMillis(), isolate()->name());
-  }
-#endif  // !defined(PRODUCT)
-}
-
-void Thread::RestoreOOBMessageInterrupts() {
-  MonitorLocker ml(&thread_lock_);
-  defer_oob_messages_count_--;
-  if (defer_oob_messages_count_ > 0) {
-    return;
-  }
-  ASSERT(defer_oob_messages_count_ == 0);
-  ASSERT(deferred_interrupts_mask_ == kMessageInterrupt);
-  deferred_interrupts_mask_ = 0;
-  if (deferred_interrupts_ != 0) {
-    if (stack_limit_ == saved_stack_limit_) {
-      stack_limit_ = kInterruptStackLimit & ~kInterruptsMask;
-    }
-    stack_limit_ = stack_limit_ | deferred_interrupts_;
-    deferred_interrupts_ = 0;
-  }
-#if !defined(PRODUCT)
-  if (FLAG_trace_service && FLAG_trace_service_verbose) {
-    OS::PrintErr("[+%" Pd64 "ms] Isolate %s restoring OOB interrupts\n",
-                 Dart::UptimeMillis(), isolate()->name());
-  }
-#endif  // !defined(PRODUCT)
-}
-
 ErrorPtr Thread::HandleInterrupts() {
   uword interrupt_bits = GetAndClearInterrupts();
   if ((interrupt_bits & kVMInterrupt) != 0) {
@@ -507,6 +448,15 @@
       }
       heap()->CollectGarbage(Heap::kNew);
     }
+
+#if !defined(PRODUCT)
+    // Processes completed SampleBlocks and sends CPU sample events over the
+    // service protocol when applicable.
+    SampleBlockBuffer* sample_buffer = Profiler::sample_block_buffer();
+    if (sample_buffer != nullptr && sample_buffer->process_blocks()) {
+      sample_buffer->ProcessCompletedBlocks();
+    }
+#endif  // !defined(PRODUCT)
   }
   if ((interrupt_bits & kMessageInterrupt) != 0) {
     MessageHandler::MessageStatus status =
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 2d80830..6e3ff67 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -417,11 +417,10 @@
   };
 
   void ScheduleInterrupts(uword interrupt_bits);
-  void ScheduleInterruptsLocked(uword interrupt_bits);
   ErrorPtr HandleInterrupts();
   uword GetAndClearInterrupts();
   bool HasScheduledInterrupts() const {
-    return (stack_limit_ & kInterruptsMask) != 0;
+    return (stack_limit_.load() & kInterruptsMask) != 0;
   }
 
   // Monitor corresponding to this thread.
@@ -1031,7 +1030,7 @@
   // in SIMARM(IA32) and ARM, and the same offsets in SIMARM64(X64) and ARM64.
   // We use only word-sized fields to avoid differences in struct packing on the
   // different architectures. See also CheckOffsets in dart.cc.
-  RelaxedAtomic<uword> stack_limit_;
+  volatile RelaxedAtomic<uword> stack_limit_;
   uword write_barrier_mask_;
   uword heap_base_;
   Isolate* isolate_;
@@ -1107,9 +1106,6 @@
   int32_t no_safepoint_scope_depth_;
 #endif
   VMHandles reusable_handles_;
-  intptr_t defer_oob_messages_count_;
-  uint16_t deferred_interrupts_mask_;
-  uint16_t deferred_interrupts_;
   int32_t stack_overflow_count_;
   uint32_t runtime_call_count_ = 0;
 
@@ -1205,9 +1201,6 @@
 
   static void SetCurrent(Thread* current) { OSThread::SetCurrentTLS(current); }
 
-  void DeferOOBMessageInterrupts();
-  void RestoreOOBMessageInterrupts();
-
 #define REUSABLE_FRIEND_DECLARATION(name)                                      \
   friend class Reusable##name##HandleScope;
   REUSABLE_HANDLE_LIST(REUSABLE_FRIEND_DECLARATION)
@@ -1218,9 +1211,7 @@
   friend class InterruptChecker;
   friend class Isolate;
   friend class IsolateGroup;
-  friend class IsolateTestHelper;
   friend class NoActiveIsolateScope;
-  friend class NoOOBMessageScope;
   friend class NoReloadScope;
   friend class Simulator;
   friend class StackZone;
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 45d98c8..28b108b 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -50,7 +50,7 @@
       string_ = lib_.url();
       curl = OS::SCreate(Z, "%s_", string_.ToCString());
     } else {
-      static intptr_t counter = 0;
+      static std::atomic<intptr_t> counter = 0;
       curl = OS::SCreate(Z, "nolib%" Pd "_", counter++);
     }
 
diff --git a/runtime/vm/v8_snapshot_writer.h b/runtime/vm/v8_snapshot_writer.h
index 644a2e0..c69abdc 100644
--- a/runtime/vm/v8_snapshot_writer.h
+++ b/runtime/vm/v8_snapshot_writer.h
@@ -58,7 +58,8 @@
    private:
     static constexpr size_t kIdSpaceBits =
         Utils::BitLength(static_cast<int64_t>(IdSpace::kArtificial));
-    static constexpr int64_t kIdSpaceMask = Utils::NBitMaskUnsafe(kIdSpaceBits);
+    static constexpr int64_t kIdSpaceMask =
+        Utils::NBitMask<int64_t>(kIdSpaceBits);
     static const char* IdSpaceToCString(IdSpace space);
 
     int64_t encoded_;
diff --git a/runtime/vm/version_in.cc b/runtime/vm/version_in.cc
index 2fcf5c5..4fe06a5 100644
--- a/runtime/vm/version_in.cc
+++ b/runtime/vm/version_in.cc
@@ -2,23 +2,31 @@
 // for 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/version.h"
+#include "platform/atomic.h"
 
 #include "vm/cpu.h"
 #include "vm/os.h"
+#include "vm/version.h"
 
 namespace dart {
 
-// TODO(iposva): Avoid racy initialization.
-static const char* formatted_version = NULL;
+// We use acquire-release semantics to ensure initializing stores to the string
+// are visible when the string becomes visible.
+static AcqRelAtomic<const char*> formatted_version = nullptr;
 
 const char* Version::String() {
-  if (formatted_version == NULL) {
+  if (formatted_version.load() == nullptr) {
     const char* os = OS::Name();
     const char* arch = CPU::Id();
-    formatted_version = OS::SCreate(NULL, "%s on \"%s_%s\"", str_, os, arch);
+    char* version_string =
+        OS::SCreate(nullptr, "%s on \"%s_%s\"", str_, os, arch);
+    const char* expect_old_is_null = nullptr;
+    if (!formatted_version.compare_exchange_strong(expect_old_is_null,
+                                                   version_string)) {
+      free(version_string);
+    }
   }
-  return formatted_version;
+  return formatted_version.load();
 }
 
 const char* Version::SnapshotString() {
diff --git a/runtime/vm/virtual_memory_win.cc b/runtime/vm/virtual_memory_win.cc
index 5348b3c..e352adc 100644
--- a/runtime/vm/virtual_memory_win.cc
+++ b/runtime/vm/virtual_memory_win.cc
@@ -62,10 +62,7 @@
                             PAGE_READWRITE, nullptr);
     if (address == nullptr) {
       int error = GetLastError();
-      const int kBufferSize = 1024;
-      char error_buf[kBufferSize];
-      FATAL2("Failed to reserve region for compressed heap: %d (%s)", error,
-             Utils::StrError(error, error_buf, kBufferSize));
+      FATAL("Failed to reserve region for compressed heap: %d", error);
     }
     VirtualMemoryCompressedHeap::Init(address);
   }
@@ -74,8 +71,9 @@
 
 void VirtualMemory::Cleanup() {
 #if defined(DART_COMPRESSED_POINTERS)
-  VirtualFree(VirtualMemoryCompressedHeap::Cleanup(), kCompressedHeapSize,
-              MEM_RELEASE);
+  void* heap_base = VirtualMemoryCompressedHeap::GetRegion();
+  VirtualFree(heap_base, kCompressedHeapSize, MEM_RELEASE);
+  VirtualMemoryCompressedHeap::Cleanup();
 #endif  // defined(DART_COMPRESSED_POINTERS)
 }
 
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 8d6dcb2..2f21ac1 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -70,7 +70,6 @@
   "dart.cc",
   "dart.h",
   "dart_api_impl.h",
-  "dart_api_message.cc",
   "dart_api_message.h",
   "dart_api_state.cc",
   "dart_api_state.h",
@@ -169,6 +168,8 @@
   "message.h",
   "message_handler.cc",
   "message_handler.h",
+  "message_snapshot.cc",
+  "message_snapshot.h",
   "metrics.cc",
   "metrics.h",
   "native_arguments.h",
@@ -186,6 +187,8 @@
   "object.h",
   "object_graph.cc",
   "object_graph.h",
+  "object_graph_copy.cc",
+  "object_graph_copy.h",
   "object_id_ring.cc",
   "object_id_ring.h",
   "object_reload.cc",
@@ -233,7 +236,6 @@
   "raw_object.h",
   "raw_object_fields.cc",
   "raw_object_fields.h",
-  "raw_object_snapshot.cc",
   "regexp.cc",
   "regexp.h",
   "regexp_assembler.cc",
@@ -287,7 +289,6 @@
   "simulator_arm64.h",
   "snapshot.cc",
   "snapshot.h",
-  "snapshot_ids.h",
   "source_report.cc",
   "source_report.h",
   "stack_frame.cc",
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index 2022c9d..cb45741 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -177,6 +177,7 @@
 
   friend class StackZone;
   friend class ApiZone;
+  friend class AllocOnlyStackZone;
   template <typename T, typename B, typename Allocator>
   friend class BaseGrowableArray;
   template <typename T, typename B, typename Allocator>
@@ -212,6 +213,23 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(StackZone);
 };
 
+class AllocOnlyStackZone : public ValueObject {
+ public:
+  AllocOnlyStackZone() : zone_() {}
+  ~AllocOnlyStackZone() {
+    // This zone is not linked into the thread, so any handles would not be
+    // visited.
+    ASSERT(zone_.handles()->IsEmpty());
+  }
+
+  Zone* GetZone() { return &zone_; }
+
+ private:
+  Zone zone_;
+
+  DISALLOW_COPY_AND_ASSIGN(AllocOnlyStackZone);
+};
+
 inline uword Zone::AllocUnsafe(intptr_t size) {
   ASSERT(size >= 0);
   // Round up the requested size to fit the alignment.
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
index 041dfd5..882f10c 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
@@ -364,8 +364,8 @@
       Map<String, String>? environment,
       bool includeParentEnvironment = true,
       bool runInShell = false,
-      Encoding stdoutEncoding = systemEncoding,
-      Encoding stderrEncoding = systemEncoding}) {
+      Encoding? stdoutEncoding = systemEncoding,
+      Encoding? stderrEncoding = systemEncoding}) {
     throw UnsupportedError("Process.run");
   }
 
@@ -375,8 +375,8 @@
       Map<String, String>? environment,
       bool includeParentEnvironment = true,
       bool runInShell = false,
-      Encoding stdoutEncoding = systemEncoding,
-      Encoding stderrEncoding = systemEncoding}) {
+      Encoding? stdoutEncoding = systemEncoding,
+      Encoding? stderrEncoding = systemEncoding}) {
     throw UnsupportedError("Process.runSync");
   }
 
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart
index feb5ef1..033b303 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart
@@ -9,6 +9,7 @@
 
 import 'dart:_js_helper' show patch, NoReifyGeneric, Primitives;
 import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show JavaScriptObject;
 import 'dart:_runtime' as dart;
 
 @patch
@@ -367,7 +368,7 @@
     int ms = JS('!', '#.getTime()', o);
     return DateTime.fromMillisecondsSinceEpoch(ms);
   } else if (o is _DartObject &&
-      !identical(dart.getReifiedType(o), dart.jsobject)) {
+      !identical(dart.getReifiedType(o), dart.typeRep<JavaScriptObject>())) {
     return o._dartObj;
   } else {
     return _wrapToDart(o);
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index 54576b0..33854c7 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -85,10 +85,14 @@
 gbind(f, @rest List<Object> typeArgs) {
   GenericFunctionType type = JS('!', '#[#]', f, _runtimeType);
   type.checkBounds(typeArgs);
-  // Create a JS wrapper function that will also pass the type arguments, and
-  // tag it with the instantiated function type.
+  // Create a JS wrapper function that will also pass the type arguments.
   var result =
       JS('', '(...args) => #.apply(null, #.concat(args))', f, typeArgs);
+  // Tag the wrapper with the original function to be used for equality checks.
+  JS('', '#["_originalFn"] = #', result, f);
+  JS('', '#["_typeArgs"] = #', result, constList(typeArgs, Object));
+
+  // Tag the wrapper with the instantiated function type.
   return fn(result, type.instantiate(typeArgs));
 }
 
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
index 1f362a8..9e99b26 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
@@ -92,13 +92,13 @@
         return JS('', '#.constructor', obj);
       }
       var result = JS('', '#[#]', obj, _extensionType);
-      if (result == null) return JS('', '#', jsobject);
+      if (result == null) return typeRep<JavaScriptObject>();
       return result;
     case "function":
       // All Dart functions and callable classes must set _runtimeType
       var result = JS('', '#[#]', obj, _runtimeType);
       if (result != null) return result;
-      return JS('', '#', jsobject);
+      return typeRep<JavaScriptObject>();
     case "undefined":
       return JS('', '#', Null);
     case "number":
@@ -109,7 +109,7 @@
       return JS('', '#', String);
     case "symbol":
     default:
-      return JS('', '#', jsobject);
+      return typeRep<JavaScriptObject>();
   }
 }
 
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
index e4afbf4..6ff9de7 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
@@ -10,7 +10,8 @@
 
 import 'dart:_debugger' show stackTraceMapper, trackCall;
 import 'dart:_foreign_helper' show JS, JSExportName, rest, spread;
-import 'dart:_interceptors' show JSArray, jsNull, JSFunction, NativeError;
+import 'dart:_interceptors'
+    show JSArray, jsNull, JSFunction, NativeError, JavaScriptObject;
 import 'dart:_internal' as internal show LateError, Symbol;
 import 'dart:_js_helper'
     show
@@ -180,8 +181,8 @@
 /// A list of functions to reset static fields back to their uninitialized
 /// state.
 ///
-/// This is populated by [defineLazyField] and [LazyJSType] and only contains
-/// fields that have been initialized.
+/// This is populated by [defineLazyField] and only contains fields that have
+/// been initialized.
 @notNull
 final List<void Function()> _resetFields = JS('', '[]');
 
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 7874940..3c0267d 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -81,6 +81,15 @@
 
 final metadata = JS('', 'Symbol("metadata")');
 
+/// A javascript Symbol used to store a canonical version of T? on T.
+final _cachedNullable = JS('', 'Symbol("cachedNullable")');
+
+/// A javascript Symbol used to store a canonical version of T* on T.
+final _cachedLegacy = JS('', 'Symbol("cachedLegacy")');
+
+/// A javascript Symbol used to store prior subtype checks and their results.
+final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
+
 /// Types in dart are represented internally at runtime as follows.
 ///
 ///   - Normal nominal types, produced from classes, are represented
@@ -154,7 +163,8 @@
 }
 
 @notNull
-bool _isJsObject(obj) => JS('!', '# === #', getReifiedType(obj), jsobject);
+bool _isJsObject(obj) =>
+    JS('!', '# === #', getReifiedType(obj), typeRep<JavaScriptObject>());
 
 /// Asserts that [f] is a native JS functions and returns it if so.
 ///
@@ -196,67 +206,17 @@
   return JS('', '#', ret);
 }
 
-/// The Dart type that represents a JavaScript class(/constructor) type.
-///
-/// The JavaScript type may not exist, either because it's not loaded yet, or
-/// because it's not available (such as with mocks). To handle this gracefully,
-/// we disable type checks for in these cases, and allow any JS object to work
-/// as if it were an instance of this JS type.
-class LazyJSType extends DartType {
-  Function() _getRawJSTypeFn;
-  @notNull
-  final String _dartName;
-  Object? _rawJSType;
-
-  LazyJSType(this._getRawJSTypeFn, this._dartName);
-
-  toString() {
-    var raw = _getRawJSType();
-    return raw != null ? typeName(raw) : "JSObject<$_dartName>";
-  }
-
-  Object? _getRawJSType() {
-    var raw = _rawJSType;
-    if (raw != null) return raw;
-
-    // Try to evaluate the JS type. If this fails for any reason, we'll try
-    // again next time.
-    // TODO(jmesserly): is it worth trying again? It may create unnecessary
-    // overhead, especially if exceptions are being thrown. Also it means the
-    // behavior of a given type check can change later on.
-    try {
-      raw = _getRawJSTypeFn();
-    } catch (e) {}
-
-    if (raw == null) {
-      _warn('Cannot find native JavaScript type ($_dartName) for type check');
-    } else {
-      _rawJSType = raw;
-      JS('', '#.push(() => # = null)', _resetFields, _rawJSType);
-    }
-    return raw;
-  }
-
-  Object rawJSTypeForCheck() => _getRawJSType() ?? jsobject;
-
-  @notNull
-  @JSExportName('is')
-  bool is_T(obj) =>
-      obj != null &&
-      (_isJsObject(obj) || isSubtypeOf(getReifiedType(obj), this));
-
-  @JSExportName('as')
-  as_T(obj) => is_T(obj) ? obj : castError(obj, this);
-}
-
-/// An anonymous JS type
+/// Dart type that represents a package:js class type (either anonymous or not).
 ///
 /// For the purposes of subtype checks, these match any JS type.
-class AnonymousJSType extends DartType {
+class PackageJSType extends DartType {
   final String _dartName;
-  AnonymousJSType(this._dartName);
-  toString() => _dartName;
+  PackageJSType(this._dartName);
 
+  @override
+  String toString() => _dartName;
+
+  @notNull
   @JSExportName('is')
   bool is_T(obj) =>
       obj != null &&
@@ -298,35 +258,25 @@
   }
 }
 
-var _lazyJSTypes = JS<Object>('', 'new Map()');
-var _anonymousJSTypes = JS<Object>('', 'new Map()');
+var _packageJSTypes = JS<Object>('', 'new Map()');
 
-lazyJSType(Function() getJSTypeCallback, String name) {
-  var ret = JS('', '#.get(#)', _lazyJSTypes, name);
+packageJSType(String name) {
+  var ret = JS('', '#.get(#)', _packageJSTypes, name);
   if (ret == null) {
-    ret = LazyJSType(getJSTypeCallback, name);
-    JS('', '#.set(#, #)', _lazyJSTypes, name, ret);
+    ret = PackageJSType(name);
+    JS('', '#.set(#, #)', _packageJSTypes, name, ret);
   }
   return ret;
 }
 
-anonymousJSType(String name) {
-  var ret = JS('', '#.get(#)', _anonymousJSTypes, name);
-  if (ret == null) {
-    ret = AnonymousJSType(name);
-    JS('', '#.set(#, #)', _anonymousJSTypes, name, ret);
-  }
-  return ret;
-}
-
-/// A javascript Symbol used to store a canonical version of T? on T.
-final _cachedNullable = JS('', 'Symbol("cachedNullable")');
-
-/// A javascript Symbol used to store a canonical version of T* on T.
-final _cachedLegacy = JS('', 'Symbol("cachedLegacy")');
-
-/// A javascript Symbol used to store prior subtype checks and their results.
-final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
+/// Since package:js types are all subtypes of each other, we use this var to
+/// denote *some* package:js type in our subtyping logic.
+///
+/// Used only when a concrete PackageJSType is not available i.e. when neither
+/// the object nor the target type is a PackageJSType. Avoids initializating a
+/// new PackageJSType every time. Note that we don't add it to the set of JS
+/// types, since it's not an actual JS class.
+final _pkgJSTypeForSubtyping = PackageJSType('');
 
 /// Returns a nullable (question, ?) version of [type].
 ///
@@ -478,12 +428,6 @@
 
 final bottom = unwrapType(Null);
 
-class JSObjectType extends DartType {
-  toString() => 'NativeJavaScriptObject';
-}
-
-final jsobject = JSObjectType();
-
 /// Dev Compiler's implementation of Type, wrapping its internal [_type].
 class _Type extends Type {
   /// The internal type representation, either a [DartType] or class constructor
@@ -1518,8 +1462,29 @@
       return ${_equalType(t2, Function)};
     }
 
-    // All JS types are subtypes of anonymous JS types.
-    if ($t1 === $jsobject && ${_jsInstanceOf(t2, AnonymousJSType)}) {
+    // Even though lazy and anonymous JS types are natural subtypes of
+    // JavaScriptObject, JS types should be treated as mutual subtypes of each
+    // other. This allows users to be able to interface with both extension
+    // types on JavaScriptObject and package:js using the same object.
+    //
+    // Therefore, the following relationships hold true:
+    //
+    // JavaScriptObject <: package:js types
+    // package:js types <: JavaScriptObject
+
+    if (${_isInterfaceSubtype(t1, JavaScriptObject, strictMode)}
+        &&
+            // TODO: Since package:js types are instances of PackageJSType and
+            // we don't have a mechanism to determine if *some* package:js type
+            // implements t2. This will possibly require keeping a map of these
+            // relationships for this subtyping check. For now, this will only
+            // work if t2 is also a PackageJSType.
+            ${_isInterfaceSubtype(_pkgJSTypeForSubtyping, t2, strictMode)}) {
+      return true;
+    }
+
+    if (${_isInterfaceSubtype(JavaScriptObject, t2, strictMode)}
+        && ${_isInterfaceSubtype(t1, _pkgJSTypeForSubtyping, strictMode)}) {
       return true;
     }
 
@@ -1587,10 +1552,11 @@
 })()''');
 
 bool _isInterfaceSubtype(t1, t2, @notNull bool strictMode) => JS('', '''(() => {
-  // If we have lazy JS types, unwrap them.  This will effectively
-  // reduce to a prototype check below.
-  if (${_jsInstanceOf(t1, LazyJSType)}) $t1 = $t1.rawJSTypeForCheck();
-  if (${_jsInstanceOf(t2, LazyJSType)}) $t2 = $t2.rawJSTypeForCheck();
+  // Instances of PackageJSType are all subtypes of each other.
+  if (${_jsInstanceOf(t1, PackageJSType)}
+      && ${_jsInstanceOf(t2, PackageJSType)}) {
+    return true;
+  }
 
   if ($t1 === $t2) {
     return true;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart b/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
index 71c559c..fdc771d 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
@@ -74,45 +74,40 @@
   operator []=(int index, E value);
 }
 
-/**
- * The interface implemented by JavaScript objects.  These are methods in
- * addition to the regular Dart Object methods like [Object.hashCode].
- *
- * This is the type that should be exported by a JavaScript interop library.
- */
+/// The interface implemented by JavaScript objects.
+///
+/// These are methods in addition to the regular Dart Object methods like
+/// [Object.hashCode]. This is the type that should be exported by a JavaScript
+/// interop library.
 abstract class JSObject {}
 
-/**
- * Interceptor base class for JavaScript objects not recognized as some more
- * specific native type.
- */
+/// Interceptor base class for JavaScript objects not recognized as some more
+/// specific native type.
+
+/// Unlike dart2js, ddc does not intercept JS objects, so this is only used as
+/// an on-type for JS interop extension types. All JS interop objects should be
+/// castable to this type.
 abstract class JavaScriptObject extends Interceptor implements JSObject {
   const JavaScriptObject();
-
-  // It would be impolite to stash a property on the object.
-  int get hashCode => 0;
-
-  Type get runtimeType => JSObject;
 }
 
-/**
- * Interceptor for plain JavaScript objects created as JavaScript object
- * literals or `new Object()`.
- */
+/// Interceptor for plain JavaScript objects created as JavaScript object
+/// literals or `new Object()`.
+///
+/// Note that this isn't being used today in ddc. Instead of using interceptors,
+/// we have other type logic to distinguish JS types.
 class PlainJavaScriptObject extends JavaScriptObject {
   const PlainJavaScriptObject();
 }
 
-/**
- * Interceptor for unclassified JavaScript objects, typically objects with a
- * non-trivial prototype chain.
- *
- * This class also serves as a fallback for unknown JavaScript exceptions.
- */
+/// Interceptor for unclassified JavaScript objects, typically objects with a
+/// non-trivial prototype chain.
+///
+/// This class also serves as a fallback for unknown JavaScript exceptions.
+/// Note that this isn't being used today in ddc. Instead of using interceptors,
+/// we have other type logic to distinguish JS types.
 class UnknownJavaScriptObject extends JavaScriptObject {
   const UnknownJavaScriptObject();
-
-  String toString() => JS<String>('!', 'String(#)', this);
 }
 
 class NativeError extends Interceptor {
diff --git a/sdk/lib/_internal/js_runtime/lib/constant_map.dart b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
index d5a5174..669a7e8 100644
--- a/sdk/lib/_internal/js_runtime/lib/constant_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
@@ -12,37 +12,24 @@
 abstract class ConstantMap<K, V> implements Map<K, V> {
   // Used to create unmodifiable maps from other maps.
   factory ConstantMap.from(Map other) {
-    var keys = new List<K>.from(other.keys);
+    final keys = List<K>.from(other.keys);
     bool allStrings = true;
     for (var k in keys) {
-      if (k is! String) {
+      if (k is! String || '__proto__' == k) {
         allStrings = false;
         break;
       }
     }
     if (allStrings) {
-      bool containsProto = false;
-      var protoValue = null;
       var object = JS('=Object', '{}');
-      int length = 0;
-      for (var k in keys) {
+      for (final k in keys) {
         V v = other[k];
-        if (k != '__proto__') {
-          if (!jsHasOwnProperty(object, k as String)) length++;
-          JS('void', '#[#] = #', object, k, v);
-        } else {
-          containsProto = true;
-          protoValue = v;
-        }
+        JS('void', '#[#] = #', object, k, v);
       }
-      if (containsProto) {
-        length++;
-        return new ConstantProtoMap<K, V>._(length, object, keys, protoValue);
-      }
-      return new ConstantStringMap<K, V>._(length, object, keys);
+      return ConstantStringMap<K, V>._(keys.length, object, keys);
     }
     // TODO(lrn): Make a proper unmodifiable map implementation.
-    return new ConstantMapView<K, V>(new Map.from(other));
+    return ConstantMapView<K, V>(Map.from(other));
   }
 
   const ConstantMap._();
@@ -55,7 +42,7 @@
   String toString() => MapBase.mapToString(this);
 
   static Never _throwUnmodifiable() {
-    throw new UnsupportedError('Cannot modify unmodifiable Map');
+    throw UnsupportedError('Cannot modify unmodifiable Map');
   }
 
   void operator []=(K key, V val) {
@@ -70,14 +57,19 @@
     _throwUnmodifiable();
   }
 
-  void clear() => _throwUnmodifiable();
-  void addAll(Map<K, V> other) => _throwUnmodifiable();
+  void clear() {
+    _throwUnmodifiable();
+  }
+
+  void addAll(Map<K, V> other) {
+    _throwUnmodifiable();
+  }
 
   Iterable<MapEntry<K, V>> get entries sync* {
     // `this[key]` has static type `V?` but is always `V`. Rather than `as V`,
     // we use `as dynamic` so the upcast requires no checking and the implicit
     // downcast to `V` will be discarded in production.
-    for (var key in keys) yield new MapEntry<K, V>(key, this[key] as dynamic);
+    for (var key in keys) yield MapEntry<K, V>(key, this[key] as dynamic);
   }
 
   void addEntries(Iterable<MapEntry<K, V>> entries) {
@@ -151,32 +143,14 @@
   }
 
   Iterable<K> get keys {
-    return new _ConstantMapKeyIterable<K>(this);
+    return _ConstantMapKeyIterable<K>(this);
   }
 
   Iterable<V> get values {
-    return new MappedIterable<K, V>(_keysArray, (key) => _fetch(key));
+    return MappedIterable<K, V>(_keysArray, (key) => _fetch(key));
   }
 }
 
-class ConstantProtoMap<K, V> extends ConstantStringMap<K, V> {
-  // This constructor is not used.  The instantiation is shortcut by the
-  // compiler. It is here to make the uninitialized final fields legal.
-  ConstantProtoMap._(length, jsObject, keys, this._protoValue)
-      : super._(length, jsObject, keys);
-
-  final V _protoValue;
-
-  bool containsKey(Object? key) {
-    if (key is! String) return false;
-    if ('__proto__' == key) return true;
-    return jsHasOwnProperty(_jsObject, key);
-  }
-
-  _fetch(key) =>
-      '__proto__' == key ? _protoValue : jsPropertyAccess(_jsObject, key);
-}
-
 class _ConstantMapKeyIterable<K> extends Iterable<K> {
   ConstantStringMap<K, dynamic> _map;
   _ConstantMapKeyIterable(this._map);
@@ -199,13 +173,35 @@
   Map<K, V> _getMap() {
     LinkedHashMap<K, V>? backingMap = JS('LinkedHashMap|Null', r'#.$map', this);
     if (backingMap == null) {
-      backingMap = new JsLinkedHashMap<K, V>();
+      backingMap = LinkedHashMap<K, V>(
+          hashCode: _constantMapHashCode,
+          // In legacy mode (--no-sound-null-safety), `null` keys are
+          // permitted. In sound mode, `null` keys are permitted only if [K] is
+          // nullable.
+          isValidKey: JS_GET_FLAG('LEGACY') ? _typeTest<K?>() : _typeTest<K>());
       fillLiteralMap(_jsData, backingMap);
       JS('', r'#.$map = #', this, backingMap);
     }
     return backingMap;
   }
 
+  static int _constantMapHashCode(Object? key) {
+    // Types are tested here one-by-one so that each call to get:hashCode can be
+    // resolved differently.
+
+    // Some common primitives in a GeneralConstantMap.
+    if (key is num) return key.hashCode; // One method on JSNumber.
+
+    // Specially handled known types.
+    if (key is Symbol) return key.hashCode;
+    if (key is Type) return key.hashCode;
+
+    // Everything else, including less common primitives.
+    return identityHashCode(key);
+  }
+
+  static bool Function(Object?) _typeTest<T>() => (Object? o) => o is T;
+
   bool containsValue(Object? needle) {
     return _getMap().containsValue(needle);
   }
diff --git a/sdk/lib/_internal/js_runtime/lib/io_patch.dart b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
index 77a2530..2ee566b 100644
--- a/sdk/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
@@ -364,8 +364,8 @@
       Map<String, String>? environment,
       bool includeParentEnvironment: true,
       bool runInShell: false,
-      Encoding stdoutEncoding: systemEncoding,
-      Encoding stderrEncoding: systemEncoding}) {
+      Encoding? stdoutEncoding: systemEncoding,
+      Encoding? stderrEncoding: systemEncoding}) {
     throw new UnsupportedError("Process.run");
   }
 
@@ -375,8 +375,8 @@
       Map<String, String>? environment,
       bool includeParentEnvironment: true,
       bool runInShell: false,
-      Encoding stdoutEncoding: systemEncoding,
-      Encoding stderrEncoding: systemEncoding}) {
+      Encoding? stdoutEncoding: systemEncoding,
+      Encoding? stderrEncoding: systemEncoding}) {
     throw new UnsupportedError("Process.runSync");
   }
 
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index f04ffbb..ad83f7b 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -1489,7 +1489,8 @@
       InternetAddress addr, NetworkInterface? interface) {
     // On Mac OS using the interface index for joining IPv4 multicast groups
     // is not supported. Here the IP address of the interface is needed.
-    if (Platform.isMacOS && addr.type == InternetAddressType.IPv4) {
+    if ((Platform.isMacOS || Platform.isIOS) &&
+        addr.type == InternetAddressType.IPv4) {
       if (interface != null) {
         for (int i = 0; i < interface.addresses.length; i++) {
           if (interface.addresses[i].type == InternetAddressType.IPv4) {
diff --git a/sdk/lib/_internal/vm/lib/bigint_patch.dart b/sdk/lib/_internal/vm/lib/bigint_patch.dart
index dd627df..f040c45 100644
--- a/sdk/lib/_internal/vm/lib/bigint_patch.dart
+++ b/sdk/lib/_internal/vm/lib/bigint_patch.dart
@@ -1657,8 +1657,9 @@
    */
   int get bitLength {
     if (_used == 0) return 0;
-    if (_isNegative) return (~this).bitLength;
-    return _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
+    var highBits = _digits[_used - 1];
+    if (_isNegative) highBits -= 1;
+    return _digitBits * (_used - 1) + highBits.bitLength;
   }
 
   /**
diff --git a/sdk/lib/_internal/vm/lib/compact_hash.dart b/sdk/lib/_internal/vm/lib/compact_hash.dart
index 492e9bd..dc552c7 100644
--- a/sdk/lib/_internal/vm/lib/compact_hash.dart
+++ b/sdk/lib/_internal/vm/lib/compact_hash.dart
@@ -490,18 +490,14 @@
   E get current => _current as E;
 }
 
-// Set implementation, analogous to _CompactLinkedHashMap.
-@pragma('vm:entry-point')
-class _CompactLinkedHashSet<E> extends _HashFieldBase
-    with _HashBase, _OperatorEqualsAndHashCode, SetMixin<E>
-    implements LinkedHashSet<E> {
-  _CompactLinkedHashSet() : super(_HashBase._INITIAL_INDEX_SIZE >> 1) {
-    assert(_HashBase._UNUSED_PAIR == 0);
-  }
+abstract class _LinkedHashSetMixin<E> implements _HashBase {
+  int _hashCode(e);
+  bool _equals(e1, e2);
+  int get _checkSum;
+  bool _isModifiedSince(List oldData, int oldCheckSum);
 
-  static Set<R> _newEmpty<R>() => new _CompactLinkedHashSet<R>();
-
-  Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newEmpty);
+  bool get isEmpty => length == 0;
+  bool get isNotEmpty => !isEmpty;
   int get length => _usedData - _deletedKeys;
 
   E get first {
@@ -650,19 +646,51 @@
   Iterator<E> get iterator =>
       new _CompactIterator<E>(this, _data, _usedData, -1, 1);
 
-  // Returns a set of the same type, although this
-  // 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);
-
   // This method is called by [_rehashObjects] (see above).
   void _regenerateIndex() {
+    _index = _data.length == 0 ? _initialIndex : new Uint32List(_data.length);
+    assert(_hashMask == 0);
+    _hashMask = _HashBase._indexSizeToHashMask(_index.length);
     _rehash();
   }
 }
 
-class _CompactLinkedIdentityHashSet<E> extends _CompactLinkedHashSet<E>
-    with _IdenticalAndIdentityHashCode {
+// Set implementation, analogous to _CompactLinkedHashMap.
+@pragma('vm:entry-point')
+class _CompactLinkedHashSet<E> extends _HashVMBase
+    with
+        SetMixin<E>,
+        _LinkedHashSetMixin<E>,
+        _HashBase,
+        _OperatorEqualsAndHashCode
+    implements LinkedHashSet<E> {
+  _CompactLinkedHashSet() {
+    _index = _initialIndex;
+    _hashMask = 0;
+    _data = _initialData;
+    _usedData = 0;
+    _deletedKeys = 0;
+  }
+
+  Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newEmpty);
+
+  static Set<R> _newEmpty<R>() => new _CompactLinkedHashSet<R>();
+
+  // Returns a set of the same type, although this
+  // 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);
+}
+
+class _CompactLinkedIdentityHashSet<E> extends _HashFieldBase
+    with
+        SetMixin<E>,
+        _LinkedHashSetMixin<E>,
+        _HashBase,
+        _IdenticalAndIdentityHashCode
+    implements LinkedHashSet<E> {
+  _CompactLinkedIdentityHashSet() : super(_HashBase._INITIAL_INDEX_SIZE);
+
   Set<E> toSet() => new _CompactLinkedIdentityHashSet<E>()..addAll(this);
 
   static Set<R> _newEmpty<R>() => new _CompactLinkedIdentityHashSet<R>();
@@ -670,7 +698,9 @@
   Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newEmpty);
 }
 
-class _CompactLinkedCustomHashSet<E> extends _CompactLinkedHashSet<E> {
+class _CompactLinkedCustomHashSet<E> extends _HashFieldBase
+    with SetMixin<E>, _LinkedHashSetMixin<E>, _HashBase
+    implements LinkedHashSet<E> {
   final _equality;
   final _hasher;
   final _validKey;
@@ -683,7 +713,8 @@
   bool remove(Object? o) => _validKey(o) ? super.remove(o) : false;
 
   _CompactLinkedCustomHashSet(this._equality, this._hasher, validKey)
-      : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test;
+      : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test,
+        super(_HashBase._INITIAL_INDEX_SIZE);
 
   Set<R> cast<R>() => Set.castFrom<E, R>(this);
   Set<E> toSet() =>
diff --git a/sdk/lib/_internal/vm/lib/expando_patch.dart b/sdk/lib/_internal/vm/lib/expando_patch.dart
index cacbc02..36c65df 100644
--- a/sdk/lib/_internal/vm/lib/expando_patch.dart
+++ b/sdk/lib/_internal/vm/lib/expando_patch.dart
@@ -5,11 +5,12 @@
 // part of "core_patch.dart";
 
 @patch
+@pragma("vm:entry-point")
 class Expando<T> {
   @patch
   Expando([String? name])
       : name = name,
-        _data = new List.filled(_minSize, null),
+        _data = new List<_WeakProperty?>.filled(_minSize, null),
         _used = 0;
 
   static const _minSize = 8;
@@ -95,6 +96,7 @@
     this[object] = value; // Recursively add the value.
   }
 
+  @pragma("vm:entry-point", "call")
   _rehash() {
     // Determine the population count of the map to allocate an appropriately
     // sized map below.
@@ -119,7 +121,7 @@
 
     // Reset the mappings to empty so that we can just add the existing
     // valid entries.
-    _data = new List.filled(new_size, null);
+    _data = new List<_WeakProperty?>.filled(new_size, null);
     _used = 0;
 
     for (var i = 0; i < old_data.length; i++) {
@@ -149,9 +151,9 @@
     }
   }
 
-  get _size => _data.length;
-  get _limit => (3 * (_size ~/ 4));
+  int get _size => _data.length;
+  int get _limit => (3 * (_size ~/ 4));
 
-  List _data;
+  List<_WeakProperty?> _data;
   int _used; // Number of used (active and deleted) slots.
 }
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index 6cc2388..67501fb 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -193,6 +193,9 @@
 abstract class VMInternalsForTesting {
   // This function can be used by tests to enforce garbage collection.
   static void collectAllGarbage() native "Internal_collectAllGarbage";
+
+  static void deoptimizeFunctionsOnStack()
+      native "Internal_deoptimizeFunctionsOnStack";
 }
 
 @patch
diff --git a/sdk/lib/_internal/vm/lib/isolate_patch.dart b/sdk/lib/_internal/vm/lib/isolate_patch.dart
index 34ce5e4..9703179 100644
--- a/sdk/lib/_internal/vm/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/vm/lib/isolate_patch.dart
@@ -160,8 +160,8 @@
   }
 
   /**** Internal implementation details ****/
-  _get_id() native "RawReceivePortImpl_get_id";
-  _get_sendport() native "RawReceivePortImpl_get_sendport";
+  int _get_id() native "RawReceivePortImpl_get_id";
+  SendPort _get_sendport() native "RawReceivePortImpl_get_sendport";
 
   // Called from the VM to retrieve the handler for a message.
   @pragma("vm:entry-point", "call")
@@ -186,7 +186,7 @@
   }
 
   // Call into the VM to close the VM maintained mappings.
-  _closeInternal() native "RawReceivePortImpl_closeInternal";
+  int _closeInternal() native "RawReceivePortImpl_closeInternal";
 
   // Set this port as active or inactive in the VM. If inactive, this port
   // will not be considered live even if it hasn't been explicitly closed.
@@ -195,7 +195,7 @@
   _setActive(bool active) native "RawReceivePortImpl_setActive";
 
   void set handler(Function? value) {
-    final id = this._get_id();
+    final int id = this._get_id();
     if (!_portMap.containsKey(id)) {
       _portMap[id] = <String, dynamic>{
         'port': this,
@@ -204,7 +204,7 @@
     _portMap[id]!['handler'] = value;
   }
 
-  static final _portMap = <dynamic, Map<String, dynamic>>{};
+  static final _portMap = <int, Map<String, dynamic>>{};
 }
 
 @pragma("vm:entry-point")
diff --git a/sdk/lib/_internal/vm/lib/symbol_patch.dart b/sdk/lib/_internal/vm/lib/symbol_patch.dart
index 06eb588..eeb9e0b 100644
--- a/sdk/lib/_internal/vm/lib/symbol_patch.dart
+++ b/sdk/lib/_internal/vm/lib/symbol_patch.dart
@@ -6,6 +6,7 @@
 
 @patch
 class Symbol {
+  // TODO(http://dartbug.com/46716): Recognize Symbol in the VM.
   @patch
   const Symbol(String name) : this._name = name;
 
@@ -52,6 +53,7 @@
     return result.toString();
   }
 
+  // Must be kept in sync with Symbol::CanonicalizeHash in object.cc.
   @patch
   int get hashCode {
     const arbitraryPrime = 664597;
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 2952ad3..555bc3d 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -719,7 +719,7 @@
 /// are *expected* to complete with a value.
 /// You can use [FutureExtensions.ignore] if you also don't want to know
 /// about errors from this future.
-@Since("2.15")
+@Since("2.14")
 void unawaited(Future<void> future) {}
 
 /// Convenience methods on futures.
@@ -809,7 +809,7 @@
   /// If you merely want to silence the ["unawaited futures" lint](https://dart-lang.github.io/linter/lints/unawaited_futures.html),
   /// use the [unawaited] function instead.
   /// That will ensure that an unexpected error is still reported.
-  @Since("2.15")
+  @Since("2.14")
   void ignore() {
     var self = this;
     if (self is _Future<T>) {
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index d03e095..262b847 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1479,13 +1479,20 @@
 
   /// Creates a new stream with the same events as this stream.
   ///
-  /// Whenever more than [timeLimit] passes between two events from this stream,
-  /// the [onTimeout] function is called, which can emit further events on
+  /// When someone is listening on the returned stream and more than
+  /// [timeLimit] passes without any event being emitted by this stream,
+  /// the [onTimeout] function is called, which can then emit further events on
   /// the returned stream.
   ///
-  /// The countdown doesn't start until the returned stream is listened to.
-  /// The countdown is reset every time an event is forwarded from this stream,
-  /// or when this stream is paused and resumed.
+  /// The countdown starts when the returned stream is listened to,
+  /// and is restarted when an event from the 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.
+  /// No new countdown is started when a countdown completes
+  /// and the [onTimeout] function is called, even if events are emitted.
+  /// If the delay between events of this stream is multiple times
+  /// [timeLimit], at most one timeout will happen between events.
   ///
   /// The [onTimeout] function is called with one argument: an
   /// [EventSink] that allows putting events into the returned stream.
@@ -1493,10 +1500,10 @@
   /// Calling [EventSink.close] on the sink passed to [onTimeout] closes the
   /// returned stream, and no further events are processed.
   ///
-  /// If [onTimeout] is omitted, a timeout will just put a [TimeoutException]
+  /// If [onTimeout] is omitted, a timeout will emit a [TimeoutException]
   /// into the error channel of the returned stream.
-  /// If the call to [onTimeout] throws, the error is emitted on the returned
-  /// stream.
+  /// If the call to [onTimeout] throws, the error is emitted as an error
+  /// on the returned stream.
   ///
   /// The returned stream is a broadcast stream if this stream is.
   /// If a broadcast stream is listened to more than once, each subscription
@@ -1519,8 +1526,6 @@
             new TimeoutException("No stream event", timeLimit), null);
       };
     } else {
-      // TODO(floitsch): the return type should be 'void', and the type
-      // should be inferred.
       var registeredOnTimeout =
           zone.registerUnaryCallback<void, EventSink<T>>(onTimeout);
       var wrapper = new _ControllerEventSinkWrapper<T>(null);
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 97252ba56..fb48484 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.dart
@@ -52,6 +52,11 @@
   /// and if all elements stored into the returned queue are actually instance
   /// of [S],
   /// then the returned queue can be used as a `Queue<T>`.
+  ///
+  /// Methods like [contains] and [remove]
+  /// which accept one `Object?` as argument,
+  /// will pass the argument directly to the this queue's method
+  /// without any checks.
   static Queue<T> castFrom<S, T>(Queue<S> source) => CastQueue<S, T>(source);
 
   /// Provides a view of this queue as a queue of [R] instances, if necessary.
@@ -64,6 +69,13 @@
   /// must be instance of [R] to be valid arguments to the adding function,
   /// and they must be instances of [E] as well to be accepted by
   /// this queue as well.
+  ///
+  /// Methods like [contains] and [remove]
+  /// which accept one `Object?` as argument,
+  /// will pass the argument directly to the this queue's method
+  /// without any checks.
+  /// That means that you can do `queueOfStrings.cast<int>().remove("a")`
+  /// successfully, even if it looks like it shouldn't have any effect.
   Queue<R> cast<R>();
 
   /// Removes and returns the first element of this queue.
@@ -304,6 +316,7 @@
       DoubleLinkedQueue<E>()..addAll(elements);
 
   Queue<R> cast<R>() => Queue.castFrom<E, R>(this);
+
   int get length => _elementCount;
 
   void addLast(E value) {
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index 42db5d5..6c17632 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -187,6 +187,11 @@
   /// and if all elements stored into the returned list are actually instance
   /// of [S],
   /// then the returned list can be used as a `List<T>`.
+  ///
+  /// Methods like [contains] and [remove]
+  /// which accept `Object?` as argument
+  /// will pass the argument directly to the this list's method
+  /// without any checks.
   static List<T> castFrom<S, T>(List<S> source) => CastList<S, T>(source);
 
   /// Copy a range of one list into another list.
@@ -254,7 +259,7 @@
   /// Returns a view of this list as a list of [R] instances.
   ///
   /// If this list contains only instances of [R], all read operations
-  /// will work correctly. If any operation tries to access an element
+  /// will work correctly. If any operation tries to read an element
   /// that is not an instance of [R], the access will throw instead.
   ///
   /// Elements added to the list (e.g., by using [add] or [addAll])
@@ -262,6 +267,13 @@
   /// and they must be instances of [E] as well to be accepted by
   /// this list as well.
   ///
+  /// Methods like [contains] and [remove]
+  /// which accept `Object?` as argument
+  /// will pass the argument directly to the this list's method
+  /// without any checks.
+  /// That means that you can do `listOfStrings.cast<int>().remove("a")`
+  /// successfully, even if it looks like it shouldn't have any effect.
+  ///
   /// Typically implemented as `List.castFrom<E, R>(this)`.
   List<R> cast<R>();
 
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index 17590cc..f6d36b1 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -163,6 +163,11 @@
   /// If all accessed entries of [source] are have [K2] keys and [V2] values
   /// and if all entries added to the returned map have [K] keys and [V]] values,
   /// then the returned map can be used as a `Map<K2, V2>`.
+  ///
+  /// Methods like [containsKey], [remove] and [operator[]]
+  /// which accept `Object?` as argument
+  /// will pass the argument directly to the this map's method
+  /// without any checks.
   static Map<K2, V2> castFrom<K, V, K2, V2>(Map<K, V> source) =>
       CastMap<K, V, K2, V2>(source);
 
@@ -193,6 +198,13 @@
   ///
   /// Entries added to the map must be valid for both a `Map<K, V>` and a
   /// `Map<RK, RV>`.
+  ///
+  /// Methods like [containsKey], [remove] and [operator[]]
+  /// which accept `Object?` as argument
+  /// will pass the argument directly to the this map's method
+  /// without any checks.
+  /// That means that you can do `mapWithStringKeys.cast<int,int>().remove("a")`
+  /// successfully, even if it looks like it shouldn't have any effect.
   Map<RK, RV> cast<RK, RV>();
 
   /// Whether this map contains the given [value].
diff --git a/sdk/lib/core/set.dart b/sdk/lib/core/set.dart
index eb86364..b19ed8e 100644
--- a/sdk/lib/core/set.dart
+++ b/sdk/lib/core/set.dart
@@ -106,6 +106,11 @@
   /// and if all elements added to the returned set are actually instance
   /// of [S],
   /// then the returned set can be used as a `Set<T>`.
+  ///
+  /// Methods like [contains], [remove] and [removeAll]
+  /// which accept one or more `Object?` as argument,
+  /// will pass the argument directly to the this set's method
+  /// without any checks.
   static Set<T> castFrom<S, T>(Set<S> source, {Set<R> Function<R>()? newSet}) =>
       CastSet<S, T>(source, newSet);
 
@@ -119,6 +124,13 @@
   /// must be instance of [R] to be valid arguments to the adding function,
   /// and they must be instances of [E] as well to be accepted by
   /// this set as well.
+  ///
+  /// Methods like [contains], [remove] and [removeAll]
+  /// which accept one or more `Object?` as argument,
+  /// will pass the argument directly to the this set's method
+  /// without any checks.
+  /// That means that you can do `setOfStrings.cast<int>().remove("a")`
+  /// successfully, even if it looks like it shouldn't have any effect.
   Set<R> cast<R>();
 
   /// An iterator that iterates over the elements of this set.
diff --git a/sdk/lib/developer/service.dart b/sdk/lib/developer/service.dart
index 8715d25..9d6fe098 100644
--- a/sdk/lib/developer/service.dart
+++ b/sdk/lib/developer/service.dart
@@ -63,12 +63,13 @@
     // Port to receive response from service isolate.
     final RawReceivePort receivePort =
         new RawReceivePort(null, 'Service.getInfo');
-    final Completer<Uri?> uriCompleter = new Completer<Uri?>();
-    receivePort.handler = (Uri? uri) => uriCompleter.complete(uri);
+    final Completer<String?> completer = new Completer<String?>();
+    receivePort.handler = (String? uriString) => completer.complete(uriString);
     // Request the information from the service isolate.
     _getServerInfo(receivePort.sendPort);
     // Await the response from the service isolate.
-    Uri? uri = await uriCompleter.future;
+    String? uriString = await completer.future;
+    Uri? uri = uriString == null ? null : Uri.parse(uriString);
     // Close the port.
     receivePort.close();
     return new ServiceProtocolInfo(uri);
@@ -85,12 +86,13 @@
     // Port to receive response from service isolate.
     final RawReceivePort receivePort =
         new RawReceivePort(null, 'Service.controlWebServer');
-    final Completer<Uri> uriCompleter = new Completer<Uri>();
-    receivePort.handler = (Uri uri) => uriCompleter.complete(uri);
+    final Completer<String?> completer = new Completer<String?>();
+    receivePort.handler = (String? uriString) => completer.complete(uriString);
     // Request the information from the service isolate.
     _webServerControl(receivePort.sendPort, enable, silenceOutput);
     // Await the response from the service isolate.
-    Uri uri = await uriCompleter.future;
+    String? uriString = await completer.future;
+    Uri? uri = uriString == null ? null : Uri.parse(uriString);
     // Close the port.
     receivePort.close();
     return new ServiceProtocolInfo(uri);
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index 0e8be36..1e8a9ea 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -806,7 +806,7 @@
 ///
 /// Example:
 ///```dart
-/// @FfiNative<Int64 Function(Int64, Int64)>("FfiNative_Sum")
+/// @FfiNative<Int64 Function(Int64, Int64)>("FfiNative_Sum", isLeaf:true)
 /// external int sum(int a, int b);
 ///```
 /// Calling such functions will throw an exception if no resolver
@@ -817,7 +817,8 @@
 /// NOTE: This is an experimental feature and may change in the future.
 class FfiNative<T> {
   final String nativeName;
-  const FfiNative(this.nativeName);
+  final bool isLeaf;
+  const FfiNative(this.nativeName, {this.isLeaf: false});
 }
 
 // Bootstrapping native for getting the FFI native C function pointer to look
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 7f6f21b..15695c1 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -13442,7 +13442,7 @@
    *     var createdElement = document.body.children[0];
    *     print(createdElement.classes[0]); // Prints 'something'
    * ```
-   * 
+   *
    * See also:
    *
    * * [insertAdjacentText]
@@ -36529,7 +36529,7 @@
    * This is equivalent to the `height` function in jQuery and the calculated
    * `height` CSS value, converted to a dimensionless num in pixels. Unlike
    * [Element.getBoundingClientRect], `height` will return the same numerical
-   * width if the element is hidden or not.
+   * height if the element is hidden or not.
    */
   num get height;
 
@@ -37100,7 +37100,7 @@
       new _EventStream<T>(e, _eventType, useCapture);
 
   /**
-   * Gets an [Stream] for this event type, on the specified element.
+   * Gets a [Stream] for this event type, on the specified element.
    *
    * This will always return a broadcast stream so multiple listeners can be
    * used simultaneously.
@@ -37126,7 +37126,7 @@
   }
 
   /**
-   * Gets an [ElementEventStream] for this event type, on the list of elements.
+   * Gets a [Stream] for this event type, on the list of elements.
    *
    * This will always return a broadcast stream so multiple listeners can be
    * used simultaneously.
diff --git a/sdk/lib/html/dartium/nativewrappers.dart b/sdk/lib/html/dartium/nativewrappers.dart
index b6d2dc4..1d7787e 100644
--- a/sdk/lib/html/dartium/nativewrappers.dart
+++ b/sdk/lib/html/dartium/nativewrappers.dart
@@ -6,8 +6,18 @@
 
 class NativeFieldWrapperClass1 {}
 
-class NativeFieldWrapperClass2 {}
+class NativeFieldWrapperClass2 extends NativeFieldWrapperClass1 {}
 
-class NativeFieldWrapperClass3 {}
+class NativeFieldWrapperClass3 extends NativeFieldWrapperClass2 {}
 
-class NativeFieldWrapperClass4 {}
+class NativeFieldWrapperClass4 extends NativeFieldWrapperClass3 {}
+
+/// Gets the value of the native field of [object].
+///
+/// Throws an exception if [object] is null or if the native field was not set.
+///
+/// NOTE: This is function is temporary and will be deprecated in the near
+/// future.
+@pragma("vm:recognized", "other")
+int getNativeField(NativeFieldWrapperClass1 object)
+    native "FullyRecognizedMethod_NoNative";
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 455de12..ad56eea 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -89,13 +89,11 @@
   static KeyRange createKeyRange_only(/*Key*/ value) =>
       _only(_class(), _translateKey(value));
 
-  static KeyRange createKeyRange_lowerBound(
-          /*Key*/ bound,
+  static KeyRange createKeyRange_lowerBound(/*Key*/ bound,
           [bool open = false]) =>
       _lowerBound(_class(), _translateKey(bound), open);
 
-  static KeyRange createKeyRange_upperBound(
-          /*Key*/ bound,
+  static KeyRange createKeyRange_upperBound(/*Key*/ bound,
           [bool open = false]) =>
       _upperBound(_class(), _translateKey(bound), open);
 
diff --git a/sdk/lib/internal/symbol.dart b/sdk/lib/internal/symbol.dart
index 718ac68..e494ff6 100644
--- a/sdk/lib/internal/symbol.dart
+++ b/sdk/lib/internal/symbol.dart
@@ -12,92 +12,11 @@
  * make it accessible to Dart platform code via the static method
  * [getName].
  */
+@pragma('vm:entry-point')
 class Symbol implements core.Symbol {
+  @pragma('vm:entry-point')
   final String _name;
 
-  /**
-   * Source of RegExp matching Dart reserved words.
-   *
-   * Reserved words are not allowed as identifiers.
-   */
-  static const String reservedWordRE =
-      r'(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|'
-      r'e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|'
-      r'ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|'
-      r'v(?:ar|oid)|w(?:hile|ith))';
-  /**
-   * Source of RegExp matching any public identifier.
-   *
-   * A public identifier is a valid identifier (not a reserved word)
-   * that doesn't start with '_'.
-   */
-  static const String publicIdentifierRE =
-      r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$][\w$]*';
-  /**
-   * Source of RegExp matching any identifier.
-   *
-   * It matches identifiers but not reserved words. The identifiers
-   * may start with '_'.
-   */
-  static const String identifierRE =
-      r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$_][\w$]*';
-  /**
-   * Source of RegExp matching a declarable operator names.
-   *
-   * The operators that can be declared using `operator` declarations are
-   * also the only ones allowed as symbols. The name of the operators is
-   * the same as the operator itself except for unary minus, where the name
-   * is "unary-".
-   */
-  static const String operatorRE =
-      r'(?:[\-+*/%&|^]|\[\]=?|==|~/?|<[<=]?|>(?:|=|>>?)|unary-)';
-
-  // Grammar if symbols:
-  //    symbol ::= qualifiedName | <empty>
-  //    qualifiedName ::= publicIdentifier '.' qualifiedName | name
-  //    name ::= publicIdentifier
-  //           | publicIdentifier '='
-  //           | operator
-  // where publicIdentifier is any valid identifier (not a reserved word)
-  // that isn't private (doesn't start with '_').
-  //
-  // Railroad diagram of the accepted grammar:
-  //
-  //    /----------------\
-  //    |                |
-  //    |          /-[.]-/     /-[=]-\
-  //    \         /           /       \
-  //  -------[id]------------------------->
-  //       \                     /
-  //        \------[operator]---/
-  //            \              /
-  //             \------------/
-  //
-
-  /**
-   * RegExp that validates a non-empty non-private symbol.
-   *
-   * The empty symbol is handled before this regexp is used, and is not
-   * accepted.
-   */
-  static final RegExp publicSymbolPattern = new RegExp(
-      '^(?:$operatorRE\$|$publicIdentifierRE(?:=?\$|[.](?!\$)))+?\$');
-
-  // The grammar of symbols that may be private is the same as for public
-  // symbols, except that "publicIdentifier" is replaced by "identifier",
-  // which matches any identifier.
-
-  /**
-   * RegExp that validates a non-empty symbol.
-   *
-   * Private symbols are accepted.
-   *
-   * The empty symbol is handled before this regexp is used, and is not
-   * accepted.
-   */
-  static final RegExp symbolPattern =
-      new RegExp('^(?:$operatorRE\$|$identifierRE(?:=?\$|[.](?!\$)))+?\$');
-
   external const Symbol(String name);
 
   /**
@@ -115,25 +34,5 @@
   /// Platform-private accessor which cannot be called from user libraries.
   static String getName(Symbol symbol) => symbol._name;
 
-  static String validatePublicSymbol(String name) {
-    if (name.isEmpty || publicSymbolPattern.hasMatch(name)) return name;
-    if (name.startsWith('_')) {
-      // There may be other private parts in a qualified name than the first
-      // one, but this is a common case that deserves a specific error
-      // message.
-      throw new ArgumentError('"$name" is a private identifier');
-    }
-    throw new ArgumentError('"$name" is not a valid (qualified) symbol name');
-  }
-
-  /**
-   * Checks whether name is a valid symbol name.
-   *
-   * This test allows both private and non-private symbols.
-   */
-  static bool isValidSymbol(String name) {
-    return (name.isEmpty || symbolPattern.hasMatch(name));
-  }
-
   external static String computeUnmangledName(Symbol symbol);
 }
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 3e7a592..8a68d10 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -567,10 +567,16 @@
   /// Sends an asynchronous [message] through this send port, to its
   /// corresponding `ReceivePort`.
   ///
-  /// The content of [message] can be: primitive values
-  /// (null, num, bool, double, String), instances of [SendPort],
-  /// and lists and maps whose elements are any of these.
-  /// List and maps are also allowed to contain cyclic references.
+  /// The content of [message] can be:
+  ///   - [Null]
+  ///   - [bool]
+  ///   - [int]
+  ///   - [double]
+  ///   - [String]
+  ///   - [List] or [Map] (whose elements are any of these)
+  ///   - [TransferableTypedData]
+  ///   - [SendPort]
+  ///   - [Capability]
   ///
   /// In the special circumstances when two isolates share the same code and are
   /// running in the same process (e.g. isolates created via [Isolate.spawn]),
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 6262221..9a1a1d8 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -5,7 +5,7 @@
 # Note: if you edit this file, you must also generate libraries.json in this
 # directory:
 #
-#     python3 ./tools/yaml2json.py sdk/lib/libraries.yaml sdk/lib/libraries.json
+#     dart tools/yaml2json.dart sdk/lib/libraries.yaml sdk/lib/libraries.json
 #
 # We currently have several different files that needs to be updated when
 # changing libraries, sources, and patch files.  See
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index d492dcf..dacc9d5 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -366,7 +366,7 @@
           return;
         }
         final uri = await webServerControl(enable, silenceOutput);
-        sp.send(uri);
+        sp.send(uri?.toString());
         break;
       case Constants.SERVER_INFO_MESSAGE_ID:
         final serverInformation = VMServiceEmbedderHooks.serverInformation;
@@ -375,7 +375,7 @@
           return;
         }
         final uri = await serverInformation();
-        sp.send(uri);
+        sp.send(uri?.toString());
         break;
     }
   }
diff --git a/sdk/lib/vmservice_libraries.yaml b/sdk/lib/vmservice_libraries.yaml
index 40015c3..d5e049c 100644
--- a/sdk/lib/vmservice_libraries.yaml
+++ b/sdk/lib/vmservice_libraries.yaml
@@ -5,7 +5,7 @@
 # Note: if you edit this file, you must also generate libraries.json in this
 # directory:
 #
-#     python3 ./tools/yaml2json.py sdk/lib/vmservice_libraries.yaml sdk/lib/vmservice_libraries.json
+#     dart tools/yaml2json.dart sdk/lib/vmservice_libraries.yaml sdk/lib/vmservice_libraries.json
 #
 # We currently have several different files that needs to be updated when
 # changing libraries, sources, and patch files.  See
diff --git a/tests/co19_2/co19_2-co19.status b/tests/co19_2/co19_2-co19.status
index c281e44..3d7b0c2 100644
--- a/tests/co19_2/co19_2-co19.status
+++ b/tests/co19_2/co19_2-co19.status
@@ -2,5 +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.
 
-[ $compiler != fasta ]
-
+Language/Generics/Superbounded_types/typedef1_A01_t03: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
+Language/Generics/Superbounded_types/typedef1_A01_t04: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
+Language/Generics/Superbounded_types/typedef2_A01_t04: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
+Language/Generics/typedef_A08_t02: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
+Language/Generics/typedef_A08_t03: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
+Language/Generics/typedef_A08_t04: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index 5ba60fe..5c38055 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -6,6 +6,7 @@
 Language/Expressions/Null/instance_of_class_null_t01: SkipByDesign # dart:mirrors not supported https://github.com/dart-lang/co19/issues/522.
 Language/Expressions/Numbers/syntax_t06: SkipByDesign # uses integer literal not representable as JavaScript number
 Language/Expressions/Numbers/syntax_t09: SkipByDesign # uses integer literal not representable as JavaScript number
+Language/Expressions/Object_Identity/object_t02: SkipByDesign # https://github.com/dart-lang/sdk/issues/42222#issuecomment-640431711
 Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign
 Language/Functions/External_Functions/not_connected_to_a_body_t01: SkipByDesign # Non-JS-interop external members are not supported
 Language/Libraries_and_Scripts/Scripts/top_level_syntax_t01: SkipByDesign # Non-JS-interop external members are not supported
diff --git a/tests/dartdevc/debugger/debugger_test_golden.txt b/tests/dartdevc/debugger/debugger_test_golden.txt
index 76772be..a879c6e 100644
--- a/tests/dartdevc/debugger/debugger_test_golden.txt
+++ b/tests/dartdevc/debugger/debugger_test_golden.txt
@@ -6519,7 +6519,7 @@
     {
         "style": "background-color: #d9edf7;color: black"
     },
-    "Instance of 'TestGenericClass<JSObject<ExampleJSClass>, int>'"
+    "Instance of 'TestGenericClass<ExampleJSClass, int>'"
 ]
 -----------------------------------
 Test: TestGenericClassJSInterop instance body
@@ -6616,7 +6616,7 @@
     {
         "style": "background-color: #d9edf7;color: black"
     },
-    "TestGenericClass<JSObject<ExampleJSClass>, int>"
+    "TestGenericClass<ExampleJSClass, int>"
 ]
 -----------------------------------
 Test: TestGenericClassJSInterop definition formatting body
diff --git a/tests/dartdevc_2/debugger/debugger_test_golden.txt b/tests/dartdevc_2/debugger/debugger_test_golden.txt
index 76772be..a879c6e 100644
--- a/tests/dartdevc_2/debugger/debugger_test_golden.txt
+++ b/tests/dartdevc_2/debugger/debugger_test_golden.txt
@@ -6519,7 +6519,7 @@
     {
         "style": "background-color: #d9edf7;color: black"
     },
-    "Instance of 'TestGenericClass<JSObject<ExampleJSClass>, int>'"
+    "Instance of 'TestGenericClass<ExampleJSClass, int>'"
 ]
 -----------------------------------
 Test: TestGenericClassJSInterop instance body
@@ -6616,7 +6616,7 @@
     {
         "style": "background-color: #d9edf7;color: black"
     },
-    "TestGenericClass<JSObject<ExampleJSClass>, int>"
+    "TestGenericClass<ExampleJSClass, int>"
 ]
 -----------------------------------
 Test: TestGenericClassJSInterop definition formatting body
diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status
index 16826bf..c54ce09 100644
--- a/tests/ffi/ffi.status
+++ b/tests/ffi/ffi.status
@@ -40,7 +40,3 @@
 
 [ $compiler == dart2analyzer || $compiler == fasta ]
 vmspecific_enable_ffi_test: SkipByDesign # This is a check for VM only.
-
-[ $hot_reload || $hot_reload_rollback ]
-snapshot_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-vmspecific_function_callbacks_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
diff --git a/tests/ffi/ffi_native_test.dart b/tests/ffi/ffi_native_test.dart
new file mode 100644
index 0000000..b700981
--- /dev/null
+++ b/tests/ffi/ffi_native_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.
+//
+// SharedObjects=ffi_test_functions
+
+// NOTE: There is no `test/ffi_2/...` version of this test since annotations
+// with type arguments isn't supported in that version of Dart.
+
+import 'dart:ffi';
+
+import 'package:expect/expect.dart';
+
+import 'dylib_utils.dart';
+
+final nativeLib = dlopenPlatformSpecific('ffi_test_functions');
+final getRootLibraryUrl = nativeLib
+    .lookupFunction<Handle Function(), Object Function()>('GetRootLibraryUrl');
+final setFfiNativeResolverForTest = nativeLib
+    .lookupFunction<Void Function(Handle), void Function(Object)>('SetFfiNativeResolverForTest');
+
+@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr')
+external int returnIntPtr(int x);
+
+@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr', isLeaf: true)
+external int returnIntPtrLeaf(int x);
+
+@FfiNative<IntPtr Function()>('IsThreadInGenerated')
+external int isThreadInGenerated();
+
+@FfiNative<IntPtr Function()>('IsThreadInGenerated', isLeaf: true)
+external int isThreadInGeneratedLeaf();
+
+// Error: FFI leaf call must not have Handle return type.
+@FfiNative<Handle Function()>("foo", isLeaf: true)  //# 01: compile-time error
+external Object foo();  //# 01: compile-time error
+
+// Error: FFI leaf call must not have Handle argument types.
+@FfiNative<Void Function(Handle)>("bar", isLeaf: true)  //# 02: compile-time error
+external void bar(Object);  //# 02: compile-time error
+
+class Classy {
+  @FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr')
+  external static int returnIntPtrStatic(int x);
+
+  // Error: FfiNative annotations can only be used on static functions.
+  @FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr')  //# 03: compile-time error
+  external int returnIntPtrMethod(int x);  //# 03: compile-time error
+}
+
+void main() {
+  // Register test resolver for top-level functions above.
+  final root_lib_url = getRootLibraryUrl();
+  setFfiNativeResolverForTest(root_lib_url);
+
+  // Test we can call FfiNative functions.
+  Expect.equals(123, returnIntPtr(123));
+  Expect.equals(123, returnIntPtrLeaf(123));
+  Expect.equals(123, Classy.returnIntPtrStatic(123));
+
+  // Test FfiNative leaf calls remain in generated code.
+  // Regular calls should transition generated -> native.
+  Expect.equals(0, isThreadInGenerated());
+  // Leaf calls should remain in generated state.
+  Expect.equals(1, isThreadInGeneratedLeaf());
+}
diff --git a/tests/ffi/snapshot_test.dart b/tests/ffi/snapshot_test.dart
index 5bb0b10..b27b88b 100644
--- a/tests/ffi/snapshot_test.dart
+++ b/tests/ffi/snapshot_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Checks that the VM throws an appropriate exception when FFI objects are
diff --git a/tests/ffi/vmspecific_function_callbacks_test.dart b/tests/ffi/vmspecific_function_callbacks_test.dart
index f35ae18..6d192a9 100644
--- a/tests/ffi/vmspecific_function_callbacks_test.dart
+++ b/tests/ffi/vmspecific_function_callbacks_test.dart
@@ -5,7 +5,7 @@
 //
 // Dart test program for testing dart:ffi function pointers with callbacks.
 //
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 // VMOptions=--stacktrace-every=100
 // VMOptions=--write-protect-code --no-dual-map-code
diff --git a/tests/ffi_2/ffi_2.status b/tests/ffi_2/ffi_2.status
index 16826bf..c54ce09 100644
--- a/tests/ffi_2/ffi_2.status
+++ b/tests/ffi_2/ffi_2.status
@@ -40,7 +40,3 @@
 
 [ $compiler == dart2analyzer || $compiler == fasta ]
 vmspecific_enable_ffi_test: SkipByDesign # This is a check for VM only.
-
-[ $hot_reload || $hot_reload_rollback ]
-snapshot_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-vmspecific_function_callbacks_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
diff --git a/tests/ffi_2/snapshot_test.dart b/tests/ffi_2/snapshot_test.dart
index 129a8d0..7574cea 100644
--- a/tests/ffi_2/snapshot_test.dart
+++ b/tests/ffi_2/snapshot_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Checks that the VM throws an appropriate exception when FFI objects are
diff --git a/tests/ffi_2/vmspecific_function_callbacks_test.dart b/tests/ffi_2/vmspecific_function_callbacks_test.dart
index 6d9311f..e86bb95 100644
--- a/tests/ffi_2/vmspecific_function_callbacks_test.dart
+++ b/tests/ffi_2/vmspecific_function_callbacks_test.dart
@@ -7,7 +7,7 @@
 // Dart test program for testing dart:ffi function pointers with callbacks.
 //
 // SharedObjects=ffi_test_functions
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 // VMOptions=--stacktrace-every=100
 // VMOptions=--use-slow-path
diff --git a/tests/language/abstract/exact_selector_runtime_test.dart b/tests/language/abstract/exact_selector_runtime_test.dart
index e8fc4ec..3d8f29e 100644
--- a/tests/language/abstract/exact_selector_runtime_test.dart
+++ b/tests/language/abstract/exact_selector_runtime_test.dart
@@ -9,13 +9,13 @@
 // methods to handle `noSuchMethod`.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 class Foo {
   noSuchMethod(im) => 42;
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 returnFoo() {
   (() => 42)();
   return new Foo();
diff --git a/tests/language/abstract/exact_selector_test.dart b/tests/language/abstract/exact_selector_test.dart
index 0df1020..fc6dba8 100644
--- a/tests/language/abstract/exact_selector_test.dart
+++ b/tests/language/abstract/exact_selector_test.dart
@@ -6,13 +6,13 @@
 // methods to handle `noSuchMethod`.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 abstract class Foo {
   noSuchMethod(im) => 42;
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 returnFoo() {
   (() => 42)();
   return new Foo();
diff --git a/tests/language/closure/regress46568_test.dart b/tests/language/closure/regress46568_test.dart
new file mode 100644
index 0000000..33e34b6
--- /dev/null
+++ b/tests/language/closure/regress46568_test.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.
+
+import 'package:expect/expect.dart';
+
+// Regression test for https://github.com/dart-lang/sdk/issues/46568.
+
+var genericTopLevelFunctionCallCount = 0;
+var genericStaticMethodCallCount = 0;
+
+T? genericTopLevelFunction<T>() {
+  genericTopLevelFunctionCallCount++;
+  return null;
+}
+
+class A {
+  static T? genericStaticMethod<T>() {
+    genericStaticMethodCallCount++;
+    return null;
+  }
+}
+
+const int? Function() cIntTopLevelFunction1 = genericTopLevelFunction;
+const int? Function() cIntStaticMethod1 = A.genericStaticMethod;
+
+void main() {
+  // Two different const generic function instantiations should not be
+  // canonicalized to the same value.
+  Expect.isFalse(identical(cIntTopLevelFunction1, cIntStaticMethod1));
+  Expect.notEquals(cIntTopLevelFunction1, cIntStaticMethod1);
+
+  cIntTopLevelFunction1();
+  Expect.equals(1, genericTopLevelFunctionCallCount);
+  Expect.equals(0, genericStaticMethodCallCount);
+
+  cIntStaticMethod1();
+  Expect.equals(1, genericTopLevelFunctionCallCount);
+  Expect.equals(1, genericStaticMethodCallCount);
+}
diff --git a/tests/language/compiler_annotations.dart b/tests/language/compiler_annotations.dart
deleted file mode 100644
index c920add..0000000
--- a/tests/language/compiler_annotations.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library compiler_annotations;
-
-// This library contains annotations useful for testing.
-
-// TODO(ngeoffray): Implement in dart2js.
-class DontInline {
-  const DontInline();
-}
diff --git a/tests/language/const/constructor_mixin2_test.dart b/tests/language/const/constructor_mixin2_test.dart
index a7bc863..873141d 100644
--- a/tests/language/const/constructor_mixin2_test.dart
+++ b/tests/language/const/constructor_mixin2_test.dart
@@ -15,8 +15,6 @@
 {
   const B(foo) : super(foo);
 //      ^
-// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
-//      ^
 // [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD
 //               ^
 // [cfe] A constant constructor can't call a non-constant super constructor.
diff --git a/tests/language/const/map2_runtime_test.dart b/tests/language/const/map2_runtime_test.dart
index 9e1fe97..02e6a9e 100644
--- a/tests/language/const/map2_runtime_test.dart
+++ b/tests/language/const/map2_runtime_test.dart
@@ -13,12 +13,10 @@
 
 class B implements A {
   const B();
-
-
 }
 
 confuse(x) {
-  if (new DateTime.now() == 42) return confuse(2);
+  if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(2);
   return x;
 }
 
diff --git a/tests/language/const/map2_test.dart b/tests/language/const/map2_test.dart
index a5f3798..dd392be 100644
--- a/tests/language/const/map2_test.dart
+++ b/tests/language/const/map2_test.dart
@@ -15,7 +15,7 @@
 }
 
 confuse(x) {
-  if (new DateTime.now() == 42) return confuse(2);
+  if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(2);
   return x;
 }
 
diff --git a/tests/language/const/map5_test.dart b/tests/language/const/map5_test.dart
new file mode 100644
index 0000000..0fbd8de
--- /dev/null
+++ b/tests/language/const/map5_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.
+
+// Tests lookup of type literals of user-defined classes in const maps.
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class C<T> {}
+
+typedef F = T Function<T>();
+typedef Cint = C<int>;
+
+const aType = A;
+const fType = F;
+const cIntType = Cint;
+
+main() {
+  final map = const {A: 42, F: 2, 'asdf': 'fdsa', Cint: 'foo'};
+  Expect.equals(42, map[getValueNonOptimized(A)]);
+  Expect.equals(42, map[getValueNonOptimized(aType)]);
+  Expect.equals(2, map[getValueNonOptimized(F)]);
+  Expect.equals(2, map[getValueNonOptimized(fType)]);
+  Expect.equals('foo', map[getValueNonOptimized(Cint)]);
+  Expect.equals('foo', map[getValueNonOptimized(cIntType)]);
+  Expect.isTrue(map.containsKey(getValueNonOptimized(A)));
+  Expect.isTrue(map.containsKey(getValueNonOptimized(aType)));
+  Expect.isTrue(map.containsKey(getValueNonOptimized(F)));
+  Expect.isTrue(map.containsKey(getValueNonOptimized(fType)));
+  Expect.isTrue(map.containsKey(getValueNonOptimized(Cint)));
+  Expect.isTrue(map.containsKey(getValueNonOptimized(cIntType)));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
+  return x;
+}
diff --git a/tests/language/const/map_hashcode_override2_test.dart b/tests/language/const/map_hashcode_override2_test.dart
index b747a97..d2e5858 100644
--- a/tests/language/const/map_hashcode_override2_test.dart
+++ b/tests/language/const/map_hashcode_override2_test.dart
@@ -7,9 +7,13 @@
 /// Returns its argument.
 ///
 /// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
-  // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
-  if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
   return x;
 }
 
diff --git a/tests/language/const/map_hashcode_override_test.dart b/tests/language/const/map_hashcode_override_test.dart
index e378e05..f8aa3cc 100644
--- a/tests/language/const/map_hashcode_override_test.dart
+++ b/tests/language/const/map_hashcode_override_test.dart
@@ -7,9 +7,13 @@
 /// Returns its argument.
 ///
 /// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
-  // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
-  if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
   return x;
 }
 
diff --git a/tests/language/const/map_null_lookup_test.dart b/tests/language/const/map_null_lookup_test.dart
new file mode 100644
index 0000000..e493653
--- /dev/null
+++ b/tests/language/const/map_null_lookup_test.dart
@@ -0,0 +1,29 @@
+// 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.
+
+// Tests lookup of null in const maps.
+
+import 'package:expect/expect.dart';
+
+main() {
+  final map1 = const {1: 42, null: 2, 'asdf': 'fdsa'};
+  Expect.equals(2, map1[getValueNonOptimized(null)]);
+  Expect.isTrue(map1.containsKey(null));
+  final map2 = const {1: 42, 2: 2, 'asdf': 'fdsa'};
+  Expect.equals(null, map2[getValueNonOptimized(null)]);
+  Expect.isFalse(map2.containsKey(null));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
+  return x;
+}
diff --git a/tests/language/const/map_test.dart b/tests/language/const/map_test.dart
index 13c6720..d1a88fe 100644
--- a/tests/language/const/map_test.dart
+++ b/tests/language/const/map_test.dart
@@ -7,9 +7,13 @@
 /// Returns its argument.
 ///
 /// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
-  // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
-  if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
   return x;
 }
 
diff --git a/tests/language/const/set5_test.dart b/tests/language/const/set5_test.dart
new file mode 100644
index 0000000..f27b5f9
--- /dev/null
+++ b/tests/language/const/set5_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.
+
+// Tests lookup of type literals of user-defined classes in const sets.
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class C<T> {}
+
+typedef F = T Function<T>();
+typedef Cint = C<int>;
+
+const aType = A;
+const fType = F;
+const cIntType = Cint;
+
+main() {
+  final set1 = const {A, 1, 'asdf', F, Cint};
+  Expect.isTrue(set1.contains(getValueNonOptimized(A)));
+  Expect.isTrue(set1.contains(getValueNonOptimized(aType)));
+  Expect.isTrue(set1.contains(getValueNonOptimized(F)));
+  Expect.isTrue(set1.contains(getValueNonOptimized(fType)));
+  Expect.isTrue(set1.contains(getValueNonOptimized(Cint)));
+  Expect.isTrue(set1.contains(getValueNonOptimized(cIntType)));
+  Expect.equals(A, set1.lookup(getValueNonOptimized(A)));
+  Expect.equals(A, set1.lookup(getValueNonOptimized(aType)));
+  Expect.equals(F, set1.lookup(getValueNonOptimized(F)));
+  Expect.equals(F, set1.lookup(getValueNonOptimized(fType)));
+  Expect.equals(Cint, set1.lookup(getValueNonOptimized(Cint)));
+  Expect.equals(Cint, set1.lookup(getValueNonOptimized(cIntType)));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
+  return x;
+}
diff --git a/tests/language/const/set_hashcode_override2_test.dart b/tests/language/const/set_hashcode_override2_test.dart
index 1fc8665..cbe8944 100644
--- a/tests/language/const/set_hashcode_override2_test.dart
+++ b/tests/language/const/set_hashcode_override2_test.dart
@@ -7,9 +7,13 @@
 /// Returns its argument.
 ///
 /// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
-  // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
-  if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
   return x;
 }
 
diff --git a/tests/language/const/set_null_lookup_test.dart b/tests/language/const/set_null_lookup_test.dart
new file mode 100644
index 0000000..a2b4044
--- /dev/null
+++ b/tests/language/const/set_null_lookup_test.dart
@@ -0,0 +1,29 @@
+// 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.
+
+// Tests lookup of null in const maps.
+
+import 'package:expect/expect.dart';
+
+main() {
+  final set1 = const {null, 1, 'asdf'};
+  Expect.isTrue(set1.contains(getValueNonOptimized(null)));
+  Expect.equals(null, set1.lookup(null));
+  final set2 = const {42, 1, 'asdf'};
+  Expect.isFalse(set2.contains(getValueNonOptimized(null)));
+  Expect.equals(null, set2.lookup(null));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
+  return x;
+}
diff --git a/tests/language/constructor/multiple_field_assignment_constructor_test.dart b/tests/language/constructor/multiple_field_assignment_constructor_test.dart
index 7292e80..c499161 100644
--- a/tests/language/constructor/multiple_field_assignment_constructor_test.dart
+++ b/tests/language/constructor/multiple_field_assignment_constructor_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 var a = [null];
 
@@ -11,7 +10,8 @@
   var foo;
   var bar;
 
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   A() {
     // Currently defeat inlining by using a closure.
     bar = () => 42;
@@ -24,7 +24,8 @@
   var foo;
   var bar;
 
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   B() {
     // Currently defeat inlining by using a closure.
     bar = () => 42;
@@ -44,7 +45,8 @@
   new B();
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 bar() {
   // Currently defeat inlining by using a closure.
   Expect.throwsNoSuchMethodError(() => new A().foo + 42);
diff --git a/tests/language/constructor/tear_off_test.dart b/tests/language/constructor/tear_off_test.dart
index f890b44..a0764886 100644
--- a/tests/language/constructor/tear_off_test.dart
+++ b/tests/language/constructor/tear_off_test.dart
@@ -24,18 +24,16 @@
   const NGenRedir._(this.x);
 }
 
-class NFac {
+class NFac implements NFacRedir {
   final int x;
-  factory NFac(int x) => NFacRedir._(x);
-  factory NFac.named(int x) => NFacRedir._(x);
-  NFac._(this.x);
+  factory NFac(int x) => NFac._(x);
+  factory NFac.named(int x) => NFac._(x);
+  const NFac._(this.x);
 }
 
 class NFacRedir {
-  final int x;
   const factory NFacRedir(int x) = NFac._;
   const factory NFacRedir.named(int x) = NFac._;
-  NFacRedir._(this.x);
 }
 
 // Generic classes.
@@ -52,18 +50,16 @@
   const GGenRedir._(this.x);
 }
 
-class GFac<T> {
+class GFac<T> implements GFacRedir<T> {
   final int x;
-  factory GFac(int x) => GFacRedir._(x);
-  factory GFac.named(int x) => GFacRedir._(x);
-  GFac._(this.x);
+  factory GFac(int x) => GFac._(x);
+  factory GFac.named(int x) => GFac._(x);
+  const GFac._(this.x);
 }
 
 class GFacRedir<T> {
-  final int x;
   const factory GFacRedir(int x) = GFac._;
   const factory GFacRedir.named(int x) = GFac._;
-  GFacRedir._(this.x);
 }
 
 class Optional<T> {
@@ -96,9 +92,9 @@
   GGen<int>.new.expectStaticType<Exactly<GGen<int> Function(int)>>();
   GGen<int>.named.expectStaticType<Exactly<GGen<int> Function(int)>>();
   GGenRedir<int>.new
-      .expectStaticType<Exactly<GGenRedir<T> Function<T>(int)>>();
+      .expectStaticType<Exactly<GGenRedir<int> Function(int)>>();
   GGenRedir<int>.named
-      .expectStaticType<Exactly<GGenRedir<T> Function<T>(int)>>();
+      .expectStaticType<Exactly<GGenRedir<int> Function(int)>>();
   GFac<int>.new.expectStaticType<Exactly<GFac<int> Function(int)>>();
   GFac<int>.named.expectStaticType<Exactly<GFac<int> Function(int)>>();
   GFacRedir<int>.new
@@ -106,26 +102,26 @@
   GFacRedir<int>.named
       .expectStaticType<Exactly<GFacRedir<int> Function(int)>>();
 
-  contextType<GGen<int> Function(int)>(
+  context<GGen<int> Function(int)>(
       GGen.new..expectStaticType<Exactly<GGen<int> Function(int)>>());
-  contextType<GGen<int> Function(int)>(
+  context<GGen<int> Function(int)>(
       GGen.named..expectStaticType<Exactly<GGen<int> Function(int)>>());
-  contextType<GGenRedir<int> Function(int)>(GGenRedir.new
+  context<GGenRedir<int> Function(int)>(GGenRedir.new
     ..expectStaticType<Exactly<GGenRedir<int> Function(int)>>());
-  contextType<GGenRedir<int> Function(int)>(GGenRedir.named
+  context<GGenRedir<int> Function(int)>(GGenRedir.named
     ..expectStaticType<Exactly<GGenRedir<int> Function(int)>>());
-  contextType<GFac<int> Function(int)>(
+  context<GFac<int> Function(int)>(
       GFac.new..expectStaticType<Exactly<GFac<int> Function(int)>>());
-  contextType<GFac<int> Function(int)>(
+  context<GFac<int> Function(int)>(
       GFac.named..expectStaticType<Exactly<GFac<int> Function(int)>>());
-  contextType<GFacRedir<int> Function(int)>(
+  context<GFacRedir<int> Function(int)>(
       GFacRedir.new..expectStaticType<Exactly<GFacRedir<int> Function(int)>>());
-  contextType<GFacRedir<int> Function(int)>(GFacRedir.named
+  context<GFacRedir<int> Function(int)>(GFacRedir.named
     ..expectStaticType<Exactly<GFacRedir<int> Function(int)>>());
 
-  contextType<Optional<int> Function()>(Optional.new
+  context<Optional<int> Function()>(Optional.new
     ..expectStaticType<Exactly<Optional<int> Function([int, int])>>());
-  contextType<Optional<int> Function()>(Optional.named
+  context<Optional<int> Function()>(Optional.named
     ..expectStaticType<Exactly<Optional<int> Function({int x, int y})>>());
 
   // Check that tear-offs are canonicalized where possible
diff --git a/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart b/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart
index 968ae22..5813d60 100644
--- a/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart
+++ b/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart
@@ -68,7 +68,8 @@
 
     Expect.identical(staticMethod<int, String>, staticTearOff);
 
-    Expect.equals(
+    // Extension instance methods are not equal unless identical.
+    Expect.notEquals(
         extInstanceMethod<int, String>, this.extInstanceMethod<int, String>);
   }
 }
@@ -132,7 +133,9 @@
       o.instanceMethod<int, String>, o.instanceMethod<int, String>);
   Expect.equals(
       o.mixinInstanceMethod<int, String>, o.mixinInstanceMethod<int, String>);
-  Expect.equals(
+
+  // Instantiated extension methods are not equal unless they are identical.
+  Expect.notEquals(
       o.extInstanceMethod<int, String>, o.extInstanceMethod<int, String>);
 
   // And not canonicalized where they shouldn't (different types).
diff --git a/tests/language/map/literal15_test.dart b/tests/language/map/literal15_test.dart
new file mode 100644
index 0000000..049486e
--- /dev/null
+++ b/tests/language/map/literal15_test.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.
+
+// Test the use of `null` keys in const maps.
+
+library map_literal15_test;
+
+import "package:expect/expect.dart";
+
+void main() {
+  var m1 = const <String, int>{null: 10, 'null': 20};
+  //                           ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.MAP_KEY_TYPE_NOT_ASSIGNABLE
+  // [cfe] The value 'null' can't be assigned to a variable of type 'String' because 'String' is not nullable.
+
+  var m2 = const <Comparable, int>{null: 10, 'null': 20};
+  //                               ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.MAP_KEY_TYPE_NOT_ASSIGNABLE
+  // [cfe] The value 'null' can't be assigned to a variable of type 'Comparable<dynamic>' because 'Comparable<dynamic>' is not nullable.
+}
diff --git a/tests/language/optimize/inferrer_constructor2_test.dart b/tests/language/optimize/inferrer_constructor2_test.dart
index 58da3ad..4d28519 100644
--- a/tests/language/optimize/inferrer_constructor2_test.dart
+++ b/tests/language/optimize/inferrer_constructor2_test.dart
@@ -7,13 +7,13 @@
 // inlined.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 class A {
   var foo;
   var bar;
 
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   A() {
     // Currently defeat inlining by using a closure.
     bar = () => 42;
@@ -33,7 +33,8 @@
 class B {
   var bar;
   var closure;
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   B() {
     // Currently defeat inlining by using a closure.
     closure = () => 42;
@@ -41,7 +42,8 @@
   }
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 bar() {
   // Make sure B's constructor is analyzed first by surrounding the
   // body by two allocations.
@@ -52,7 +54,8 @@
   new B();
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 codegenLast() {
   // This assignment currently defeats simple type inference, but not
   // the optimistic inferrer.
diff --git a/tests/language/optimize/inferrer_constructor3_test.dart b/tests/language/optimize/inferrer_constructor3_test.dart
index 395f113..a3e9038 100644
--- a/tests/language/optimize/inferrer_constructor3_test.dart
+++ b/tests/language/optimize/inferrer_constructor3_test.dart
@@ -7,7 +7,6 @@
 // inlined.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 class A {
   var field;
@@ -24,14 +23,16 @@
   bar();
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 doIt() {
   () => 42;
   var c = new A(null);
   Expect.throwsNoSuchMethodError(() => c.field + 42);
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 bar() {
   () => 42;
   return inlineLevel1();
diff --git a/tests/language/optimize/inferrer_named_parameter_test.dart b/tests/language/optimize/inferrer_named_parameter_test.dart
index a6655b4..c06fc38 100644
--- a/tests/language/optimize/inferrer_named_parameter_test.dart
+++ b/tests/language/optimize/inferrer_named_parameter_test.dart
@@ -6,9 +6,9 @@
 // correctly infer optional named parameters.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 foo({path}) {
   () => 42;
   return path;
diff --git a/tests/language/optimize/inferrer_synthesized_super_constructor_test.dart b/tests/language/optimize/inferrer_synthesized_super_constructor_test.dart
index 1a7284b..dc81959 100644
--- a/tests/language/optimize/inferrer_synthesized_super_constructor_test.dart
+++ b/tests/language/optimize/inferrer_synthesized_super_constructor_test.dart
@@ -2,10 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../compiler_annotations.dart';
-
 class A {
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   A([a]) {
     () => 42;
     if (a != null) throw 'Test failed';
diff --git a/tests/language/regress/regress12284_test.dart b/tests/language/regress/regress12284_test.dart
index 4164c44..aeaf366 100644
--- a/tests/language/regress/regress12284_test.dart
+++ b/tests/language/regress/regress12284_test.dart
@@ -3,12 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 class A {
   int field = -1;
 
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   A(param) {
     // Currently defeat inlining by using a closure.
     var bar = () => 42;
diff --git a/tests/language/regress/regress12336_test.dart b/tests/language/regress/regress12336_test.dart
index 029c3f1..7630c49 100644
--- a/tests/language/regress/regress12336_test.dart
+++ b/tests/language/regress/regress12336_test.dart
@@ -6,7 +6,6 @@
 // [foo].
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 main() {
   var result = foo(1, 2);
@@ -18,7 +17,8 @@
   Expect.listEquals([], result[1]);
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 foo(a, b) {
   () => 42;
   if (a is List) {
diff --git a/tests/language/regress/regress15720_test.dart b/tests/language/regress/regress15720_test.dart
index 638fc98..85c102c 100644
--- a/tests/language/regress/regress15720_test.dart
+++ b/tests/language/regress/regress15720_test.dart
@@ -7,7 +7,7 @@
 class B {}
 
 confuse(x) {
-  if (new DateTime.now() == 42) return confuse(x);
+  if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(x);
   return x;
 }
 
diff --git a/tests/language/regress/regress23244_test.dart b/tests/language/regress/regress23244_test.dart
index c955874..6a25b57 100644
--- a/tests/language/regress/regress23244_test.dart
+++ b/tests/language/regress/regress23244_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Regression test case for http://dartbug.com/23244
diff --git a/tests/language/regress/regress46550_test.dart b/tests/language/regress/regress46550_test.dart
new file mode 100644
index 0000000..9b609da
--- /dev/null
+++ b/tests/language/regress/regress46550_test.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.
+
+// VMOptions=--optimization_counter_threshold=100 --deterministic
+
+import "package:expect/expect.dart";
+
+typedef void test1<T extends num>();
+
+void t1<T extends int>() {
+  Expect.equals(int, T);
+}
+
+const test1 res1 = t1;
+
+main() {
+  for (int i = 0; i < 120; ++i) {
+    res1();
+  }
+}
diff --git a/tests/language/static_type_helper.dart b/tests/language/static_type_helper.dart
index 4a7809a..14acd63 100644
--- a/tests/language/static_type_helper.dart
+++ b/tests/language/static_type_helper.dart
@@ -6,7 +6,7 @@
 Type typeOf<T>() => T;
 
 /// Ensures a context type of [T] for the operand.
-void context<T>(T x) {}
+Object? context<T>(T x) => x;
 
 /// Captures the context type of the call and returns the same type.
 ///
diff --git a/tests/language/string/optimizations_test.dart b/tests/language/string/optimizations_test.dart
index a40bc0b..b595437 100644
--- a/tests/language/string/optimizations_test.dart
+++ b/tests/language/string/optimizations_test.dart
@@ -6,15 +6,16 @@
 // correctly infer optional named parameters.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 foo({path}) {
   () => 42;
   return path.toString();
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 bar({path}) {
   () => 42;
   return path;
diff --git a/tests/language/type_object/explicit_instantiated_type_literal_test.dart b/tests/language/type_object/explicit_instantiated_type_literal_test.dart
index 07fa243..6b3b07f 100644
--- a/tests/language/type_object/explicit_instantiated_type_literal_test.dart
+++ b/tests/language/type_object/explicit_instantiated_type_literal_test.dart
@@ -18,8 +18,8 @@
 Type type<T>() => T;
 
 void main() {
-  C.expectStaticType<Type>();
-  C<int>.expectStaticType<Type>();
+  (C).expectStaticType<Exactly<Type>>();
+  (C<int>).expectStaticType<Exactly<Type>>();
 
   Expect.identical(C<num>, C);
   Expect.identical(C<int>, C<int>);
@@ -30,8 +30,8 @@
   Expect.identical(C<dynamic>, C<dynamic>);
   Expect.equals(C<dynamic>, type<C<dynamic>>());
 
-  prefix.C.expectStaticType<Type>();
-  prefix.C<int>.expectStaticType<Type>();
+  (prefix.C).expectStaticType<Exactly<Type>>();
+  (prefix.C<int>).expectStaticType<Exactly<Type>>();
 
   Expect.identical(prefix.C<num>, prefix.C);
   Expect.identical(prefix.C<int>, prefix.C<int>);
diff --git a/tests/language/typedef/aliased_constructor_tear_off_test.dart b/tests/language/typedef/aliased_constructor_tear_off_test.dart
index e63b693..7d51dfb 100644
--- a/tests/language/typedef/aliased_constructor_tear_off_test.dart
+++ b/tests/language/typedef/aliased_constructor_tear_off_test.dart
@@ -14,7 +14,7 @@
 void use(Type type) {}
 
 class C<T> {
-  final T value;
+  final T x;
   C(this.x);
   C.named(this.x);
 }
@@ -37,7 +37,7 @@
   // or if instantiated with a constant type.
   const List<Object> constructors = [
     Special.new,
-    Spceial.named,
+    Special.named,
     Direct.new,
     Direct.named,
     Bounded.new,
@@ -64,12 +64,12 @@
       Wrapping.new,
       Wrapping.named,
     ],
-    const <C<int, int> Function(C<int>)>[
+    const <C<int> Function(int)>[
       Extra.new,
       Extra.named,
     ]
   ];
-  Expect.notNull(constructors); // Use variable.
+  Expect.isNotNull(constructors); // Use variable.
 
   // The static type is as expected.
 
@@ -83,8 +83,8 @@
   Bounded.new.expectStaticType<Exactly<C<T> Function<T extends num>(T)>>();
   Bounded.named.expectStaticType<Exactly<C<T> Function<T extends num>(T)>>();
 
-  Wrapping.new.expectStaticType<Exactly<C<C<T>> Function<T>(T)>>();
-  Wrapping.named.expectStaticType<Exactly<C<C<T>> Function<T>(T)>>();
+  Wrapping.new.expectStaticType<Exactly<C<C<T>> Function<T>(C<T>)>>();
+  Wrapping.named.expectStaticType<Exactly<C<C<T>> Function<T>(C<T>)>>();
 
   Extra.new.expectStaticType<Exactly<C<T> Function<T, S>(T)>>();
   Extra.named.expectStaticType<Exactly<C<T> Function<T, S>(T)>>();
@@ -105,24 +105,24 @@
   Extra<int, String>.named.expectStaticType<Exactly<C<int> Function(int)>>();
 
   // Implicitly instantiated.
-  contextType<C<int> Function(int)>(
-      Direct<int>.new..expectStaticType<Exactly<C<int> Function(int)>>());
-  contextType<C<int> Function(int)>(
-      Direct<int>.named..expectStaticType<Exactly<C<int> Function(int)>>());
+  context<C<int> Function(int)>(
+      Direct.new..expectStaticType<Exactly<C<int> Function(int)>>());
+  context<C<int> Function(int)>(
+      Direct.named..expectStaticType<Exactly<C<int> Function(int)>>());
 
-  contextType<C<int> Function(int)>(
-      Bounded<int>.new..expectStaticType<Exactly<C<int> Function(int)>>());
-  contextType<C<int> Function(int)>(
-      Bounded<int>.named..expectStaticType<Exactly<C<int> Function(int)>>());
+  context<C<int> Function(int)>(
+      Bounded.new..expectStaticType<Exactly<C<int> Function(int)>>());
+  context<C<int> Function(int)>(
+      Bounded.named..expectStaticType<Exactly<C<int> Function(int)>>());
 
-  contextType<C<C<int>> Function(C<int>)>(Wrapping<int>.new
+  context<C<C<int>> Function(C<int>)>(Wrapping.new
     ..expectStaticType<Exactly<C<C<int>> Function(C<int>)>>());
-  contextType<C<C<int>> Function(C<int>)>(Wrapping<int>.named
+  context<C<C<int>> Function(C<int>)>(Wrapping.named
     ..expectStaticType<Exactly<C<C<int>> Function(C<int>)>>());
 
-  contextType<C<int, String> Function(int)>(Extra<int, String>.new
+  context<C<int> Function(int)>(Extra.new
     ..expectStaticType<Exactly<C<int> Function(int)>>());
-  contextType<C<int, String> Function(int)>(Extra<int, String>.named
+  context<C<int> Function(int)>(Extra.named
     ..expectStaticType<Exactly<C<int> Function(int)>>());
 
   // Uninstantiated tear-offs always canonicalize.
@@ -176,35 +176,35 @@
 
   // Implicit instantiation.
   Expect.identical(
-    contextType<C<int> Function(int)>(Direct.new),
+    context<C<int> Function(int)>(Direct.new),
     C<int>.new,
   );
   Expect.identical(
-    contextType<C<int> Function(int)>(Direct.named),
+    context<C<int> Function(int)>(Direct.named),
     C<int>.named,
   );
   Expect.identical(
-    contextType<C<int> Function(int)>(Bounded.new),
+    context<C<int> Function(int)>(Bounded.new),
     C<int>.new,
   );
   Expect.identical(
-    contextType<C<int> Function(int)>(Bounded.named),
+    context<C<int> Function(int)>(Bounded.named),
     C<int>.named,
   );
   Expect.identical(
-    contextType<C<C<int>> Function(C<int>)>(Wrapping.new),
+    context<C<C<int>> Function(C<int>)>(Wrapping.new),
     C<C<int>>.new,
   );
   Expect.identical(
-    contextType<C<C<int>> Function(C<int>)>(Wrapping.named),
+    context<C<C<int>> Function(C<int>)>(Wrapping.named),
     C<C<int>>.named,
   );
   Expect.identical(
-    contextType<D<int, String> Function()>(Swapped.new),
+    context<D<int, String> Function()>(Swapped.new),
     D<int, String>.new,
   );
   Expect.identical(
-    contextType<D<int, String> Function()>(Swapped.named),
+    context<D<int, String> Function()>(Swapped.named),
     D<int, String>.named,
   );
 
diff --git a/tests/language/typedef/aliased_type_literal_instantiation_test.dart b/tests/language/typedef/aliased_type_literal_instantiation_test.dart
index c99e904..25dc8f9 100644
--- a/tests/language/typedef/aliased_type_literal_instantiation_test.dart
+++ b/tests/language/typedef/aliased_type_literal_instantiation_test.dart
@@ -10,7 +10,7 @@
 import "package:expect/expect.dart";
 
 class C<T> {
-  final T value;
+  final T x;
   C(this.x);
   C.named(this.x);
 }
@@ -55,7 +55,7 @@
   Expect.identical(e2, co);
   Expect.identical(e3, ci);
 
-  (<T>() {
+  (<T extends num>() {
     // Using a non-constant type.
     Expect.equals(Direct<T>, ci);
     Expect.equals(Bounded<T>, ci);
diff --git a/tests/language/unsorted/refine_receiver_null_test.dart b/tests/language/unsorted/refine_receiver_null_test.dart
index 499e998..50a5fa7 100644
--- a/tests/language/unsorted/refine_receiver_null_test.dart
+++ b/tests/language/unsorted/refine_receiver_null_test.dart
@@ -7,7 +7,6 @@
 // work for Object methods.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 main() {
   var a = true ? null : 42;
@@ -15,7 +14,8 @@
   foo(a);
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 foo(a) {
   var f = () => 42;
   Expect.throwsNoSuchMethodError(() => a + 42);
diff --git a/tests/language/vm/optimized_guarded_field_isolates_test.dart b/tests/language/vm/optimized_guarded_field_isolates_test.dart
index 428fd8d..9278ea9 100644
--- a/tests/language/vm/optimized_guarded_field_isolates_test.dart
+++ b/tests/language/vm/optimized_guarded_field_isolates_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 // VMOptions=--optimization_counter_threshold=100 --no-background_compilation
 
diff --git a/tests/language/vm/regress_flutter_85311_test.dart b/tests/language/vm/regress_flutter_85311_test.dart
new file mode 100644
index 0000000..122d13a
--- /dev/null
+++ b/tests/language/vm/regress_flutter_85311_test.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.
+
+// This is a regression test for the bug in
+// https://github.com/flutter/flutter/issues/51828.
+// Verifies that temporaries aren't incorrectly assigned types when they're
+// reused.
+
+import "package:expect/expect.dart";
+
+bool wasCalled = false;
+
+class Z {
+  bool operator ==(Object other) {
+    wasCalled = true;
+    return true;
+  }
+}
+
+class Y {
+  final dynamic v;
+  Y(this.v);
+}
+
+Future<bool> crash(dynamic y) async {
+  return (y.v == (await 7) || y == (await 9));
+}
+
+void main() async {
+  await crash(Y(Z()));
+
+  Expect.isTrue(wasCalled);
+}
diff --git a/tests/language_2/abstract/exact_selector_runtime_test.dart b/tests/language_2/abstract/exact_selector_runtime_test.dart
index 2d18f98..eb8d0c8 100644
--- a/tests/language_2/abstract/exact_selector_runtime_test.dart
+++ b/tests/language_2/abstract/exact_selector_runtime_test.dart
@@ -11,14 +11,13 @@
 // methods to handle `noSuchMethod`.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
-
-    class Foo {
+class Foo {
   noSuchMethod(im) => 42;
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 returnFoo() {
   (() => 42)();
   return new Foo();
diff --git a/tests/language_2/abstract/exact_selector_test.dart b/tests/language_2/abstract/exact_selector_test.dart
index 23a69e0..dff88cb 100644
--- a/tests/language_2/abstract/exact_selector_test.dart
+++ b/tests/language_2/abstract/exact_selector_test.dart
@@ -8,14 +8,13 @@
 // methods to handle `noSuchMethod`.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
-abstract
-    class Foo {
+abstract class Foo {
   noSuchMethod(im) => 42;
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 returnFoo() {
   (() => 42)();
   return new Foo();
diff --git a/tests/language_2/closure/regress46568_test.dart b/tests/language_2/closure/regress46568_test.dart
new file mode 100644
index 0000000..1117775
--- /dev/null
+++ b/tests/language_2/closure/regress46568_test.dart
@@ -0,0 +1,42 @@
+// 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 'package:expect/expect.dart';
+
+// Regression test for https://github.com/dart-lang/sdk/issues/46568.
+
+var genericTopLevelFunctionCallCount = 0;
+var genericStaticMethodCallCount = 0;
+
+T genericTopLevelFunction<T>() {
+  genericTopLevelFunctionCallCount++;
+  return null;
+}
+
+class A {
+  static T genericStaticMethod<T>() {
+    genericStaticMethodCallCount++;
+    return null;
+  }
+}
+
+const int Function() cIntTopLevelFunction1 = genericTopLevelFunction;
+const int Function() cIntStaticMethod1 = A.genericStaticMethod;
+
+void main() {
+  // Two different const generic function instantiations should not be
+  // canonicalized to the same value.
+  Expect.isFalse(identical(cIntTopLevelFunction1, cIntStaticMethod1));
+  Expect.notEquals(cIntTopLevelFunction1, cIntStaticMethod1);
+
+  cIntTopLevelFunction1();
+  Expect.equals(1, genericTopLevelFunctionCallCount);
+  Expect.equals(0, genericStaticMethodCallCount);
+
+  cIntStaticMethod1();
+  Expect.equals(1, genericTopLevelFunctionCallCount);
+  Expect.equals(1, genericStaticMethodCallCount);
+}
diff --git a/tests/language_2/compiler_annotations.dart b/tests/language_2/compiler_annotations.dart
deleted file mode 100644
index 9264514..0000000
--- a/tests/language_2/compiler_annotations.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart = 2.9
-
-library compiler_annotations;
-
-// This library contains annotations useful for testing.
-
-// TODO(ngeoffray): Implement in dart2js.
-class DontInline {
-  const DontInline();
-}
diff --git a/tests/language_2/const/constructor_mixin2_test.dart b/tests/language_2/const/constructor_mixin2_test.dart
index 5794d86..de57333 100644
--- a/tests/language_2/const/constructor_mixin2_test.dart
+++ b/tests/language_2/const/constructor_mixin2_test.dart
@@ -17,8 +17,6 @@
 {
   const B(foo) : super(foo);
 //      ^
-// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
-//      ^
 // [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD
 //               ^
 // [cfe] A constant constructor can't call a non-constant super constructor.
diff --git a/tests/language_2/const/map2_runtime_test.dart b/tests/language_2/const/map2_runtime_test.dart
index 5ce67f2..d9a2e80 100644
--- a/tests/language_2/const/map2_runtime_test.dart
+++ b/tests/language_2/const/map2_runtime_test.dart
@@ -15,12 +15,10 @@
 
 class B implements A {
   const B();
-
-
 }
 
 confuse(x) {
-  if (new DateTime.now() == 42) return confuse(2);
+  if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(2);
   return x;
 }
 
diff --git a/tests/language_2/const/map2_test.dart b/tests/language_2/const/map2_test.dart
index 55f729e..216886c 100644
--- a/tests/language_2/const/map2_test.dart
+++ b/tests/language_2/const/map2_test.dart
@@ -17,7 +17,7 @@
 }
 
 confuse(x) {
-  if (new DateTime.now() == 42) return confuse(2);
+  if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(2);
   return x;
 }
 
diff --git a/tests/language_2/const/map5_test.dart b/tests/language_2/const/map5_test.dart
new file mode 100644
index 0000000..4827e54
--- /dev/null
+++ b/tests/language_2/const/map5_test.dart
@@ -0,0 +1,43 @@
+// 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.
+
+// Tests lookup of type literals of user-defined classes in const maps.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class C<T> {}
+
+typedef F = T Function<T>();
+
+const aType = A;
+const fType = F;
+
+main() {
+  final map = const {A: 42, F: 2, 'asdf': 'fdsa'};
+  Expect.equals(42, map[getValueNonOptimized(A)]);
+  Expect.equals(42, map[getValueNonOptimized(aType)]);
+  Expect.equals(2, map[getValueNonOptimized(F)]);
+  Expect.equals(2, map[getValueNonOptimized(fType)]);
+  Expect.isTrue(map.containsKey(getValueNonOptimized(A)));
+  Expect.isTrue(map.containsKey(getValueNonOptimized(aType)));
+  Expect.isTrue(map.containsKey(getValueNonOptimized(F)));
+  Expect.isTrue(map.containsKey(getValueNonOptimized(fType)));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
+  return x;
+}
diff --git a/tests/language_2/const/map_hashcode_override2_test.dart b/tests/language_2/const/map_hashcode_override2_test.dart
index 86ced20..a5add26 100644
--- a/tests/language_2/const/map_hashcode_override2_test.dart
+++ b/tests/language_2/const/map_hashcode_override2_test.dart
@@ -9,9 +9,13 @@
 /// Returns its argument.
 ///
 /// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
-  // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
-  if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
   return x;
 }
 
diff --git a/tests/language_2/const/map_hashcode_override_test.dart b/tests/language_2/const/map_hashcode_override_test.dart
index 47223e7..a696d36 100644
--- a/tests/language_2/const/map_hashcode_override_test.dart
+++ b/tests/language_2/const/map_hashcode_override_test.dart
@@ -9,9 +9,13 @@
 /// Returns its argument.
 ///
 /// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
-  // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
-  if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
   return x;
 }
 
diff --git a/tests/language_2/const/map_null_lookup_test.dart b/tests/language_2/const/map_null_lookup_test.dart
new file mode 100644
index 0000000..612f3ca
--- /dev/null
+++ b/tests/language_2/const/map_null_lookup_test.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.
+
+// Tests lookup of null in const maps.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+main() {
+  final map1 = const {1: 42, null: 2, 'asdf': 'fdsa'};
+  Expect.equals(2, map1[getValueNonOptimized(null)]);
+  Expect.isTrue(map1.containsKey(null));
+  final map2 = const {1: 42, 2: 2, 'asdf': 'fdsa'};
+  Expect.equals(null, map2[getValueNonOptimized(null)]);
+  Expect.isFalse(map2.containsKey(null));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
+  return x;
+}
diff --git a/tests/language_2/const/map_test.dart b/tests/language_2/const/map_test.dart
index bbd4a8f..3ffcf7a 100644
--- a/tests/language_2/const/map_test.dart
+++ b/tests/language_2/const/map_test.dart
@@ -9,9 +9,13 @@
 /// Returns its argument.
 ///
 /// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
-  // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
-  if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
   return x;
 }
 
diff --git a/tests/language_2/const/set5_test.dart b/tests/language_2/const/set5_test.dart
new file mode 100644
index 0000000..dc0088d
--- /dev/null
+++ b/tests/language_2/const/set5_test.dart
@@ -0,0 +1,43 @@
+// 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.
+
+// Tests lookup of type literals of user-defined classes in const sets.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class C<T> {}
+
+typedef F = T Function<T>();
+
+const aType = A;
+const fType = F;
+
+main() {
+  final set1 = const {A, 1, 'asdf', F};
+  Expect.isTrue(set1.contains(getValueNonOptimized(A)));
+  Expect.isTrue(set1.contains(getValueNonOptimized(aType)));
+  Expect.isTrue(set1.contains(getValueNonOptimized(F)));
+  Expect.isTrue(set1.contains(getValueNonOptimized(fType)));
+  Expect.equals(A, set1.lookup(getValueNonOptimized(A)));
+  Expect.equals(A, set1.lookup(getValueNonOptimized(aType)));
+  Expect.equals(F, set1.lookup(getValueNonOptimized(F)));
+  Expect.equals(F, set1.lookup(getValueNonOptimized(fType)));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
+  return x;
+}
diff --git a/tests/language_2/const/set_hashcode_override2_test.dart b/tests/language_2/const/set_hashcode_override2_test.dart
index 7035373..0be2136 100644
--- a/tests/language_2/const/set_hashcode_override2_test.dart
+++ b/tests/language_2/const/set_hashcode_override2_test.dart
@@ -9,9 +9,13 @@
 /// Returns its argument.
 ///
 /// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
-  // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
-  if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
   return x;
 }
 
diff --git a/tests/language_2/const/set_null_lookup_test.dart b/tests/language_2/const/set_null_lookup_test.dart
new file mode 100644
index 0000000..1e7a09a
--- /dev/null
+++ b/tests/language_2/const/set_null_lookup_test.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.
+
+// Tests lookup of null in const sets.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+main() {
+  final set1 = const {null, 1, 'asdf'};
+  Expect.isTrue(set1.contains(getValueNonOptimized(null)));
+  Expect.equals(null, set1.lookup(null));
+  final set2 = const {42, 1, 'asdf'};
+  Expect.isFalse(set2.contains(getValueNonOptimized(null)));
+  Expect.equals(null, set2.lookup(null));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+  // DateTime.now() cannot be predicted statically, never equal to 42.
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    return getValueNonOptimized(2);
+  }
+  return x;
+}
diff --git a/tests/language_2/constructor/multiple_field_assignment_constructor_test.dart b/tests/language_2/constructor/multiple_field_assignment_constructor_test.dart
index 48ee8b9..6e76204 100644
--- a/tests/language_2/constructor/multiple_field_assignment_constructor_test.dart
+++ b/tests/language_2/constructor/multiple_field_assignment_constructor_test.dart
@@ -5,7 +5,6 @@
 // @dart = 2.9
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 var a = [null];
 
@@ -13,7 +12,8 @@
   var foo;
   var bar;
 
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   A() {
     // Currently defeat inlining by using a closure.
     bar = () => 42;
@@ -26,7 +26,8 @@
   var foo;
   var bar;
 
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   B() {
     // Currently defeat inlining by using a closure.
     bar = () => 42;
@@ -46,7 +47,8 @@
   new B();
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 bar() {
   // Currently defeat inlining by using a closure.
   Expect.throwsNoSuchMethodError(() => new A().foo + 42);
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 4cb75ed..ad85c7e 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -45,6 +45,4 @@
 
 [ $hot_reload || $hot_reload_rollback ]
 regress/regress22780_test/01: Crash # Issue 29094
-regress/regress23244_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-vm/optimized_guarded_field_isolates_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
 vm/optimized_stacktrace_test: Slow, Pass
diff --git a/tests/language_2/map/literal15_test.dart b/tests/language_2/map/literal15_test.dart
new file mode 100644
index 0000000..3ce3460
--- /dev/null
+++ b/tests/language_2/map/literal15_test.dart
@@ -0,0 +1,54 @@
+// 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
+
+// Test the use of `null` keys in const maps. In versions before 2.12, when
+// nullable types were introduced, types were nullable so it was legal to have
+// `null` keys in maps.
+
+library map_literal15_test;
+
+import "package:expect/expect.dart";
+
+void test1() {
+  var m1 = const <String, int>{null: 10, 'null': 20};
+  Expect.isTrue(m1.containsKey(null));
+  Expect.isTrue(m1.containsKey(undefined()));
+  Expect.equals(10, m1[null]);
+  Expect.equals(10, m1[undefined()]);
+  Expect.isTrue(m1.containsKey('null'));
+  Expect.equals(20, m1['null']);
+  // The '.keys' carry the 'String' type
+  Expect.type<Iterable<String>>(m1.keys);
+  Expect.type<Iterable<Comparable>>(m1.keys);
+  Expect.notType<Iterable<int>>(m1.keys);
+}
+
+void test2() {
+  var m2 = const <Comparable, int>{null: 10, 'null': 20};
+  Expect.isTrue(m2.containsKey(null));
+  Expect.isTrue(m2.containsKey(undefined()));
+  Expect.equals(10, m2[null]);
+  Expect.equals(10, m2[undefined()]);
+  Expect.isTrue(m2.containsKey('null'));
+  Expect.equals(20, m2['null']);
+  // The '.keys' carry the 'Comparable' type
+  Expect.notType<Iterable<String>>(m2.keys);
+  Expect.type<Iterable<Comparable>>(m2.keys);
+  Expect.notType<Iterable<int>>(m2.keys);
+}
+
+main() {
+  test1();
+  test2();
+}
+
+// Calling `undefined()` gives us a `null` that is implemented as JavaScript
+// `undefined` on dart2js.
+@pragma('dart2js:noInline')
+dynamic get undefined => _undefined;
+
+@pragma('dart2js:noInline')
+void _undefined() {}
diff --git a/tests/language_2/optimize/inferrer_constructor2_test.dart b/tests/language_2/optimize/inferrer_constructor2_test.dart
index 3b8d026..3db6e22 100644
--- a/tests/language_2/optimize/inferrer_constructor2_test.dart
+++ b/tests/language_2/optimize/inferrer_constructor2_test.dart
@@ -9,13 +9,13 @@
 // inlined.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 class A {
   var foo;
   var bar;
 
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   A() {
     // Currently defeat inlining by using a closure.
     bar = () => 42;
@@ -35,7 +35,8 @@
 class B {
   var bar;
   var closure;
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   B() {
     // Currently defeat inlining by using a closure.
     closure = () => 42;
@@ -43,7 +44,8 @@
   }
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 bar() {
   // Make sure B's constructor is analyzed first by surrounding the
   // body by two allocations.
@@ -54,7 +56,8 @@
   new B();
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 codegenLast() {
   // This assignment currently defeats simple type inference, but not
   // the optimistic inferrer.
diff --git a/tests/language_2/optimize/inferrer_constructor3_test.dart b/tests/language_2/optimize/inferrer_constructor3_test.dart
index ab89c9d..91c5e8e 100644
--- a/tests/language_2/optimize/inferrer_constructor3_test.dart
+++ b/tests/language_2/optimize/inferrer_constructor3_test.dart
@@ -9,7 +9,6 @@
 // inlined.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 class A {
   var field;
@@ -26,14 +25,16 @@
   bar();
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 doIt() {
   () => 42;
   var c = new A(null);
   Expect.throwsNoSuchMethodError(() => c.field + 42);
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 bar() {
   () => 42;
   return inlineLevel1();
diff --git a/tests/language_2/optimize/inferrer_named_parameter_test.dart b/tests/language_2/optimize/inferrer_named_parameter_test.dart
index a2edd32..fd95b33 100644
--- a/tests/language_2/optimize/inferrer_named_parameter_test.dart
+++ b/tests/language_2/optimize/inferrer_named_parameter_test.dart
@@ -8,9 +8,9 @@
 // correctly infer optional named parameters.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 foo({path}) {
   () => 42;
   return path;
diff --git a/tests/language_2/optimize/inferrer_synthesized_super_constructor_test.dart b/tests/language_2/optimize/inferrer_synthesized_super_constructor_test.dart
index 07db1d2..8b686ae 100644
--- a/tests/language_2/optimize/inferrer_synthesized_super_constructor_test.dart
+++ b/tests/language_2/optimize/inferrer_synthesized_super_constructor_test.dart
@@ -4,10 +4,9 @@
 
 // @dart = 2.9
 
-import '../compiler_annotations.dart';
-
 class A {
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   A([a]) {
     () => 42;
     if (a != null) throw 'Test failed';
diff --git a/tests/language_2/regress/regress12284_test.dart b/tests/language_2/regress/regress12284_test.dart
index 25a91f1..4c5b0bb 100644
--- a/tests/language_2/regress/regress12284_test.dart
+++ b/tests/language_2/regress/regress12284_test.dart
@@ -5,12 +5,12 @@
 // @dart = 2.9
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 class A {
   int field;
 
-  @DontInline()
+  @pragma('vm:never-inline')
+  @pragma('dart2js:noInline')
   A(param) {
     // Currently defeat inlining by using a closure.
     var bar = () => 42;
diff --git a/tests/language_2/regress/regress12336_test.dart b/tests/language_2/regress/regress12336_test.dart
index 9c62ae0..df72870 100644
--- a/tests/language_2/regress/regress12336_test.dart
+++ b/tests/language_2/regress/regress12336_test.dart
@@ -8,7 +8,6 @@
 // [foo].
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 main() {
   var result = foo(1, 2);
@@ -20,7 +19,8 @@
   Expect.listEquals([], result[1]);
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 foo(a, b) {
   () => 42;
   if (a is List) {
diff --git a/tests/language_2/regress/regress15720_test.dart b/tests/language_2/regress/regress15720_test.dart
index f07405e..14d5b18 100644
--- a/tests/language_2/regress/regress15720_test.dart
+++ b/tests/language_2/regress/regress15720_test.dart
@@ -9,7 +9,7 @@
 class B {}
 
 confuse(x) {
-  if (new DateTime.now() == 42) return confuse(x);
+  if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(x);
   return x;
 }
 
diff --git a/tests/language_2/regress/regress23244_test.dart b/tests/language_2/regress/regress23244_test.dart
index 87e244d..1fb8a80 100644
--- a/tests/language_2/regress/regress23244_test.dart
+++ b/tests/language_2/regress/regress23244_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Regression test case for http://dartbug.com/23244
diff --git a/tests/language_2/regress/regress46550_test.dart b/tests/language_2/regress/regress46550_test.dart
new file mode 100644
index 0000000..9b609da
--- /dev/null
+++ b/tests/language_2/regress/regress46550_test.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.
+
+// VMOptions=--optimization_counter_threshold=100 --deterministic
+
+import "package:expect/expect.dart";
+
+typedef void test1<T extends num>();
+
+void t1<T extends int>() {
+  Expect.equals(int, T);
+}
+
+const test1 res1 = t1;
+
+main() {
+  for (int i = 0; i < 120; ++i) {
+    res1();
+  }
+}
diff --git a/tests/language_2/string/optimizations_test.dart b/tests/language_2/string/optimizations_test.dart
index 7b8ea64..5c2bb9de 100644
--- a/tests/language_2/string/optimizations_test.dart
+++ b/tests/language_2/string/optimizations_test.dart
@@ -8,15 +8,16 @@
 // correctly infer optional named parameters.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 foo({path}) {
   () => 42;
   return path.toString();
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 bar({path}) {
   () => 42;
   return path;
diff --git a/tests/language_2/unsorted/refine_receiver_null_test.dart b/tests/language_2/unsorted/refine_receiver_null_test.dart
index 46df819..df580ba 100644
--- a/tests/language_2/unsorted/refine_receiver_null_test.dart
+++ b/tests/language_2/unsorted/refine_receiver_null_test.dart
@@ -9,7 +9,6 @@
 // work for Object methods.
 
 import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
 
 main() {
   var a = true ? null : 42;
@@ -17,7 +16,8 @@
   foo(a);
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 foo(a) {
   var f = () => 42;
   Expect.throwsNoSuchMethodError(() => a + 42);
diff --git a/tests/language_2/vm/optimized_guarded_field_isolates_test.dart b/tests/language_2/vm/optimized_guarded_field_isolates_test.dart
index c08c957..be65d88 100644
--- a/tests/language_2/vm/optimized_guarded_field_isolates_test.dart
+++ b/tests/language_2/vm/optimized_guarded_field_isolates_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 // VMOptions=--optimization_counter_threshold=100 --no-background_compilation
 
diff --git a/tests/language_2/vm/regress_flutter_85311_test.dart b/tests/language_2/vm/regress_flutter_85311_test.dart
new file mode 100644
index 0000000..a3458f9
--- /dev/null
+++ b/tests/language_2/vm/regress_flutter_85311_test.dart
@@ -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.
+
+// @dart = 2.9
+
+// This is a regression test for the bug in
+// https://github.com/flutter/flutter/issues/51828.
+// Verifies that temporaries aren't incorrectly assigned types when they're
+// reused.
+
+import "package:expect/expect.dart";
+
+bool wasCalled = false;
+
+class Z {
+  bool operator ==(Object other) {
+    wasCalled = true;
+    return true;
+  }
+}
+
+class Y {
+  final dynamic v;
+  Y(this.v);
+}
+
+Future<bool> crash(dynamic y) async {
+  return (y.v == (await 7) || y == (await 9));
+}
+
+void main() async {
+  await crash(Y(Z()));
+
+  Expect.isTrue(wasCalled);
+}
diff --git a/tests/lib/html/js_typed_interop_lazy_test.dart b/tests/lib/html/js_typed_interop_lazy_test.dart
index 63c578d..1825174 100644
--- a/tests/lib/html/js_typed_interop_lazy_test.dart
+++ b/tests/lib/html/js_typed_interop_lazy_test.dart
@@ -142,10 +142,9 @@
       expect(new Object() is! AnonClass2, isTrue);
 
       expect(<AnonClass>[] is List<AnonClass>, isTrue);
-      // TODO(jacobr): why doesn't this test pass?
-      // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+      expect(<AnonClass>[] is List<AnonClass2>, isTrue);
       expect(<int>[] is! List<AnonClass>, isTrue);
-      expect(<AnonClass>[] is! List<LazyClass>, isTrue); //# 01: ok
+      expect(<AnonClass>[] is List<LazyClass>, isTrue);
       expect(<int>[] is! List<LazyClass>, isTrue);
       expect(<LazyClass>[] is List<LazyClass>, isTrue);
 
@@ -234,10 +233,9 @@
       expect(new Object() is! AnonClass2, isTrue);
 
       expect(<AnonClass>[] is List<AnonClass>, isTrue);
-      // TODO(jacobr): why doesn't this test pass?
-      // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+      expect(<AnonClass>[] is List<AnonClass2>, isTrue);
       expect(<int>[] is! List<AnonClass>, isTrue);
-      expect(<AnonClass>[] is! List<NestedLazyClass>, isTrue); //# 01: ok
+      expect(<AnonClass>[] is List<NestedLazyClass>, isTrue);
       expect(<int>[] is! List<NestedLazyClass>, isTrue);
       expect(<NestedLazyClass>[] is List<NestedLazyClass>, isTrue);
 
diff --git a/tests/lib/isolate/bool_from_environment_default_value_test.dart b/tests/lib/isolate/bool_from_environment_default_value_test.dart
index 65992ab..fb9d49b 100644
--- a/tests/lib/isolate/bool_from_environment_default_value_test.dart
+++ b/tests/lib/isolate/bool_from_environment_default_value_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/capability_test.dart b/tests/lib/isolate/capability_test.dart
index 4c09118..fd6c4d3 100644
--- a/tests/lib/isolate/capability_test.dart
+++ b/tests/lib/isolate/capability_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/compile_time_error_test.dart b/tests/lib/isolate/compile_time_error_test.dart
index 866cb3b..21197fa 100644
--- a/tests/lib/isolate/compile_time_error_test.dart
+++ b/tests/lib/isolate/compile_time_error_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing that errors thrown from isolates are
diff --git a/tests/lib/isolate/count_test.dart b/tests/lib/isolate/count_test.dart
index 2315e12..cc96b3f 100644
--- a/tests/lib/isolate/count_test.dart
+++ b/tests/lib/isolate/count_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 library CountTest;
diff --git a/tests/lib/isolate/cross_isolate_message_test.dart b/tests/lib/isolate/cross_isolate_message_test.dart
index 3b406cc..ede3792 100644
--- a/tests/lib/isolate/cross_isolate_message_test.dart
+++ b/tests/lib/isolate/cross_isolate_message_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing that isolates can communicate to isolates
diff --git a/tests/lib/isolate/deferred_in_isolate2_test.dart b/tests/lib/isolate/deferred_in_isolate2_test.dart
index 9eddc1c..52e5428 100644
--- a/tests/lib/isolate/deferred_in_isolate2_test.dart
+++ b/tests/lib/isolate/deferred_in_isolate2_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library deferred_in_isolate2_test;
diff --git a/tests/lib/isolate/deferred_in_isolate_test.dart b/tests/lib/isolate/deferred_in_isolate_test.dart
index 167815b..d44f075 100644
--- a/tests/lib/isolate/deferred_in_isolate_test.dart
+++ b/tests/lib/isolate/deferred_in_isolate_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test that deferred libraries are supported from isolates other than the root
diff --git a/tests/lib/isolate/enum_const_test.dart b/tests/lib/isolate/enum_const_test.dart
index 3766cb5..0a57f13 100644
--- a/tests/lib/isolate/enum_const_test.dart
+++ b/tests/lib/isolate/enum_const_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/error_at_spawn_test.dart b/tests/lib/isolate/error_at_spawn_test.dart
index dcb033b..c22f41e 100644
--- a/tests/lib/isolate/error_at_spawn_test.dart
+++ b/tests/lib/isolate/error_at_spawn_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library error_at_spawn;
diff --git a/tests/lib/isolate/error_at_spawnuri_test.dart b/tests/lib/isolate/error_at_spawnuri_test.dart
index 2c33f11..6d0e073 100644
--- a/tests/lib/isolate/error_at_spawnuri_test.dart
+++ b/tests/lib/isolate/error_at_spawnuri_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library error_at_spawnuri;
diff --git a/tests/lib/isolate/error_exit_at_spawn_test.dart b/tests/lib/isolate/error_exit_at_spawn_test.dart
index 7033c1f..9543025 100644
--- a/tests/lib/isolate/error_exit_at_spawn_test.dart
+++ b/tests/lib/isolate/error_exit_at_spawn_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library error_exit_at_spawn;
diff --git a/tests/lib/isolate/error_exit_at_spawnuri_test.dart b/tests/lib/isolate/error_exit_at_spawnuri_test.dart
index 7f4f4d6..cf32b98 100644
--- a/tests/lib/isolate/error_exit_at_spawnuri_test.dart
+++ b/tests/lib/isolate/error_exit_at_spawnuri_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library error_exit_at_spawnuri;
diff --git a/tests/lib/isolate/exit_at_spawn_test.dart b/tests/lib/isolate/exit_at_spawn_test.dart
index 3feb840..4a2574e 100644
--- a/tests/lib/isolate/exit_at_spawn_test.dart
+++ b/tests/lib/isolate/exit_at_spawn_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library exit_at_spawn;
diff --git a/tests/lib/isolate/exit_at_spawnuri_test.dart b/tests/lib/isolate/exit_at_spawnuri_test.dart
index e77fe04..5bb9ed8 100644
--- a/tests/lib/isolate/exit_at_spawnuri_test.dart
+++ b/tests/lib/isolate/exit_at_spawnuri_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library exit_at_spawn;
diff --git a/tests/lib/isolate/function_send1_test.dart b/tests/lib/isolate/function_send1_test.dart
index 4390735..1955c96 100644
--- a/tests/lib/isolate/function_send1_test.dart
+++ b/tests/lib/isolate/function_send1_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/function_send_test.dart b/tests/lib/isolate/function_send_test.dart
index ea75c63..82b6123 100644
--- a/tests/lib/isolate/function_send_test.dart
+++ b/tests/lib/isolate/function_send_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/handle_error2_test.dart b/tests/lib/isolate/handle_error2_test.dart
index e3e3b66..8e36364 100644
--- a/tests/lib/isolate/handle_error2_test.dart
+++ b/tests/lib/isolate/handle_error2_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library handle_error_test;
diff --git a/tests/lib/isolate/handle_error3_test.dart b/tests/lib/isolate/handle_error3_test.dart
index 165e210..170f130 100644
--- a/tests/lib/isolate/handle_error3_test.dart
+++ b/tests/lib/isolate/handle_error3_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library handle_error_test;
diff --git a/tests/lib/isolate/handle_error_test.dart b/tests/lib/isolate/handle_error_test.dart
index fad1719..a453072 100644
--- a/tests/lib/isolate/handle_error_test.dart
+++ b/tests/lib/isolate/handle_error_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library handle_error_test;
diff --git a/tests/lib/isolate/illegal_msg_function_test.dart b/tests/lib/isolate/illegal_msg_function_test.dart
index 5fcaf8a..5b5aa45 100644
--- a/tests/lib/isolate/illegal_msg_function_test.dart
+++ b/tests/lib/isolate/illegal_msg_function_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library illegal_msg_function_test;
diff --git a/tests/lib/isolate/illegal_msg_mirror_test.dart b/tests/lib/isolate/illegal_msg_mirror_test.dart
index 7fd70ab..a15572d 100644
--- a/tests/lib/isolate/illegal_msg_mirror_test.dart
+++ b/tests/lib/isolate/illegal_msg_mirror_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library illegal_msg_mirror_test;
diff --git a/tests/lib/isolate/int32_length_overflow_test.dart b/tests/lib/isolate/int32_length_overflow_test.dart
index b7f51cf..85e2bd7 100644
--- a/tests/lib/isolate/int32_length_overflow_test.dart
+++ b/tests/lib/isolate/int32_length_overflow_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/lib/isolate/int_from_environment_default_value_test.dart b/tests/lib/isolate/int_from_environment_default_value_test.dart
index 7bf0761..af7ccac 100644
--- a/tests/lib/isolate/int_from_environment_default_value_test.dart
+++ b/tests/lib/isolate/int_from_environment_default_value_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/isolate_complex_messages_test.dart b/tests/lib/isolate/isolate_complex_messages_test.dart
index 606b3af..bbf728d 100644
--- a/tests/lib/isolate/isolate_complex_messages_test.dart
+++ b/tests/lib/isolate/isolate_complex_messages_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing isolate communication with
diff --git a/tests/lib/isolate/isolate_current_test.dart b/tests/lib/isolate/isolate_current_test.dart
index b4b0baea..1c2f1bb 100644
--- a/tests/lib/isolate/isolate_current_test.dart
+++ b/tests/lib/isolate/isolate_current_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 library isolate_current_test;
diff --git a/tests/lib/isolate/isolate_import_test.dart b/tests/lib/isolate/isolate_import_test.dart
index 0438a4e..781e13c 100644
--- a/tests/lib/isolate/isolate_import_test.dart
+++ b/tests/lib/isolate/isolate_import_test.dart
@@ -2,15 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library IsolateImportNegativeTest;
 
 // Omitting the following import is an error:
-/* // //# 01: runtime error, compile-time error
+/* //# 01: compile-time error
 import 'dart:isolate';
-*/ // //# 01: continued
+*/ //# 01: continued
 import 'package:async_helper/async_helper.dart';
 
 void entry(msg) {}
diff --git a/tests/lib/isolate/issue_21398_parent_isolate1_test.dart b/tests/lib/isolate/issue_21398_parent_isolate1_test.dart
index 78f19d5..6a0b458 100644
--- a/tests/lib/isolate/issue_21398_parent_isolate1_test.dart
+++ b/tests/lib/isolate/issue_21398_parent_isolate1_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/tests/lib/isolate/issue_21398_parent_isolate2_test.dart b/tests/lib/isolate/issue_21398_parent_isolate2_test.dart
index d092152..feee51b 100644
--- a/tests/lib/isolate/issue_21398_parent_isolate2_test.dart
+++ b/tests/lib/isolate/issue_21398_parent_isolate2_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/tests/lib/isolate/issue_21398_parent_isolate_test.dart b/tests/lib/isolate/issue_21398_parent_isolate_test.dart
index 2dcb5c1..5264827 100644
--- a/tests/lib/isolate/issue_21398_parent_isolate_test.dart
+++ b/tests/lib/isolate/issue_21398_parent_isolate_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/tests/lib/isolate/issue_22778_test.dart b/tests/lib/isolate/issue_22778_test.dart
index 67d90a2..28107cc 100644
--- a/tests/lib/isolate/issue_22778_test.dart
+++ b/tests/lib/isolate/issue_22778_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/issue_24243_parent_isolate_test.dart b/tests/lib/isolate/issue_24243_parent_isolate_test.dart
index 92a9549..c38e5e4 100644
--- a/tests/lib/isolate/issue_24243_parent_isolate_test.dart
+++ b/tests/lib/isolate/issue_24243_parent_isolate_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:collection';
diff --git a/tests/lib/isolate/issue_35626_test.dart b/tests/lib/isolate/issue_35626_test.dart
index 26ee9c6..2b392ad 100644
--- a/tests/lib/isolate/issue_35626_test.dart
+++ b/tests/lib/isolate/issue_35626_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 // Tests that sets of enums can be set through ports.
diff --git a/tests/lib/isolate/issue_6610_test.dart b/tests/lib/isolate/issue_6610_test.dart
index 9a37e51..962955e 100644
--- a/tests/lib/isolate/issue_6610_test.dart
+++ b/tests/lib/isolate/issue_6610_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Testing that Isolate.spawn copies the source code of the parent isolate,
diff --git a/tests/lib/isolate/kill2_test.dart b/tests/lib/isolate/kill2_test.dart
index 0c946f0..9391fc8 100644
--- a/tests/lib/isolate/kill2_test.dart
+++ b/tests/lib/isolate/kill2_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/kill_infinite_loop_in_initializer_test.dart b/tests/lib/isolate/kill_infinite_loop_in_initializer_test.dart
new file mode 100644
index 0000000..1d41541
--- /dev/null
+++ b/tests/lib/isolate/kill_infinite_loop_in_initializer_test.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.
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+
+// Regression test against out-of-band messages being blocked during lazy
+// static field initialization.
+
+import "dart:isolate";
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+dynamic staticFieldWithBadInitializer = badInitializer();
+
+badInitializer() {
+  print("badInitializer");
+  for (;;) {}
+  return 42; // Unreachable.
+}
+
+child(message) {
+  print("child");
+  RawReceivePort port = new RawReceivePort();
+  print(staticFieldWithBadInitializer);
+  port.close(); // Unreachable.
+}
+
+void main() {
+  asyncStart();
+  Isolate.spawn(child, null).then((Isolate isolate) {
+    print("spawned");
+    late RawReceivePort exitSignal;
+    exitSignal = new RawReceivePort((_) {
+      print("onExit");
+      exitSignal.close();
+      asyncEnd();
+    });
+    isolate.addOnExitListener(exitSignal.sendPort);
+    isolate.kill(priority: Isolate.immediate);
+  });
+}
diff --git a/tests/lib/isolate/kill_self_synchronously_test.dart b/tests/lib/isolate/kill_self_synchronously_test.dart
index 1cfc4ff..19f3a2e 100644
--- a/tests/lib/isolate/kill_self_synchronously_test.dart
+++ b/tests/lib/isolate/kill_self_synchronously_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/kill_self_test.dart b/tests/lib/isolate/kill_self_test.dart
index ace983f..157b30f 100644
--- a/tests/lib/isolate/kill_self_test.dart
+++ b/tests/lib/isolate/kill_self_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/kill_test.dart b/tests/lib/isolate/kill_test.dart
index 7c97bfd..07e0dfe8 100644
--- a/tests/lib/isolate/kill_test.dart
+++ b/tests/lib/isolate/kill_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/large_byte_data_leak_test.dart b/tests/lib/isolate/large_byte_data_leak_test.dart
index fe2fda1..9797a54 100644
--- a/tests/lib/isolate/large_byte_data_leak_test.dart
+++ b/tests/lib/isolate/large_byte_data_leak_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/lib/isolate/large_byte_data_test.dart b/tests/lib/isolate/large_byte_data_test.dart
index 3861e5c..8a78238 100644
--- a/tests/lib/isolate/large_byte_data_test.dart
+++ b/tests/lib/isolate/large_byte_data_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/lib/isolate/mandel_isolate_test.dart b/tests/lib/isolate/mandel_isolate_test.dart
index 22f7760..50d564a 100644
--- a/tests/lib/isolate/mandel_isolate_test.dart
+++ b/tests/lib/isolate/mandel_isolate_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library MandelIsolateTest;
diff --git a/tests/lib/isolate/message2_test.dart b/tests/lib/isolate/message2_test.dart
index 422b499..fd7550c 100644
--- a/tests/lib/isolate/message2_test.dart
+++ b/tests/lib/isolate/message2_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing serialization of messages.
diff --git a/tests/lib/isolate/message3_test.dart b/tests/lib/isolate/message3_test.dart
index bb8a007fa..37bf159 100644
--- a/tests/lib/isolate/message3_test.dart
+++ b/tests/lib/isolate/message3_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing serialization of messages.
diff --git a/tests/lib/isolate/message4_test.dart b/tests/lib/isolate/message4_test.dart
index 3cc4641..4644ddb 100644
--- a/tests/lib/isolate/message4_test.dart
+++ b/tests/lib/isolate/message4_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing serialization of messages with static
diff --git a/tests/lib/isolate/message_const_type_arguments_1_test.dart b/tests/lib/isolate/message_const_type_arguments_1_test.dart
index 480cda5..e5133aa 100644
--- a/tests/lib/isolate/message_const_type_arguments_1_test.dart
+++ b/tests/lib/isolate/message_const_type_arguments_1_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // https://github.com/dart-lang/sdk/issues/35778
diff --git a/tests/lib/isolate/message_const_type_arguments_2_test.dart b/tests/lib/isolate/message_const_type_arguments_2_test.dart
index 8398d2b..002aa6e 100644
--- a/tests/lib/isolate/message_const_type_arguments_2_test.dart
+++ b/tests/lib/isolate/message_const_type_arguments_2_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // https://github.com/dart-lang/sdk/issues/35778
diff --git a/tests/lib/isolate/message_enum_test.dart b/tests/lib/isolate/message_enum_test.dart
index 55eb38b..801afd4d 100644
--- a/tests/lib/isolate/message_enum_test.dart
+++ b/tests/lib/isolate/message_enum_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'package:expect/expect.dart';
diff --git a/tests/lib/isolate/message_test.dart b/tests/lib/isolate/message_test.dart
index 5e6cd6b..8a7ec69 100644
--- a/tests/lib/isolate/message_test.dart
+++ b/tests/lib/isolate/message_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing serialization of messages.
diff --git a/tests/lib/isolate/mint_maker_test.dart b/tests/lib/isolate/mint_maker_test.dart
index f82315e..c4b25ec 100644
--- a/tests/lib/isolate/mint_maker_test.dart
+++ b/tests/lib/isolate/mint_maker_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library MintMakerTest;
diff --git a/tests/lib/isolate/native_wrapper_message_test.dart b/tests/lib/isolate/native_wrapper_message_test.dart
index 27c294c..366a84b 100644
--- a/tests/lib/isolate/native_wrapper_message_test.dart
+++ b/tests/lib/isolate/native_wrapper_message_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/tests/lib/isolate/nested_spawn2_test.dart b/tests/lib/isolate/nested_spawn2_test.dart
index f8cf00a..d335909 100644
--- a/tests/lib/isolate/nested_spawn2_test.dart
+++ b/tests/lib/isolate/nested_spawn2_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing that isolates can spawn other isolates and
diff --git a/tests/lib/isolate/nested_spawn_test.dart b/tests/lib/isolate/nested_spawn_test.dart
index 952c192..0bc8c77 100644
--- a/tests/lib/isolate/nested_spawn_test.dart
+++ b/tests/lib/isolate/nested_spawn_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing that isolates can spawn other isolates.
diff --git a/tests/lib/isolate/non_fatal_exception_in_timer_callback_test.dart b/tests/lib/isolate/non_fatal_exception_in_timer_callback_test.dart
index 0d2e8cc..b361171 100644
--- a/tests/lib/isolate/non_fatal_exception_in_timer_callback_test.dart
+++ b/tests/lib/isolate/non_fatal_exception_in_timer_callback_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:async';
diff --git a/tests/lib/isolate/object_leak_test.dart b/tests/lib/isolate/object_leak_test.dart
index d563786..b8b94b4 100644
--- a/tests/lib/isolate/object_leak_test.dart
+++ b/tests/lib/isolate/object_leak_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Regression test for http://dartbug.com/18942
diff --git a/tests/lib/isolate/ondone_test.dart b/tests/lib/isolate/ondone_test.dart
index 0f11aaf..f378855 100644
--- a/tests/lib/isolate/ondone_test.dart
+++ b/tests/lib/isolate/ondone_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/package_config_test.dart b/tests/lib/isolate/package_config_test.dart
index c4119b2..a2cfece 100644
--- a/tests/lib/isolate/package_config_test.dart
+++ b/tests/lib/isolate/package_config_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 // VMOptions=--trace_shutdown
 import 'dart:io';
diff --git a/tests/lib/isolate/package_resolve_test.dart b/tests/lib/isolate/package_resolve_test.dart
index 99cb6f1..50686a3 100644
--- a/tests/lib/isolate/package_resolve_test.dart
+++ b/tests/lib/isolate/package_resolve_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:io';
diff --git a/tests/lib/isolate/package_root_test.dart b/tests/lib/isolate/package_root_test.dart
index 4b3d46b..390df69 100644
--- a/tests/lib/isolate/package_root_test.dart
+++ b/tests/lib/isolate/package_root_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:io';
diff --git a/tests/lib/isolate/pause_test.dart b/tests/lib/isolate/pause_test.dart
index 31e091d..1e97f00a 100644
--- a/tests/lib/isolate/pause_test.dart
+++ b/tests/lib/isolate/pause_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/ping_pause_test.dart b/tests/lib/isolate/ping_pause_test.dart
index d83d55f..48ad135 100644
--- a/tests/lib/isolate/ping_pause_test.dart
+++ b/tests/lib/isolate/ping_pause_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/ping_test.dart b/tests/lib/isolate/ping_test.dart
index e9a0d05..4371a4c0 100644
--- a/tests/lib/isolate/ping_test.dart
+++ b/tests/lib/isolate/ping_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/port_test.dart b/tests/lib/isolate/port_test.dart
index b66fc4f..937d75e 100644
--- a/tests/lib/isolate/port_test.dart
+++ b/tests/lib/isolate/port_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test properties of ports.
diff --git a/tests/lib/isolate/raw_port_test.dart b/tests/lib/isolate/raw_port_test.dart
index d0b8695..6f24212 100644
--- a/tests/lib/isolate/raw_port_test.dart
+++ b/tests/lib/isolate/raw_port_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test RawReceivePort.
diff --git a/tests/lib/isolate/regress_34752_test.dart b/tests/lib/isolate/regress_34752_test.dart
index fc17139..ed870a6 100644
--- a/tests/lib/isolate/regress_34752_test.dart
+++ b/tests/lib/isolate/regress_34752_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 // Verifies that large BigInt can be passed through a message port and
diff --git a/tests/lib/isolate/regress_flutter_22796_test.dart b/tests/lib/isolate/regress_flutter_22796_test.dart
index f97ca05..1cab5f1 100644
--- a/tests/lib/isolate/regress_flutter_22796_test.dart
+++ b/tests/lib/isolate/regress_flutter_22796_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Verifies that large typed data can be passed in a field through message port.
diff --git a/tests/lib/isolate/request_reply_test.dart b/tests/lib/isolate/request_reply_test.dart
index 3dd9274..54d4d7c 100644
--- a/tests/lib/isolate/request_reply_test.dart
+++ b/tests/lib/isolate/request_reply_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library RequestReplyTest;
diff --git a/tests/lib/isolate/resolve_package_uri_test.dart b/tests/lib/isolate/resolve_package_uri_test.dart
index b926ccd..9ea1d03 100644
--- a/tests/lib/isolate/resolve_package_uri_test.dart
+++ b/tests/lib/isolate/resolve_package_uri_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Regression test for faulty encoding of `Isolate.resolvePackageUri` by
diff --git a/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart b/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
index 99cb6f1..50686a3 100644
--- a/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
+++ b/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:io';
diff --git a/tests/lib/isolate/send_private_test.dart b/tests/lib/isolate/send_private_test.dart
index 46114c8..8ed717f 100644
--- a/tests/lib/isolate/send_private_test.dart
+++ b/tests/lib/isolate/send_private_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/simple_message_test.dart b/tests/lib/isolate/simple_message_test.dart
index 677998c..f0310af 100644
--- a/tests/lib/isolate/simple_message_test.dart
+++ b/tests/lib/isolate/simple_message_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing that isolates are spawned.
diff --git a/tests/lib/isolate/spawn_function_custom_class_test.dart b/tests/lib/isolate/spawn_function_custom_class_test.dart
index 5abcae6..0046cef 100644
--- a/tests/lib/isolate/spawn_function_custom_class_test.dart
+++ b/tests/lib/isolate/spawn_function_custom_class_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Create a user-defined class in a new isolate.
diff --git a/tests/lib/isolate/spawn_function_test.dart b/tests/lib/isolate/spawn_function_test.dart
index 22c5c8a..bd8d1c1 100644
--- a/tests/lib/isolate/spawn_function_test.dart
+++ b/tests/lib/isolate/spawn_function_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Example of spawning an isolate from a function.
diff --git a/tests/lib/isolate/spawn_generic_test.dart b/tests/lib/isolate/spawn_generic_test.dart
index 572f985..109f2a8 100644
--- a/tests/lib/isolate/spawn_generic_test.dart
+++ b/tests/lib/isolate/spawn_generic_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Check that Isolate.spawn is generic.
diff --git a/tests/lib/isolate/spawn_uri_exported_main_test.dart b/tests/lib/isolate/spawn_uri_exported_main_test.dart
index 20959cd..837486e 100644
--- a/tests/lib/isolate/spawn_uri_exported_main_test.dart
+++ b/tests/lib/isolate/spawn_uri_exported_main_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/lib/isolate/spawn_uri_fail_test.dart b/tests/lib/isolate/spawn_uri_fail_test.dart
index 84d54b0..6c9dc98 100644
--- a/tests/lib/isolate/spawn_uri_fail_test.dart
+++ b/tests/lib/isolate/spawn_uri_fail_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:io";
diff --git a/tests/lib/isolate/spawn_uri_missing_from_isolate_test.dart b/tests/lib/isolate/spawn_uri_missing_from_isolate_test.dart
index 915ffa4..02521b6 100644
--- a/tests/lib/isolate/spawn_uri_missing_from_isolate_test.dart
+++ b/tests/lib/isolate/spawn_uri_missing_from_isolate_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 /// Tests that Isolate.spawnUri completes with an error when the given URI
diff --git a/tests/lib/isolate/spawn_uri_missing_test.dart b/tests/lib/isolate/spawn_uri_missing_test.dart
index 86eaf9d..19344ba 100644
--- a/tests/lib/isolate/spawn_uri_missing_test.dart
+++ b/tests/lib/isolate/spawn_uri_missing_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 /// Tests that Isolate.spanUri completes with an error when the given URI
diff --git a/tests/lib/isolate/spawn_uri_multi_test.dart b/tests/lib/isolate/spawn_uri_multi_test.dart
index 38a22ee..d5fdc46 100644
--- a/tests/lib/isolate/spawn_uri_multi_test.dart
+++ b/tests/lib/isolate/spawn_uri_multi_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Negative test to make sure that we are reaching all assertions.
diff --git a/tests/lib/isolate/spawn_uri_nested_vm_test.dart b/tests/lib/isolate/spawn_uri_nested_vm_test.dart
index 5da7fa9..087b5fc 100644
--- a/tests/lib/isolate/spawn_uri_nested_vm_test.dart
+++ b/tests/lib/isolate/spawn_uri_nested_vm_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Example of nested spawning of isolates from a URI
diff --git a/tests/lib/isolate/spawn_uri_test.dart b/tests/lib/isolate/spawn_uri_test.dart
index 543b627..28d7bce 100644
--- a/tests/lib/isolate/spawn_uri_test.dart
+++ b/tests/lib/isolate/spawn_uri_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Example of spawning an isolate from a URI
diff --git a/tests/lib/isolate/spawn_uri_vm_test.dart b/tests/lib/isolate/spawn_uri_vm_test.dart
index 48d30a2..3832b42 100644
--- a/tests/lib/isolate/spawn_uri_vm_test.dart
+++ b/tests/lib/isolate/spawn_uri_vm_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Example of spawning an isolate from a URI
diff --git a/tests/lib/isolate/start_paused_test.dart b/tests/lib/isolate/start_paused_test.dart
index 5ca7fef..c9b2b57 100644
--- a/tests/lib/isolate/start_paused_test.dart
+++ b/tests/lib/isolate/start_paused_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library start_paused_test;
diff --git a/tests/lib/isolate/static_function_test.dart b/tests/lib/isolate/static_function_test.dart
index 92151ac..e1ece06 100644
--- a/tests/lib/isolate/static_function_test.dart
+++ b/tests/lib/isolate/static_function_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test starting isolate with static functions (and toplevel ones, for sanity).
diff --git a/tests/lib/isolate/string_from_environment_default_value_test.dart b/tests/lib/isolate/string_from_environment_default_value_test.dart
index 6c2adfb..78b2feb 100644
--- a/tests/lib/isolate/string_from_environment_default_value_test.dart
+++ b/tests/lib/isolate/string_from_environment_default_value_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib/isolate/timer_isolate_test.dart b/tests/lib/isolate/timer_isolate_test.dart
index b2c98d9..58e93c5 100644
--- a/tests/lib/isolate/timer_isolate_test.dart
+++ b/tests/lib/isolate/timer_isolate_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library multiple_timer_test;
diff --git a/tests/lib/isolate/timer_multiple_isolates_test.dart b/tests/lib/isolate/timer_multiple_isolates_test.dart
index a2f5611..3f7d8f3 100644
--- a/tests/lib/isolate/timer_multiple_isolates_test.dart
+++ b/tests/lib/isolate/timer_multiple_isolates_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library timer_multiple_isolates_test;
diff --git a/tests/lib/isolate/transferable_failed_to_send_test.dart b/tests/lib/isolate/transferable_failed_to_send_test.dart
index a8d3bcd..c1d714a 100644
--- a/tests/lib/isolate/transferable_failed_to_send_test.dart
+++ b/tests/lib/isolate/transferable_failed_to_send_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:io" show ServerSocket;
diff --git a/tests/lib/isolate/transferable_test.dart b/tests/lib/isolate/transferable_test.dart
index f8888e7..2264c8c 100644
--- a/tests/lib/isolate/transferable_test.dart
+++ b/tests/lib/isolate/transferable_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/lib/isolate/type_ref_message_test.dart b/tests/lib/isolate/type_ref_message_test.dart
new file mode 100644
index 0000000..1c47e35
--- /dev/null
+++ b/tests/lib/isolate/type_ref_message_test.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.
+
+// See https://github.com/flutter/flutter/issues/84691
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+
+class B<T> {}
+class D<S> extends B<D> {}
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var list = message as List<D<String>>;
+    var element = list[0] as D<String>;
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var list = <D<String>>[ new D() ];
+  port.sendPort.send(list);
+}
diff --git a/tests/lib/isolate/typed_message_test.dart b/tests/lib/isolate/typed_message_test.dart
index 955204d..38e24d0 100644
--- a/tests/lib/isolate/typed_message_test.dart
+++ b/tests/lib/isolate/typed_message_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 // Dart test program for testing isolate communication with
 // typed objects.
diff --git a/tests/lib/isolate/unresolved_ports_test.dart b/tests/lib/isolate/unresolved_ports_test.dart
index fa41bb4..7707fab 100644
--- a/tests/lib/isolate/unresolved_ports_test.dart
+++ b/tests/lib/isolate/unresolved_ports_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // spawns multiple isolates and sends unresolved ports between them.
diff --git a/tests/lib/isolate/vm_rehash_test.dart b/tests/lib/isolate/vm_rehash_test.dart
index 6c1065c..f5a0a73 100644
--- a/tests/lib/isolate/vm_rehash_test.dart
+++ b/tests/lib/isolate/vm_rehash_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:async';
diff --git a/tests/lib/isolate/weak_property_message_1_test.dart b/tests/lib/isolate/weak_property_message_1_test.dart
new file mode 100644
index 0000000..2f4d344
--- /dev/null
+++ b/tests/lib/isolate/weak_property_message_1_test.dart
@@ -0,0 +1,48 @@
+// 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.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var expando1 = message[0] as Expando;
+    var expando2 = message[1] as Expando;
+    var expando3 = message[2] as Expando;
+    var key1 = message[3];
+
+    var key2 = expando1[key1!];
+    Expect.isNotNull(key2);
+    var key3 = expando2[key2!];
+    Expect.isNotNull(key3);
+    var value = expando3[key3!];
+    Expect.equals(value, "value");
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var key1 = new Object();
+  var key2 = new Object();
+  var key3 = new Object();
+  var expando1 = new Expando();
+  var expando2 = new Expando();
+  var expando3 = new Expando();
+  expando1[key1] = key2;
+  expando2[key2] = key3;
+  expando3[key3] = "value";
+
+  // key1 is placed after expando1 so that its reachability is uncertain when
+  // expando1 is first encountered.
+  var message = <dynamic>[expando1, expando2, expando3, key1];
+  port.sendPort.send(message);
+}
diff --git a/tests/lib/isolate/weak_property_message_2_test.dart b/tests/lib/isolate/weak_property_message_2_test.dart
new file mode 100644
index 0000000..236bcfe3
--- /dev/null
+++ b/tests/lib/isolate/weak_property_message_2_test.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.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+import "dart:async";
+import "dart:developer";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var expando = message as Expando;
+
+    // Sent and received without error.
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var unwrittenKey = new Object();
+  var expando = new Expando();
+  expando[unwrittenKey] = new UserTag("cant send this");
+
+  port.sendPort.send(expando);
+
+  print(unwrittenKey);  // Ensure [unwrittenKey] is live during [send].
+}
diff --git a/tests/lib/js/extends_test/extends_subtyping_live_test.dart b/tests/lib/js/extends_test/extends_subtyping_live_test.dart
new file mode 100644
index 0000000..b46818e
--- /dev/null
+++ b/tests/lib/js/extends_test/extends_subtyping_live_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Tests inheritance subtyping relationships after making package:js types live.
+
+@JS()
+library extends_subtyping_live_test;
+
+import 'package:js/js.dart';
+import 'extends_test_util.dart';
+
+@JS()
+external dynamic get externalGetter;
+
+void main() {
+  // Call to foreign function should trigger dart2js to assume types are live.
+  externalGetter;
+  testSubtyping();
+}
diff --git a/tests/lib/js/extends_test/extends_subtyping_not_live_test.dart b/tests/lib/js/extends_test/extends_subtyping_not_live_test.dart
new file mode 100644
index 0000000..3cb0fbb
--- /dev/null
+++ b/tests/lib/js/extends_test/extends_subtyping_not_live_test.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.
+
+// Tests inheritance subtyping relationships without making package:js types
+// live.
+
+import 'extends_test_util.dart';
+
+void main() {
+  testSubtyping();
+}
diff --git a/tests/lib/js/extends_test/extends_test_util.dart b/tests/lib/js/extends_test/extends_test_util.dart
index e39e1b9..0698ef9 100644
--- a/tests/lib/js/extends_test/extends_test_util.dart
+++ b/tests/lib/js/extends_test/extends_test_util.dart
@@ -15,6 +15,7 @@
 
 @JS()
 class JSClass {
+  external JSClass();
   external int get a;
   external int getA();
   external int getAOrB();
@@ -57,12 +58,10 @@
   external int getAOrB();
 }
 
+external AnonymousClass get anon;
 external AnonymousExtendAnonymousClass get anonExtendAnon;
 external AnonymousExtendJSClass get anonExtendJS;
 
-void useJSClass(JSClass js) {}
-void useAnonymousClass(AnonymousClass a) {}
-
 void setUpWithoutES6Syntax() {
   // Use the old way to define inheritance between JS objects.
   eval(r"""
@@ -77,6 +76,7 @@
       }
     }
     function JSClass(a) {
+      if (arguments.length == 0) a = 1;
       this.a = a;
       this.getA = function() {
         return this.a;
@@ -109,6 +109,7 @@
         return this.getB();
       }
     }
+    self.anon = new JSClass(1);
     self.anonExtendAnon = new JSExtendAnonymousClass(1, 2);
     self.anonExtendJS = new JSExtendJSClass(1, 2);
   """);
@@ -119,6 +120,7 @@
   eval(r"""
     class JSClass {
       constructor(a) {
+        if (arguments.length == 0) a = 1;
         this.a = a;
       }
       getA() {
@@ -128,6 +130,7 @@
         return this.getA();
       }
     }
+    self.JSClass = JSClass;
     class JSExtendJSClass extends JSClass {
       constructor(a, b) {
         super(a);
@@ -157,16 +160,13 @@
       }
     }
     self.JSExtendAnonymousClass = JSExtendAnonymousClass;
+    self.anon = new JSClass(1);
     self.anonExtendAnon = new JSExtendAnonymousClass(1, 2);
     self.anonExtendJS = new JSExtendJSClass(1, 2);
   """);
 }
 
 void testInheritance() {
-  // Note that for the following, there are no meaningful tests for is checks or
-  // as casts, since the web compilers should return true and succeed for all JS
-  // types.
-
   var jsExtendJS = JSExtendJSClass(1, 2);
   expect(jsExtendJS.a, 1);
   expect(jsExtendJS.b, 2);
@@ -193,18 +193,86 @@
   expect(anonExtendJS.getB(), 2);
   expect(anonExtendJS.getAOrB(), 2);
   expect((anonExtendJS as JSClass).getAOrB(), 2);
+
+  // Test type checking and casts succeeds regardless of type hierarchy.
+
+  // Test type checking at runtime by disabling inlining. We still, however, do
+  // `is` checks directly below to test those optimizations.
+  @pragma('dart2js:noInline')
+  void runtimeIsAndAs<T>(instance) {
+    expect(instance is T, true);
+    expect(() => instance as T, returnsNormally);
+  }
+
+  // Test that base JS type can be used as any subtype.
+  var js = JSClass();
+  expect(js is JSExtendJSClass, true);
+  runtimeIsAndAs<JSExtendJSClass>(js);
+  expect(js is AnonymousExtendJSClass, true);
+  runtimeIsAndAs<AnonymousExtendJSClass>(js);
+
+  // Test that base anonymous type can be use as any subtype.
+  // Conversion from external getter value to a variable is needed to coerce
+  // compile time optimization of type checks. This applies for below as well.
+  var anonVar = anon;
+  expect(anonVar is JSExtendAnonymousClass, true);
+  runtimeIsAndAs<JSExtendAnonymousClass>(anonVar);
+  expect(anonVar is AnonymousExtendAnonymousClass, true);
+  runtimeIsAndAs<AnonymousExtendAnonymousClass>(anonVar);
+
+  // Test that instance of subtypes can be used as their JS supertype.
+  expect(jsExtendJS is JSClass, true);
+  runtimeIsAndAs<JSClass>(jsExtendJS);
+  var anonExtendJSVar = anonExtendJS;
+  expect(anonExtendJSVar is JSClass, true);
+  runtimeIsAndAs<JSClass>(anonExtendJSVar);
+
+  // Test that instance of subtypes can be used as their anonymous supertype.
+  var anonExtendAnonVar = anonExtendAnon;
+  expect(anonExtendAnonVar is AnonymousClass, true);
+  runtimeIsAndAs<AnonymousClass>(anonExtendAnonVar);
+  expect(jsExtendAnon is AnonymousClass, true);
+  runtimeIsAndAs<AnonymousClass>(jsExtendAnon);
+}
+
+JSClass returnJS() => throw '';
+
+AnonymousClass returnAnon() => throw '';
+
+JSExtendJSClass returnJSExtendJS() => throw '';
+
+JSExtendAnonymousClass returnJSExtendAnon() => throw '';
+
+AnonymousExtendJSClass returnAnonExtendJS() => throw '';
+
+AnonymousExtendAnonymousClass returnAnonExtendAnon() => throw '';
+
+@pragma('dart2js:noInline')
+void isRuntimeSubtypeBothWays<T, U>() {
+  // Test T <: U and U <: T. With interop types, type checks should pass
+  // regardless of type hierarchy. Note that dart2js does these type checks at
+  // runtime. Below, we do compile-time checks using top-level functions.
+  T f1() => throw '';
+  U f2() => throw '';
+  expect(f1 is U Function(), true);
+  expect(f2 is T Function(), true);
 }
 
 void testSubtyping() {
   // Test subtyping for inheritance between JS and anonymous classes.
-  expect(useJSClass is void Function(JSExtendJSClass js), true);
-  expect(useAnonymousClass is void Function(AnonymousExtendAnonymousClass a),
-      true);
-  expect(useJSClass is void Function(AnonymousExtendJSClass a), true);
-  expect(useAnonymousClass is void Function(JSExtendAnonymousClass js), true);
+  expect(returnJS is JSExtendJSClass Function(), true);
+  expect(returnJSExtendJS is JSClass Function(), true);
+  isRuntimeSubtypeBothWays<JSClass, JSExtendJSClass>();
 
-  expect(useJSClass is void Function(AnonymousExtendAnonymousClass a), false);
-  expect(useAnonymousClass is void Function(JSExtendJSClass js), false);
-  expect(useJSClass is void Function(JSExtendAnonymousClass js), false);
-  expect(useAnonymousClass is void Function(AnonymousExtendJSClass a), false);
+  expect(returnJS is AnonymousExtendJSClass Function(), true);
+  expect(returnAnonExtendJS is JSClass Function(), true);
+  isRuntimeSubtypeBothWays<JSClass, AnonymousExtendJSClass>();
+
+  expect(returnAnon is JSExtendAnonymousClass Function(), true);
+  expect(returnJSExtendAnon is AnonymousClass Function(), true);
+  isRuntimeSubtypeBothWays<AnonymousClass, JSExtendAnonymousClass>();
+
+  expect(returnAnon is AnonymousExtendAnonymousClass Function(), true);
+  expect(returnAnonExtendAnon is AnonymousClass Function(), true);
+  isRuntimeSubtypeBothWays<AnonymousClass, AnonymousExtendAnonymousClass>();
 }
diff --git a/tests/lib/js/external_nonjs_static_test.dart b/tests/lib/js/external_nonjs_static_test.dart
index 47b6252..87c4615 100644
--- a/tests/lib/js/external_nonjs_static_test.dart
+++ b/tests/lib/js/external_nonjs_static_test.dart
@@ -7,6 +7,7 @@
 
 library external_nonjs_static_test;
 
+import 'dart:html';
 import 'package:js/js.dart';
 
 external var topLevelField;
@@ -98,4 +99,81 @@
   // [web] Only JS interop members may be 'external'.
 }
 
+extension ExtensionNonJS on NonJSClass {
+  external var field;
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external final finalField;
+  //             ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static var staticField;
+  //                  ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static final staticFinalField;
+  //                    ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  external get getter;
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external set setter(_);
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  external static get staticGetter;
+  //                  ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static set staticSetter(_);
+  //                  ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  external method();
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static staticMethod();
+  //              ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external optionalParameterMethod([int? a, int b = 0]);
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external overridenMethod();
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  nonExternalMethod() => 1;
+  static nonExternalStaticMethod() => 2;
+}
+
+class NonJSClass {
+  void overridenMethod() => 5;
+}
+
+extension ExtensionGenericNonJS<T> on GenericNonJSClass<T> {
+  external T method();
+  //         ^
+  // [web] JS interop or Native class required for 'external' extension members.
+}
+
+class GenericNonJSClass<T> {}
+
+extension ExtensionNative on HtmlElement {
+  external var field;
+  external final finalField;
+  external static var staticField;
+  external static final staticFinalField;
+
+  external get getter;
+  external set setter(_);
+
+  external static get staticGetter;
+  external static set staticSetter(_);
+
+  external method();
+  external static staticMethod();
+  external optionalParameterMethod([int? a, int b = 0]);
+
+  nonExternalMethod() => 1;
+  static nonExternalStaticMethod() => 2;
+}
+
 main() {}
diff --git a/tests/lib/js/external_static_test.dart b/tests/lib/js/external_static_test.dart
index 8fac26db..a455de0 100644
--- a/tests/lib/js/external_static_test.dart
+++ b/tests/lib/js/external_static_test.dart
@@ -8,6 +8,7 @@
 @JS()
 library external_static_test;
 
+import 'dart:html';
 import 'package:js/js.dart';
 
 // external top level members ok in @JS() library.
@@ -86,4 +87,167 @@
   // [web] Only JS interop members may be 'external'.
 }
 
+extension ExtensionNonJS on NonJSClass {
+  external var field;
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external final finalField;
+  //             ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static var staticField;
+  //                  ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static final staticFinalField;
+  //                    ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  external get getter;
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external set setter(_);
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  external static get staticGetter;
+  //                  ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static set staticSetter(_);
+  //                  ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  external method();
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static staticMethod();
+  //              ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external optionalParameterMethod([int? a, int b = 0]);
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external overridenMethod();
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  @JS('fieldAnnotation')
+  external var annotatedField;
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  @JS('memberAnnotation')
+  external annotatedMethod();
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  nonExternalMethod() => 1;
+  static nonExternalStaticMethod() => 2;
+}
+
+class NonJSClass {
+  void overridenMethod() => 5;
+}
+
+extension ExtensionGenericNonJS<T> on GenericNonJSClass<T> {
+  external T method();
+  //         ^
+  // [web] JS interop or Native class required for 'external' extension members.
+}
+
+class GenericNonJSClass<T> {}
+
+extension ExtensionJS on JSClass {
+  external var field;
+  external final finalField;
+  external static var staticField;
+  external static final staticFinalField;
+
+  external get getter;
+  external set setter(_);
+
+  external static get staticGetter;
+  external static set staticSetter(_);
+
+  external method();
+  external static staticMethod();
+  external optionalParameterMethod([int? a, int b = 0]);
+
+  @JS('fieldAnnotation')
+  external var annotatedField;
+
+  @JS('memberAnnotation')
+  external annotatedMethod();
+
+  nonExternalMethod() => 1;
+  static nonExternalStaticMethod() => 2;
+}
+
+@JS()
+class JSClass {}
+
+extension ExtensionGenericJS<T> on GenericJSClass<T> {
+  external T method();
+}
+
+@JS()
+class GenericJSClass<T> {}
+
+extension ExtensionAnonymousJS on AnonymousJSClass {
+  external var field;
+  external get getter;
+  external set setter(_);
+  external method();
+}
+
+@JS()
+@anonymous
+class AnonymousJSClass {}
+
+extension ExtensionAbstractJS on AbstractJSClass {
+  external var field;
+  external get getter;
+  external set setter(_);
+  external method();
+}
+
+@JS()
+abstract class AbstractJSClass {}
+
+extension ExtensionAnnotatedJS on AnnotatedJSClass {
+  external var field;
+  external get getter;
+  external set setter(_);
+  external method();
+}
+
+@JS('Annotation')
+class AnnotatedJSClass {}
+
+extension ExtensionPrivateJS on _privateJSClass {
+  external var field;
+  external get getter;
+  external set setter(_);
+  external method();
+}
+
+@JS()
+class _privateJSClass {}
+
+extension ExtensionNative on HtmlElement {
+  external var field;
+  external final finalField;
+  external static var staticField;
+  external static final staticFinalField;
+
+  external get getter;
+  external set setter(_);
+
+  external static get staticGetter;
+  external static set staticSetter(_);
+
+  external method();
+  external static staticMethod();
+  external optionalParameterMethod([int? a, int b = 0]);
+
+  nonExternalMethod() => 1;
+  static nonExternalStaticMethod() => 2;
+}
+
 main() {}
diff --git a/tests/lib/js/is_check_and_as_cast_test.dart b/tests/lib/js/is_check_and_as_cast_test.dart
index b84e625..40216d6 100644
--- a/tests/lib/js/is_check_and_as_cast_test.dart
+++ b/tests/lib/js/is_check_and_as_cast_test.dart
@@ -34,13 +34,6 @@
   external int get a;
 }
 
-@JS()
-class Baz {
-  external Baz(int a, int b);
-  external int get a;
-  external int get b;
-}
-
 // JS object literals
 @JS()
 @anonymous
@@ -60,6 +53,11 @@
 
 class DartClass {}
 
+// Avoid static type optimization by running all tests using this.
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
 void main() {
   eval(r"""
     function Foo(a) {
@@ -68,11 +66,6 @@
     function Bar(a) {
       this.a = a;
     }
-    function Baz(a, b) {
-      Foo.call(this, a);
-      this.b = b;
-    }
-    Baz.prototype.__proto__ = Foo.prototype;
     var a = {
       x: 1,
     };
@@ -84,6 +77,7 @@
   // JS class object can be checked and casted with itself.
   var foo = Foo(42);
   expect(foo is Foo, isTrue);
+  expect(confuse(foo) is Foo, isTrue);
   expect(() => (foo as Foo), returnsNormally);
 
   // Try it with dynamic.
@@ -93,64 +87,73 @@
 
   // Casts are allowed between any JS class objects.
   expect(foo is Bar, isTrue);
+  expect(confuse(foo) is Bar, isTrue);
   expect(d is Bar, isTrue);
   expect(() => (foo as Bar), returnsNormally);
   expect(() => (d as Bar), returnsNormally);
 
-  // Type-checking and casting works regardless of the inheritance chain.
-  var baz = Baz(42, 43);
-  expect(baz is Foo, isTrue);
-  expect(() => (baz as Foo), returnsNormally);
-  expect(foo is Baz, isTrue);
-  expect(() => (foo as Baz), returnsNormally);
-
   // BarCopy is the same JS class as Bar.
   var barCopy = BarCopy(42);
   expect(barCopy is Bar, isTrue);
+  expect(confuse(barCopy) is Bar, isTrue);
   expect(() => (barCopy as Bar), returnsNormally);
 
   // JS object literal can be checked and casted with itself.
   expect(a is LiteralA, isTrue);
+  expect(confuse(a) is LiteralA, isTrue);
   expect(() => (a as LiteralA), returnsNormally);
 
   // Like class objects, casts are allowed between any object literals.
   expect(a is LiteralB, isTrue);
+  expect(confuse(a) is LiteralB, isTrue);
   expect(() => (a as LiteralB), returnsNormally);
 
   // Similarly, casts are allowed between any class objects and object literals.
   expect(foo is LiteralB, isTrue);
+  expect(confuse(foo) is LiteralB, isTrue);
   expect(() => (foo as LiteralB), returnsNormally);
   expect(a is Foo, isTrue);
+  expect(confuse(a) is Foo, isTrue);
   expect(() => (a as Foo), returnsNormally);
 
   // You cannot cast between JS interop objects and Dart objects, however.
   var dartClass = DartClass();
   expect(dartClass is Foo, isFalse);
+  expect(confuse(dartClass) is Foo, isFalse);
   expect(() => (dartClass as Foo), throws);
   expect(dartClass is LiteralA, isFalse);
+  expect(confuse(dartClass) is LiteralA, isFalse);
   expect(() => (dartClass as LiteralA), throws);
 
   expect(foo is DartClass, isFalse);
+  expect(confuse(foo) is DartClass, isFalse);
   expect(() => (foo as DartClass), throws);
   expect(a is DartClass, isFalse);
+  expect(confuse(a) is DartClass, isFalse);
   expect(() => (a as DartClass), throws);
 
   // Test that nullability is still respected with JS types.
   expect(foo is Foo?, isTrue);
+  expect(confuse(foo) is Foo?, isTrue);
   expect(() => (foo as Foo?), returnsNormally);
   Foo? nullableFoo = null;
   expect(nullableFoo is Foo?, isTrue);
+  expect(confuse(nullableFoo) is Foo?, isTrue);
   expect(() => (nullableFoo as Foo?), returnsNormally);
   expect(nullableFoo is Foo, isFalse);
+  expect(confuse(nullableFoo) is Foo, isFalse);
   expect(() => (nullableFoo as Foo),
       hasUnsoundNullSafety ? returnsNormally : throws);
 
   expect(a is LiteralA?, isTrue);
+  expect(confuse(a) is LiteralA?, isTrue);
   expect(() => (a as LiteralA?), returnsNormally);
   LiteralA? nullableA = null;
   expect(nullableA is LiteralA?, isTrue);
+  expect(confuse(nullableA) is LiteralA?, isTrue);
   expect(() => (nullableA as LiteralA?), returnsNormally);
   expect(nullableA is LiteralA, isFalse);
+  expect(confuse(nullableA) is LiteralA, isFalse);
   expect(() => (nullableA as LiteralA),
       hasUnsoundNullSafety ? returnsNormally : throws);
 }
diff --git a/tests/lib/js/parameters_static_test.dart b/tests/lib/js/parameters_static_test.dart
index 7fa7ddc..b6c68fe 100644
--- a/tests/lib/js/parameters_static_test.dart
+++ b/tests/lib/js/parameters_static_test.dart
@@ -58,4 +58,13 @@
   // [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
 }
 
+extension ExtensionFoo on Foo {
+  external int singleNamedArg({int? a});
+  //                                ^
+  // [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
+  external int mixedNamedArgs(int a, {int? b});
+  //                                       ^
+  // [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
+}
+
 main() {}
diff --git a/tests/lib/js/subtyping_test.dart b/tests/lib/js/subtyping_test.dart
deleted file mode 100644
index 2551fcd..0000000
--- a/tests/lib/js/subtyping_test.dart
+++ /dev/null
@@ -1,88 +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 file.
-
-// Tests subtyping relationships between JS and anonymous classes.
-
-@JS()
-library subtyping_test;
-
-import 'package:js/js.dart';
-import 'package:expect/expect.dart' show hasUnsoundNullSafety;
-import 'package:expect/minitest.dart';
-
-@JS()
-class JSClassA {}
-
-@JS()
-class JSClassB {}
-
-@JS()
-@anonymous
-class AnonymousClassA {}
-
-@JS()
-@anonymous
-class AnonymousClassB {}
-
-class DartClass {}
-
-void useJSClassA(JSClassA _) {}
-void useAnonymousClassA(AnonymousClassA _) {}
-void useDartClass(DartClass _) {}
-
-void useNullableJSClassA(JSClassA? _) {}
-void useNullableAnonymousClassA(AnonymousClassA? _) {}
-
-// Avoid static type optimization by running all tests using this.
-@pragma('dart2js:noInline')
-@pragma('dart2js:assumeDynamic')
-confuse(x) => x;
-
-void main() {
-  // Checks subtyping with the same type and nullability subtyping.
-  expect(useJSClassA is void Function(JSClassA), true);
-  expect(useAnonymousClassA is void Function(AnonymousClassA), true);
-  expect(useJSClassA is void Function(JSClassA?), hasUnsoundNullSafety);
-  expect(useAnonymousClassA is void Function(AnonymousClassA?),
-      hasUnsoundNullSafety);
-  expect(useNullableJSClassA is void Function(JSClassA?), true);
-  expect(useNullableAnonymousClassA is void Function(AnonymousClassA?), true);
-  expect(useNullableJSClassA is void Function(JSClassA), true);
-  expect(useNullableAnonymousClassA is void Function(AnonymousClassA), true);
-
-  expect(confuse(useJSClassA) is void Function(JSClassA), true);
-  expect(confuse(useAnonymousClassA) is void Function(AnonymousClassA), true);
-  expect(
-      confuse(useJSClassA) is void Function(JSClassA?), hasUnsoundNullSafety);
-  expect(confuse(useAnonymousClassA) is void Function(AnonymousClassA?),
-      hasUnsoundNullSafety);
-  expect(confuse(useNullableJSClassA) is void Function(JSClassA?), true);
-  expect(confuse(useNullableAnonymousClassA) is void Function(AnonymousClassA?),
-      true);
-  expect(confuse(useNullableJSClassA) is void Function(JSClassA), true);
-  expect(confuse(useNullableAnonymousClassA) is void Function(AnonymousClassA),
-      true);
-
-  // No subtyping between JS and anonymous classes.
-  expect(useJSClassA is void Function(AnonymousClassA), false);
-  expect(useAnonymousClassA is void Function(JSClassA), false);
-
-  expect(confuse(useJSClassA) is void Function(AnonymousClassA), false);
-  expect(confuse(useAnonymousClassA) is void Function(JSClassA), false);
-
-  // No subtyping between separate classes even if they're both JS classes or
-  // anonymous classes.
-  expect(useJSClassA is void Function(JSClassB), false);
-  expect(useAnonymousClassA is void Function(AnonymousClassB), false);
-
-  expect(confuse(useJSClassA) is void Function(JSClassB), false);
-  expect(confuse(useAnonymousClassA) is void Function(AnonymousClassB), false);
-
-  // No subtyping between JS/anonymous classes and Dart classes.
-  expect(useJSClassA is void Function(DartClass), false);
-  expect(useAnonymousClassA is void Function(DartClass), false);
-
-  expect(confuse(useJSClassA) is void Function(DartClass), false);
-  expect(confuse(useAnonymousClassA) is void Function(DartClass), false);
-}
diff --git a/tests/lib/js/subtyping_test/subtyping_live_test.dart b/tests/lib/js/subtyping_test/subtyping_live_test.dart
new file mode 100644
index 0000000..d137ba6
--- /dev/null
+++ b/tests/lib/js/subtyping_test/subtyping_live_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Tests subtyping relationships after making package:js types live.
+
+@JS()
+library subtyping_live_test;
+
+import 'package:js/js.dart';
+import 'subtyping_test_util.dart';
+
+@JS()
+external dynamic get externalGetter;
+
+void main() {
+  // Call to foreign function should trigger dart2js to assume types are live.
+  externalGetter;
+  testSubtyping();
+}
diff --git a/tests/lib/js/subtyping_test/subtyping_not_live_test.dart b/tests/lib/js/subtyping_test/subtyping_not_live_test.dart
new file mode 100644
index 0000000..5344280
--- /dev/null
+++ b/tests/lib/js/subtyping_test/subtyping_not_live_test.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.
+
+// Tests subtyping relationships without making package:js types live.
+
+import 'package:js/js.dart';
+import 'subtyping_test_util.dart';
+
+void main() {
+  testSubtyping();
+}
diff --git a/tests/lib/js/subtyping_test/subtyping_test_util.dart b/tests/lib/js/subtyping_test/subtyping_test_util.dart
new file mode 100644
index 0000000..c8f7740
--- /dev/null
+++ b/tests/lib/js/subtyping_test/subtyping_test_util.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.
+
+// Tests subtyping relationships between JS and anonymous classes.
+
+@JS()
+library subtyping_test_util;
+
+import 'package:js/js.dart';
+import 'package:expect/expect.dart' show hasUnsoundNullSafety;
+import 'package:expect/minitest.dart';
+
+@JS()
+class JSClassA {}
+
+@JS()
+class JSClassB {}
+
+@JS()
+@anonymous
+class AnonymousClassA {}
+
+@JS()
+@anonymous
+class AnonymousClassB {}
+
+class DartClass {}
+
+JSClassA returnJS() => throw '';
+JSClassA? returnNullableJS() => throw '';
+
+AnonymousClassA returnAnon() => throw '';
+AnonymousClassA? returnNullableAnon() => throw '';
+
+DartClass returnDartClass() => throw '';
+
+// Avoid static type optimization by running all tests using this.
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+void testSubtyping() {
+  // Checks subtyping with the same type and nullability subtyping.
+  expect(returnJS is JSClassA Function(), true);
+  expect(returnAnon is AnonymousClassA Function(), true);
+  expect(returnJS is JSClassA? Function(), true);
+  expect(returnAnon is AnonymousClassA? Function(), true);
+  expect(returnNullableJS is JSClassA? Function(), true);
+  expect(returnNullableAnon is AnonymousClassA? Function(), true);
+  expect(returnNullableJS is JSClassA Function(), hasUnsoundNullSafety);
+  expect(
+      returnNullableAnon is AnonymousClassA Function(), hasUnsoundNullSafety);
+
+  // Subtyping between JS and anonymous classes.
+  expect(returnJS is AnonymousClassA Function(), true);
+  expect(returnAnon is JSClassA Function(), true);
+
+  // Subtyping between same type of package:js classes.
+  expect(returnJS is JSClassB Function(), true);
+  expect(returnAnon is AnonymousClassB Function(), true);
+
+  // No subtyping between JS/anonymous classes and Dart classes.
+  expect(returnJS is DartClass Function(), false);
+  expect(returnDartClass is JSClassA Function(), false);
+  expect(returnAnon is DartClass Function(), false);
+  expect(returnDartClass is AnonymousClassA Function(), false);
+
+  // Repeat the checks but using `confuse` to coerce runtime checks instead of
+  // compile-time like above.
+  expect(confuse(returnJS) is JSClassA Function(), true);
+  expect(confuse(returnAnon) is AnonymousClassA Function(), true);
+  expect(confuse(returnJS) is JSClassA? Function(), true);
+  expect(confuse(returnAnon) is AnonymousClassA? Function(), true);
+  expect(confuse(returnNullableJS) is JSClassA? Function(), true);
+  expect(confuse(returnNullableAnon) is AnonymousClassA? Function(), true);
+  expect(
+      confuse(returnNullableJS) is JSClassA Function(), hasUnsoundNullSafety);
+  expect(confuse(returnNullableAnon) is AnonymousClassA Function(),
+      hasUnsoundNullSafety);
+
+  expect(confuse(returnJS) is AnonymousClassA Function(), true);
+  expect(confuse(returnAnon) is JSClassA Function(), true);
+
+  expect(confuse(returnJS) is JSClassB Function(), true);
+  expect(confuse(returnAnon) is AnonymousClassB Function(), true);
+
+  expect(confuse(returnJS) is DartClass Function(), false);
+  expect(confuse(returnDartClass) is JSClassA Function(), false);
+  expect(confuse(returnAnon) is DartClass Function(), false);
+  expect(confuse(returnDartClass) is AnonymousClassA Function(), false);
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index b931e84..9e573fb 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -36,8 +36,12 @@
 [ $csp ]
 html/js_interop_constructor_name/*: SkipByDesign # Issue 42085.
 isolate/deferred_in_isolate2_test: Skip # Issue 16898. Deferred loading does not work from an isolate in CSP-mode
+js/extends_test/extends_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/extends_test/extends_with_es6_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/is_check_and_as_cast_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/async_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/javascriptobject_extensions_test.dart: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/jsify_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/promise_reject_null_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/properties_implicit_checks_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
@@ -72,9 +76,6 @@
 async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
 async/stream_timeout_test: SkipSlow # Times out. Issue 22050
 
-[ $runtime == dart_precompiled || $runtime == vm ]
-isolate/isolate_stress_test: Skip # Issue 12588: Uses dart:html. This should be able to pass when we have wrapper-less tests.
-
 # It makes no sense to run any test that uses spawnURI under the simulator
 # as that would involve running CFE (the front end) in simulator mode
 # to compile the URI file specified in spawnURI code.
diff --git a/tests/lib/lib_vm.status b/tests/lib/lib_vm.status
index 2489080..07ece5a 100644
--- a/tests/lib/lib_vm.status
+++ b/tests/lib/lib_vm.status
@@ -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.
 
-[ $runtime == vm ]
-isolate/*: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-
 [ $runtime != vm ]
 isolate/native_wrapper_message_test: Skip # A VM specific test.
 
@@ -88,90 +85,4 @@
 convert/utf85_test: SkipSlow
 
 [ $hot_reload || $hot_reload_rollback ]
-isolate/bool_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/capability_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/compile_time_error_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/count_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/cross_isolate_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/enum_const_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_exit_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_exit_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/exit_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/exit_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/function_send1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/function_send_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error3_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/illegal_msg_function_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/illegal_msg_mirror_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/int32_length_overflow_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/int_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_complex_messages_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_current_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_import_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_22778_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_35626_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_6610_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_self_synchronously_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_self_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/large_byte_data_leak_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/large_byte_data_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/mandel_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message3_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message4_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_const_type_arguments_1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_const_type_arguments_2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_enum_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/mint_maker_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/native_wrapper_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/nested_spawn2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/nested_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/non_fatal_exception_in_timer_callback_test/none: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/non_fatal_exception_in_timer_callback_test/sleep: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/object_leak_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/ondone_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_config_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_resolve_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_root_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/pause_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/ping_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/port_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/raw_port_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/regress_34752_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/regress_flutter_22796_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/request_reply_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/resolve_package_uri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/scenarios/package_data_uri_spec/package_resolve_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/send_private_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/simple_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_function_custom_class_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_function_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_generic_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri__package_uri__test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_exported_main_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_fail_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_missing_from_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_missing_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_multi_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_nested_vm_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_vm_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/start_paused_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/string_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/timer_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/timer_multiple_isolates_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/transferable_failed_to_send_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/transferable_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/typed_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/unresolved_ports_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/vm_rehash_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
+isolate/int32_length_overflow_test: SkipSlow # Iterates over Uint8List(1 << 30).
diff --git a/tests/lib_2/html/js_typed_interop_lazy_test.dart b/tests/lib_2/html/js_typed_interop_lazy_test.dart
index a7b49a9..918193d 100644
--- a/tests/lib_2/html/js_typed_interop_lazy_test.dart
+++ b/tests/lib_2/html/js_typed_interop_lazy_test.dart
@@ -144,10 +144,9 @@
       expect(new Object() is! AnonClass2, isTrue);
 
       expect(<AnonClass>[] is List<AnonClass>, isTrue);
-      // TODO(jacobr): why doesn't this test pass?
-      // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+      expect(<AnonClass>[] is List<AnonClass2>, isTrue);
       expect(<int>[] is! List<AnonClass>, isTrue);
-      expect(<AnonClass>[] is! List<LazyClass>, isTrue); //# 01: ok
+      expect(<AnonClass>[] is List<LazyClass>, isTrue);
       expect(<int>[] is! List<LazyClass>, isTrue);
       expect(<LazyClass>[] is List<LazyClass>, isTrue);
 
@@ -236,10 +235,9 @@
       expect(new Object() is! AnonClass2, isTrue);
 
       expect(<AnonClass>[] is List<AnonClass>, isTrue);
-      // TODO(jacobr): why doesn't this test pass?
-      // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+      expect(<AnonClass>[] is List<AnonClass2>, isTrue);
       expect(<int>[] is! List<AnonClass>, isTrue);
-      expect(<AnonClass>[] is! List<NestedLazyClass>, isTrue); //# 01: ok
+      expect(<AnonClass>[] is List<NestedLazyClass>, isTrue);
       expect(<int>[] is! List<NestedLazyClass>, isTrue);
       expect(<NestedLazyClass>[] is List<NestedLazyClass>, isTrue);
 
diff --git a/tests/lib_2/isolate/bool_from_environment_default_value_test.dart b/tests/lib_2/isolate/bool_from_environment_default_value_test.dart
index 30ea663..fe0bd39 100644
--- a/tests/lib_2/isolate/bool_from_environment_default_value_test.dart
+++ b/tests/lib_2/isolate/bool_from_environment_default_value_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/capability_test.dart b/tests/lib_2/isolate/capability_test.dart
index 04c39ee..5f4ef37 100644
--- a/tests/lib_2/isolate/capability_test.dart
+++ b/tests/lib_2/isolate/capability_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/compile_time_error_test.dart b/tests/lib_2/isolate/compile_time_error_test.dart
index efadcd1..da85090 100644
--- a/tests/lib_2/isolate/compile_time_error_test.dart
+++ b/tests/lib_2/isolate/compile_time_error_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing that errors thrown from isolates are
diff --git a/tests/lib_2/isolate/count_test.dart b/tests/lib_2/isolate/count_test.dart
index 0d92759..e351ef9 100644
--- a/tests/lib_2/isolate/count_test.dart
+++ b/tests/lib_2/isolate/count_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 library CountTest;
diff --git a/tests/lib_2/isolate/cross_isolate_message_test.dart b/tests/lib_2/isolate/cross_isolate_message_test.dart
index f24a36e..59b9ed6 100644
--- a/tests/lib_2/isolate/cross_isolate_message_test.dart
+++ b/tests/lib_2/isolate/cross_isolate_message_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing that isolates can communicate to isolates
diff --git a/tests/lib_2/isolate/deferred_in_isolate2_test.dart b/tests/lib_2/isolate/deferred_in_isolate2_test.dart
index 4a4405b..0db87c3 100644
--- a/tests/lib_2/isolate/deferred_in_isolate2_test.dart
+++ b/tests/lib_2/isolate/deferred_in_isolate2_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library deferred_in_isolate2_test;
diff --git a/tests/lib_2/isolate/deferred_in_isolate_test.dart b/tests/lib_2/isolate/deferred_in_isolate_test.dart
index d37817d..25d9fcf4 100644
--- a/tests/lib_2/isolate/deferred_in_isolate_test.dart
+++ b/tests/lib_2/isolate/deferred_in_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test that deferred libraries are supported from isolates other than the root
diff --git a/tests/lib_2/isolate/enum_const_test.dart b/tests/lib_2/isolate/enum_const_test.dart
index 5ce5c9b..b93202d 100644
--- a/tests/lib_2/isolate/enum_const_test.dart
+++ b/tests/lib_2/isolate/enum_const_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/error_at_spawn_test.dart b/tests/lib_2/isolate/error_at_spawn_test.dart
index 9af087d..7eab826 100644
--- a/tests/lib_2/isolate/error_at_spawn_test.dart
+++ b/tests/lib_2/isolate/error_at_spawn_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library error_at_spawn;
diff --git a/tests/lib_2/isolate/error_at_spawnuri_test.dart b/tests/lib_2/isolate/error_at_spawnuri_test.dart
index 66de296..8d7254d 100644
--- a/tests/lib_2/isolate/error_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/error_at_spawnuri_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library error_at_spawnuri;
diff --git a/tests/lib_2/isolate/error_exit_at_spawn_test.dart b/tests/lib_2/isolate/error_exit_at_spawn_test.dart
index 1c493ef..17f5cd6 100644
--- a/tests/lib_2/isolate/error_exit_at_spawn_test.dart
+++ b/tests/lib_2/isolate/error_exit_at_spawn_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library error_exit_at_spawn;
diff --git a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
index 29330ec..8b43578 100644
--- a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library error_exit_at_spawnuri;
diff --git a/tests/lib_2/isolate/exit_at_spawn_test.dart b/tests/lib_2/isolate/exit_at_spawn_test.dart
index d737c29..ca8cfa5 100644
--- a/tests/lib_2/isolate/exit_at_spawn_test.dart
+++ b/tests/lib_2/isolate/exit_at_spawn_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library exit_at_spawn;
diff --git a/tests/lib_2/isolate/exit_at_spawnuri_test.dart b/tests/lib_2/isolate/exit_at_spawnuri_test.dart
index 3813adf..f6f4919 100644
--- a/tests/lib_2/isolate/exit_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/exit_at_spawnuri_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library exit_at_spawn;
diff --git a/tests/lib_2/isolate/function_send1_test.dart b/tests/lib_2/isolate/function_send1_test.dart
index a706600..2acd91b 100644
--- a/tests/lib_2/isolate/function_send1_test.dart
+++ b/tests/lib_2/isolate/function_send1_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/function_send_test.dart b/tests/lib_2/isolate/function_send_test.dart
index 8d24312..e5e72cf 100644
--- a/tests/lib_2/isolate/function_send_test.dart
+++ b/tests/lib_2/isolate/function_send_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/handle_error2_test.dart b/tests/lib_2/isolate/handle_error2_test.dart
index dd3b113..0a09262 100644
--- a/tests/lib_2/isolate/handle_error2_test.dart
+++ b/tests/lib_2/isolate/handle_error2_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library handle_error_test;
diff --git a/tests/lib_2/isolate/handle_error3_test.dart b/tests/lib_2/isolate/handle_error3_test.dart
index 0f86863..4d4db96 100644
--- a/tests/lib_2/isolate/handle_error3_test.dart
+++ b/tests/lib_2/isolate/handle_error3_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library handle_error_test;
diff --git a/tests/lib_2/isolate/handle_error_test.dart b/tests/lib_2/isolate/handle_error_test.dart
index 6c414db..cbc707f 100644
--- a/tests/lib_2/isolate/handle_error_test.dart
+++ b/tests/lib_2/isolate/handle_error_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library handle_error_test;
diff --git a/tests/lib_2/isolate/illegal_msg_function_test.dart b/tests/lib_2/isolate/illegal_msg_function_test.dart
index f61432c..5ea24f0 100644
--- a/tests/lib_2/isolate/illegal_msg_function_test.dart
+++ b/tests/lib_2/isolate/illegal_msg_function_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library illegal_msg_function_test;
diff --git a/tests/lib_2/isolate/illegal_msg_mirror_test.dart b/tests/lib_2/isolate/illegal_msg_mirror_test.dart
index c2fab94..ada58e9 100644
--- a/tests/lib_2/isolate/illegal_msg_mirror_test.dart
+++ b/tests/lib_2/isolate/illegal_msg_mirror_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library illegal_msg_mirror_test;
diff --git a/tests/lib_2/isolate/int32_length_overflow_test.dart b/tests/lib_2/isolate/int32_length_overflow_test.dart
index 5d0273c..9d97252 100644
--- a/tests/lib_2/isolate/int32_length_overflow_test.dart
+++ b/tests/lib_2/isolate/int32_length_overflow_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/lib_2/isolate/int_from_environment_default_value_test.dart b/tests/lib_2/isolate/int_from_environment_default_value_test.dart
index 4733aaf..fdf1c67 100644
--- a/tests/lib_2/isolate/int_from_environment_default_value_test.dart
+++ b/tests/lib_2/isolate/int_from_environment_default_value_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/isolate_complex_messages_test.dart b/tests/lib_2/isolate/isolate_complex_messages_test.dart
index 30322a1..6599829 100644
--- a/tests/lib_2/isolate/isolate_complex_messages_test.dart
+++ b/tests/lib_2/isolate/isolate_complex_messages_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing isolate communication with
diff --git a/tests/lib_2/isolate/isolate_current_test.dart b/tests/lib_2/isolate/isolate_current_test.dart
index 3850591..c5d1432 100644
--- a/tests/lib_2/isolate/isolate_current_test.dart
+++ b/tests/lib_2/isolate/isolate_current_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 library isolate_current_test;
diff --git a/tests/lib_2/isolate/isolate_import_test.dart b/tests/lib_2/isolate/isolate_import_test.dart
index ff80fcb..02f5276 100644
--- a/tests/lib_2/isolate/isolate_import_test.dart
+++ b/tests/lib_2/isolate/isolate_import_test.dart
@@ -4,15 +4,15 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library IsolateImportNegativeTest;
 
 // Omitting the following import is an error:
-/* // //# 01: runtime error, compile-time error
+/* //# 01: compile-time error
 import 'dart:isolate';
-*/ // //# 01: continued
+*/ //# 01: continued
 import 'package:async_helper/async_helper.dart';
 
 void entry(msg) {}
diff --git a/tests/lib_2/isolate/isolate_stress_test.dart b/tests/lib_2/isolate/isolate_stress_test.dart
deleted file mode 100644
index 81eb41b..0000000
--- a/tests/lib_2/isolate/isolate_stress_test.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart = 2.9
-
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
-// VMOptions=--no-enable-isolate-groups
-
-// This test creates a lot of isolates.  This is meant to exhaust
-// resources if the isolates aren't closed correctly (which happened
-// in dart2js).
-
-import 'dart:async';
-import 'dart:isolate';
-
-// TODO(12588): Remove this import when we have wrapper-less testing.
-import 'dart:html';
-
-worker(SendPort replyTo) {
-  replyTo.send('Hello from Worker');
-}
-
-main() {
-  try {
-    // Create a Worker to confuse broken isolate implementation in dart2js.
-    new Worker('data:application/javascript,').terminate();
-  } catch (e) {
-    // Ignored.
-  }
-  var doneClosure;
-  int isolateCount = 0;
-  spawnMany(reply) {
-    if (reply != 'Hello from Worker') {
-      throw new Exception('Unexpected reply from worker: $reply');
-    }
-    if (++isolateCount > 200) {
-      window.postMessage('unittest-suite-success', '*');
-      return;
-    }
-    ReceivePort response = new ReceivePort();
-    var remote = Isolate.spawn(worker, response.sendPort);
-    remote.then((_) => response.first).then(spawnMany);
-    print('isolateCount = $isolateCount');
-  }
-
-  spawnMany('Hello from Worker');
-  window.postMessage('unittest-suite-wait-for-done', '*');
-}
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
index 4207c21..314d563 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
index b072fa3..a22fcb5 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
index 9459d31..86f28b4 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/tests/lib_2/isolate/issue_22778_test.dart b/tests/lib_2/isolate/issue_22778_test.dart
index 05df46b..6675134 100644
--- a/tests/lib_2/isolate/issue_22778_test.dart
+++ b/tests/lib_2/isolate/issue_22778_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
index a991a25..7def95e 100644
--- a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
+++ b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:collection';
diff --git a/tests/lib_2/isolate/issue_35626_test.dart b/tests/lib_2/isolate/issue_35626_test.dart
index 9e9dbfe..83c371c 100644
--- a/tests/lib_2/isolate/issue_35626_test.dart
+++ b/tests/lib_2/isolate/issue_35626_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 // Tests that sets of enums can be set through ports.
diff --git a/tests/lib_2/isolate/kill2_test.dart b/tests/lib_2/isolate/kill2_test.dart
index 9918c9f..e363a3d 100644
--- a/tests/lib_2/isolate/kill2_test.dart
+++ b/tests/lib_2/isolate/kill2_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/kill_infinite_loop_in_initializer_test.dart b/tests/lib_2/isolate/kill_infinite_loop_in_initializer_test.dart
new file mode 100644
index 0000000..591b187
--- /dev/null
+++ b/tests/lib_2/isolate/kill_infinite_loop_in_initializer_test.dart
@@ -0,0 +1,46 @@
+// 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
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+
+// Regression test against out-of-band messages being blocked during lazy
+// static field initialization.
+
+import "dart:isolate";
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+dynamic staticFieldWithBadInitializer = badInitializer();
+
+badInitializer() {
+  print("badInitializer");
+  for (;;) {}
+  return 42; // Unreachable.
+}
+
+child(message) {
+  print("child");
+  RawReceivePort port = new RawReceivePort();
+  print(staticFieldWithBadInitializer);
+  port.close(); // Unreachable.
+}
+
+void main() {
+  asyncStart();
+  Isolate.spawn(child, null).then((Isolate isolate) {
+    print("spawned");
+    RawReceivePort exitSignal;
+    exitSignal = new RawReceivePort((_) {
+      print("onExit");
+      exitSignal.close();
+      asyncEnd();
+    });
+    isolate.addOnExitListener(exitSignal.sendPort);
+    isolate.kill(priority: Isolate.immediate);
+  });
+}
diff --git a/tests/lib_2/isolate/kill_self_synchronously_test.dart b/tests/lib_2/isolate/kill_self_synchronously_test.dart
index 3ddb461..74edac1 100644
--- a/tests/lib_2/isolate/kill_self_synchronously_test.dart
+++ b/tests/lib_2/isolate/kill_self_synchronously_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/kill_self_test.dart b/tests/lib_2/isolate/kill_self_test.dart
index e78cb5e..0ea47b5 100644
--- a/tests/lib_2/isolate/kill_self_test.dart
+++ b/tests/lib_2/isolate/kill_self_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/kill_test.dart b/tests/lib_2/isolate/kill_test.dart
index 0e695cf..dd53477 100644
--- a/tests/lib_2/isolate/kill_test.dart
+++ b/tests/lib_2/isolate/kill_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/large_byte_data_leak_test.dart b/tests/lib_2/isolate/large_byte_data_leak_test.dart
index 7db4ff5..76fafd5 100644
--- a/tests/lib_2/isolate/large_byte_data_leak_test.dart
+++ b/tests/lib_2/isolate/large_byte_data_leak_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/lib_2/isolate/large_byte_data_test.dart b/tests/lib_2/isolate/large_byte_data_test.dart
index 16811fa..ff55e0a 100644
--- a/tests/lib_2/isolate/large_byte_data_test.dart
+++ b/tests/lib_2/isolate/large_byte_data_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/lib_2/isolate/mandel_isolate_test.dart b/tests/lib_2/isolate/mandel_isolate_test.dart
index c7da8a9..1d75cb2 100644
--- a/tests/lib_2/isolate/mandel_isolate_test.dart
+++ b/tests/lib_2/isolate/mandel_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library MandelIsolateTest;
diff --git a/tests/lib_2/isolate/message2_test.dart b/tests/lib_2/isolate/message2_test.dart
index ccb33b33..81892d4 100644
--- a/tests/lib_2/isolate/message2_test.dart
+++ b/tests/lib_2/isolate/message2_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing serialization of messages.
diff --git a/tests/lib_2/isolate/message3_test.dart b/tests/lib_2/isolate/message3_test.dart
index b9813bd..f5c436d 100644
--- a/tests/lib_2/isolate/message3_test.dart
+++ b/tests/lib_2/isolate/message3_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing serialization of messages.
diff --git a/tests/lib_2/isolate/message4_test.dart b/tests/lib_2/isolate/message4_test.dart
index 2d53736..045cde1 100644
--- a/tests/lib_2/isolate/message4_test.dart
+++ b/tests/lib_2/isolate/message4_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing serialization of messages with static
diff --git a/tests/lib_2/isolate/message_const_type_arguments_1_test.dart b/tests/lib_2/isolate/message_const_type_arguments_1_test.dart
index f4ffd0e..8e3144e 100644
--- a/tests/lib_2/isolate/message_const_type_arguments_1_test.dart
+++ b/tests/lib_2/isolate/message_const_type_arguments_1_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // https://github.com/dart-lang/sdk/issues/35778
diff --git a/tests/lib_2/isolate/message_const_type_arguments_2_test.dart b/tests/lib_2/isolate/message_const_type_arguments_2_test.dart
index 46d76d4..87c76ab 100644
--- a/tests/lib_2/isolate/message_const_type_arguments_2_test.dart
+++ b/tests/lib_2/isolate/message_const_type_arguments_2_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // https://github.com/dart-lang/sdk/issues/35778
diff --git a/tests/lib_2/isolate/message_enum_test.dart b/tests/lib_2/isolate/message_enum_test.dart
index e0fef28..5487f73 100644
--- a/tests/lib_2/isolate/message_enum_test.dart
+++ b/tests/lib_2/isolate/message_enum_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'package:expect/expect.dart';
diff --git a/tests/lib_2/isolate/message_test.dart b/tests/lib_2/isolate/message_test.dart
index b2cdf5a..7ca930a 100644
--- a/tests/lib_2/isolate/message_test.dart
+++ b/tests/lib_2/isolate/message_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing serialization of messages.
diff --git a/tests/lib_2/isolate/mint_maker_test.dart b/tests/lib_2/isolate/mint_maker_test.dart
index 7fd3650..9b1b15c 100644
--- a/tests/lib_2/isolate/mint_maker_test.dart
+++ b/tests/lib_2/isolate/mint_maker_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library MintMakerTest;
diff --git a/tests/lib_2/isolate/native_wrapper_message_test.dart b/tests/lib_2/isolate/native_wrapper_message_test.dart
index 814a581..4c91d647 100644
--- a/tests/lib_2/isolate/native_wrapper_message_test.dart
+++ b/tests/lib_2/isolate/native_wrapper_message_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:isolate';
diff --git a/tests/lib_2/isolate/nested_spawn2_test.dart b/tests/lib_2/isolate/nested_spawn2_test.dart
index 6a955ba..5c0c8be 100644
--- a/tests/lib_2/isolate/nested_spawn2_test.dart
+++ b/tests/lib_2/isolate/nested_spawn2_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing that isolates can spawn other isolates and
diff --git a/tests/lib_2/isolate/nested_spawn_test.dart b/tests/lib_2/isolate/nested_spawn_test.dart
index 095f790..050f383 100644
--- a/tests/lib_2/isolate/nested_spawn_test.dart
+++ b/tests/lib_2/isolate/nested_spawn_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing that isolates can spawn other isolates.
diff --git a/tests/lib_2/isolate/non_fatal_exception_in_timer_callback_test.dart b/tests/lib_2/isolate/non_fatal_exception_in_timer_callback_test.dart
index 352827f..03db0b8 100644
--- a/tests/lib_2/isolate/non_fatal_exception_in_timer_callback_test.dart
+++ b/tests/lib_2/isolate/non_fatal_exception_in_timer_callback_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:async';
diff --git a/tests/lib_2/isolate/object_leak_test.dart b/tests/lib_2/isolate/object_leak_test.dart
index aee8af3..719b8d8 100644
--- a/tests/lib_2/isolate/object_leak_test.dart
+++ b/tests/lib_2/isolate/object_leak_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Regression test for http://dartbug.com/18942
diff --git a/tests/lib_2/isolate/ondone_test.dart b/tests/lib_2/isolate/ondone_test.dart
index 2ca9592..bc5d363 100644
--- a/tests/lib_2/isolate/ondone_test.dart
+++ b/tests/lib_2/isolate/ondone_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/package_config_test.dart b/tests/lib_2/isolate/package_config_test.dart
index 25b7b48..264aba2 100644
--- a/tests/lib_2/isolate/package_config_test.dart
+++ b/tests/lib_2/isolate/package_config_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 // VMOptions=--trace_shutdown
 import 'dart:io';
diff --git a/tests/lib_2/isolate/package_resolve_test.dart b/tests/lib_2/isolate/package_resolve_test.dart
index efb4fd6..c36c430 100644
--- a/tests/lib_2/isolate/package_resolve_test.dart
+++ b/tests/lib_2/isolate/package_resolve_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:io';
diff --git a/tests/lib_2/isolate/package_root_test.dart b/tests/lib_2/isolate/package_root_test.dart
index e29f99b..a8ef249 100644
--- a/tests/lib_2/isolate/package_root_test.dart
+++ b/tests/lib_2/isolate/package_root_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:io';
diff --git a/tests/lib_2/isolate/pause_test.dart b/tests/lib_2/isolate/pause_test.dart
index 20a588b..240229e 100644
--- a/tests/lib_2/isolate/pause_test.dart
+++ b/tests/lib_2/isolate/pause_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/ping_pause_test.dart b/tests/lib_2/isolate/ping_pause_test.dart
index b96b0b1..2c14c4f 100644
--- a/tests/lib_2/isolate/ping_pause_test.dart
+++ b/tests/lib_2/isolate/ping_pause_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/ping_test.dart b/tests/lib_2/isolate/ping_test.dart
index 79cad0e..8f191b5 100644
--- a/tests/lib_2/isolate/ping_test.dart
+++ b/tests/lib_2/isolate/ping_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/port_test.dart b/tests/lib_2/isolate/port_test.dart
index 1493048..b46a048 100644
--- a/tests/lib_2/isolate/port_test.dart
+++ b/tests/lib_2/isolate/port_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test properties of ports.
diff --git a/tests/lib_2/isolate/raw_port_test.dart b/tests/lib_2/isolate/raw_port_test.dart
index cd9c7c2..08c1cc9 100644
--- a/tests/lib_2/isolate/raw_port_test.dart
+++ b/tests/lib_2/isolate/raw_port_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test RawReceivePort.
diff --git a/tests/lib_2/isolate/regress_34752_test.dart b/tests/lib_2/isolate/regress_34752_test.dart
index 7390247..8fe3c74 100644
--- a/tests/lib_2/isolate/regress_34752_test.dart
+++ b/tests/lib_2/isolate/regress_34752_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 // Verifies that large BigInt can be passed through a message port and
diff --git a/tests/lib_2/isolate/regress_flutter_22796_test.dart b/tests/lib_2/isolate/regress_flutter_22796_test.dart
index 1fe759b..72200b8 100644
--- a/tests/lib_2/isolate/regress_flutter_22796_test.dart
+++ b/tests/lib_2/isolate/regress_flutter_22796_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Verifies that large typed data can be passed in a field through message port.
diff --git a/tests/lib_2/isolate/request_reply_test.dart b/tests/lib_2/isolate/request_reply_test.dart
index 3802b40..a2a0f53 100644
--- a/tests/lib_2/isolate/request_reply_test.dart
+++ b/tests/lib_2/isolate/request_reply_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library RequestReplyTest;
diff --git a/tests/lib_2/isolate/resolve_package_uri_test.dart b/tests/lib_2/isolate/resolve_package_uri_test.dart
index 2cab226..ce53991 100644
--- a/tests/lib_2/isolate/resolve_package_uri_test.dart
+++ b/tests/lib_2/isolate/resolve_package_uri_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Regression test for faulty encoding of `Isolate.resolvePackageUri` by
diff --git a/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart b/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
index efb4fd6..c36c430 100644
--- a/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
+++ b/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:io';
diff --git a/tests/lib_2/isolate/send_private_test.dart b/tests/lib_2/isolate/send_private_test.dart
index f8481ec..645c12b 100644
--- a/tests/lib_2/isolate/send_private_test.dart
+++ b/tests/lib_2/isolate/send_private_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/simple_message_test.dart b/tests/lib_2/isolate/simple_message_test.dart
index bb549cb..f5a394c 100644
--- a/tests/lib_2/isolate/simple_message_test.dart
+++ b/tests/lib_2/isolate/simple_message_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Dart test program for testing that isolates are spawned.
diff --git a/tests/lib_2/isolate/spawn_function_custom_class_test.dart b/tests/lib_2/isolate/spawn_function_custom_class_test.dart
index 45151be..0e9ad2b 100644
--- a/tests/lib_2/isolate/spawn_function_custom_class_test.dart
+++ b/tests/lib_2/isolate/spawn_function_custom_class_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Create a user-defined class in a new isolate.
diff --git a/tests/lib_2/isolate/spawn_function_test.dart b/tests/lib_2/isolate/spawn_function_test.dart
index b8b7659..b12246e 100644
--- a/tests/lib_2/isolate/spawn_function_test.dart
+++ b/tests/lib_2/isolate/spawn_function_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Example of spawning an isolate from a function.
diff --git a/tests/lib_2/isolate/spawn_generic_test.dart b/tests/lib_2/isolate/spawn_generic_test.dart
index f73b711..05ea808 100644
--- a/tests/lib_2/isolate/spawn_generic_test.dart
+++ b/tests/lib_2/isolate/spawn_generic_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Check that Isolate.spawn is generic.
diff --git a/tests/lib_2/isolate/spawn_uri_exported_main_test.dart b/tests/lib_2/isolate/spawn_uri_exported_main_test.dart
index ba704e8..463181f 100644
--- a/tests/lib_2/isolate/spawn_uri_exported_main_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_exported_main_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/lib_2/isolate/spawn_uri_fail_test.dart b/tests/lib_2/isolate/spawn_uri_fail_test.dart
index 06b6bf5..9b5346f 100644
--- a/tests/lib_2/isolate/spawn_uri_fail_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_fail_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:io";
diff --git a/tests/lib_2/isolate/spawn_uri_missing_from_isolate_test.dart b/tests/lib_2/isolate/spawn_uri_missing_from_isolate_test.dart
index a7f9e7a..204fa9c 100644
--- a/tests/lib_2/isolate/spawn_uri_missing_from_isolate_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_missing_from_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 /// Tests that Isolate.spawnUri completes with an error when the given URI
diff --git a/tests/lib_2/isolate/spawn_uri_missing_test.dart b/tests/lib_2/isolate/spawn_uri_missing_test.dart
index 83aa2e9..fe27ff0 100644
--- a/tests/lib_2/isolate/spawn_uri_missing_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_missing_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 /// Tests that Isolate.spanUri completes with an error when the given URI
diff --git a/tests/lib_2/isolate/spawn_uri_multi_test.dart b/tests/lib_2/isolate/spawn_uri_multi_test.dart
index 83eb117..dc50328 100644
--- a/tests/lib_2/isolate/spawn_uri_multi_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_multi_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Negative test to make sure that we are reaching all assertions.
diff --git a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
index 6ecabb1..423821d 100644
--- a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Example of nested spawning of isolates from a URI
diff --git a/tests/lib_2/isolate/spawn_uri_test.dart b/tests/lib_2/isolate/spawn_uri_test.dart
index 1698d46..88e99bf 100644
--- a/tests/lib_2/isolate/spawn_uri_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Example of spawning an isolate from a URI
diff --git a/tests/lib_2/isolate/spawn_uri_vm_test.dart b/tests/lib_2/isolate/spawn_uri_vm_test.dart
index e64db64..536b912 100644
--- a/tests/lib_2/isolate/spawn_uri_vm_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_vm_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Example of spawning an isolate from a URI
diff --git a/tests/lib_2/isolate/start_paused_test.dart b/tests/lib_2/isolate/start_paused_test.dart
index 3005918..7ee4993 100644
--- a/tests/lib_2/isolate/start_paused_test.dart
+++ b/tests/lib_2/isolate/start_paused_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library start_paused_test;
diff --git a/tests/lib_2/isolate/static_function_test.dart b/tests/lib_2/isolate/static_function_test.dart
index e213876..17f18e5 100644
--- a/tests/lib_2/isolate/static_function_test.dart
+++ b/tests/lib_2/isolate/static_function_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // Test starting isolate with static functions (and toplevel ones, for sanity).
diff --git a/tests/lib_2/isolate/string_from_environment_default_value_test.dart b/tests/lib_2/isolate/string_from_environment_default_value_test.dart
index 46c48a5..f920f65 100644
--- a/tests/lib_2/isolate/string_from_environment_default_value_test.dart
+++ b/tests/lib_2/isolate/string_from_environment_default_value_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:isolate";
diff --git a/tests/lib_2/isolate/timer_isolate_test.dart b/tests/lib_2/isolate/timer_isolate_test.dart
index 972f592..07485a6 100644
--- a/tests/lib_2/isolate/timer_isolate_test.dart
+++ b/tests/lib_2/isolate/timer_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library multiple_timer_test;
diff --git a/tests/lib_2/isolate/timer_multiple_isolates_test.dart b/tests/lib_2/isolate/timer_multiple_isolates_test.dart
index 29bab19..0321a8b 100644
--- a/tests/lib_2/isolate/timer_multiple_isolates_test.dart
+++ b/tests/lib_2/isolate/timer_multiple_isolates_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library timer_multiple_isolates_test;
diff --git a/tests/lib_2/isolate/transferable_failed_to_send_test.dart b/tests/lib_2/isolate/transferable_failed_to_send_test.dart
index 8ee6226..8f339585 100644
--- a/tests/lib_2/isolate/transferable_failed_to_send_test.dart
+++ b/tests/lib_2/isolate/transferable_failed_to_send_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:io" show ServerSocket;
diff --git a/tests/lib_2/isolate/transferable_test.dart b/tests/lib_2/isolate/transferable_test.dart
index aef8d97..26cb2e0 100644
--- a/tests/lib_2/isolate/transferable_test.dart
+++ b/tests/lib_2/isolate/transferable_test.dart
@@ -4,7 +4,8 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/lib_2/isolate/type_ref_message_test.dart b/tests/lib_2/isolate/type_ref_message_test.dart
new file mode 100644
index 0000000..8dd2a79
--- /dev/null
+++ b/tests/lib_2/isolate/type_ref_message_test.dart
@@ -0,0 +1,33 @@
+// 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.
+
+// See https://github.com/flutter/flutter/issues/84691
+
+// @dart = 2.9
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+
+class B<T> {}
+class D<S> extends B<D> {}
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var list = message as List<D<String>>;
+    var element = list[0] as D<String>;
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var list = <D<String>>[ new D() ];
+  port.sendPort.send(list);
+}
diff --git a/tests/lib_2/isolate/typed_message_test.dart b/tests/lib_2/isolate/typed_message_test.dart
index 0700261..3b30415 100644
--- a/tests/lib_2/isolate/typed_message_test.dart
+++ b/tests/lib_2/isolate/typed_message_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 // Dart test program for testing isolate communication with
 // typed objects.
diff --git a/tests/lib_2/isolate/unresolved_ports_test.dart b/tests/lib_2/isolate/unresolved_ports_test.dart
index e930123..408a26e 100644
--- a/tests/lib_2/isolate/unresolved_ports_test.dart
+++ b/tests/lib_2/isolate/unresolved_ports_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 // spawns multiple isolates and sends unresolved ports between them.
diff --git a/tests/lib_2/isolate/vm_rehash_test.dart b/tests/lib_2/isolate/vm_rehash_test.dart
index b854343..3813b67 100644
--- a/tests/lib_2/isolate/vm_rehash_test.dart
+++ b/tests/lib_2/isolate/vm_rehash_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:async';
diff --git a/tests/lib_2/isolate/weak_property_message_1_test.dart b/tests/lib_2/isolate/weak_property_message_1_test.dart
new file mode 100644
index 0000000..fa8a6d1
--- /dev/null
+++ b/tests/lib_2/isolate/weak_property_message_1_test.dart
@@ -0,0 +1,50 @@
+// 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.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+// @dart = 2.9
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var expando1 = message[0] as Expando;
+    var expando2 = message[1] as Expando;
+    var expando3 = message[2] as Expando;
+    var key1 = message[3];
+
+    var key2 = expando1[key1];
+    Expect.isNotNull(key2);
+    var key3 = expando2[key2];
+    Expect.isNotNull(key3);
+    var value = expando3[key3];
+    Expect.equals(value, "value");
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var key1 = new Object();
+  var key2 = new Object();
+  var key3 = new Object();
+  var expando1 = new Expando();
+  var expando2 = new Expando();
+  var expando3 = new Expando();
+  expando1[key1] = key2;
+  expando2[key2] = key3;
+  expando3[key3] = "value";
+
+  // key1 is placed after expando1 so that its reachability is uncertain when
+  // expando1 is first encountered.
+  var message = <dynamic>[expando1, expando2, expando3, key1];
+  port.sendPort.send(message);
+}
diff --git a/tests/lib_2/isolate/weak_property_message_2_test.dart b/tests/lib_2/isolate/weak_property_message_2_test.dart
new file mode 100644
index 0000000..7b5ad95
--- /dev/null
+++ b/tests/lib_2/isolate/weak_property_message_2_test.dart
@@ -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.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+// @dart = 2.9
+
+import "dart:async";
+import "dart:developer";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var expando = message as Expando;
+
+    // Sent and received without error.
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var unwrittenKey = new Object();
+  var expando = new Expando();
+  expando[unwrittenKey] = new UserTag("cant send this");
+
+  port.sendPort.send(expando);
+
+  print(unwrittenKey);  // Ensure [unwrittenKey] is live during [send].
+}
diff --git a/tests/lib_2/js/extends_test/extends_subtyping_live_test.dart b/tests/lib_2/js/extends_test/extends_subtyping_live_test.dart
new file mode 100644
index 0000000..b46818e
--- /dev/null
+++ b/tests/lib_2/js/extends_test/extends_subtyping_live_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Tests inheritance subtyping relationships after making package:js types live.
+
+@JS()
+library extends_subtyping_live_test;
+
+import 'package:js/js.dart';
+import 'extends_test_util.dart';
+
+@JS()
+external dynamic get externalGetter;
+
+void main() {
+  // Call to foreign function should trigger dart2js to assume types are live.
+  externalGetter;
+  testSubtyping();
+}
diff --git a/tests/lib_2/js/extends_test/extends_subtyping_not_live_test.dart b/tests/lib_2/js/extends_test/extends_subtyping_not_live_test.dart
new file mode 100644
index 0000000..3cb0fbb
--- /dev/null
+++ b/tests/lib_2/js/extends_test/extends_subtyping_not_live_test.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.
+
+// Tests inheritance subtyping relationships without making package:js types
+// live.
+
+import 'extends_test_util.dart';
+
+void main() {
+  testSubtyping();
+}
diff --git a/tests/lib/js/extends_test/extends_subtyping_test.dart b/tests/lib_2/js/extends_test/extends_test.dart
similarity index 72%
rename from tests/lib/js/extends_test/extends_subtyping_test.dart
rename to tests/lib_2/js/extends_test/extends_test.dart
index 76dc51e..4286838 100644
--- a/tests/lib/js/extends_test/extends_subtyping_test.dart
+++ b/tests/lib_2/js/extends_test/extends_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -6,5 +6,5 @@
 
 void main() {
   setUpWithoutES6Syntax();
-  testSubtyping();
+  testInheritance();
 }
diff --git a/tests/lib_2/js/extends_test/extends_test_util.dart b/tests/lib_2/js/extends_test/extends_test_util.dart
new file mode 100644
index 0000000..9a21c51
--- /dev/null
+++ b/tests/lib_2/js/extends_test/extends_test_util.dart
@@ -0,0 +1,278 @@
+// 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.
+
+// Tests inheritance relationships between `JS` and `anonymous` classes/objects.
+
+@JS()
+library extends_test;
+
+import 'package:expect/minitest.dart';
+import 'package:js/js.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class JSClass {
+  external JSClass();
+  external int get a;
+  external int getA();
+  external int getAOrB();
+}
+
+@JS()
+@anonymous
+class AnonymousClass {
+  external int get a;
+  external int getA();
+}
+
+@JS()
+class JSExtendJSClass extends JSClass {
+  external JSExtendJSClass(int a, int b);
+  external int get b;
+  external int getB();
+  external int getAOrB();
+}
+
+@JS()
+class JSExtendAnonymousClass extends AnonymousClass {
+  external JSExtendAnonymousClass(int a, int b);
+  external int get b;
+  external int getB();
+}
+
+@JS()
+@anonymous
+class AnonymousExtendAnonymousClass extends AnonymousClass {
+  external int get b;
+  external int getB();
+}
+
+@JS()
+@anonymous
+class AnonymousExtendJSClass extends JSClass {
+  external int get b;
+  external int getB();
+  external int getAOrB();
+}
+
+external AnonymousClass get anon;
+external AnonymousExtendAnonymousClass get anonExtendAnon;
+external AnonymousExtendJSClass get anonExtendJS;
+
+void setUpWithoutES6Syntax() {
+  // Use the old way to define inheritance between JS objects.
+  eval(r"""
+    function inherits(child, parent) {
+      if (child.prototype.__proto__) {
+        child.prototype.__proto__ = parent.prototype;
+      } else {
+        function tmp() {};
+        tmp.prototype = parent.prototype;
+        child.prototype = new tmp();
+        child.prototype.constructor = child;
+      }
+    }
+    function JSClass(a) {
+      if (arguments.length == 0) a = 1;
+      this.a = a;
+      this.getA = function() {
+        return this.a;
+      }
+      this.getAOrB = function() {
+        return this.getA();
+      }
+    }
+    function JSExtendJSClass(a, b) {
+      JSClass.call(this, a);
+      this.b = b;
+      this.getB = function() {
+        return this.b;
+      }
+      this.getAOrB = function() {
+        return this.getB();
+      }
+    }
+    inherits(JSExtendJSClass, JSClass);
+    function JSExtendAnonymousClass(a, b) {
+      this.a = a;
+      this.b = b;
+      this.getA = function() {
+        return this.a;
+      }
+      this.getB = function() {
+        return this.b;
+      }
+      this.getAOrB = function() {
+        return this.getB();
+      }
+    }
+    self.anon = new JSClass(1);
+    self.anonExtendAnon = new JSExtendAnonymousClass(1, 2);
+    self.anonExtendJS = new JSExtendJSClass(1, 2);
+  """);
+}
+
+void setUpWithES6Syntax() {
+  // Use the ES6 syntax for classes to make inheritance easier.
+  eval(r"""
+    class JSClass {
+      constructor(a) {
+        if (arguments.length == 0) a = 1;
+        this.a = a;
+      }
+      getA() {
+        return this.a;
+      }
+      getAOrB() {
+        return this.getA();
+      }
+    }
+    self.JSClass = JSClass;
+    class JSExtendJSClass extends JSClass {
+      constructor(a, b) {
+        super(a);
+        this.b = b;
+      }
+      getB() {
+        return this.b;
+      }
+      getAOrB() {
+        return this.getB();
+      }
+    }
+    self.JSExtendJSClass = JSExtendJSClass;
+    class JSExtendAnonymousClass {
+      constructor(a, b) {
+        this.a = a;
+        this.b = b;
+      }
+      getA() {
+        return this.a;
+      }
+      getB() {
+        return this.b;
+      }
+      getAOrB() {
+        return this.getB();
+      }
+    }
+    self.JSExtendAnonymousClass = JSExtendAnonymousClass;
+    self.anon = new JSClass(1);
+    self.anonExtendAnon = new JSExtendAnonymousClass(1, 2);
+    self.anonExtendJS = new JSExtendJSClass(1, 2);
+  """);
+}
+
+void testInheritance() {
+  var jsExtendJS = JSExtendJSClass(1, 2);
+  expect(jsExtendJS.a, 1);
+  expect(jsExtendJS.b, 2);
+  expect(jsExtendJS.getA(), 1);
+  expect(jsExtendJS.getB(), 2);
+  // Test method overrides.
+  expect(jsExtendJS.getAOrB(), 2);
+  expect((jsExtendJS as JSClass).getAOrB(), 2);
+
+  var jsExtendAnon = JSExtendAnonymousClass(1, 2);
+  expect(jsExtendAnon.a, 1);
+  expect(jsExtendAnon.b, 2);
+  expect(jsExtendAnon.getA(), 1);
+  expect(jsExtendAnon.getB(), 2);
+
+  expect(anonExtendAnon.a, 1);
+  expect(anonExtendAnon.b, 2);
+  expect(anonExtendAnon.getA(), 1);
+  expect(anonExtendAnon.getB(), 2);
+
+  expect(anonExtendJS.a, 1);
+  expect(anonExtendJS.b, 2);
+  expect(anonExtendJS.getA(), 1);
+  expect(anonExtendJS.getB(), 2);
+  expect(anonExtendJS.getAOrB(), 2);
+  expect((anonExtendJS as JSClass).getAOrB(), 2);
+
+  // Test type checking and casts succeeds regardless of type hierarchy.
+
+  // Test type checking at runtime by disabling inlining. We still, however, do
+  // `is` checks directly below to test those optimizations.
+  @pragma('dart2js:noInline')
+  void runtimeIsAndAs<T>(instance) {
+    expect(instance is T, true);
+    expect(() => instance as T, returnsNormally);
+  }
+
+  // Test that base JS type can be used as any subtype.
+  var js = JSClass();
+  expect(js is JSExtendJSClass, true);
+  runtimeIsAndAs<JSExtendJSClass>(js);
+  expect(js is AnonymousExtendJSClass, true);
+  runtimeIsAndAs<AnonymousExtendJSClass>(js);
+
+  // Test that base anonymous type can be use as any subtype.
+  // Conversion from external getter value to a variable is needed to coerce
+  // compile time optimization of type checks. This applies for below as well.
+  var anonVar = anon;
+  expect(anonVar is JSExtendAnonymousClass, true);
+  runtimeIsAndAs<JSExtendAnonymousClass>(anonVar);
+  expect(anonVar is AnonymousExtendAnonymousClass, true);
+  runtimeIsAndAs<AnonymousExtendAnonymousClass>(anonVar);
+
+  // Test that instance of subtypes can be used as their JS supertype.
+  expect(jsExtendJS is JSClass, true);
+  runtimeIsAndAs<JSClass>(jsExtendJS);
+  var anonExtendJSVar = anonExtendJS;
+  expect(anonExtendJSVar is JSClass, true);
+  runtimeIsAndAs<JSClass>(anonExtendJSVar);
+
+  // Test that instance of subtypes can be used as their anonymous supertype.
+  var anonExtendAnonVar = anonExtendAnon;
+  expect(anonExtendAnonVar is AnonymousClass, true);
+  runtimeIsAndAs<AnonymousClass>(anonExtendAnonVar);
+  expect(jsExtendAnon is AnonymousClass, true);
+  runtimeIsAndAs<AnonymousClass>(jsExtendAnon);
+}
+
+JSClass returnJS() => throw '';
+
+AnonymousClass returnAnon() => throw '';
+
+JSExtendJSClass returnJSExtendJS() => throw '';
+
+JSExtendAnonymousClass returnJSExtendAnon() => throw '';
+
+AnonymousExtendJSClass returnAnonExtendJS() => throw '';
+
+AnonymousExtendAnonymousClass returnAnonExtendAnon() => throw '';
+
+@pragma('dart2js:noInline')
+void isRuntimeSubtypeBothWays<T, U>() {
+  // Test T <: U and U <: T. With interop types, type checks should pass
+  // regardless of type hierarchy. Note that dart2js does these type checks at
+  // runtime. Below, we do compile-time checks using top-level functions.
+  T f1() => throw '';
+  U f2() => throw '';
+  expect(f1 is U Function(), true);
+  expect(f2 is T Function(), true);
+}
+
+void testSubtyping() {
+  // Test subtyping for inheritance between JS and anonymous classes.
+  expect(returnJS is JSExtendJSClass Function(), true);
+  expect(returnJSExtendJS is JSClass Function(), true);
+  isRuntimeSubtypeBothWays<JSClass, JSExtendJSClass>();
+
+  expect(returnJS is AnonymousExtendJSClass Function(), true);
+  expect(returnAnonExtendJS is JSClass Function(), true);
+  isRuntimeSubtypeBothWays<JSClass, AnonymousExtendJSClass>();
+
+  expect(returnAnon is JSExtendAnonymousClass Function(), true);
+  expect(returnJSExtendAnon is AnonymousClass Function(), true);
+  isRuntimeSubtypeBothWays<AnonymousClass, JSExtendAnonymousClass>();
+
+  expect(returnAnon is AnonymousExtendAnonymousClass Function(), true);
+  expect(returnAnonExtendAnon is AnonymousClass Function(), true);
+  isRuntimeSubtypeBothWays<AnonymousClass, AnonymousExtendAnonymousClass>();
+}
diff --git a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart b/tests/lib_2/js/extends_test/extends_with_es6_test.dart
similarity index 72%
rename from tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
rename to tests/lib_2/js/extends_test/extends_with_es6_test.dart
index e6185da..e0ed10d 100644
--- a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
+++ b/tests/lib_2/js/extends_test/extends_with_es6_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -6,5 +6,5 @@
 
 void main() {
   setUpWithES6Syntax();
-  testSubtyping();
+  testInheritance();
 }
diff --git a/tests/lib_2/js/external_nonjs_static_test.dart b/tests/lib_2/js/external_nonjs_static_test.dart
index 6635d27..d0fa7df 100644
--- a/tests/lib_2/js/external_nonjs_static_test.dart
+++ b/tests/lib_2/js/external_nonjs_static_test.dart
@@ -9,6 +9,7 @@
 
 library external_nonjs_static_test;
 
+import 'dart:html';
 import 'package:js/js.dart';
 
 external get topLevelGetter;
@@ -72,4 +73,63 @@
   // [web] Only JS interop members may be 'external'.
 }
 
+extension ExtensionNonJS on NonJSClass {
+  external get getter;
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external set setter(_);
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  external static get staticGetter;
+  //                  ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static set staticSetter(_);
+  //                  ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  external method();
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static staticMethod();
+  //              ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external optionalParameterMethod([int a, int b = 0]);
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external overridenMethod();
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  nonExternalMethod() => 1;
+  static nonExternalStaticMethod() => 2;
+}
+
+class NonJSClass {
+  void overridenMethod() => 5;
+}
+
+extension ExtensionGenericNonJS<T> on GenericNonJSClass<T> {
+  external T method();
+  //         ^
+  // [web] JS interop or Native class required for 'external' extension members.
+}
+
+class GenericNonJSClass<T> {}
+
+extension ExtensionNative on HtmlElement {
+  external get getter;
+  external set setter(_);
+
+  external static get staticGetter;
+  external static set staticSetter(_);
+
+  external method();
+  external static staticMethod();
+  external optionalParameterMethod([int a, int b = 0]);
+
+  nonExternalMethod() => 1;
+  static nonExternalStaticMethod() => 2;
+}
+
 main() {}
diff --git a/tests/lib_2/js/external_static_test.dart b/tests/lib_2/js/external_static_test.dart
index 8ac09be..8084a72 100644
--- a/tests/lib_2/js/external_static_test.dart
+++ b/tests/lib_2/js/external_static_test.dart
@@ -10,6 +10,7 @@
 @JS()
 library external_static_test;
 
+import 'dart:html';
 import 'package:js/js.dart';
 
 // external top level members ok in @JS() library.
@@ -66,4 +67,133 @@
   // [web] Only JS interop members may be 'external'.
 }
 
+extension ExtensionNonJS on NonJSClass {
+  external get getter;
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external set setter(_);
+  //           ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  external static get staticGetter;
+  //                  ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static set staticSetter(_);
+  //                  ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  external method();
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external static staticMethod();
+  //              ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external optionalParameterMethod([int a, int b = 0]);
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+  external overridenMethod();
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  @JS('memberAnnotation')
+  external annotatedMethod();
+  //       ^
+  // [web] JS interop or Native class required for 'external' extension members.
+
+  nonExternalMethod() => 1;
+  static nonExternalStaticMethod() => 2;
+}
+
+class NonJSClass {
+  void overridenMethod() => 5;
+}
+
+extension ExtensionGenericNonJS<T> on GenericNonJSClass<T> {
+  external T method();
+  //         ^
+  // [web] JS interop or Native class required for 'external' extension members.
+}
+
+class GenericNonJSClass<T> {}
+
+extension ExtensionJS on JSClass {
+  external get getter;
+  external set setter(_);
+
+  external static get staticGetter;
+  external static set staticSetter(_);
+
+  external method();
+  external static staticMethod();
+  external optionalParameterMethod([int a, int b = 0]);
+
+  @JS('memberAnnotation')
+  external annotatedMethod();
+
+  nonExternalMethod() => 1;
+  static nonExternalStaticMethod() => 2;
+}
+
+@JS()
+class JSClass {}
+
+extension ExtensionGenericJS<T> on GenericJSClass<T> {
+  external T method();
+}
+
+@JS()
+class GenericJSClass<T> {}
+
+extension ExtensionAnonymousJS on AnonymousJSClass {
+  external get getter;
+  external set setter(_);
+  external method();
+}
+
+@JS()
+@anonymous
+class AnonymousJSClass {}
+
+extension ExtensionAbstractJS on AbstractJSClass {
+  external get getter;
+  external set setter(_);
+  external method();
+}
+
+@JS()
+abstract class AbstractJSClass {}
+
+extension ExtensionAnnotatedJS on AnnotatedJSClass {
+  external get getter;
+  external set setter(_);
+  external method();
+}
+
+@JS('Annotation')
+class AnnotatedJSClass {}
+
+extension ExtensionPrivateJS on _privateJSClass {
+  external get getter;
+  external set setter(_);
+  external method();
+}
+
+@JS()
+class _privateJSClass {}
+
+extension ExtensionNative on HtmlElement {
+  external get getter;
+  external set setter(_);
+
+  external static get staticGetter;
+  external static set staticSetter(_);
+
+  external method();
+  external static staticMethod();
+  external optionalParameterMethod([int a, int b = 0]);
+
+  nonExternalMethod() => 1;
+  static nonExternalStaticMethod() => 2;
+}
+
 main() {}
diff --git a/tests/lib_2/js/is_check_and_as_cast_test.dart b/tests/lib_2/js/is_check_and_as_cast_test.dart
new file mode 100644
index 0000000..fe11da5
--- /dev/null
+++ b/tests/lib_2/js/is_check_and_as_cast_test.dart
@@ -0,0 +1,133 @@
+// 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.
+
+// Tests `is` checks and `as` casts between various JS objects. Currently, all
+// checks and casts should be allowed between JS objects.
+
+@JS()
+library is_check_and_as_cast_test;
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class Foo {
+  external Foo(int a);
+  external int get a;
+}
+
+// Class with same structure as Foo but separate JS class.
+@JS()
+class Bar {
+  external Bar(int a);
+  external int get a;
+}
+
+@JS('Bar')
+class BarCopy {
+  external BarCopy(int a);
+  external int get a;
+}
+
+// JS object literals
+@JS()
+@anonymous
+class LiteralA {
+  external int get x;
+}
+
+@JS()
+@anonymous
+class LiteralB {
+  external int get y;
+}
+
+// Library is annotated with JS so we don't need the annotation here.
+external LiteralA get a;
+external LiteralB get b;
+
+class DartClass {}
+
+// Avoid static type optimization by running all tests using this.
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+void main() {
+  eval(r"""
+    function Foo(a) {
+      this.a = a;
+    }
+    function Bar(a) {
+      this.a = a;
+    }
+    var a = {
+      x: 1,
+    };
+    var b = {
+      y: 2,
+    };
+      """);
+
+  // JS class object can be checked and casted with itself.
+  var foo = Foo(42);
+  expect(foo is Foo, isTrue);
+  expect(confuse(foo) is Foo, isTrue);
+  expect(() => (foo as Foo), returnsNormally);
+
+  // Try it with dynamic.
+  dynamic d = Foo(42);
+  expect(d is Foo, isTrue);
+  expect(() => (d as Foo), returnsNormally);
+
+  // Casts are allowed between any JS class objects.
+  expect(foo is Bar, isTrue);
+  expect(confuse(foo) is Bar, isTrue);
+  expect(d is Bar, isTrue);
+  expect(() => (foo as Bar), returnsNormally);
+  expect(() => (d as Bar), returnsNormally);
+
+  // BarCopy is the same JS class as Bar.
+  var barCopy = BarCopy(42);
+  expect(barCopy is Bar, isTrue);
+  expect(confuse(barCopy) is Bar, isTrue);
+  expect(() => (barCopy as Bar), returnsNormally);
+
+  // JS object literal can be checked and casted with itself.
+  expect(a is LiteralA, isTrue);
+  expect(confuse(a) is LiteralA, isTrue);
+  expect(() => (a as LiteralA), returnsNormally);
+
+  // Like class objects, casts are allowed between any object literals.
+  expect(a is LiteralB, isTrue);
+  expect(confuse(a) is LiteralB, isTrue);
+  expect(() => (a as LiteralB), returnsNormally);
+
+  // Similarly, casts are allowed between any class objects and object literals.
+  expect(foo is LiteralB, isTrue);
+  expect(confuse(foo) is LiteralB, isTrue);
+  expect(() => (foo as LiteralB), returnsNormally);
+  expect(a is Foo, isTrue);
+  expect(confuse(a) is Foo, isTrue);
+  expect(() => (a as Foo), returnsNormally);
+
+  // You cannot cast between JS interop objects and Dart objects, however.
+  var dartClass = DartClass();
+  expect(dartClass is Foo, isFalse);
+  expect(confuse(dartClass) is Foo, isFalse);
+  expect(() => (dartClass as Foo), throws);
+  expect(dartClass is LiteralA, isFalse);
+  expect(confuse(dartClass) is LiteralA, isFalse);
+  expect(() => (dartClass as LiteralA), throws);
+
+  expect(foo is DartClass, isFalse);
+  expect(confuse(foo) is DartClass, isFalse);
+  expect(() => (foo as DartClass), throws);
+  expect(a is DartClass, isFalse);
+  expect(confuse(a) is DartClass, isFalse);
+  expect(() => (a as DartClass), throws);
+}
diff --git a/tests/lib_2/js/subtyping_test/subtyping_live_test.dart b/tests/lib_2/js/subtyping_test/subtyping_live_test.dart
new file mode 100644
index 0000000..d137ba6
--- /dev/null
+++ b/tests/lib_2/js/subtyping_test/subtyping_live_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Tests subtyping relationships after making package:js types live.
+
+@JS()
+library subtyping_live_test;
+
+import 'package:js/js.dart';
+import 'subtyping_test_util.dart';
+
+@JS()
+external dynamic get externalGetter;
+
+void main() {
+  // Call to foreign function should trigger dart2js to assume types are live.
+  externalGetter;
+  testSubtyping();
+}
diff --git a/tests/lib_2/js/subtyping_test/subtyping_not_live_test.dart b/tests/lib_2/js/subtyping_test/subtyping_not_live_test.dart
new file mode 100644
index 0000000..5344280
--- /dev/null
+++ b/tests/lib_2/js/subtyping_test/subtyping_not_live_test.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.
+
+// Tests subtyping relationships without making package:js types live.
+
+import 'package:js/js.dart';
+import 'subtyping_test_util.dart';
+
+void main() {
+  testSubtyping();
+}
diff --git a/tests/lib_2/js/subtyping_test/subtyping_test_util.dart b/tests/lib_2/js/subtyping_test/subtyping_test_util.dart
new file mode 100644
index 0000000..a39efb9
--- /dev/null
+++ b/tests/lib_2/js/subtyping_test/subtyping_test_util.dart
@@ -0,0 +1,74 @@
+// 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.
+
+// Tests subtyping relationships between JS and anonymous classes.
+
+@JS()
+library subtyping_test_util;
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+@JS()
+class JSClassA {}
+
+@JS()
+class JSClassB {}
+
+@JS()
+@anonymous
+class AnonymousClassA {}
+
+@JS()
+@anonymous
+class AnonymousClassB {}
+
+class DartClass {}
+
+JSClassA returnJS() => throw '';
+
+AnonymousClassA returnAnon() => throw '';
+
+DartClass returnDartClass() => throw '';
+
+// Avoid static type optimization by running all tests using this.
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+void testSubtyping() {
+  // Checks subtyping with the same type.
+  expect(returnJS is JSClassA Function(), true);
+  expect(returnAnon is AnonymousClassA Function(), true);
+
+  // Subtyping between JS and anonymous classes.
+  expect(returnJS is AnonymousClassA Function(), true);
+  expect(returnAnon is JSClassA Function(), true);
+
+  // Subtyping between same type of package:js classes.
+  expect(returnJS is JSClassB Function(), true);
+  expect(returnAnon is AnonymousClassB Function(), true);
+
+  // No subtyping between JS/anonymous classes and Dart classes.
+  expect(returnJS is DartClass Function(), false);
+  expect(returnDartClass is JSClassA Function(), false);
+  expect(returnAnon is DartClass Function(), false);
+  expect(returnDartClass is AnonymousClassA Function(), false);
+
+  // Repeat the checks but using `confuse` to coerce runtime checks instead of
+  // compile-time like above.
+  expect(confuse(returnJS) is JSClassA Function(), true);
+  expect(confuse(returnAnon) is AnonymousClassA Function(), true);
+
+  expect(confuse(returnJS) is AnonymousClassA Function(), true);
+  expect(confuse(returnAnon) is JSClassA Function(), true);
+
+  expect(confuse(returnJS) is JSClassB Function(), true);
+  expect(confuse(returnAnon) is AnonymousClassB Function(), true);
+
+  expect(confuse(returnJS) is DartClass Function(), false);
+  expect(confuse(returnDartClass) is JSClassA Function(), false);
+  expect(confuse(returnAnon) is DartClass Function(), false);
+  expect(confuse(returnDartClass) is AnonymousClassA Function(), false);
+}
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 7fbd5a0..fb8a8bf 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -36,8 +36,12 @@
 [ $csp ]
 html/js_interop_constructor_name/*: SkipByDesign # Issue 42085.
 isolate/deferred_in_isolate2_test: Skip # Issue 16898. Deferred loading does not work from an isolate in CSP-mode
+js/extends_test/extends_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/extends_test/extends_with_es6_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/is_check_and_as_cast_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/async_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/javascriptobject_extensions_test.dart: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/jsify_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/promise_reject_null_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/properties_implicit_checks_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
@@ -72,9 +76,6 @@
 async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
 async/stream_timeout_test: SkipSlow # Times out. Issue 22050
 
-[ $runtime == dart_precompiled || $runtime == vm ]
-isolate/isolate_stress_test: Skip # Issue 12588: Uses dart:html. This should be able to pass when we have wrapper-less tests.
-
 # It makes no sense to run any test that uses spawnURI under the simulator
 # as that would involve running CFE (the front end) in simulator mode
 # to compile the URI file specified in spawnURI code.
diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status
index 0cdb365..c2e26f4 100644
--- a/tests/lib_2/lib_2_vm.status
+++ b/tests/lib_2/lib_2_vm.status
@@ -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.
 
-[ $runtime == vm ]
-isolate/*: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-
 [ $runtime != vm ]
 isolate/native_wrapper_message_test: Skip # A VM specific test.
 
@@ -69,96 +66,10 @@
 mirrors/library_uri_io_test: RuntimeError
 mirrors/library_uri_package_test: RuntimeError
 
-[ $arch == simarm || $arch == simarm64 || $arch ==simarm64c || $hot_reload || $hot_reload_rollback ]
+[ $arch == simarm || $arch == simarm64 || $arch == simarm64c || $hot_reload || $hot_reload_rollback ]
 convert/chunked_conversion_utf88_test: SkipSlow
 convert/streamed_conversion_json_utf8_decode_test: SkipSlow
 convert/utf85_test: SkipSlow
 
 [ $hot_reload || $hot_reload_rollback ]
-isolate/bool_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/capability_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/compile_time_error_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/count_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/cross_isolate_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/enum_const_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_exit_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_exit_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/exit_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/exit_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/function_send1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/function_send_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error3_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/illegal_msg_function_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/illegal_msg_mirror_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/int32_length_overflow_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/int_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_complex_messages_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_current_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_import_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_22778_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_35626_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_6610_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_self_synchronously_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_self_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/large_byte_data_leak_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/large_byte_data_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/mandel_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message3_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message4_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_const_type_arguments_1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_const_type_arguments_2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_enum_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/mint_maker_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/native_wrapper_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/nested_spawn2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/nested_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/non_fatal_exception_in_timer_callback_test/none: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/non_fatal_exception_in_timer_callback_test/sleep: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/object_leak_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/ondone_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_config_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_resolve_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_root_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/pause_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/ping_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/port_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/raw_port_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/regress_34752_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/regress_flutter_22796_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/request_reply_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/resolve_package_uri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/scenarios/package_data_uri_spec/package_resolve_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/send_private_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/simple_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_function_custom_class_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_function_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_generic_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri__package_uri__test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_exported_main_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_fail_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_missing_from_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_missing_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_multi_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_nested_vm_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_vm_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/start_paused_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/string_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/timer_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/timer_multiple_isolates_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/transferable_failed_to_send_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/transferable_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/typed_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/unresolved_ports_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/vm_rehash_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
+isolate/int32_length_overflow_test: SkipSlow # Iterates over Uint8List(1 << 30).
diff --git a/tests/standalone/io/directory_list_sync_test.dart b/tests/standalone/io/directory_list_sync_test.dart
index 0df5081..6e3b257 100644
--- a/tests/standalone/io/directory_list_sync_test.dart
+++ b/tests/standalone/io/directory_list_sync_test.dart
@@ -4,10 +4,11 @@
 
 import 'dart:io';
 
+import 'package:path/path.dart' as path;
+
 void testList() {
-  File script = new File.fromUri(Platform.script);
-  // tests/standalone/io/../..
-  Directory startingDir = script.parent.parent.parent;
+  final startingDir =
+      Directory(path.normalize(path.join(Platform.executable, '../../../')));
   print("Recursively listing entries in directory ${startingDir.path} ...");
   List<FileSystemEntity> each =
       startingDir.listSync(recursive: true, followLinks: false);
diff --git a/tests/standalone/io/echo_server_stream_test.dart b/tests/standalone/io/echo_server_stream_test.dart
index 18dc94a..6da8ca2 100644
--- a/tests/standalone/io/echo_server_stream_test.dart
+++ b/tests/standalone/io/echo_server_stream_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Echo server test program to test socket streams.
diff --git a/tests/standalone/io/file_fuzz_test.dart b/tests/standalone/io/file_fuzz_test.dart
index f7f89c8..bfcb7c9 100644
--- a/tests/standalone/io/file_fuzz_test.dart
+++ b/tests/standalone/io/file_fuzz_test.dart
@@ -10,113 +10,122 @@
 import 'dart:io';
 
 import 'fuzz_support.dart';
+import 'file_write_only_test.dart' show withTempDir, withTempDirSync;
 
 import "package:async_helper/async_helper.dart";
 
 fuzzSyncMethods() {
-  typeMapping.forEach((k, v) {
-    File? file;
-    doItSync(() => file = new File(v as String));
-    if (file == null) return;
-    final f = file!;
-    doItSync(f.existsSync);
-    doItSync(f.createSync);
-    doItSync(f.deleteSync);
-    doItSync(f.lengthSync);
-    doItSync(f.lastModifiedSync);
-    doItSync(() => f.path);
-    doItSync(() => f.openRead().listen((_) {}, onError: (e) {}));
-    doItSync(f.readAsBytesSync);
-    doItSync(f.readAsStringSync);
-    doItSync(f.readAsLinesSync);
-    typeMapping.forEach((k2, v2) {
-      doItSync(() => f.openSync(mode: v2 as FileMode));
-      doItSync(() => f.openWrite(mode: v2 as FileMode));
-      doItSync(() => f.readAsStringSync(encoding: v2 as Encoding));
-      doItSync(() => f.readAsLinesSync(encoding: v2 as Encoding));
+  withTempDirSync('dart_file_fuzz', (temp) {
+    typeMapping.forEach((k, v) {
+      File? file;
+      doItSync(() => file = new File('${temp.path}/${v as String}'));
+      if (file == null) return;
+      final f = file!;
+      doItSync(f.existsSync);
+      doItSync(f.createSync);
+      doItSync(f.deleteSync);
+      doItSync(f.lengthSync);
+      doItSync(f.lastModifiedSync);
+      doItSync(() => f.path);
+      doItSync(() => f.openRead().listen((_) {}, onError: (e) {}));
+      doItSync(f.readAsBytesSync);
+      doItSync(f.readAsStringSync);
+      doItSync(f.readAsLinesSync);
+      typeMapping.forEach((k2, v2) {
+        doItSync(() => f.openSync(mode: v2 as FileMode));
+        doItSync(() => f.openWrite(mode: v2 as FileMode));
+        doItSync(() => f.readAsStringSync(encoding: v2 as Encoding));
+        doItSync(() => f.readAsLinesSync(encoding: v2 as Encoding));
+      });
     });
   });
 }
 
-fuzzAsyncMethods() {
+fuzzAsyncMethods() async {
   asyncStart();
-  var futures = <Future>[];
-  typeMapping.forEach((k, v) {
-    File? file;
-    doItSync(() => file = new File(v as String));
-    if (file == null) return;
-    final f = file!;
-    futures.add(doItAsync(f.exists));
-    futures.add(doItAsync(f.delete));
-    futures.add(doItAsync(() => f.parent));
-    futures.add(doItAsync(f.length));
-    futures.add(doItAsync(f.lastModified));
-    futures.add(doItAsync(f.open));
-    futures.add(doItAsync(() => f.path));
-    futures.add(doItAsync(f.readAsBytes));
-    futures.add(doItAsync(f.readAsLines));
-    futures.add(doItAsync(f.readAsString));
-    typeMapping.forEach((k2, v2) {
-      futures.add(doItAsync(() => f.open(mode: v2 as FileMode)));
-      futures.add(doItAsync(() => f.readAsString(encoding: v2 as Encoding)));
-      futures.add(doItAsync(() => f.readAsLines(encoding: v2 as Encoding)));
+  withTempDir('dart_file_fuzz', (temp) async {
+    final futures = <Future>[];
+    typeMapping.forEach((k, v) {
+      File? file;
+      doItSync(() => file = new File('${temp.path}/${v as String}'));
+      if (file == null) return;
+      final f = file!;
+      futures.add(doItAsync(f.exists));
+      futures.add(doItAsync(f.delete));
+      futures.add(doItAsync(() => f.parent));
+      futures.add(doItAsync(f.length));
+      futures.add(doItAsync(f.lastModified));
+      futures.add(doItAsync(f.open));
+      futures.add(doItAsync(() => f.path));
+      futures.add(doItAsync(f.readAsBytes));
+      futures.add(doItAsync(f.readAsLines));
+      futures.add(doItAsync(f.readAsString));
+      typeMapping.forEach((k2, v2) {
+        futures.add(doItAsync(() => f.open(mode: v2 as FileMode)));
+        futures.add(doItAsync(() => f.readAsString(encoding: v2 as Encoding)));
+        futures.add(doItAsync(() => f.readAsLines(encoding: v2 as Encoding)));
+      });
+    });
+    await Future.wait(futures).then((_) {
+      asyncEnd();
     });
   });
-  Future.wait(futures).then((_) => asyncEnd());
 }
 
 fuzzSyncRandomAccessMethods() {
-  var temp = Directory.systemTemp.createTempSync('dart_file_fuzz');
-  var file = new File('${temp.path}/x');
-  file.createSync();
-  var modes = [FileMode.read, FileMode.write, FileMode.append];
-  for (var m in modes) {
-    var opened = file.openSync(mode: m);
-    typeMapping.forEach((k, v) {
-      doItSync(() => opened.setPositionSync(v as int));
-      doItSync(() => opened.truncateSync(v as int));
-      doItSync(() => opened.writeByteSync(v as int));
-    });
-    for (var p in typePermutations(2)) {
-      doItSync(() => opened.writeStringSync(p[0], encoding: p[1]));
-    }
-    for (var p in typePermutations(3)) {
-      doItSync(() => opened.readIntoSync(p[0], p[1], p[2]));
-      doItSync(() => opened.writeFromSync(p[0], p[1], p[2]));
-    }
-    opened.closeSync();
-  }
-  temp.deleteSync(recursive: true);
-}
-
-fuzzAsyncRandomAccessMethods() {
-  var temp = Directory.systemTemp.createTempSync('dart_file_fuzz');
-  var file = new File('${temp.path}/x');
-  file.createSync();
-  var modes = [FileMode.read, FileMode.write, FileMode.append];
-  var futures = <Future>[];
-  var openedFiles = [];
-  for (var m in modes) {
-    var opened = file.openSync(mode: m);
-    openedFiles.add(opened);
-    typeMapping.forEach((k, v) {
-      futures.add(doItAsync(() => opened.setPosition(v as int)));
-      futures.add(doItAsync(() => opened.truncate(v as int)));
-      futures.add(doItAsync(() => opened.writeByte(v as int)));
-    });
-    for (var p in typePermutations(2)) {
-      futures.add(doItAsync(() => opened.writeString(p[0], encoding: p[1])));
-    }
-    for (var p in typePermutations(3)) {
-      futures.add(doItAsync(() => opened.readInto(p[0], p[1], p[2])));
-      futures.add(doItAsync(() => opened.writeFrom(p[0], p[1], p[2])));
-    }
-  }
-  Future.wait(futures).then((ignore) {
-    for (var opened in openedFiles) {
+  withTempDirSync('dart_file_fuzz', (temp) {
+    var file = new File('${temp.path}/x');
+    file.createSync();
+    var modes = [FileMode.read, FileMode.write, FileMode.append];
+    for (var m in modes) {
+      var opened = file.openSync(mode: m);
+      typeMapping.forEach((k, v) {
+        doItSync(() => opened.setPositionSync(v as int));
+        doItSync(() => opened.truncateSync(v as int));
+        doItSync(() => opened.writeByteSync(v as int));
+      });
+      for (var p in typePermutations(2)) {
+        doItSync(() => opened.writeStringSync(p[0], encoding: p[1]));
+      }
+      for (var p in typePermutations(3)) {
+        doItSync(() => opened.readIntoSync(p[0], p[1], p[2]));
+        doItSync(() => opened.writeFromSync(p[0], p[1], p[2]));
+      }
       opened.closeSync();
     }
-    temp.deleteSync(recursive: true);
+  });
+}
+
+fuzzAsyncRandomAccessMethods() async {
+  asyncStart();
+  await withTempDir('dart_file_fuzz', (temp) async {
+    var file = new File('${temp.path}/x');
+    file.createSync();
+    var modes = [FileMode.read, FileMode.write, FileMode.append];
+    var futures = <Future>[];
+    var openedFiles = [];
+    for (var m in modes) {
+      var opened = file.openSync(mode: m);
+      openedFiles.add(opened);
+      typeMapping.forEach((k, v) {
+        futures.add(doItAsync(() => opened.setPosition(v as int)));
+        futures.add(doItAsync(() => opened.truncate(v as int)));
+        futures.add(doItAsync(() => opened.writeByte(v as int)));
+      });
+      for (var p in typePermutations(2)) {
+        futures.add(doItAsync(() => opened.writeString(p[0], encoding: p[1])));
+      }
+      for (var p in typePermutations(3)) {
+        futures.add(doItAsync(() => opened.readInto(p[0], p[1], p[2])));
+        futures.add(doItAsync(() => opened.writeFrom(p[0], p[1], p[2])));
+      }
+    }
+    await Future.wait(futures).then((ignore) {
+      for (var opened in openedFiles) {
+        opened.closeSync();
+      }
+      asyncEnd();
+    });
   });
 }
 
diff --git a/tests/standalone/io/file_system_watcher_large_set_test.dart b/tests/standalone/io/file_system_watcher_large_set_test.dart
index 0f010cf..2a4ed9d 100644
--- a/tests/standalone/io/file_system_watcher_large_set_test.dart
+++ b/tests/standalone/io/file_system_watcher_large_set_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--delayed-filewatch-callback --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--delayed-filewatch-callback --enable-isolate-groups
 // VMOptions=--delayed-filewatch-callback --no-enable-isolate-groups
 
 // Verifies that cancelling subscription from inside of the event handler
diff --git a/tests/standalone/io/file_system_watcher_test.dart b/tests/standalone/io/file_system_watcher_test.dart
index e10bf9d..dae7f9d 100644
--- a/tests/standalone/io/file_system_watcher_test.dart
+++ b/tests/standalone/io/file_system_watcher_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/standalone/io/http_advanced_test.dart b/tests/standalone/io/http_advanced_test.dart
index 0ee5d65..87553d9 100644
--- a/tests/standalone/io/http_advanced_test.dart
+++ b/tests/standalone/io/http_advanced_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // VMOptions=
diff --git a/tests/standalone/io/http_basic_test.dart b/tests/standalone/io/http_basic_test.dart
index 54e1a35..acc6eb5 100644
--- a/tests/standalone/io/http_basic_test.dart
+++ b/tests/standalone/io/http_basic_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // VMOptions=--trace_shutdown
diff --git a/tests/standalone/io/http_read_test.dart b/tests/standalone/io/http_read_test.dart
index af75740..b6f4a7e 100644
--- a/tests/standalone/io/http_read_test.dart
+++ b/tests/standalone/io/http_read_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // VMOptions=
diff --git a/tests/standalone/io/issue_30687_test.dart b/tests/standalone/io/issue_30687_test.dart
index 96b514d..e994f09 100644
--- a/tests/standalone/io/issue_30687_test.dart
+++ b/tests/standalone/io/issue_30687_test.dart
@@ -5,40 +5,41 @@
 import 'dart:io';
 
 import 'package:expect/expect.dart';
+import 'package:path/path.dart' as path;
+
+import 'unix_socket_test.dart' show withTempDir;
 
 main() async {
-  Link link1 = new Link(
-      Directory.systemTemp.path + Platform.pathSeparator + 'link1.lnk');
-  Link link2 = new Link(
-      Directory.systemTemp.path + Platform.pathSeparator + 'link2.lnk');
+  await withTempDir('issue_30687', (Directory tempDir) async {
+    final link1 = Link(tempDir.path + Platform.pathSeparator + 'link1.lnk');
+    final link2 = Link(tempDir.path + Platform.pathSeparator + 'link2.lnk');
 
-  Directory target1 = new Directory(
-      Directory.systemTemp.path + Platform.pathSeparator + 'target1');
-  Directory target2 = new Directory(
-      Directory.systemTemp.path + Platform.pathSeparator + 'target2');
+    final target1 = Directory(path.join(tempDir.path, 'target1'));
+    final target2 = Directory(path.join(tempDir.path, 'target2'));
 
-  target1.createSync();
-  target2.createSync();
+    target1.createSync();
+    target2.createSync();
 
-  Expect.isTrue(target1.existsSync());
-  Expect.isTrue(target2.existsSync());
+    Expect.isTrue(target1.existsSync());
+    Expect.isTrue(target2.existsSync());
 
-  link1.createSync(target1.path);
-  link2.createSync(target2.path);
-  Expect.isTrue(link1.existsSync());
-  Expect.isTrue(link2.existsSync());
+    link1.createSync(target1.path);
+    link2.createSync(target2.path);
+    Expect.isTrue(link1.existsSync());
+    Expect.isTrue(link2.existsSync());
 
-  try {
-    Link renamed = await link1.rename(link2.path);
-    Expect.isFalse(link1.existsSync());
-    Expect.isTrue(renamed.existsSync());
-    Expect.equals(renamed.path, link2.path);
-  } finally {
-    target1.delete();
-    target2.delete();
-    link2.delete();
-    if (link1.existsSync()) {
-      link1.delete();
+    try {
+      Link renamed = await link1.rename(link2.path);
+      Expect.isFalse(link1.existsSync());
+      Expect.isTrue(renamed.existsSync());
+      Expect.equals(renamed.path, link2.path);
+    } finally {
+      target1.deleteSync();
+      target2.deleteSync();
+      link2.deleteSync();
+      if (link1.existsSync()) {
+        link1.deleteSync();
+      }
     }
-  }
+  });
 }
diff --git a/tests/standalone/io/pipe_server_test.dart b/tests/standalone/io/pipe_server_test.dart
index ab6b8e1..52d93b6 100644
--- a/tests/standalone/io/pipe_server_test.dart
+++ b/tests/standalone/io/pipe_server_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // OtherResources=readline_test1.dat
diff --git a/tests/standalone/io/platform_test.dart b/tests/standalone/io/platform_test.dart
index adea57e..ace9d85 100644
--- a/tests/standalone/io/platform_test.dart
+++ b/tests/standalone/io/platform_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/standalone/io/raw_datagram_read_all_test.dart b/tests/standalone/io/raw_datagram_read_all_test.dart
index 73d11c4..225da8e 100644
--- a/tests/standalone/io/raw_datagram_read_all_test.dart
+++ b/tests/standalone/io/raw_datagram_read_all_test.dart
@@ -29,7 +29,7 @@
         var datagram = receiver.receive()!;
         Expect.listEquals([0], datagram.data);
         if (timer != null) timer.cancel();
-        timer = new Timer(const Duration(milliseconds: 200), () {
+        timer = new Timer(const Duration(seconds: 1), () {
           Expect.isNull(receiver.receive());
           receiver.close();
           asyncEnd();
diff --git a/tests/standalone/io/raw_synchronous_socket_test.dart b/tests/standalone/io/raw_synchronous_socket_test.dart
index 180c6bd..50cb0f2 100644
--- a/tests/standalone/io/raw_synchronous_socket_test.dart
+++ b/tests/standalone/io/raw_synchronous_socket_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/standalone/io/shared_socket_test.dart b/tests/standalone/io/shared_socket_test.dart
index 15dac09..3195b63 100644
--- a/tests/standalone/io/shared_socket_test.dart
+++ b/tests/standalone/io/shared_socket_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:async';
diff --git a/tests/standalone/io/socket_close_test.dart b/tests/standalone/io/socket_close_test.dart
index 41fa8ac..72a15de 100644
--- a/tests/standalone/io/socket_close_test.dart
+++ b/tests/standalone/io/socket_close_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // VMOptions=
diff --git a/tests/standalone/io/socket_finalizer_test.dart b/tests/standalone/io/socket_finalizer_test.dart
index 94c9bcc..c82be22 100644
--- a/tests/standalone/io/socket_finalizer_test.dart
+++ b/tests/standalone/io/socket_finalizer_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // This test checks that sockets belonging to an isolate are properly cleaned up
diff --git a/tests/standalone/io/socket_many_connections_test.dart b/tests/standalone/io/socket_many_connections_test.dart
index 6b73038..0140df7 100644
--- a/tests/standalone/io/socket_many_connections_test.dart
+++ b/tests/standalone/io/socket_many_connections_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Test creating a large number of socket connections.
diff --git a/tests/standalone/io/stdio_socket_finalizer_test.dart b/tests/standalone/io/stdio_socket_finalizer_test.dart
index 46b4231..c33da51 100644
--- a/tests/standalone/io/stdio_socket_finalizer_test.dart
+++ b/tests/standalone/io/stdio_socket_finalizer_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // This test checks that stdin is *not* closed when an Isolate leaks it.
diff --git a/tests/standalone/io/unix_socket_regress_46634_test.dart b/tests/standalone/io/unix_socket_regress_46634_test.dart
new file mode 100644
index 0000000..31bce79
--- /dev/null
+++ b/tests/standalone/io/unix_socket_regress_46634_test.dart
@@ -0,0 +1,20 @@
+// 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 'unix_socket_test.dart' show withTempDir, testListenCloseListenClose;
+
+void main() async {
+  if (!Platform.isMacOS && !Platform.isLinux && !Platform.isAndroid) {
+    return;
+  }
+  final futures = <Future>[];
+  for (int i = 0; i < 10; ++i) {
+    futures.add(withTempDir('unix_socket_test', (Directory dir) async {
+      await testListenCloseListenClose('${dir.path}');
+    }));
+  }
+  await Future.wait(futures);
+}
diff --git a/tests/standalone/io/unix_socket_test.dart b/tests/standalone/io/unix_socket_test.dart
index 0553e6a..d510fb6 100644
--- a/tests/standalone/io/unix_socket_test.dart
+++ b/tests/standalone/io/unix_socket_test.dart
@@ -3,8 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io';
 import 'dart:convert';
+import 'dart:io';
 
 import 'package:expect/expect.dart';
 
@@ -12,8 +12,6 @@
   var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
   var server = await ServerSocket.bind(address, 0);
 
-  var type = FileSystemEntity.typeSync(address.address);
-
   var client = await Socket.connect(address, server.port);
   var completer = Completer<void>();
   server.listen((socket) async {
@@ -58,22 +56,23 @@
 }
 
 testBind(String name) async {
-  var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
-  var server = await ServerSocket.bind(address, 0, shared: false);
+  final address = InternetAddress('$name/sock', type: InternetAddressType.unix);
+  final server = await ServerSocket.bind(address, 0, shared: false);
   Expect.isTrue(server.address.toString().contains(name));
   // Unix domain socket does not have a valid port number.
   Expect.equals(server.port, 0);
 
-  var type = FileSystemEntity.typeSync(address.address);
-
-  var sub;
-  sub = server.listen((s) {
-    sub.cancel();
-    server.close();
+  final serverContinue = Completer();
+  final clientContinue = Completer();
+  server.listen((s) async {
+    await serverContinue.future;
+    clientContinue.complete();
   });
 
-  var socket = await Socket.connect(address, server.port);
+  final socket = await Socket.connect(address, server.port);
   socket.write(" socket content");
+  serverContinue.complete();
+  await clientContinue.future;
 
   socket.destroy();
   await server.close();
@@ -89,8 +88,6 @@
   // test if it is working correctly.
   await socket.close();
 
-  var type = FileSystemEntity.typeSync(address.address);
-
   // For robustness we ignore any clients unrelated to this test.
   List<int> sendData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
   socket2.listen((Socket client) async {
@@ -127,8 +124,6 @@
     completer.complete();
   });
 
-  var type = FileSystemEntity.typeSync(address.address);
-
   Socket client =
       await Socket.connect(address, server.port, sourceAddress: localAddress);
   Expect.equals(client.remoteAddress.address, address.address);
@@ -138,12 +133,12 @@
   await server.close();
 }
 
-Future testAbstractAddress() async {
+Future testAbstractAddress(String uniqueName) async {
   if (!Platform.isLinux && !Platform.isAndroid) {
     return;
   }
   var serverAddress =
-      InternetAddress('@temp.sock', type: InternetAddressType.unix);
+      InternetAddress('@temp.sock.$uniqueName', type: InternetAddressType.unix);
   ServerSocket server = await ServerSocket.bind(serverAddress, 0);
   final completer = Completer<void>();
   final content = 'random string';
@@ -171,7 +166,7 @@
   return buffer.toString();
 }
 
-Future testShortAbstractAddress() async {
+Future testShortAbstractAddress(String uniqueName) async {
   if (!Platform.isLinux && !Platform.isAndroid) {
     return;
   }
@@ -181,7 +176,7 @@
   Future? stdoutFuture;
   Future? stderrFuture;
   try {
-    var socketAddress = '@hidden';
+    var socketAddress = '@temp.sock.$uniqueName';
     var abstractSocketServer = getAbstractSocketTestFileName();
     // check if the executable exists, some build configurations do not
     // build it (e.g: precompiled simarm/simarm64)
@@ -189,7 +184,7 @@
       return;
     }
 
-    // Start up a subprocess that listens on '@hidden'.
+    // Start up a subprocess that listens on [socketAddress].
     process = await Process.start(abstractSocketServer, [socketAddress]);
     stdoutFuture = process.stdout
         .transform(const Utf8Decoder(allowMalformed: true))
@@ -453,10 +448,10 @@
 void main() async {
   try {
     await withTempDir('unix_socket_test', (Directory dir) async {
-      await testBind('${dir.path}');
+      await testAddress('${dir.path}');
     });
     await withTempDir('unix_socket_test', (Directory dir) async {
-      await testAddress('${dir.path}');
+      await testBind('${dir.path}');
     });
     await withTempDir('unix_socket_test', (Directory dir) async {
       await testBindShared('${dir.path}');
@@ -467,7 +462,9 @@
     await withTempDir('unix_socket_test', (Directory dir) async {
       await testSourceAddressConnect('${dir.path}');
     });
-    await testAbstractAddress();
+    await withTempDir('unix_socket_test', (Directory dir) async {
+      await testAbstractAddress(dir.uri.pathSegments.last);
+    });
     await withTempDir('unix_socket_test', (Directory dir) async {
       await testExistingFile('${dir.path}');
     });
@@ -477,7 +474,9 @@
     await withTempDir('unix_socket_test', (Directory dir) async {
       await testHttpServer('${dir.path}');
     });
-    await testShortAbstractAddress();
+    await withTempDir('unix_socket_test', (Directory dir) async {
+      await testShortAbstractAddress(dir.uri.pathSegments.last);
+    });
   } catch (e) {
     if (Platform.isMacOS || Platform.isLinux || Platform.isAndroid) {
       Expect.fail("Unexpected exception $e is thrown");
diff --git a/tests/standalone/io/wait_for_event_isolate_test.dart b/tests/standalone/io/wait_for_event_isolate_test.dart
index 15b970f..ce624e2 100644
--- a/tests/standalone/io/wait_for_event_isolate_test.dart
+++ b/tests/standalone/io/wait_for_event_isolate_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:async';
diff --git a/tests/standalone/packages_file_test.dart b/tests/standalone/packages_file_test.dart
index d39c6dc..99c2ab5 100644
--- a/tests/standalone/packages_file_test.dart
+++ b/tests/standalone/packages_file_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/standalone/regress_26031_test.dart b/tests/standalone/regress_26031_test.dart
index 25e9490..60dd89b 100644
--- a/tests/standalone/regress_26031_test.dart
+++ b/tests/standalone/regress_26031_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:io';
diff --git a/tests/standalone/regress_28854_1_test.dart b/tests/standalone/regress_28854_1_test.dart
index 2517e30..30b304a 100644
--- a/tests/standalone/regress_28854_1_test.dart
+++ b/tests/standalone/regress_28854_1_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library regress;
diff --git a/tests/standalone/regress_28854_2_test.dart b/tests/standalone/regress_28854_2_test.dart
index e528d34..21395c1 100644
--- a/tests/standalone/regress_28854_2_test.dart
+++ b/tests/standalone/regress_28854_2_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library regress;
diff --git a/tests/standalone/standalone_vm.status b/tests/standalone/standalone_vm.status
index 6a36f12..86c5c3c 100644
--- a/tests/standalone/standalone_vm.status
+++ b/tests/standalone/standalone_vm.status
@@ -7,9 +7,6 @@
 link_natives_lazily_test: SkipByDesign # Not supported.
 no_allow_absolute_addresses_test: SkipByDesign # Not supported.
 
-[ $runtime == vm ]
-typed_data_isolate_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-
 [ $system == android ]
 io/file_stat_test: Skip # Issue 26376
 io/file_system_watcher_test: Skip # Issue 26376
diff --git a/tests/standalone/typed_array_int64_uint64_test.dart b/tests/standalone/typed_array_int64_uint64_test.dart
index fb6bd2d..7b57986 100644
--- a/tests/standalone/typed_array_int64_uint64_test.dart
+++ b/tests/standalone/typed_array_int64_uint64_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Dart test program for testing native typed arrays, int64 and uint64 only.
diff --git a/tests/standalone/typed_array_test.dart b/tests/standalone/typed_array_test.dart
index d443da9..6e4c6c3 100644
--- a/tests/standalone/typed_array_test.dart
+++ b/tests/standalone/typed_array_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Dart test program for testing native float and int arrays.  64-bit int arrays
diff --git a/tests/standalone/typed_data_isolate_test.dart b/tests/standalone/typed_data_isolate_test.dart
index 80efe40..2573ada 100644
--- a/tests/standalone/typed_data_isolate_test.dart
+++ b/tests/standalone/typed_data_isolate_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Dart test program for testing typed data.
diff --git a/tests/standalone_2/io/directory_list_sync_test.dart b/tests/standalone_2/io/directory_list_sync_test.dart
index ec63715..b148ffd 100644
--- a/tests/standalone_2/io/directory_list_sync_test.dart
+++ b/tests/standalone_2/io/directory_list_sync_test.dart
@@ -6,10 +6,11 @@
 
 import 'dart:io';
 
+import 'package:path/path.dart' as path;
+
 void testList() {
-  File script = new File.fromUri(Platform.script);
-  // tests/standalone/io/../..
-  Directory startingDir = script.parent.parent.parent;
+  final startingDir =
+      Directory(path.normalize(path.join(Platform.executable, '../../../')));
   print("Recursively listing entries in directory ${startingDir.path} ...");
   List<FileSystemEntity> each =
       startingDir.listSync(recursive: true, followLinks: false);
diff --git a/tests/standalone_2/io/echo_server_stream_test.dart b/tests/standalone_2/io/echo_server_stream_test.dart
index 6b0b6c7..e0449a3 100644
--- a/tests/standalone_2/io/echo_server_stream_test.dart
+++ b/tests/standalone_2/io/echo_server_stream_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Echo server test program to test socket streams.
diff --git a/tests/standalone_2/io/file_fuzz_test.dart b/tests/standalone_2/io/file_fuzz_test.dart
index 60a7e5b..32ce6aa 100644
--- a/tests/standalone_2/io/file_fuzz_test.dart
+++ b/tests/standalone_2/io/file_fuzz_test.dart
@@ -11,111 +11,120 @@
 import 'dart:io';
 
 import 'fuzz_support.dart';
+import 'file_write_only_test.dart' show withTempDir, withTempDirSync;
 
 import "package:async_helper/async_helper.dart";
 
 fuzzSyncMethods() {
-  typeMapping.forEach((k, v) {
-    File f;
-    doItSync(() => f = new File(v));
-    if (f == null) return;
-    doItSync(f.existsSync);
-    doItSync(f.createSync);
-    doItSync(f.deleteSync);
-    doItSync(f.lengthSync);
-    doItSync(f.lastModifiedSync);
-    doItSync(() => f.path);
-    doItSync(() => f.openRead().listen((_) {}, onError: (e) {}));
-    doItSync(f.readAsBytesSync);
-    doItSync(f.readAsStringSync);
-    doItSync(f.readAsLinesSync);
-    typeMapping.forEach((k2, v2) {
-      doItSync(() => f.openSync(mode: v2));
-      doItSync(() => f.openWrite(mode: v2));
-      doItSync(() => f.readAsStringSync(encoding: v2));
-      doItSync(() => f.readAsLinesSync(encoding: v2));
+  withTempDirSync('dart_file_fuzz', (temp) {
+    typeMapping.forEach((k, v) {
+      File f;
+      doItSync(() => f = new File('${temp.path}/$v'));
+      if (f == null) return;
+      doItSync(f.existsSync);
+      doItSync(f.createSync);
+      doItSync(f.deleteSync);
+      doItSync(f.lengthSync);
+      doItSync(f.lastModifiedSync);
+      doItSync(() => f.path);
+      doItSync(() => f.openRead().listen((_) {}, onError: (e) {}));
+      doItSync(f.readAsBytesSync);
+      doItSync(f.readAsStringSync);
+      doItSync(f.readAsLinesSync);
+      typeMapping.forEach((k2, v2) {
+        doItSync(() => f.openSync(mode: v2));
+        doItSync(() => f.openWrite(mode: v2));
+        doItSync(() => f.readAsStringSync(encoding: v2));
+        doItSync(() => f.readAsLinesSync(encoding: v2));
+      });
     });
   });
 }
 
 fuzzAsyncMethods() {
   asyncStart();
-  var futures = <Future>[];
-  typeMapping.forEach((k, v) {
-    File f;
-    doItSync(() => f = new File(v));
-    if (f == null) return;
-    futures.add(doItAsync(f.exists));
-    futures.add(doItAsync(f.delete));
-    futures.add(doItAsync(() => f.parent));
-    futures.add(doItAsync(f.length));
-    futures.add(doItAsync(f.lastModified));
-    futures.add(doItAsync(f.open));
-    futures.add(doItAsync(() => f.path));
-    futures.add(doItAsync(f.readAsBytes));
-    futures.add(doItAsync(f.readAsLines));
-    futures.add(doItAsync(f.readAsString));
-    typeMapping.forEach((k2, v2) {
-      futures.add(doItAsync(() => f.open(mode: v2)));
-      futures.add(doItAsync(() => f.readAsString(encoding: v2)));
-      futures.add(doItAsync(() => f.readAsLines(encoding: v2)));
+  withTempDir('dart_file_fuzz', (temp) async {
+    var futures = <Future>[];
+    typeMapping.forEach((k, v) {
+      File f;
+      doItSync(() => f = new File('${temp.path}/$v'));
+      if (f == null) return;
+      futures.add(doItAsync(f.exists));
+      futures.add(doItAsync(f.delete));
+      futures.add(doItAsync(() => f.parent));
+      futures.add(doItAsync(f.length));
+      futures.add(doItAsync(f.lastModified));
+      futures.add(doItAsync(f.open));
+      futures.add(doItAsync(() => f.path));
+      futures.add(doItAsync(f.readAsBytes));
+      futures.add(doItAsync(f.readAsLines));
+      futures.add(doItAsync(f.readAsString));
+      typeMapping.forEach((k2, v2) {
+        futures.add(doItAsync(() => f.open(mode: v2)));
+        futures.add(doItAsync(() => f.readAsString(encoding: v2)));
+        futures.add(doItAsync(() => f.readAsLines(encoding: v2)));
+      });
+    });
+    await Future.wait(futures).then((_) {
+      asyncEnd();
     });
   });
-  Future.wait(futures).then((_) => asyncEnd());
 }
 
 fuzzSyncRandomAccessMethods() {
-  var temp = Directory.systemTemp.createTempSync('dart_file_fuzz');
-  var file = new File('${temp.path}/x');
-  file.createSync();
-  var modes = [FileMode.read, FileMode.write, FileMode.append];
-  for (var m in modes) {
-    var opened = file.openSync(mode: m);
-    typeMapping.forEach((k, v) {
-      doItSync(() => opened.setPositionSync(v));
-      doItSync(() => opened.truncateSync(v));
-      doItSync(() => opened.writeByteSync(v));
-    });
-    for (var p in typePermutations(2)) {
-      doItSync(() => opened.writeStringSync(p[0], encoding: p[1]));
-    }
-    for (var p in typePermutations(3)) {
-      doItSync(() => opened.readIntoSync(p[0], p[1], p[2]));
-      doItSync(() => opened.writeFromSync(p[0], p[1], p[2]));
-    }
-    opened.closeSync();
-  }
-  temp.deleteSync(recursive: true);
-}
-
-fuzzAsyncRandomAccessMethods() {
-  var temp = Directory.systemTemp.createTempSync('dart_file_fuzz');
-  var file = new File('${temp.path}/x');
-  file.createSync();
-  var modes = [FileMode.read, FileMode.write, FileMode.append];
-  var futures = <Future>[];
-  var openedFiles = [];
-  for (var m in modes) {
-    var opened = file.openSync(mode: m);
-    openedFiles.add(opened);
-    typeMapping.forEach((k, v) {
-      futures.add(doItAsync(() => opened.setPosition(v)));
-      futures.add(doItAsync(() => opened.truncate(v)));
-      futures.add(doItAsync(() => opened.writeByte(v)));
-    });
-    for (var p in typePermutations(2)) {
-      futures.add(doItAsync(() => opened.writeString(p[0], encoding: p[1])));
-    }
-    for (var p in typePermutations(3)) {
-      futures.add(doItAsync(() => opened.readInto(p[0], p[1], p[2])));
-      futures.add(doItAsync(() => opened.writeFrom(p[0], p[1], p[2])));
-    }
-  }
-  Future.wait(futures).then((ignore) {
-    for (var opened in openedFiles) {
+  withTempDirSync('dart_file_fuzz', (temp) {
+    var file = new File('${temp.path}/x');
+    file.createSync();
+    var modes = [FileMode.read, FileMode.write, FileMode.append];
+    for (var m in modes) {
+      var opened = file.openSync(mode: m);
+      typeMapping.forEach((k, v) {
+        doItSync(() => opened.setPositionSync(v));
+        doItSync(() => opened.truncateSync(v));
+        doItSync(() => opened.writeByteSync(v));
+      });
+      for (var p in typePermutations(2)) {
+        doItSync(() => opened.writeStringSync(p[0], encoding: p[1]));
+      }
+      for (var p in typePermutations(3)) {
+        doItSync(() => opened.readIntoSync(p[0], p[1], p[2]));
+        doItSync(() => opened.writeFromSync(p[0], p[1], p[2]));
+      }
       opened.closeSync();
     }
-    temp.deleteSync(recursive: true);
+  });
+}
+
+fuzzAsyncRandomAccessMethods() async {
+  asyncStart();
+  await withTempDir('dart_file_fuzz', (temp) async {
+    var file = new File('${temp.path}/x');
+    file.createSync();
+    var modes = [FileMode.read, FileMode.write, FileMode.append];
+    var futures = <Future>[];
+    var openedFiles = [];
+    for (var m in modes) {
+      var opened = file.openSync(mode: m);
+      openedFiles.add(opened);
+      typeMapping.forEach((k, v) {
+        futures.add(doItAsync(() => opened.setPosition(v)));
+        futures.add(doItAsync(() => opened.truncate(v)));
+        futures.add(doItAsync(() => opened.writeByte(v)));
+      });
+      for (var p in typePermutations(2)) {
+        futures.add(doItAsync(() => opened.writeString(p[0], encoding: p[1])));
+      }
+      for (var p in typePermutations(3)) {
+        futures.add(doItAsync(() => opened.readInto(p[0], p[1], p[2])));
+        futures.add(doItAsync(() => opened.writeFrom(p[0], p[1], p[2])));
+      }
+    }
+    await Future.wait(futures).then((ignore) {
+      for (var opened in openedFiles) {
+        opened.closeSync();
+      }
+      asyncEnd();
+    });
   });
 }
 
diff --git a/tests/standalone_2/io/file_system_watcher_large_set_test.dart b/tests/standalone_2/io/file_system_watcher_large_set_test.dart
index 9b3e290..326d201 100644
--- a/tests/standalone_2/io/file_system_watcher_large_set_test.dart
+++ b/tests/standalone_2/io/file_system_watcher_large_set_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=--delayed-filewatch-callback --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--delayed-filewatch-callback --enable-isolate-groups
 // VMOptions=--delayed-filewatch-callback --no-enable-isolate-groups
 
 // Verifies that cancelling subscription from inside of the event handler
diff --git a/tests/standalone_2/io/file_system_watcher_test.dart b/tests/standalone_2/io/file_system_watcher_test.dart
index 478f7077..bde35ce 100644
--- a/tests/standalone_2/io/file_system_watcher_test.dart
+++ b/tests/standalone_2/io/file_system_watcher_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/standalone_2/io/http_advanced_test.dart b/tests/standalone_2/io/http_advanced_test.dart
index c188870..10b6a5b 100644
--- a/tests/standalone_2/io/http_advanced_test.dart
+++ b/tests/standalone_2/io/http_advanced_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // VMOptions=
diff --git a/tests/standalone_2/io/http_basic_test.dart b/tests/standalone_2/io/http_basic_test.dart
index 4356479..1cae05b 100644
--- a/tests/standalone_2/io/http_basic_test.dart
+++ b/tests/standalone_2/io/http_basic_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // VMOptions=--trace_shutdown
diff --git a/tests/standalone_2/io/http_read_test.dart b/tests/standalone_2/io/http_read_test.dart
index 0cc4575..120e9ff 100644
--- a/tests/standalone_2/io/http_read_test.dart
+++ b/tests/standalone_2/io/http_read_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // VMOptions=
diff --git a/tests/standalone_2/io/issue_30687_test.dart b/tests/standalone_2/io/issue_30687_test.dart
index 1392012..71ee6fd 100644
--- a/tests/standalone_2/io/issue_30687_test.dart
+++ b/tests/standalone_2/io/issue_30687_test.dart
@@ -7,40 +7,41 @@
 import 'dart:io';
 
 import 'package:expect/expect.dart';
+import 'package:path/path.dart' as path;
+
+import 'unix_socket_test.dart' show withTempDir;
 
 main() async {
-  Link link1 = new Link(
-      Directory.systemTemp.path + Platform.pathSeparator + 'link1.lnk');
-  Link link2 = new Link(
-      Directory.systemTemp.path + Platform.pathSeparator + 'link2.lnk');
+  await withTempDir('issue_30687', (Directory tempDir) async {
+    final link1 = Link(tempDir.path + Platform.pathSeparator + 'link1.lnk');
+    final link2 = Link(tempDir.path + Platform.pathSeparator + 'link2.lnk');
 
-  Directory target1 = new Directory(
-      Directory.systemTemp.path + Platform.pathSeparator + 'target1');
-  Directory target2 = new Directory(
-      Directory.systemTemp.path + Platform.pathSeparator + 'target2');
+    final target1 = Directory(path.join(tempDir.path, 'target1'));
+    final target2 = Directory(path.join(tempDir.path, 'target2'));
 
-  target1.createSync();
-  target2.createSync();
+    target1.createSync();
+    target2.createSync();
 
-  Expect.isTrue(target1.existsSync());
-  Expect.isTrue(target2.existsSync());
+    Expect.isTrue(target1.existsSync());
+    Expect.isTrue(target2.existsSync());
 
-  link1.createSync(target1.path);
-  link2.createSync(target2.path);
-  Expect.isTrue(link1.existsSync());
-  Expect.isTrue(link2.existsSync());
+    link1.createSync(target1.path);
+    link2.createSync(target2.path);
+    Expect.isTrue(link1.existsSync());
+    Expect.isTrue(link2.existsSync());
 
-  try {
-    Link renamed = await link1.rename(link2.path);
-    Expect.isFalse(link1.existsSync());
-    Expect.isTrue(renamed.existsSync());
-    Expect.equals(renamed.path, link2.path);
-  } finally {
-    target1.delete();
-    target2.delete();
-    link2.delete();
-    if (link1.existsSync()) {
-      link1.delete();
+    try {
+      Link renamed = await link1.rename(link2.path);
+      Expect.isFalse(link1.existsSync());
+      Expect.isTrue(renamed.existsSync());
+      Expect.equals(renamed.path, link2.path);
+    } finally {
+      target1.deleteSync();
+      target2.deleteSync();
+      link2.deleteSync();
+      if (link1.existsSync()) {
+        link1.deleteSync();
+      }
     }
-  }
+  });
 }
diff --git a/tests/standalone_2/io/pipe_server_test.dart b/tests/standalone_2/io/pipe_server_test.dart
index 56253d5..4628c69 100644
--- a/tests/standalone_2/io/pipe_server_test.dart
+++ b/tests/standalone_2/io/pipe_server_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // OtherResources=readline_test1.dat
diff --git a/tests/standalone_2/io/platform_test.dart b/tests/standalone_2/io/platform_test.dart
index c91fdb5..2ddc45d 100644
--- a/tests/standalone_2/io/platform_test.dart
+++ b/tests/standalone_2/io/platform_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/standalone_2/io/raw_datagram_read_all_test.dart b/tests/standalone_2/io/raw_datagram_read_all_test.dart
index d8f9fab..8b7a7d7 100644
--- a/tests/standalone_2/io/raw_datagram_read_all_test.dart
+++ b/tests/standalone_2/io/raw_datagram_read_all_test.dart
@@ -31,7 +31,7 @@
         var datagram = receiver.receive();
         Expect.listEquals([0], datagram.data);
         if (timer != null) timer.cancel();
-        timer = new Timer(const Duration(milliseconds: 200), () {
+        timer = new Timer(const Duration(seconds: 1), () {
           Expect.isNull(receiver.receive());
           receiver.close();
           asyncEnd();
diff --git a/tests/standalone_2/io/raw_synchronous_socket_test.dart b/tests/standalone_2/io/raw_synchronous_socket_test.dart
index 1aa56d8..9e5b6bb 100644
--- a/tests/standalone_2/io/raw_synchronous_socket_test.dart
+++ b/tests/standalone_2/io/raw_synchronous_socket_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/standalone_2/io/shared_socket_test.dart b/tests/standalone_2/io/shared_socket_test.dart
index e4248bd..6a12132 100644
--- a/tests/standalone_2/io/shared_socket_test.dart
+++ b/tests/standalone_2/io/shared_socket_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:async';
diff --git a/tests/standalone_2/io/socket_close_test.dart b/tests/standalone_2/io/socket_close_test.dart
index 16a285a..f9ad2d0 100644
--- a/tests/standalone_2/io/socket_close_test.dart
+++ b/tests/standalone_2/io/socket_close_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // VMOptions=
diff --git a/tests/standalone_2/io/socket_finalizer_test.dart b/tests/standalone_2/io/socket_finalizer_test.dart
index a0cf894..ecd8de3 100644
--- a/tests/standalone_2/io/socket_finalizer_test.dart
+++ b/tests/standalone_2/io/socket_finalizer_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // This test checks that sockets belonging to an isolate are properly cleaned up
diff --git a/tests/standalone_2/io/socket_many_connections_test.dart b/tests/standalone_2/io/socket_many_connections_test.dart
index 0f53fe2..0e665dc 100644
--- a/tests/standalone_2/io/socket_many_connections_test.dart
+++ b/tests/standalone_2/io/socket_many_connections_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Test creating a large number of socket connections.
diff --git a/tests/standalone_2/io/stdio_socket_finalizer_test.dart b/tests/standalone_2/io/stdio_socket_finalizer_test.dart
index b42a023..7cc1b64 100644
--- a/tests/standalone_2/io/stdio_socket_finalizer_test.dart
+++ b/tests/standalone_2/io/stdio_socket_finalizer_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // This test checks that stdin is *not* closed when an Isolate leaks it.
diff --git a/tests/standalone_2/io/unix_socket_regress_46634_test.dart b/tests/standalone_2/io/unix_socket_regress_46634_test.dart
new file mode 100644
index 0000000..8920965
--- /dev/null
+++ b/tests/standalone_2/io/unix_socket_regress_46634_test.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.
+
+// @dart = 2.9
+import 'dart:io';
+
+import 'unix_socket_test.dart' show withTempDir, testListenCloseListenClose;
+
+void main() async {
+  if (!Platform.isMacOS && !Platform.isLinux && !Platform.isAndroid) {
+    return;
+  }
+  final futures = <Future>[];
+  for (int i = 0; i < 10; ++i) {
+    futures.add(withTempDir('unix_socket_test', (Directory dir) async {
+      await testListenCloseListenClose('${dir.path}');
+    }));
+  }
+  await Future.wait(futures);
+}
diff --git a/tests/standalone_2/io/unix_socket_test.dart b/tests/standalone_2/io/unix_socket_test.dart
index e63b9d8..a82a155 100644
--- a/tests/standalone_2/io/unix_socket_test.dart
+++ b/tests/standalone_2/io/unix_socket_test.dart
@@ -14,8 +14,6 @@
   var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
   var server = await ServerSocket.bind(address, 0);
 
-  var type = FileSystemEntity.typeSync(address.address);
-
   var client = await Socket.connect(address, server.port);
   var completer = Completer<void>();
   server.listen((socket) async {
@@ -60,22 +58,23 @@
 }
 
 testBind(String name) async {
-  var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
-  var server = await ServerSocket.bind(address, 0, shared: false);
+  final address = InternetAddress('$name/sock', type: InternetAddressType.unix);
+  final server = await ServerSocket.bind(address, 0, shared: false);
   Expect.isTrue(server.address.toString().contains(name));
   // Unix domain socket does not have a valid port number.
   Expect.equals(server.port, 0);
 
-  var type = FileSystemEntity.typeSync(address.address);
-
-  var sub;
-  sub = server.listen((s) {
-    sub.cancel();
-    server.close();
+  final serverContinue = Completer();
+  final clientContinue = Completer();
+  server.listen((s) async {
+    await serverContinue.future;
+    clientContinue.complete();
   });
 
-  var socket = await Socket.connect(address, server.port);
+  final socket = await Socket.connect(address, server.port);
   socket.write(" socket content");
+  serverContinue.complete();
+  await clientContinue.future;
 
   socket.destroy();
   await server.close();
@@ -91,8 +90,6 @@
   // test if it is working correctly.
   await socket.close();
 
-  var type = FileSystemEntity.typeSync(address.address);
-
   // For robustness we ignore any clients unrelated to this test.
   List<int> sendData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
   socket2.listen((Socket client) async {
@@ -129,8 +126,6 @@
     completer.complete();
   });
 
-  var type = FileSystemEntity.typeSync(address.address);
-
   Socket client =
       await Socket.connect(address, server.port, sourceAddress: localAddress);
   Expect.equals(client.remoteAddress.address, address.address);
@@ -140,12 +135,12 @@
   await server.close();
 }
 
-Future testAbstractAddress() async {
+Future testAbstractAddress(String uniqueName) async {
   if (!Platform.isLinux && !Platform.isAndroid) {
     return;
   }
   var serverAddress =
-      InternetAddress('@temp.sock', type: InternetAddressType.unix);
+      InternetAddress('@temp.sock.$uniqueName', type: InternetAddressType.unix);
   ServerSocket server = await ServerSocket.bind(serverAddress, 0);
   final completer = Completer<void>();
   final content = 'random string';
@@ -173,7 +168,7 @@
   return buffer.toString();
 }
 
-Future testShortAbstractAddress() async {
+Future testShortAbstractAddress(String uniqueName) async {
   if (!Platform.isLinux && !Platform.isAndroid) {
     return;
   }
@@ -183,7 +178,7 @@
   var stdoutFuture;
   var stderrFuture;
   try {
-    var socketAddress = '@hidden';
+    var socketAddress = '@temp.sock.$uniqueName';
     var abstractSocketServer = getAbstractSocketTestFileName();
     // check if the executable exists, some build configurations do not
     // build it (e.g: precompiled simarm/simarm64)
@@ -191,7 +186,7 @@
       return;
     }
 
-    // Start up a subprocess that listens on '@hidden'.
+    // Start up a subprocess that listens on [socketAddress].
     process = await Process.start(abstractSocketServer, [socketAddress]);
     stdoutFuture = process.stdout
         .transform(const Utf8Decoder(allowMalformed: true))
@@ -469,7 +464,9 @@
     await withTempDir('unix_socket_test', (Directory dir) async {
       await testSourceAddressConnect('${dir.path}');
     });
-    await testAbstractAddress();
+    await withTempDir('unix_socket_test', (Directory dir) async {
+      await testAbstractAddress(dir.uri.pathSegments.last);
+    });
     await withTempDir('unix_socket_test', (Directory dir) async {
       await testExistingFile('${dir.path}');
     });
@@ -479,7 +476,9 @@
     await withTempDir('unix_socket_test', (Directory dir) async {
       await testHttpServer('${dir.path}');
     });
-    await testShortAbstractAddress();
+    await withTempDir('unix_socket_test', (Directory dir) async {
+      await testShortAbstractAddress(dir.uri.pathSegments.last);
+    });
   } catch (e) {
     if (Platform.isMacOS || Platform.isLinux || Platform.isAndroid) {
       Expect.fail("Unexpected exception $e is thrown");
diff --git a/tests/standalone_2/io/wait_for_event_isolate_test.dart b/tests/standalone_2/io/wait_for_event_isolate_test.dart
index f3638ec..a22ce25 100644
--- a/tests/standalone_2/io/wait_for_event_isolate_test.dart
+++ b/tests/standalone_2/io/wait_for_event_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:async';
diff --git a/tests/standalone_2/packages_file_test.dart b/tests/standalone_2/packages_file_test.dart
index 94132d6..a527ab4 100644
--- a/tests/standalone_2/packages_file_test.dart
+++ b/tests/standalone_2/packages_file_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import "dart:async";
diff --git a/tests/standalone_2/regress_26031_test.dart b/tests/standalone_2/regress_26031_test.dart
index fc161c8..933f5b9 100644
--- a/tests/standalone_2/regress_26031_test.dart
+++ b/tests/standalone_2/regress_26031_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 import 'dart:io';
diff --git a/tests/standalone_2/regress_28854_1_test.dart b/tests/standalone_2/regress_28854_1_test.dart
index 7b35e32..fdc3cc1 100644
--- a/tests/standalone_2/regress_28854_1_test.dart
+++ b/tests/standalone_2/regress_28854_1_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library regress;
diff --git a/tests/standalone_2/regress_28854_2_test.dart b/tests/standalone_2/regress_28854_2_test.dart
index 23c26eb..d05b294 100644
--- a/tests/standalone_2/regress_28854_2_test.dart
+++ b/tests/standalone_2/regress_28854_2_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library regress;
diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status
index 4d8d63c..86c5c3c 100644
--- a/tests/standalone_2/standalone_2_vm.status
+++ b/tests/standalone_2/standalone_2_vm.status
@@ -7,9 +7,6 @@
 link_natives_lazily_test: SkipByDesign # Not supported.
 no_allow_absolute_addresses_test: SkipByDesign # Not supported.
 
-[ $runtime == vm ]
-typed_data_isolate_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-
 [ $system == android ]
 io/file_stat_test: Skip # Issue 26376
 io/file_system_watcher_test: Skip # Issue 26376
@@ -78,19 +75,3 @@
 io/dart_std_io_pipe_test: Timeout, Pass
 io/http_client_stays_alive_test: Skip # Spawns process in Dart2 mode.
 io/process_sync_test: Timeout, Pass
-
-[ $hot_reload || $hot_reload_rollback ]
-io/file_system_watcher_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/platform_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/raw_synchronous_socket_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/shared_socket_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/socket_finalizer_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/socket_many_connections_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/stdio_socket_finalizer_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/wait_for_event_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-regress_26031_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-regress_28854_1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-regress_28854_2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-typed_array_int64_uint64_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-typed_array_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-typed_data_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
diff --git a/tests/standalone_2/typed_array_int64_uint64_test.dart b/tests/standalone_2/typed_array_int64_uint64_test.dart
index 3153df9..3eb3833 100644
--- a/tests/standalone_2/typed_array_int64_uint64_test.dart
+++ b/tests/standalone_2/typed_array_int64_uint64_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Dart test program for testing native typed arrays, int64 and uint64 only.
diff --git a/tests/standalone_2/typed_array_test.dart b/tests/standalone_2/typed_array_test.dart
index 0f08a80..94be7ec 100644
--- a/tests/standalone_2/typed_array_test.dart
+++ b/tests/standalone_2/typed_array_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Dart test program for testing native float and int arrays.  64-bit int arrays
diff --git a/tests/standalone_2/typed_data_isolate_test.dart b/tests/standalone_2/typed_data_isolate_test.dart
index bf2eaa4..0868696 100644
--- a/tests/standalone_2/typed_data_isolate_test.dart
+++ b/tests/standalone_2/typed_data_isolate_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 //
 // Dart test program for testing typed data.
diff --git a/tests/web/inferrer_is_int_test.dart b/tests/web/inferrer_is_int_test.dart
index f544578..59813ff 100644
--- a/tests/web/inferrer_is_int_test.dart
+++ b/tests/web/inferrer_is_int_test.dart
@@ -6,16 +6,17 @@
 // literal might become an int at runtime.
 
 import "package:expect/expect.dart";
-import '../language/compiler_annotations.dart';
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 callWithStringAndDouble(value) {
   () => 42;
   if (value is! int) throw new ArgumentError(value);
   return 42;
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 callWithDouble(value) {
   () => 42;
   if (value is! int) throw new ArgumentError(value);
diff --git a/tests/web/internal/javascriptobject_extensions_test.dart b/tests/web/internal/javascriptobject_extensions_test.dart
new file mode 100644
index 0000000..4edd79d
--- /dev/null
+++ b/tests/web/internal/javascriptobject_extensions_test.dart
@@ -0,0 +1,197 @@
+// 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.
+
+// Tests that JS objects can be referred to as extensions of JavaScriptObject.
+
+@JS()
+library javascriptobject_extensions_test;
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart';
+import 'package:expect/expect.dart' show hasUnsoundNullSafety;
+import 'package:expect/minitest.dart';
+
+import 'dart:typed_data';
+import 'dart:_interceptors'
+    show JavaScriptObject, UnknownJavaScriptObject, JSObject;
+
+@JS()
+external void eval(String code);
+
+class InterfaceClass {}
+
+@JS('JSClass')
+class JSClass implements InterfaceClass {
+  external JSClass();
+  external String get name;
+}
+
+class ImplementationClass implements JSClass {
+  String get name => 'ImplementationClass';
+}
+
+@JS()
+@anonymous
+class AnonymousClass {
+  external String get name;
+}
+
+class DartClass {}
+
+external AnonymousClass get anonymousObj;
+
+external ByteBuffer get arrayBuffer;
+
+@JS('arrayBuffer')
+external dynamic get arrayBufferDynamic;
+
+// Extension on JavaScriptObject. In the future, when extension types are
+// introduced, this will be explicitly disallowed.
+extension JavaScriptObjectExtension on JavaScriptObject {
+  // Use `className` instead so there's no ambiguity on what method is called.
+  String get className => getProperty(this, 'name');
+}
+
+// Test runtime type checks and casts.
+@pragma('dart2js:noInline')
+void runtimeIsAndAs<T>(instance, [bool expectation = true]) {
+  expect(instance is T, expectation);
+  expect(() => instance as T, expectation ? returnsNormally : throws);
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+JavaScriptObject returnJavaScriptObject() => throw '';
+
+JavaScriptObject? returnNullableJavaScriptObject() => throw '';
+
+JSClass returnJS() => throw '';
+
+AnonymousClass returnAnon() => throw '';
+
+UnknownJavaScriptObject returnUnknownJavaScriptObject() => throw '';
+
+ImplementationClass returnImpl() => throw '';
+
+main() {
+  eval(r'''
+    function JSClass() {
+      this.name = 'JSClass';
+    }
+    self.anonymousObj = {
+      name: 'AnonymousClass',
+    };
+    self.arrayBuffer = new ArrayBuffer();
+  ''');
+
+  // Instances of JS classes can be casted to JavaScriptObject and back.
+  var jsObj = JSClass();
+  expect(jsObj is JavaScriptObject, true);
+  runtimeIsAndAs<JavaScriptObject>(jsObj);
+  var javaScriptObject = jsObj as JavaScriptObject;
+  expect(javaScriptObject.className == 'JSClass', true);
+  expect(javaScriptObject is JSClass, true);
+  runtimeIsAndAs<JSClass>(javaScriptObject);
+
+  // Object literals can be casted to JavaScriptObject and back.
+  expect(anonymousObj is JavaScriptObject, true);
+  runtimeIsAndAs<JavaScriptObject>(anonymousObj);
+  javaScriptObject = anonymousObj as JavaScriptObject;
+  expect(javaScriptObject.className == 'AnonymousClass', true);
+  expect(javaScriptObject is AnonymousClass, true);
+  runtimeIsAndAs<AnonymousClass>(javaScriptObject);
+
+  // Dart objects that don't implement a JS type cannot be casted to or from
+  // JavaScriptObject.
+  var dartObj = DartClass();
+  expect(dartObj is JavaScriptObject, false);
+  runtimeIsAndAs<JavaScriptObject>(dartObj, false);
+  expect(javaScriptObject is DartClass, false);
+  runtimeIsAndAs<DartClass>(javaScriptObject, false);
+
+  // Native objects cannot be casted to or from JavaScriptObject.
+  expect(arrayBuffer is JavaScriptObject, false);
+  runtimeIsAndAs<JavaScriptObject>(arrayBuffer, false);
+  expect(javaScriptObject is ByteBuffer, false);
+  runtimeIsAndAs<ByteBuffer>(javaScriptObject, false);
+
+  // Dynamic native objects are intercepted and cannot be casted to
+  // JavaScriptObject.
+  runtimeIsAndAs<JavaScriptObject>(arrayBufferDynamic, false);
+
+  // Make sure `Object` methods work with JavaScriptObject like they do with JS
+  // interop objects.
+  expect(anonymousObj == javaScriptObject, true);
+  expect(javaScriptObject.hashCode, isNotNull);
+  expect(javaScriptObject.toString, isNotNull);
+  expect(javaScriptObject.noSuchMethod, isNotNull);
+  expect(javaScriptObject.runtimeType, isNotNull);
+
+  // Test that nullability works as expected.
+  expect(null is JavaScriptObject?, true);
+  runtimeIsAndAs<JavaScriptObject?>(null);
+  expect(null is JavaScriptObject, false);
+  runtimeIsAndAs<JavaScriptObject>(null, hasUnsoundNullSafety);
+
+  // Transitive is and as.
+  // JS type <: JavaScriptObject <: JSObject
+  expect(jsObj is JSObject, true);
+  runtimeIsAndAs<JSObject>(jsObj);
+  // JavaScriptObject <: JS type <: Dart interface
+  expect(javaScriptObject is InterfaceClass, true);
+  runtimeIsAndAs<InterfaceClass>(javaScriptObject);
+  // Dart implementation <: JS type <: JavaScriptObject
+  var impl = ImplementationClass();
+  expect(impl is JavaScriptObject, true);
+  runtimeIsAndAs<JavaScriptObject>(impl);
+  // Dart implementation <: JS type <: JavaScriptObject <: JSObject
+  expect(impl is JSObject, true);
+  runtimeIsAndAs<JSObject>(impl);
+
+  // Test that subtyping with nullability works as expected.
+  expect(returnJavaScriptObject is JavaScriptObject? Function(), true);
+  expect(returnNullableJavaScriptObject is JavaScriptObject Function(),
+      hasUnsoundNullSafety);
+
+  // Test that JavaScriptObject can be used in place of package:js types in
+  // function types, and vice versa.
+  expect(returnJavaScriptObject is JSClass Function(), true);
+  expect(returnJS is JavaScriptObject Function(), true);
+  expect(returnJavaScriptObject is AnonymousClass Function(), true);
+  expect(returnAnon is JavaScriptObject Function(), true);
+
+  // Transitive subtyping.
+  // UnknownJavaScriptObject <: JavaScriptObject <: JS type
+  expect(returnUnknownJavaScriptObject is JSClass Function(), true);
+  // JS type <: JavaScriptObject <: JSObject
+  expect(returnJS is JSObject Function(), true);
+  // JavaScriptObject <: JS type <: Dart interface
+  expect(returnJavaScriptObject is InterfaceClass Function(), true);
+  // Dart implementation <: JS type <: JavaScriptObject
+  expect(returnImpl is JavaScriptObject Function(), true);
+  // UnknownJavaScriptObject <: JavaScriptObject <: JS type <: Dart interface
+  expect(returnUnknownJavaScriptObject is InterfaceClass Function(), true);
+  // Dart implementation <: JS type <: JavaScriptObject <: JSObject
+  expect(returnImpl is JSObject Function(), true);
+
+  // Run above subtype checks but at runtime.
+  expect(confuse(returnJavaScriptObject) is JavaScriptObject? Function(), true);
+  expect(confuse(returnNullableJavaScriptObject) is JavaScriptObject Function(),
+      hasUnsoundNullSafety);
+
+  expect(confuse(returnJavaScriptObject) is JSClass Function(), true);
+  expect(confuse(returnJS) is JavaScriptObject Function(), true);
+  expect(confuse(returnJavaScriptObject) is AnonymousClass Function(), true);
+  expect(confuse(returnAnon) is JavaScriptObject Function(), true);
+
+  expect(confuse(returnUnknownJavaScriptObject) is JSClass Function(), true);
+  expect(confuse(returnJS) is JSObject Function(), true);
+  expect(confuse(returnJavaScriptObject) is InterfaceClass Function(), true);
+  expect(confuse(returnImpl) is JavaScriptObject Function(), true);
+  expect(confuse(returnUnknownJavaScriptObject) is InterfaceClass Function(),
+      true);
+  expect(confuse(returnImpl) is JSObject Function(), true);
+}
diff --git a/tests/web/regress/46589_test.dart b/tests/web/regress/46589_test.dart
new file mode 100644
index 0000000..c4070d5
--- /dev/null
+++ b/tests/web/regress/46589_test.dart
@@ -0,0 +1,16 @@
+// 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:expect/expect.dart';
+
+typedef MyVoid = void;
+
+bool isVoid<X>() {
+  return X == MyVoid;
+}
+
+void main() {
+  Expect.isFalse(isVoid<int>());
+  Expect.isTrue(isVoid<void>());
+}
diff --git a/tests/web_2/inferrer_is_int_test.dart b/tests/web_2/inferrer_is_int_test.dart
index 4aa7717..0f58deb 100644
--- a/tests/web_2/inferrer_is_int_test.dart
+++ b/tests/web_2/inferrer_is_int_test.dart
@@ -8,16 +8,17 @@
 // literal might become an int at runtime.
 
 import "package:expect/expect.dart";
-import '../language_2/compiler_annotations.dart';
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 callWithStringAndDouble(value) {
   () => 42;
   if (value is! int) throw new ArgumentError(value);
   return 42;
 }
 
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
 callWithDouble(value) {
   () => 42;
   if (value is! int) throw new ArgumentError(value);
diff --git a/tests/web_2/internal/javascriptobject_extensions_test.dart b/tests/web_2/internal/javascriptobject_extensions_test.dart
new file mode 100644
index 0000000..6189667
--- /dev/null
+++ b/tests/web_2/internal/javascriptobject_extensions_test.dart
@@ -0,0 +1,179 @@
+// 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.
+
+// Tests that JS objects can be referred to as extensions of JavaScriptObject.
+
+@JS()
+library javascriptobject_extensions_test;
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart';
+import 'package:expect/minitest.dart';
+
+import 'dart:typed_data';
+import 'dart:_interceptors'
+    show JavaScriptObject, UnknownJavaScriptObject, JSObject;
+
+@JS()
+external void eval(String code);
+
+class InterfaceClass {}
+
+@JS('JSClass')
+class JSClass implements InterfaceClass {
+  external JSClass();
+  external String get name;
+}
+
+class ImplementationClass implements JSClass {
+  String get name => 'ImplementationClass';
+}
+
+@JS()
+@anonymous
+class AnonymousClass {
+  external String get name;
+}
+
+class DartClass {}
+
+external AnonymousClass get anonymousObj;
+
+external ByteBuffer get arrayBuffer;
+
+@JS('arrayBuffer')
+external dynamic get arrayBufferDynamic;
+
+// Extension on JavaScriptObject. In the future, when extension types are
+// introduced, this will be explicitly disallowed.
+extension JavaScriptObjectExtension on JavaScriptObject {
+  // Use `className` instead so there's no ambiguity on what method is called.
+  String get className => getProperty(this, 'name');
+}
+
+// Test runtime type checks and casts.
+@pragma('dart2js:noInline')
+void runtimeIsAndAs<T>(instance, [bool expectation = true]) {
+  expect(instance is T, expectation);
+  expect(() => instance as T, expectation ? returnsNormally : throws);
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+JavaScriptObject returnJavaScriptObject() => throw '';
+
+JSClass returnJS() => throw '';
+
+AnonymousClass returnAnon() => throw '';
+
+UnknownJavaScriptObject returnUnknownJavaScriptObject() => throw '';
+
+ImplementationClass returnImpl() => throw '';
+
+main() {
+  eval(r'''
+    function JSClass() {
+      this.name = 'JSClass';
+    }
+    self.anonymousObj = {
+      name: 'AnonymousClass',
+    };
+    self.arrayBuffer = new ArrayBuffer();
+  ''');
+
+  // Instances of JS classes can be casted to JavaScriptObject and back.
+  var jsObj = JSClass();
+  expect(jsObj is JavaScriptObject, true);
+  runtimeIsAndAs<JavaScriptObject>(jsObj);
+  var javaScriptObject = jsObj as JavaScriptObject;
+  expect(javaScriptObject.className == 'JSClass', true);
+  expect(javaScriptObject is JSClass, true);
+  runtimeIsAndAs<JSClass>(javaScriptObject);
+
+  // Object literals can be casted to JavaScriptObject and back.
+  expect(anonymousObj is JavaScriptObject, true);
+  runtimeIsAndAs<JavaScriptObject>(anonymousObj);
+  javaScriptObject = anonymousObj as JavaScriptObject;
+  expect(javaScriptObject.className == 'AnonymousClass', true);
+  expect(javaScriptObject is AnonymousClass, true);
+  runtimeIsAndAs<AnonymousClass>(javaScriptObject);
+
+  // Dart objects that don't implement a JS type cannot be casted to or from
+  // JavaScriptObject.
+  var dartObj = DartClass();
+  expect(dartObj is JavaScriptObject, false);
+  runtimeIsAndAs<JavaScriptObject>(dartObj, false);
+  expect(javaScriptObject is DartClass, false);
+  runtimeIsAndAs<DartClass>(javaScriptObject, false);
+
+  // Native objects cannot be casted to or from JavaScriptObject.
+  expect(arrayBuffer is JavaScriptObject, false);
+  runtimeIsAndAs<JavaScriptObject>(arrayBuffer, false);
+  expect(javaScriptObject is ByteBuffer, false);
+  runtimeIsAndAs<ByteBuffer>(javaScriptObject, false);
+
+  // Dynamic native objects are intercepted and cannot be casted to
+  // JavaScriptObject.
+  runtimeIsAndAs<JavaScriptObject>(arrayBufferDynamic, false);
+
+  // Make sure `Object` methods work with JavaScriptObject like they do with JS
+  // interop objects.
+  expect(anonymousObj == javaScriptObject, true);
+  expect(javaScriptObject.hashCode, isNotNull);
+  expect(javaScriptObject.toString, isNotNull);
+  expect(javaScriptObject.noSuchMethod, isNotNull);
+  expect(javaScriptObject.runtimeType, isNotNull);
+
+  // Transitive is and as.
+  // JS type <: JavaScriptObject <: JSObject
+  expect(jsObj is JSObject, true);
+  runtimeIsAndAs<JSObject>(jsObj);
+  // JavaScriptObject <: JS type <: Dart interface
+  expect(javaScriptObject is InterfaceClass, true);
+  runtimeIsAndAs<InterfaceClass>(javaScriptObject);
+  // Dart implementation <: JS type <: JavaScriptObject
+  var impl = ImplementationClass();
+  expect(impl is JavaScriptObject, true);
+  runtimeIsAndAs<JavaScriptObject>(impl);
+  // Dart implementation <: JS type <: JavaScriptObject <: JSObject
+  expect(impl is JSObject, true);
+  runtimeIsAndAs<JSObject>(impl);
+
+  // Test that JavaScriptObject can be used in place of package:js types in
+  // function types, and vice versa.
+  expect(returnJavaScriptObject is JSClass Function(), true);
+  expect(returnJS is JavaScriptObject Function(), true);
+  expect(returnJavaScriptObject is AnonymousClass Function(), true);
+  expect(returnAnon is JavaScriptObject Function(), true);
+
+  // Transitive subtyping.
+  // UnknownJavaScriptObject <: JavaScriptObject <: JS type
+  expect(returnUnknownJavaScriptObject is JSClass Function(), true);
+  // JS type <: JavaScriptObject <: JSObject
+  expect(returnJS is JSObject Function(), true);
+  // JavaScriptObject <: JS type <: Dart interface
+  expect(returnJavaScriptObject is InterfaceClass Function(), true);
+  // Dart implementation <: JS type <: JavaScriptObject
+  expect(returnImpl is JavaScriptObject Function(), true);
+  // UnknownJavaScriptObject <: JavaScriptObject <: JS type <: Dart interface
+  expect(returnUnknownJavaScriptObject is InterfaceClass Function(), true);
+  // Dart implementation <: JS type <: JavaScriptObject <: JSObject
+  expect(returnImpl is JSObject Function(), true);
+
+  // Run above subtype checks but at runtime.
+  expect(confuse(returnJavaScriptObject) is JSClass Function(), true);
+  expect(confuse(returnJS) is JavaScriptObject Function(), true);
+  expect(confuse(returnJavaScriptObject) is AnonymousClass Function(), true);
+  expect(confuse(returnAnon) is JavaScriptObject Function(), true);
+
+  expect(confuse(returnUnknownJavaScriptObject) is JSClass Function(), true);
+  expect(confuse(returnJS) is JSObject Function(), true);
+  expect(confuse(returnJavaScriptObject) is InterfaceClass Function(), true);
+  expect(confuse(returnImpl) is JavaScriptObject Function(), true);
+  expect(confuse(returnUnknownJavaScriptObject) is InterfaceClass Function(),
+      true);
+  expect(confuse(returnImpl) is JSObject Function(), true);
+}
diff --git a/tests/web_2/regress/46589_test.dart b/tests/web_2/regress/46589_test.dart
new file mode 100644
index 0000000..c4070d5
--- /dev/null
+++ b/tests/web_2/regress/46589_test.dart
@@ -0,0 +1,16 @@
+// 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:expect/expect.dart';
+
+typedef MyVoid = void;
+
+bool isVoid<X>() {
+  return X == MyVoid;
+}
+
+void main() {
+  Expect.isFalse(isVoid<int>());
+  Expect.isTrue(isVoid<void>());
+}
diff --git a/third_party/devtools/update.sh b/third_party/devtools/update.sh
index ae3aa49..90533c5 100755
--- a/third_party/devtools/update.sh
+++ b/third_party/devtools/update.sh
@@ -38,4 +38,3 @@
   -install-mode copy \
   -preserve-writable \
   -tag git_revision:$1
-
diff --git a/tools/VERSION b/tools/VERSION
index 08a3fdb..c8fc427 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 301
-PRERELEASE_PATCH 2
\ No newline at end of file
+PRERELEASE 377
+PRERELEASE_PATCH 1
\ No newline at end of file
diff --git a/tools/bots/flutter/analyze_flutter_plugins.sh b/tools/bots/flutter/analyze_flutter_plugins.sh
index 9696c74..3616faa 100755
--- a/tools/bots/flutter/analyze_flutter_plugins.sh
+++ b/tools/bots/flutter/analyze_flutter_plugins.sh
@@ -36,4 +36,6 @@
 (cd script/tool; dart analyze --fatal-infos)
 
 # Invoke the repo's analysis script.
-./script/tool_runner.sh analyze --analysis-sdk $sdk
+./script/tool_runner.sh analyze \
+  --analysis-sdk $sdk \
+  --custom-analysis=script/configs/custom_analysis.yaml
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 0120f7e..6120112 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -1727,11 +1727,44 @@
       },
       "steps": [
         {
-          "name": "build dart",
+          "name": "build dart ia32",
           "script": "tools/build.py",
           "arguments": [
             "--mode=all",
-            "--arch=all",
+            "--arch=ia32",
+            "--no-clang",
+            "--no-goma",
+            "runtime"
+          ]
+        },
+        {
+          "name": "build dart x64",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=all",
+            "--arch=x64",
+            "--no-clang",
+            "--no-goma",
+            "runtime"
+          ]
+        },
+        {
+          "name": "build dart simarm",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=all",
+            "--arch=simarm",
+            "--no-clang",
+            "--no-goma",
+            "runtime"
+          ]
+        },
+        {
+          "name": "build dart simarm64",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=all",
+            "--arch=simarm64",
             "--no-clang",
             "--no-goma",
             "runtime"
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index f24f9ed..72cf73a 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -117,7 +117,9 @@
         "/**",
         " * An opaque canvas object representing a gradient.",
         " *",
-        " * Created by calling [createLinearGradient] or [createRadialGradient] on a",
+        " * Created by calling the methods",
+        " * [CanvasRenderingContext2D.createLinearGradient] or",
+        " * [CanvasRenderingContext2D.createRadialGradient] on a",
         " * [CanvasRenderingContext2D] object.",
         " *",
         " * Example usage:",
@@ -164,7 +166,8 @@
         "/**",
         " * An opaque object representing a pattern of image, canvas, or video.",
         " *",
-        " * Created by calling [createPattern] on a [CanvasRenderingContext2D] object.",
+        " * Created by calling [CanvasRenderingContext2D.createPattern] on a",
+        " * [CanvasRenderingContext2D] object.",
         " *",
         " * Example usage:",
         " *",
@@ -2553,7 +2556,7 @@
           "   * * [COMMENT_NODE] if this node is a [Comment].",
           "   * * [DOCUMENT_FRAGMENT_NODE] if this node is a [DocumentFragment].",
           "   * * [DOCUMENT_NODE] if this node is a [Document].",
-          "   * * [DOCUMENT_TYPE_NODE] if this node is a [DocumentType] node.",
+          "   * * [DOCUMENT_TYPE_NODE] if this node is a [_DocumentType] node.",
           "   * * [ELEMENT_NODE] if this node is an [Element].",
           "   * * [ENTITY_NODE] if this node is an entity.",
           "   * * [ENTITY_REFERENCE_NODE] if this node is an entity reference.",
@@ -3171,7 +3174,7 @@
         " * The message event handler receives a [MessageEvent] object",
         " * as its sole argument.",
         " * You can also define open, close, and error handlers,",
-        " * as specified by [WebSocketEvents].",
+        " * as specified by [Event]s.",
         " *",
         " * For more information, see the",
         " * [WebSockets](http://www.dartlang.org/docs/library-tour/#html-websockets)",
@@ -4355,7 +4358,8 @@
           "   * Length of time in milliseconds before a request is automatically",
           "   * terminated.",
           "   *",
-          "   * When the time has passed, a [TimeoutEvent] is dispatched.",
+          "   * When the time has passed, a [HttpRequestEventTarget.timeoutEvent] is",
+          "   * dispatched.",
           "   *",
           "   * If [timeout] is set to 0, then the request will not time out.",
           "   *",
@@ -4370,7 +4374,6 @@
         "upload": [
           "/**",
           "   * [EventTarget] that can hold listeners to track the progress of the request.",
-          "   * The events fired will be members of [HttpRequestUploadEvents].",
           "   */"
         ],
         "withCredentials": [
@@ -5157,9 +5160,9 @@
           "/**",
           "   * Get a Stream that fires events when AudioProcessingEvents occur.",
           "   * This particular stream is special in that it only allows one listener to a",
-          "   * given stream. Converting the returned Stream [asBroadcast] will likely ruin",
-          "   * the soft-real-time properties which which these events are fired and can",
-          "   * be processed.",
+          "   * given stream. Converting the returned [Stream.asBroadcastStream] will",
+          "   * likely ruin the soft-real-time properties which which these events are",
+          "   * fired and can be processed.",
           "   */"
         ]
       }
diff --git a/tools/dom/scripts/dartdomgenerator.py b/tools/dom/scripts/dartdomgenerator.py
index 6e529a4..944d36a 100755
--- a/tools/dom/scripts/dartdomgenerator.py
+++ b/tools/dom/scripts/dartdomgenerator.py
@@ -207,9 +207,9 @@
         prefix_arg, 'cd', library_dir, ';', copy_dart_script, output_dir, library_filename
     ])
     subprocess.call([command], shell=True)
-    prebuilt_dartfmt = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dartfmt')
+    dart_bin = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dart')
     sdk_file = os.path.join(library_dir, output_dir, library_filename)
-    formatCommand = ' '.join([prebuilt_dartfmt, '-w', sdk_file])
+    formatCommand = ' '.join([dart_bin, 'format', sdk_file])
     subprocess.call([formatCommand], shell=True)
 
 
diff --git a/tools/dom/src/CssRectangle.dart b/tools/dom/src/CssRectangle.dart
index d26aac7..6aa6393 100644
--- a/tools/dom/src/CssRectangle.dart
+++ b/tools/dom/src/CssRectangle.dart
@@ -182,8 +182,8 @@
    *
    * This is equivalent to the `height` function in jQuery and the calculated
    * `height` CSS value, converted to a dimensionless num in pixels. Unlike
-   * [getBoundingClientRect], `height` will return the same numerical width if
-   * the element is hidden or not.
+   * [Element.getBoundingClientRect], `height` will return the same numerical
+   * height if the element is hidden or not.
    */
   num get height;
 
@@ -192,8 +192,8 @@
    *
    * This is equivalent to the `width` function in jQuery and the calculated
    * `width` CSS value, converted to a dimensionless num in pixels. Unlike
-   * [getBoundingClientRect], `width` will return the same numerical width if
-   * the element is hidden or not.
+   * [Element.getBoundingClientRect], `width` will return the same numerical
+   * width if the element is hidden or not.
    */
   num get width;
 
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index feadc26..90b19aa 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -38,7 +38,7 @@
       new _EventStream<T>(e, _eventType, useCapture);
 
   /**
-   * Gets an [ElementEventStream] for this event type, on the specified element.
+   * Gets a [Stream] for this event type, on the specified element.
    *
    * This will always return a broadcast stream so multiple listeners can be
    * used simultaneously.
@@ -64,7 +64,7 @@
   }
 
   /**
-   * Gets an [ElementEventStream] for this event type, on the list of elements.
+   * Gets a [Stream] for this event type, on the list of elements.
    *
    * This will always return a broadcast stream so multiple listeners can be
    * used simultaneously.
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 0b19506..fd4069b 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -18,6 +18,7 @@
  * For information on writing web apps with Dart, see https://dart.dev/web.
  *
  * {@category Web}
+ * {@canonicalFor dart:_internal.HttpStatus}
  */
 library dart.dom.html;
 
diff --git a/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate b/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
index dc05346..8373820 100644
--- a/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
@@ -69,8 +69,6 @@
  * basic mechanism that stores data as a [Map],
  * and where both the keys and the values are strings.
  *
- * * [dart:web_sql]&mdash;a database that can be queried with SQL.
- *
  * MDN provides [API
  * documentation](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).
  *
diff --git a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
index 2e9ba25..ec1f2e4 100644
--- a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
@@ -279,7 +279,7 @@
    * options, such as typeface and size, and the current
    * [CanvasRenderingContext2D.fillStyle] for style options such as color.
    * The current [CanvasRenderingContext2D.textAlign] and
-   * [CanvasRenderingContext2D.textBaseLine] properties are also applied to the
+   * [CanvasRenderingContext2D.textBaseline] properties are also applied to the
    * drawn text.
    */
   void fillText(String text, num x, num y, [num$NULLABLE maxWidth]) {
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 4368af2..fadfc3b 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -215,7 +215,7 @@
   CssStyleDeclarationBase get style;
 
   /**
-   * Access dimensions and position of the Elements in this list.
+   * Access dimensions and position of the [Element]s in this list.
    *
    * Setting the height or width properties will set the height or width
    * property for all elements in the list. This returns a rectangle with the
@@ -224,46 +224,48 @@
    * property. Getting the height or width returns the height or width of the
    * first Element in this list.
    *
-   * Unlike [getBoundingClientRect], the dimensions of this rectangle
+   * Unlike [Element.getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not.
    */
   CssRect get contentEdge;
 
   /**
-   * Access dimensions and position of the first Element's content + padding box
-   * in this list.
+   * Access dimensions and position of the first [Element]'s content + padding
+   * box in this list.
    *
    * This returns a rectangle with the dimensions actually available for content
    * in this element, in pixels, regardless of this element's box-sizing
-   * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
-   * will return the same numerical height if the element is hidden or not. This
-   * can be used to retrieve jQuery's `innerHeight` value for an element. This
-   * is also a rectangle equalling the dimensions of clientHeight and
-   * clientWidth.
+   * property. Unlike [Element.getBoundingClientRect], the dimensions of this
+   * rectangle will return the same numerical height if the element is hidden
+   * or not. This can be used to retrieve jQuery's `innerHeight` value for an
+   * element. This is also a rectangle equalling the dimensions of clientHeight
+   * and clientWidth.
    */
   CssRect get paddingEdge;
 
   /**
-   * Access dimensions and position of the first Element's content + padding +
+   * Access dimensions and position of the first [Element]'s content + padding +
    * border box in this list.
    *
    * This returns a rectangle with the dimensions actually available for content
    * in this element, in pixels, regardless of this element's box-sizing
-   * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
-   * will return the same numerical height if the element is hidden or not. This
-   * can be used to retrieve jQuery's `outerHeight` value for an element.
+   * property. Unlike [Element.getBoundingClientRect], the dimensions of this
+   * rectangle will return the same numerical height if the element is hidden
+   * or not. This can be used to retrieve jQuery's `outerHeight` value for an
+   * element.
    */
   CssRect get borderEdge;
 
   /**
-   * Access dimensions and position of the first Element's content + padding +
+   * Access dimensions and position of the first [Element]'s content + padding +
    * border + margin box in this list.
    *
    * This returns a rectangle with the dimensions actually available for content
    * in this element, in pixels, regardless of this element's box-sizing
-   * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
-   * will return the same numerical height if the element is hidden or not. This
-   * can be used to retrieve jQuery's `outerHeight` value for an element.
+   * property. Unlike [Element.getBoundingClientRect], the dimensions of this
+   * rectangle will return the same numerical height if the element is hidden
+   * or not. This can be used to retrieve jQuery's `outerHeight` value for an
+   * element.
    */
   CssRect get marginEdge;
 $!STREAM_GETTER_SIGNATURES
@@ -927,9 +929,9 @@
    *
    * The [frames] parameter is an Iterable<Map>, where the
    * map entries specify CSS animation effects. The
-   * [timing] paramter can be a double, representing the number of milliseconds
-   * for the transition, or a Map with fields corresponding to those
-   * of the [Timing] object.
+   * [timing] parameter can be a double, representing the number of
+   * milliseconds for the transition, or a Map with fields corresponding to
+   * those of the [timing] object.
    */
   @SupportedBrowser(SupportedBrowser.CHROME, '36')
   Animation animate(Iterable<Map<String, dynamic>> frames, [timing]) {
@@ -1081,11 +1083,13 @@
    * * 'beforeEnd': As the last child of this element.
    * * 'afterEnd': Immediately after this element.
    *
+   * ```dart
    *     var html = '<div class="something">content</div>';
    *     // Inserts as the first child
    *     document.body.insertAdjacentHtml('afterBegin', html);
    *     var createdElement = document.body.children[0];
    *     print(createdElement.classes[0]); // Prints 'something'
+   * ```
    *
    * See also:
    *
diff --git a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
index 19aa838..50f57db 100644
--- a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
@@ -463,7 +463,7 @@
 
 
 /**
- * A control that when used with other [ReadioButtonInputElement] controls
+ * A control that when used with other [RadioButtonInputElement] controls
  * forms a radio button group in which only one control can be checked at a
  * time.
  *
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 98e07f0..15f8219 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -157,8 +157,8 @@
   /**
    * Gets an instance of the Indexed DB factory to being using Indexed DB.
    *
-   * Use [indexed_db.IdbFactory.supported] to check if Indexed DB is supported on the
-   * current platform.
+   * Use [dart:indexed_db.IdbFactory.supported] to check if Indexed DB is
+   * supported on the current platform.
    */
   @SupportedBrowser(SupportedBrowser.CHROME, '23.0')
   @SupportedBrowser(SupportedBrowser.FIREFOX, '15.0')
diff --git a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
index 44d7ea4..7e92f1d 100644
--- a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
+++ b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
@@ -148,7 +148,7 @@
    * * Using credentials is only useful for cross-origin requests.
    * * The `Access-Control-Allow-Origin` header of `url` cannot contain a wildcard (*).
    * * The `Access-Control-Allow-Credentials` header of `url` must be set to true.
-   * * If `Access-Control-Expose-Headers` has not been set to true, only a subset of all the response headers will be returned when calling [getAllRequestHeaders].
+   * * If `Access-Control-Expose-Headers` has not been set to true, only a subset of all the response headers will be returned when calling [getAllResponseHeaders].
    *
    * The following is equivalent to the [getString] sample above:
    *
diff --git a/tools/generate_idefiles.py b/tools/generate_idefiles.py
index 7809c64..ac75696 100755
--- a/tools/generate_idefiles.py
+++ b/tools/generate_idefiles.py
@@ -23,7 +23,6 @@
 
 def GenerateIdeFiles(options):
     GenerateCompileCommands(options)
-    GenerateAnalysisOptions(options)
 
 
 def GenerateCompileCommands(options):
@@ -81,64 +80,6 @@
     return 0
 
 
-def GenerateAnalysisOptions(options):
-    """Generate analysis_optioms.yaml for the Dart analyzer.
-
-  To prevent dartanalyzer from tripping on the non-Dart files when it is
-  started from the root dart-sdk directory.
-  https://github.com/dart-lang/sdk/issues/35562
-
-  Args:
-    options: supported options include: force, dir
-  """
-    contents = """analyzer:
-  exclude:
-    - benchmarks/**
-    - benchmarks-internal/**
-    - docs/newsletter/20171103/**
-    - pkg/**
-    - out/**
-    - runtime/**
-    - samples-dev/swarm/**
-    - sdk/lib/**
-    - tests/co19/**
-    - tests/co19_2/**
-    - tests/corelib/**
-    - tests/corelib_2/**
-    - tests/web/**
-    - tests/web_2/**
-    - tests/dartdevc/**
-    - tests/dartdevc_2/**
-    - tests/ffi/**
-    - tests/ffi_2/**
-    - tests/language/**
-    - tests/language_2/**
-    - tests/lib/**
-    - tests/lib_2/**
-    - tests/modular/**
-    - tests/standalone/**
-    - tests/standalone_2/**
-    - third_party/observatory_pub_packages/**
-    - third_party/pkg/**
-    - third_party/pkg_tested/dart_style/**
-    - third_party/tcmalloc/**
-    - tools/apps/update_homebrew/**
-    - tools/dart2js/**
-    - tools/dom/**
-    - tools/sdks/dart-sdk/lib/**
-    - tools/status_clean.dart
-    - xcodebuild/**"""
-
-    fname = os.path.join(options.dir, "analysis_options.yaml")
-
-    if os.path.isfile(fname) and not options.force:
-        print(fname + " already exists, use --force to override")
-        return
-
-    with open(fname, "w") as f:
-        f.write(contents)
-
-
 def main(argv):
     parser = argparse.ArgumentParser(
         description="Python script to generate compile_commands.json and "
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 7b9a07d..882c827 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -92,22 +92,20 @@
   packages.sort((a, b) => a["name"].compareTo(b["name"]));
 
   var configFile = File(p.join(repoRoot, '.dart_tool', 'package_config.json'));
+  var json =
+      jsonDecode(configFile.readAsStringSync()) as Map<dynamic, dynamic>;
+  var oldPackages = json['packages'] as List<dynamic>;
 
   // Validate the packages entry only, to avoid spurious failures from changes
   // in the dates embedded in the other entries.
-  if (checkOnly) {
-    var json =
-        jsonDecode(configFile.readAsStringSync()) as Map<dynamic, dynamic>;
-    var oldPackages = json['packages'] as List<dynamic>;
-    if (jsonEncode(packages) == jsonEncode(oldPackages)) {
-      print("Package config up to date");
-      exit(0);
-    } else {
-      print("Package config out of date");
-      print("Run `gclient sync -D && dart tools/generate_package_config.dart` "
-          "to update.");
-      exit(1);
-    }
+  if (jsonEncode(packages) == jsonEncode(oldPackages)) {
+    print("Package config up to date");
+    exit(0);
+  } else if (checkOnly) {
+    print("Package config out of date");
+    print("Run `gclient sync -D && dart tools/generate_package_config.dart` "
+        "to update.");
+    exit(1);
   }
 
   var year = DateTime.now().year;
@@ -130,8 +128,8 @@
   };
 
   // TODO(rnystrom): Consider using package_config_v2 to generate this instead.
-  var json = JsonEncoder.withIndent('  ').convert(config);
-  configFile.writeAsStringSync('$json\n');
+  var jsonString = JsonEncoder.withIndent('  ').convert(config);
+  configFile.writeAsStringSync('$jsonString\n');
   print('Generated .dart_tool/package_config.dart containing '
       '${packages.length} packages.');
 }
diff --git a/tools/make_version.py b/tools/make_version.py
index c99511b..bf2c9c5 100755
--- a/tools/make_version.py
+++ b/tools/make_version.py
@@ -23,7 +23,6 @@
     'object.h',
     'raw_object.h',
     'snapshot.h',
-    'snapshot_ids.h',
     'symbols.h',
     # Source files.
     'clustered_snapshot.cc',
@@ -32,7 +31,6 @@
     'image_snapshot.cc',
     'object.cc',
     'raw_object.cc',
-    'raw_object_snapshot.cc',
     'snapshot.cc',
     'symbols.cc',
 ]
diff --git a/tools/spec_parser/Dart.g b/tools/spec_parser/Dart.g
index 5f79d24..e1d7db2 100644
--- a/tools/spec_parser/Dart.g
+++ b/tools/spec_parser/Dart.g
@@ -372,7 +372,9 @@
     |    EXTERNAL? operatorSignature
     |    STATIC (FINAL | CONST) type? staticFinalDeclarationList
     |    STATIC LATE FINAL type? initializedIdentifierList
-    |    (STATIC | COVARIANT) LATE? varOrType initializedIdentifierList
+    |    STATIC LATE? varOrType initializedIdentifierList
+    |    COVARIANT LATE FINAL type? identifierList
+    |    COVARIANT LATE? varOrType initializedIdentifierList
     |    LATE? (FINAL type? | varOrType) initializedIdentifierList
     |    redirectingFactoryConstructorSignature
     |    constantConstructorSignature (redirection | initializers)?
diff --git a/tools/yaml2json.dart b/tools/yaml2json.dart
index 8ce4907..e8b6a07 100644
--- a/tools/yaml2json.dart
+++ b/tools/yaml2json.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:io' show File, exit, stderr;
 
 import 'dart:isolate' show RawReceivePort;
@@ -12,7 +10,7 @@
 
 import 'package:yaml/yaml.dart' show loadYaml;
 
-main(List<String> arguments) async {
+main(List<String> arguments) {
   var port = new RawReceivePort();
   if (arguments.length != 2) {
     stderr.writeln("Usage: yaml2json.dart input.yaml output.json");
@@ -20,7 +18,7 @@
   }
   Uri input = Uri.base.resolve(arguments[0]);
   Uri output = Uri.base.resolve(arguments[1]);
-  Map yaml = loadYaml(await new File.fromUri(input).readAsString());
+  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"] =
@@ -29,6 +27,6 @@
     result[key] = yaml[key];
   }
   File file = new File.fromUri(output);
-  await file.writeAsString(const JsonEncoder.withIndent("  ").convert(result));
+  file.writeAsStringSync(const JsonEncoder.withIndent("  ").convert(result));
   port.close();
 }
diff --git a/tools/yaml2json.py b/tools/yaml2json.py
deleted file mode 100755
index 251f657..0000000
--- a/tools/yaml2json.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python3
-# 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 os
-import subprocess
-import sys
-
-import utils
-
-
-def Main():
-    args = sys.argv[1:]
-    yaml2json_dart = os.path.relpath(
-        os.path.join(os.path.dirname(__file__), "yaml2json.dart"))
-    command = [utils.CheckedInSdkExecutable(), yaml2json_dart] + args
-
-    with utils.CoreDumpArchiver(args):
-        exit_code = subprocess.call(command)
-
-    utils.DiagnoseExitCode(exit_code, command)
-    return exit_code
-
-
-if __name__ == '__main__':
-    sys.exit(Main())
diff --git a/utils/application_snapshot.gni b/utils/application_snapshot.gni
index 317153a..6a2efbb 100644
--- a/utils/application_snapshot.gni
+++ b/utils/application_snapshot.gni
@@ -82,6 +82,9 @@
   # Build the kernel file using the prebuilt VM to speed up the debug and
   # simulator builds.
   prebuilt_dart_action(target_name + "_dill") {
+    if (defined(invoker.pool)) {
+      pool = invoker.pool
+    }
     deps = extra_deps + [
              "$_dart_root/runtime/vm:kernel_platform_files($host_toolchain)",
              "$_dart_root/runtime/vm:vm_platform",
@@ -131,6 +134,9 @@
 
   # Create a snapshot from kernel built above.
   dart_action(target_name) {
+    if (defined(invoker.pool)) {
+      pool = invoker.pool
+    }
     deps = extra_deps + [ ":${target_name}_dill" ]
     depfile = "$output.d"
 
diff --git a/utils/compile_platform.gni b/utils/compile_platform.gni
index 447ed64..37c3407 100644
--- a/utils/compile_platform.gni
+++ b/utils/compile_platform.gni
@@ -41,6 +41,9 @@
   }
 
   prebuilt_dart_action(target_name) {
+    if (defined(invoker.pool)) {
+      pool = invoker.pool
+    }
     script = "$_dart_root/pkg/front_end/tool/_fasta/compile_platform.dart"
 
     packages = "$_dart_root/.packages"