Version 2.14.0-77.0.dev

Merge commit '8a21ab195a2b748a556865894c62776a77db7963' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 99dc94b..d0ee842 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-04-30T16:02:33.294454",
+  "generated": "2021-05-03T18:00:16.673010",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -253,6 +253,18 @@
       "languageVersion": "2.3"
     },
     {
+      "name": "devtools_server",
+      "rootUri": "../third_party/devtools/devtools_server",
+      "packageUri": "lib/",
+      "languageVersion": "2.6"
+    },
+    {
+      "name": "devtools_shared",
+      "rootUri": "../third_party/devtools/devtools_shared",
+      "packageUri": "lib/",
+      "languageVersion": "2.3"
+    },
+    {
       "name": "diagnostic",
       "rootUri": "../pkg/diagnostic",
       "packageUri": "lib/",
@@ -443,6 +455,12 @@
       "languageVersion": "2.2"
     },
     {
+      "name": "mustache",
+      "rootUri": "../third_party/pkg/mustache",
+      "packageUri": "lib/",
+      "languageVersion": "2.0"
+    },
+    {
       "name": "native_stack_traces",
       "rootUri": "../pkg/native_stack_traces",
       "packageUri": "lib/",
@@ -632,6 +650,12 @@
       "languageVersion": "2.12"
     },
     {
+      "name": "stagehand",
+      "rootUri": "../third_party/pkg/stagehand",
+      "packageUri": "lib/",
+      "languageVersion": "2.10"
+    },
+    {
       "name": "status_file",
       "rootUri": "../pkg/status_file",
       "packageUri": "lib/",
diff --git a/.packages b/.packages
index af07227..1631e03 100644
--- a/.packages
+++ b/.packages
@@ -20,8 +20,8 @@
 bazel_worker:third_party/pkg/bazel_worker/lib
 benchmark_harness:third_party/pkg/benchmark_harness/lib
 boolean_selector:third_party/pkg/boolean_selector/lib
-browser_launcher:third_party/pkg/browser_launcher/lib
 build_integration:pkg/build_integration/lib
+browser_launcher:third_party/pkg/browser_launcher/lib
 charcode:third_party/pkg/charcode/lib
 cli_util:third_party/pkg/cli_util/lib
 collection:third_party/pkg/collection/lib
@@ -38,6 +38,7 @@
 dartdoc:third_party/pkg/dartdoc/lib
 dds:pkg/dds/lib
 dev_compiler:pkg/dev_compiler/lib
+devtools_shared:third_party/devtools/devtools_shared/lib
 diagnostic:pkg/diagnostic/lib
 expect:pkg/expect/lib
 ffi:third_party/pkg/ffi/lib
diff --git a/DEPS b/DEPS
index 2c75fde..1124ea3 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
   # hashes. It requires access to the dart-build-access group, which EngProd
   # has.
-  "co19_rev": "13f010c4047c4c7d52afe67ecc57ebc415ea4ea8",
+  "co19_rev": "055b5c984613ec1b8ef76516db3ea99fee63acb9",
   "co19_2_rev": "f7f583366396cb1457e58c9bfb6d6e53dc21d741",
 
   # The internal benchmarks to use. See go/dart-benchmarks-internal
@@ -80,9 +80,10 @@
   "boringssl_gen_rev": "7322fc15cc065d8d2957fccce6b62a509dc4d641",
   "boringssl_rev" : "1607f54fed72c6589d560254626909a64124f091",
   "browser-compat-data_tag": "v1.0.22",
+  "browser_launcher_rev": "12ab9f351a44ac803de9bc17bb2180bb312a9dd7",
   "charcode_rev": "bcd8a12c315b7a83390e4865ad847ecd9344cba2",
   "chrome_rev" : "19997",
-  "cli_util_rev" : "fd1b716e8a350a454e01ae56df540293d31ff6c8",
+  "cli_util_rev" : "50cc840b146615899e97b892578848401b2028d5",
   "clock_rev" : "a494269254ba978e7ef8f192c5f7fec3fc05b9d3",
   "collection_rev": "9967dcd3d7645db6de48d5abfab3018bb0c84236",
   "convert_rev": "a60156c6efd653657c8926b5788219ed609917d7",
@@ -105,8 +106,8 @@
   "dart_style_rev": "f17c23e0eea9a870601c19d904e2a9c1a7c81470",
 
   "chromedriver_tag": "83.0.4103.39",
-  "browser_launcher_rev": "12ab9f351a44ac803de9bc17bb2180bb312a9dd7",
   "dartdoc_rev" : "505f163f7cb48e917503e4a23fbff1227e08b263",
+  "devtools_rev" : "12ad5341ae0a275042c84a4e7be9a6c98db65612",
   "jsshell_tag": "version:88.0",
   "ffi_rev": "f3346299c55669cc0db48afae85b8110088bf8da",
   "fixnum_rev": "16d3890c6dc82ca629659da1934e412292508bba",
@@ -123,7 +124,7 @@
   "idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
   "intl_tag": "0.17.0-nullsafety",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
-  "json_rpc_2_rev": "5ec32a2e0e99dedcef5b3237f93167cd22c2da50",
+  "json_rpc_2_rev": "7e00f893440a72de0637970325e4ea44bd1e8c8e",
   "linter_tag": "1.4.0",
   "logging_rev": "e2f633b543ef89c54688554b15ca3d7e425b86a2",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
@@ -246,7 +247,7 @@
   Var("dart_root") + "/third_party/devtools": {
       "packages": [{
           "package": "dart/third_party/flutter/devtools",
-          "version": "revision:6729ec62c3548839018c32fa711756202431ccf7",
+          "version": "git_revision:" + Var("devtools_rev"),
       }],
       "dep_type": "cipd",
   },
@@ -319,6 +320,9 @@
       Var('chromium_git') + '/external/github.com/mdn/browser-compat-data' +
       "@" + Var("browser-compat-data_tag"),
 
+  Var("dart_root") + "/third_party/pkg/browser_launcher":
+      Var("dart_git") + "browser_launcher.git" + "@" + Var("browser_launcher_rev"),
+
   Var("dart_root") + "/third_party/tcmalloc/gperftools":
       Var('chromium_git') + '/external/github.com/gperftools/gperftools.git' +
       "@" + Var("gperftools_revision"),
@@ -335,9 +339,6 @@
   Var("dart_root") + "/third_party/pkg/boolean_selector":
       Var("dart_git") + "boolean_selector.git" +
       "@" + Var("boolean_selector_rev"),
-  Var("dart_root") + "/third_party/pkg/browser_launcher":
-      Var("dart_git") + "browser_launcher.git" +
-      "@" + Var("browser_launcher_rev"),
   Var("dart_root") + "/third_party/pkg/charcode":
       Var("dart_git") + "charcode.git" + "@" + Var("charcode_rev"),
   Var("dart_root") + "/third_party/pkg/cli_util":
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index b88f7cc..99fa136 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -244,7 +244,7 @@
   /// contain the index of the change that failed. This property is only
   /// available if the client signals a `failureHandlingStrategy` in its client
   /// capabilities.
-  final num? failedChange;
+  final int? failedChange;
 
   /// An optional textual description for why the edit was not applied. This may
   /// be used by the server for diagnostic logging or to provide a suitable
@@ -293,8 +293,8 @@
       }
       reporter.push('failedChange');
       try {
-        if (obj['failedChange'] != null && !(obj['failedChange'] is num)) {
-          reporter.reportError('must be of type num');
+        if (obj['failedChange'] != null && !(obj['failedChange'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -506,18 +506,18 @@
     final item = CallHierarchyItem.fromJson(json['item']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return CallHierarchyIncomingCallsParams(
         item: item,
         workDoneToken: workDoneToken,
@@ -528,10 +528,10 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -567,9 +567,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -578,9 +578,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -1021,18 +1021,18 @@
     final item = CallHierarchyItem.fromJson(json['item']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return CallHierarchyOutgoingCallsParams(
         item: item,
         workDoneToken: workDoneToken,
@@ -1043,10 +1043,10 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -1082,9 +1082,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -1093,9 +1093,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -1145,11 +1145,11 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     return CallHierarchyPrepareParams(
         textDocument: textDocument,
         position: position,
@@ -1163,7 +1163,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -1214,9 +1214,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -1376,16 +1376,16 @@
 
   CancelParams({required this.id});
   static CancelParams fromJson(Map<String, dynamic> json) {
-    final id = json['id'] is num
-        ? Either2<num, String>.t1(json['id'])
+    final id = json['id'] is int
+        ? Either2<int, String>.t1(json['id'])
         : (json['id'] is String
-            ? Either2<num, String>.t2(json['id'])
-            : (throw '''${json['id']} was not one of (num, String)'''));
+            ? Either2<int, String>.t2(json['id'])
+            : (throw '''${json['id']} was not one of (int, String)'''));
     return CancelParams(id: id);
   }
 
   /// The request id to cancel.
-  final Either2<num, String> id;
+  final Either2<int, String> id;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -1405,8 +1405,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!((obj['id'] is num || obj['id'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+        if (!((obj['id'] is int || obj['id'] is String))) {
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -3465,18 +3465,18 @@
     final context = CodeActionContext.fromJson(json['context']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return CodeActionParams(
         textDocument: textDocument,
         range: range,
@@ -3490,7 +3490,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The range for which the command was invoked.
   final Range range;
@@ -3499,7 +3499,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -3571,9 +3571,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -3582,9 +3582,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -4094,18 +4094,18 @@
     final textDocument = TextDocumentIdentifier.fromJson(json['textDocument']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return CodeLensParams(
         textDocument: textDocument,
         workDoneToken: workDoneToken,
@@ -4114,13 +4114,13 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The document to request code lens for.
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -4156,9 +4156,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -4167,9 +4167,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -4752,18 +4752,18 @@
     final range = Range.fromJson(json['range']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return ColorPresentationParams(
         textDocument: textDocument,
         color: color,
@@ -4777,7 +4777,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The range where the color would be inserted. Serves as a context.
   final Range range;
@@ -4786,7 +4786,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -4858,9 +4858,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -4869,9 +4869,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -6666,18 +6666,18 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return CompletionParams(
         context: context,
         textDocument: textDocument,
@@ -6692,7 +6692,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The position inside the text document.
   final Position position;
@@ -6701,7 +6701,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -6768,9 +6768,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -6779,9 +6779,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -7648,18 +7648,18 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return DeclarationParams(
         textDocument: textDocument,
         position: position,
@@ -7669,7 +7669,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The position inside the text document.
   final Position position;
@@ -7678,7 +7678,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -7732,9 +7732,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -7743,9 +7743,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -8062,18 +8062,18 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return DefinitionParams(
         textDocument: textDocument,
         position: position,
@@ -8083,7 +8083,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The position inside the text document.
   final Position position;
@@ -8092,7 +8092,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -8146,9 +8146,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -8157,9 +8157,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -9880,18 +9880,18 @@
     final textDocument = TextDocumentIdentifier.fromJson(json['textDocument']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return DocumentColorParams(
         textDocument: textDocument,
         workDoneToken: workDoneToken,
@@ -9900,13 +9900,13 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The text document.
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -9942,9 +9942,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -9953,9 +9953,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -10354,11 +10354,11 @@
     final options = FormattingOptions.fromJson(json['options']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     return DocumentFormattingParams(
         textDocument: textDocument,
         options: options,
@@ -10372,7 +10372,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -10423,9 +10423,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -10824,18 +10824,18 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return DocumentHighlightParams(
         textDocument: textDocument,
         position: position,
@@ -10845,7 +10845,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The position inside the text document.
   final Position position;
@@ -10854,7 +10854,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -10908,9 +10908,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -10919,9 +10919,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -11356,18 +11356,18 @@
     final textDocument = TextDocumentIdentifier.fromJson(json['textDocument']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return DocumentLinkParams(
         textDocument: textDocument,
         workDoneToken: workDoneToken,
@@ -11376,13 +11376,13 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The document to provide document links for.
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -11418,9 +11418,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -11429,9 +11429,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -12173,11 +12173,11 @@
     final options = FormattingOptions.fromJson(json['options']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     return DocumentRangeFormattingParams(
         textDocument: textDocument,
         range: range,
@@ -12195,7 +12195,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -12264,9 +12264,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -13065,18 +13065,18 @@
     final textDocument = TextDocumentIdentifier.fromJson(json['textDocument']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return DocumentSymbolParams(
         textDocument: textDocument,
         workDoneToken: workDoneToken,
@@ -13085,13 +13085,13 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The text document.
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -13127,9 +13127,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -13138,9 +13138,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -13298,10 +13298,10 @@
   const ErrorCodes(this._value);
   const ErrorCodes.fromJson(this._value);
 
-  final num _value;
+  final int _value;
 
   static bool canParse(Object obj, LspJsonReporter reporter) {
-    return obj is num;
+    return obj is int;
   }
 
   /// Defined by JSON RPC
@@ -13511,11 +13511,11 @@
         json['arguments']?.map((item) => item)?.cast<dynamic>()?.toList();
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     return ExecuteCommandParams(
         command: command, arguments: arguments, workDoneToken: workDoneToken);
   }
@@ -13527,7 +13527,7 @@
   final String command;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -13574,9 +13574,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -13929,7 +13929,7 @@
   }
 
   /// The change type.
-  final num type;
+  final int type;
 
   /// The file's URI.
   final String uri;
@@ -13970,8 +13970,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['type'] is num)) {
-          reporter.reportError('must be of type num');
+        if (!(obj['type'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -14593,12 +14593,12 @@
 
   /// The zero-based character offset before the folded range ends. If not
   /// defined, defaults to the length of the end line.
-  final num? endCharacter;
+  final int? endCharacter;
 
   /// The zero-based end line of the range to fold. The folded area ends with
   /// the line's last character. To be valid, the end must be zero or larger and
   /// smaller than the number of lines in the document.
-  final num endLine;
+  final int endLine;
 
   /// Describes the kind of the folding range such as `comment` or `region`. The
   /// kind is used to categorize folding ranges and used by commands like 'Fold
@@ -14608,12 +14608,12 @@
 
   /// The zero-based character offset from where the folded range starts. If not
   /// defined, defaults to the length of the start line.
-  final num? startCharacter;
+  final int? startCharacter;
 
   /// The zero-based start line of the range to fold. The folded area starts
   /// after the line's last character. To be valid, the end must be zero or
   /// larger and smaller than the number of lines in the document.
-  final num startLine;
+  final int startLine;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -14643,8 +14643,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['startLine'] is num)) {
-          reporter.reportError('must be of type num');
+        if (!(obj['startLine'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -14652,8 +14652,8 @@
       }
       reporter.push('startCharacter');
       try {
-        if (obj['startCharacter'] != null && !(obj['startCharacter'] is num)) {
-          reporter.reportError('must be of type num');
+        if (obj['startCharacter'] != null && !(obj['startCharacter'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -14669,8 +14669,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['endLine'] is num)) {
-          reporter.reportError('must be of type num');
+        if (!(obj['endLine'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -14678,8 +14678,8 @@
       }
       reporter.push('endCharacter');
       try {
-        if (obj['endCharacter'] != null && !(obj['endCharacter'] is num)) {
-          reporter.reportError('must be of type num');
+        if (obj['endCharacter'] != null && !(obj['endCharacter'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -14761,7 +14761,7 @@
   /// The maximum number of folding ranges that the client prefers to receive
   /// per document. The value serves as a hint, servers are free to follow the
   /// limit.
-  final num? rangeLimit;
+  final int? rangeLimit;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -14791,8 +14791,8 @@
       }
       reporter.push('rangeLimit');
       try {
-        if (obj['rangeLimit'] != null && !(obj['rangeLimit'] is num)) {
-          reporter.reportError('must be of type num');
+        if (obj['rangeLimit'] != null && !(obj['rangeLimit'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -14946,18 +14946,18 @@
     final textDocument = TextDocumentIdentifier.fromJson(json['textDocument']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return FoldingRangeParams(
         textDocument: textDocument,
         workDoneToken: workDoneToken,
@@ -14966,13 +14966,13 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The text document.
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -15008,9 +15008,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -15019,9 +15019,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -15208,7 +15208,7 @@
   final bool insertSpaces;
 
   /// Size of a tab in spaces.
-  final num tabSize;
+  final int tabSize;
 
   /// Trim all newlines after the final newline at the end of the file.
   ///  @since 3.15.0
@@ -15246,8 +15246,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['tabSize'] is num)) {
-          reporter.reportError('must be of type num');
+        if (!(obj['tabSize'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -15587,11 +15587,11 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     return HoverParams(
         textDocument: textDocument,
         position: position,
@@ -15605,7 +15605,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -15656,9 +15656,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -15950,18 +15950,18 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return ImplementationParams(
         textDocument: textDocument,
         position: position,
@@ -15971,7 +15971,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The position inside the text document.
   final Position position;
@@ -15980,7 +15980,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -16034,9 +16034,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -16045,9 +16045,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -16238,11 +16238,11 @@
         ?.toList();
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     return InitializeParams(
         processId: processId,
         clientInfo: clientInfo,
@@ -16278,7 +16278,7 @@
   /// the process has not been started by another process. If the parent process
   /// is not alive then the server should exit (see exit notification) its
   /// process.
-  final num? processId;
+  final int? processId;
 
   /// The rootPath of the workspace. Is null if no folder is open.
   ///  @deprecated in favour of `rootUri`.
@@ -16293,7 +16293,7 @@
   final String? trace;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   /// The workspace folders configured in the client when the server starts.
   /// This property is only available if the client supports workspace folders.
@@ -16340,8 +16340,8 @@
           reporter.reportError('must not be undefined');
           return false;
         }
-        if (obj['processId'] != null && !(obj['processId'] is num)) {
-          reporter.reportError('must be of type num');
+        if (obj['processId'] != null && !(obj['processId'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -16433,9 +16433,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -17114,11 +17114,11 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     return LinkedEditingRangeParams(
         textDocument: textDocument,
         position: position,
@@ -17132,7 +17132,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -17183,9 +17183,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -18820,18 +18820,18 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return MonikerParams(
         textDocument: textDocument,
         position: position,
@@ -18841,7 +18841,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The position inside the text document.
   final Position position;
@@ -18850,7 +18850,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -18904,9 +18904,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -18915,9 +18915,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -19171,7 +19171,7 @@
   ///
   /// The version number of a document will increase after each change,
   /// including undo/redo. The number doesn't need to be consecutive.
-  final num? version;
+  final int? version;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -19188,8 +19188,8 @@
           reporter.reportError('must not be undefined');
           return false;
         }
-        if (obj['version'] != null && !(obj['version'] is num)) {
-          reporter.reportError('must be of type num');
+        if (obj['version'] != null && !(obj['version'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -19422,17 +19422,17 @@
     }
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return PartialResultParams(partialResultToken: partialResultToken);
   }
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -19447,9 +19447,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -19696,17 +19696,17 @@
 
   ProgressParams({required this.token, this.value});
   static ProgressParams<T> fromJson<T>(Map<String, dynamic> json) {
-    final token = json['token'] is num
-        ? Either2<num, String>.t1(json['token'])
+    final token = json['token'] is int
+        ? Either2<int, String>.t1(json['token'])
         : (json['token'] is String
-            ? Either2<num, String>.t2(json['token'])
-            : (throw '''${json['token']} was not one of (num, String)'''));
+            ? Either2<int, String>.t2(json['token'])
+            : (throw '''${json['token']} was not one of (int, String)'''));
     final value = json['value'];
     return ProgressParams<T>(token: token, value: value);
   }
 
   /// The progress token provided by the client or server.
-  final Either2<num, String> token;
+  final Either2<int, String> token;
 
   /// The progress data.
   final dynamic value;
@@ -19730,8 +19730,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!((obj['token'] is num || obj['token'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+        if (!((obj['token'] is int || obj['token'] is String))) {
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -20026,7 +20026,7 @@
   /// Optional the version number of the document the diagnostics are published
   /// for.
   ///  @since 3.15.0
-  final num? version;
+  final int? version;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -20059,8 +20059,8 @@
       }
       reporter.push('version');
       try {
-        if (obj['version'] != null && !(obj['version'] is num)) {
-          reporter.reportError('must be of type num');
+        if (obj['version'] != null && !(obj['version'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -20497,18 +20497,18 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return ReferenceParams(
         context: context,
         textDocument: textDocument,
@@ -20521,7 +20521,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The position inside the text document.
   final Position position;
@@ -20530,7 +20530,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -20602,9 +20602,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -20613,9 +20613,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -21567,11 +21567,11 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     return RenameParams(
         newName: newName,
         textDocument: textDocument,
@@ -21590,7 +21590,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -21659,9 +21659,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -21821,11 +21821,11 @@
       this.params,
       required this.jsonrpc});
   static RequestMessage fromJson(Map<String, dynamic> json) {
-    final id = json['id'] is num
-        ? Either2<num, String>.t1(json['id'])
+    final id = json['id'] is int
+        ? Either2<int, String>.t1(json['id'])
         : (json['id'] is String
-            ? Either2<num, String>.t2(json['id'])
-            : (throw '''${json['id']} was not one of (num, String)'''));
+            ? Either2<int, String>.t2(json['id'])
+            : (throw '''${json['id']} was not one of (int, String)'''));
     final method = Method.fromJson(json['method']);
     final params = json['params'];
     final jsonrpc = json['jsonrpc'];
@@ -21834,7 +21834,7 @@
   }
 
   /// The request id.
-  final Either2<num, String> id;
+  final Either2<int, String> id;
   final String jsonrpc;
 
   /// The method to be invoked.
@@ -21866,8 +21866,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!((obj['id'] is num || obj['id'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+        if (!((obj['id'] is int || obj['id'] is String))) {
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -22093,11 +22093,11 @@
   static ResponseMessage fromJson(Map<String, dynamic> json) {
     final id = json['id'] == null
         ? null
-        : (json['id'] is num
-            ? Either2<num, String>.t1(json['id'])
+        : (json['id'] is int
+            ? Either2<int, String>.t1(json['id'])
             : (json['id'] is String
-                ? Either2<num, String>.t2(json['id'])
-                : (throw '''${json['id']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['id'])
+                : (throw '''${json['id']} was not one of (int, String)''')));
     final result = json['result'];
     final error =
         json['error'] != null ? ResponseError.fromJson(json['error']) : null;
@@ -22110,7 +22110,7 @@
   final ResponseError? error;
 
   /// The request id.
-  final Either2<num, String>? id;
+  final Either2<int, String>? id;
   final String jsonrpc;
 
   /// The result of a request. This member is REQUIRED on success. This member
@@ -22139,8 +22139,8 @@
           reporter.reportError('must not be undefined');
           return false;
         }
-        if (obj['id'] != null && !((obj['id'] is num || obj['id'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+        if (obj['id'] != null && !((obj['id'] is int || obj['id'] is String))) {
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -22493,18 +22493,18 @@
         ?.toList();
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return SelectionRangeParams(
         textDocument: textDocument,
         positions: positions,
@@ -22514,7 +22514,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The positions inside the text document.
   final List<Position> positions;
@@ -22523,7 +22523,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -22579,9 +22579,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -22590,9 +22590,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -23469,18 +23469,18 @@
     final previousResultId = json['previousResultId'];
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return SemanticTokensDeltaParams(
         textDocument: textDocument,
         previousResultId: previousResultId,
@@ -23490,7 +23490,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The result id of a previous response. The result Id can either point to a
   /// full response or a delta response depending on what was received last.
@@ -23500,7 +23500,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -23554,9 +23554,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -23565,9 +23565,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -23688,19 +23688,19 @@
   static SemanticTokensEdit fromJson(Map<String, dynamic> json) {
     final start = json['start'];
     final deleteCount = json['deleteCount'];
-    final data = json['data']?.map((item) => item)?.cast<num>()?.toList();
+    final data = json['data']?.map((item) => item)?.cast<int>()?.toList();
     return SemanticTokensEdit(
         start: start, deleteCount: deleteCount, data: data);
   }
 
   /// The elements to insert.
-  final List<num>? data;
+  final List<int>? data;
 
   /// The count of elements to remove.
-  final num deleteCount;
+  final int deleteCount;
 
   /// The start offset of the edit.
-  final num start;
+  final int start;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -23724,8 +23724,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['start'] is num)) {
-          reporter.reportError('must be of type num');
+        if (!(obj['start'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -23741,8 +23741,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['deleteCount'] is num)) {
-          reporter.reportError('must be of type num');
+        if (!(obj['deleteCount'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -23752,8 +23752,8 @@
       try {
         if (obj['data'] != null &&
             !((obj['data'] is List &&
-                (obj['data'].every((item) => item is num))))) {
-          reporter.reportError('must be of type List<num>');
+                (obj['data'].every((item) => item is int))))) {
+          reporter.reportError('must be of type List<int>');
           return false;
         }
       } finally {
@@ -23772,7 +23772,7 @@
         other.runtimeType == SemanticTokensEdit) {
       return start == other.start &&
           deleteCount == other.deleteCount &&
-          listEqual(data, other.data, (num a, num b) => a == b) &&
+          listEqual(data, other.data, (int a, int b) => a == b) &&
           true;
     }
     return false;
@@ -24152,18 +24152,18 @@
     final textDocument = TextDocumentIdentifier.fromJson(json['textDocument']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return SemanticTokensParams(
         textDocument: textDocument,
         workDoneToken: workDoneToken,
@@ -24172,13 +24172,13 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The text document.
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -24214,9 +24214,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -24225,9 +24225,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -24272,11 +24272,11 @@
 
   SemanticTokensPartialResult({required this.data});
   static SemanticTokensPartialResult fromJson(Map<String, dynamic> json) {
-    final data = json['data']?.map((item) => item)?.cast<num>()?.toList();
+    final data = json['data']?.map((item) => item)?.cast<int>()?.toList();
     return SemanticTokensPartialResult(data: data);
   }
 
-  final List<num> data;
+  final List<int> data;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -24297,8 +24297,8 @@
           return false;
         }
         if (!((obj['data'] is List &&
-            (obj['data'].every((item) => item is num))))) {
-          reporter.reportError('must be of type List<num>');
+            (obj['data'].every((item) => item is int))))) {
+          reporter.reportError('must be of type List<int>');
           return false;
         }
       } finally {
@@ -24315,7 +24315,7 @@
   bool operator ==(Object other) {
     if (other is SemanticTokensPartialResult &&
         other.runtimeType == SemanticTokensPartialResult) {
-      return listEqual(data, other.data, (num a, num b) => a == b) && true;
+      return listEqual(data, other.data, (int a, int b) => a == b) && true;
     }
     return false;
   }
@@ -24346,18 +24346,18 @@
     final range = Range.fromJson(json['range']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return SemanticTokensRangeParams(
         textDocument: textDocument,
         range: range,
@@ -24367,7 +24367,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The range the semantic tokens are requested for.
   final Range range;
@@ -24376,7 +24376,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -24430,9 +24430,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -24441,9 +24441,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -26776,7 +26776,7 @@
   /// parameters it is ignored. In future version of the protocol this property
   /// might become mandatory to better express the active parameter if the
   /// active signature does have any.
-  final num? activeParameter;
+  final int? activeParameter;
 
   /// The active signature. If omitted or the value lies outside the range of
   /// `signatures` the value defaults to zero or is ignore if the
@@ -26787,7 +26787,7 @@
   ///
   /// In future version of the protocol this property might become mandatory to
   /// better express this.
-  final num? activeSignature;
+  final int? activeSignature;
 
   /// One or more signatures. If no signatures are available the signature help
   /// request should return `null`.
@@ -26829,8 +26829,8 @@
       reporter.push('activeSignature');
       try {
         if (obj['activeSignature'] != null &&
-            !(obj['activeSignature'] is num)) {
-          reporter.reportError('must be of type num');
+            !(obj['activeSignature'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -26839,8 +26839,8 @@
       reporter.push('activeParameter');
       try {
         if (obj['activeParameter'] != null &&
-            !(obj['activeParameter'] is num)) {
-          reporter.reportError('must be of type num');
+            !(obj['activeParameter'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -27480,11 +27480,11 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     return SignatureHelpParams(
         context: context,
         textDocument: textDocument,
@@ -27505,7 +27505,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -27569,9 +27569,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -27837,7 +27837,7 @@
   ///
   /// If provided, this is used in place of `SignatureHelp.activeParameter`.
   ///  @since 3.16.0
-  final num? activeParameter;
+  final int? activeParameter;
 
   /// The human-readable doc-comment of this signature. Will be shown in the UI
   /// but can be omitted.
@@ -27911,8 +27911,8 @@
       reporter.push('activeParameter');
       try {
         if (obj['activeParameter'] != null &&
-            !(obj['activeParameter'] is num)) {
-          reporter.reportError('must be of type num');
+            !(obj['activeParameter'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -29137,7 +29137,7 @@
 
   /// The optional length of the range that got replaced.
   ///  @deprecated use range instead.
-  final num? rangeLength;
+  final int? rangeLength;
 
   /// The new text for the provided range.
   final String text;
@@ -29173,8 +29173,8 @@
       }
       reporter.push('rangeLength');
       try {
-        if (obj['rangeLength'] != null && !(obj['rangeLength'] is num)) {
-          reporter.reportError('must be of type num');
+        if (obj['rangeLength'] != null && !(obj['rangeLength'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -29513,7 +29513,7 @@
 
   /// The version number of this document (it will increase after each change,
   /// including undo/redo).
-  final num version;
+  final int version;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -29570,8 +29570,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['version'] is num)) {
-          reporter.reportError('must be of type num');
+        if (!(obj['version'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -30655,18 +30655,18 @@
     final position = Position.fromJson(json['position']);
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return TypeDefinitionParams(
         textDocument: textDocument,
         position: position,
@@ -30676,7 +30676,7 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// The position inside the text document.
   final Position position;
@@ -30685,7 +30685,7 @@
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -30739,9 +30739,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -30750,9 +30750,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -31129,7 +31129,7 @@
   ///
   /// The version number of a document will increase after each change,
   /// including undo/redo. The number doesn't need to be consecutive.
-  final num version;
+  final int version;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -31150,8 +31150,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['version'] is num)) {
-          reporter.reportError('must be of type num');
+        if (!(obj['version'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -31372,7 +31372,7 @@
   ///
   /// The value should be steadily rising. Clients are free to ignore values
   /// that are not following this rule. The value range is [0, 100]
-  final num? percentage;
+  final int? percentage;
 
   /// Mandatory title of the progress operation. Used to briefly inform about
   /// the kind of operation being performed.
@@ -31452,8 +31452,8 @@
       }
       reporter.push('percentage');
       try {
-        if (obj['percentage'] != null && !(obj['percentage'] is num)) {
-          reporter.reportError('must be of type num');
+        if (obj['percentage'] != null && !(obj['percentage'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -31502,16 +31502,16 @@
 
   WorkDoneProgressCancelParams({required this.token});
   static WorkDoneProgressCancelParams fromJson(Map<String, dynamic> json) {
-    final token = json['token'] is num
-        ? Either2<num, String>.t1(json['token'])
+    final token = json['token'] is int
+        ? Either2<int, String>.t1(json['token'])
         : (json['token'] is String
-            ? Either2<num, String>.t2(json['token'])
-            : (throw '''${json['token']} was not one of (num, String)'''));
+            ? Either2<int, String>.t2(json['token'])
+            : (throw '''${json['token']} was not one of (int, String)'''));
     return WorkDoneProgressCancelParams(token: token);
   }
 
   /// The token to be used to report progress.
-  final Either2<num, String> token;
+  final Either2<int, String> token;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -31531,8 +31531,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!((obj['token'] is num || obj['token'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+        if (!((obj['token'] is int || obj['token'] is String))) {
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -31572,16 +31572,16 @@
 
   WorkDoneProgressCreateParams({required this.token});
   static WorkDoneProgressCreateParams fromJson(Map<String, dynamic> json) {
-    final token = json['token'] is num
-        ? Either2<num, String>.t1(json['token'])
+    final token = json['token'] is int
+        ? Either2<int, String>.t1(json['token'])
         : (json['token'] is String
-            ? Either2<num, String>.t2(json['token'])
-            : (throw '''${json['token']} was not one of (num, String)'''));
+            ? Either2<int, String>.t2(json['token'])
+            : (throw '''${json['token']} was not one of (int, String)'''));
     return WorkDoneProgressCreateParams(token: token);
   }
 
   /// The token to be used to report progress.
-  final Either2<num, String> token;
+  final Either2<int, String> token;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -31601,8 +31601,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!((obj['token'] is num || obj['token'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+        if (!((obj['token'] is int || obj['token'] is String))) {
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -31956,16 +31956,16 @@
     }
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     return WorkDoneProgressParams(workDoneToken: workDoneToken);
   }
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -31980,9 +31980,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -32059,7 +32059,7 @@
   ///
   /// The value should be steadily rising. Clients are free to ignore values
   /// that are not following this rule. The value range is [0, 100]
-  final num? percentage;
+  final int? percentage;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -32115,8 +32115,8 @@
       }
       reporter.push('percentage');
       try {
-        if (obj['percentage'] != null && !(obj['percentage'] is num)) {
-          reporter.reportError('must be of type num');
+        if (obj['percentage'] != null && !(obj['percentage'] is int)) {
+          reporter.reportError('must be of type int');
           return false;
         }
       } finally {
@@ -33197,18 +33197,18 @@
     final query = json['query'];
     final workDoneToken = json['workDoneToken'] == null
         ? null
-        : (json['workDoneToken'] is num
-            ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is int
+            ? Either2<int, String>.t1(json['workDoneToken'])
             : (json['workDoneToken'] is String
-                ? Either2<num, String>.t2(json['workDoneToken'])
-                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['workDoneToken'])
+                : (throw '''${json['workDoneToken']} was not one of (int, String)''')));
     final partialResultToken = json['partialResultToken'] == null
         ? null
-        : (json['partialResultToken'] is num
-            ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is int
+            ? Either2<int, String>.t1(json['partialResultToken'])
             : (json['partialResultToken'] is String
-                ? Either2<num, String>.t2(json['partialResultToken'])
-                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+                ? Either2<int, String>.t2(json['partialResultToken'])
+                : (throw '''${json['partialResultToken']} was not one of (int, String)''')));
     return WorkspaceSymbolParams(
         query: query,
         workDoneToken: workDoneToken,
@@ -33217,14 +33217,14 @@
 
   /// An optional token that a server can use to report partial results (e.g.
   /// streaming) to the client.
-  final Either2<num, String>? partialResultToken;
+  final Either2<int, String>? partialResultToken;
 
   /// A query string to filter symbols by. Clients may send an empty string here
   /// to request all symbols.
   final String query;
 
   /// An optional token that a server can use to report work done progress.
-  final Either2<num, String>? workDoneToken;
+  final Either2<int, String>? workDoneToken;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -33260,9 +33260,9 @@
       reporter.push('workDoneToken');
       try {
         if (obj['workDoneToken'] != null &&
-            !((obj['workDoneToken'] is num ||
+            !((obj['workDoneToken'] is int ||
                 obj['workDoneToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
@@ -33271,9 +33271,9 @@
       reporter.push('partialResultToken');
       try {
         if (obj['partialResultToken'] != null &&
-            !((obj['partialResultToken'] is num ||
+            !((obj['partialResultToken'] is int ||
                 obj['partialResultToken'] is String))) {
-          reporter.reportError('must be of type Either2<num, String>');
+          reporter.reportError('must be of type Either2<int, String>');
           return false;
         }
       } finally {
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index 7f10b84..3b44a12 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -46,7 +46,7 @@
 const dartTypeFormattingCharacters = ['}', ';'];
 
 /// A [ProgressToken] used for reporting progress when the server is analyzing.
-final analyzingProgressToken = Either2<num, String>.t2('ANALYZING');
+final analyzingProgressToken = Either2<int, String>.t2('ANALYZING');
 
 final emptyWorkspaceEdit = WorkspaceEdit();
 
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 afe1dc7..9958c9b 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -516,7 +516,7 @@
     completers[requestId] = completer;
 
     channel.sendRequest(RequestMessage(
-      id: Either2<num, String>.t1(requestId),
+      id: Either2<int, String>.t1(requestId),
       method: method,
       params: params,
       jsonrpc: jsonRpcVersion,
diff --git a/pkg/analysis_server/lib/src/lsp/progress.dart b/pkg/analysis_server/lib/src/lsp/progress.dart
index fcb2dac..398d0b0 100644
--- a/pkg/analysis_server/lib/src/lsp/progress.dart
+++ b/pkg/analysis_server/lib/src/lsp/progress.dart
@@ -17,7 +17,7 @@
   /// Creates a reporter for a token that was supplied by the client and does
   /// not need creating prior to use.
   factory ProgressReporter.clientProvided(
-          LspAnalysisServer server, Either2<num, String> token) =>
+          LspAnalysisServer server, Either2<int, String> token) =>
       _TokenProgressReporter(server, token);
 
   /// Creates a reporter for a new token that must be created prior to being
@@ -25,7 +25,7 @@
   ///
   /// If [token] is not supplied, a random identifier will be used.
   factory ProgressReporter.serverCreated(LspAnalysisServer server,
-          [Either2<num, String>? token]) =>
+          [Either2<int, String>? token]) =>
       _ServerCreatedProgressReporter(server, token);
 
   ProgressReporter._();
@@ -50,10 +50,10 @@
 
   _ServerCreatedProgressReporter(
     LspAnalysisServer server,
-    Either2<num, String>? token,
+    Either2<int, String>? token,
   ) : super(
           server,
-          token ?? Either2<num, String>.t2(_randomTokenIdentifier()),
+          token ?? Either2<int, String>.t2(_randomTokenIdentifier()),
         );
 
   @override
@@ -102,7 +102,7 @@
 
 class _TokenProgressReporter extends ProgressReporter {
   final LspAnalysisServer _server;
-  final Either2<num, String> _token;
+  final Either2<int, String> _token;
   bool _needsEnd = false;
 
   _TokenProgressReporter(this._server, this._token) : super._();
diff --git a/pkg/analysis_server/test/integration/lsp_server/initialization_test.dart b/pkg/analysis_server/test/integration/lsp_server/initialization_test.dart
index c1ba011..214cf6f 100644
--- a/pkg/analysis_server/test/integration/lsp_server/initialization_test.dart
+++ b/pkg/analysis_server/test/integration/lsp_server/initialization_test.dart
@@ -20,7 +20,7 @@
   Future<void> test_initialize_invalidParams() async {
     final params = {'processId': 'invalid'};
     final request = RequestMessage(
-      id: Either2<num, String>.t1(1),
+      id: Either2<int, String>.t1(1),
       method: Method.initialize,
       params: params,
       jsonrpc: jsonRpcVersion,
diff --git a/pkg/analysis_server/test/lsp/code_actions_abstract.dart b/pkg/analysis_server/test/lsp/code_actions_abstract.dart
index 591a70e..8537420 100644
--- a/pkg/analysis_server/test/lsp/code_actions_abstract.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_abstract.dart
@@ -80,7 +80,7 @@
   Future verifyCodeActionEdits(Either2<Command, CodeAction> codeAction,
       String content, String expectedContent,
       {bool expectDocumentChanges = false,
-      Either2<num, String>? workDoneToken}) async {
+      Either2<int, String>? workDoneToken}) async {
     final command = codeAction.map(
       (command) => command,
       (codeAction) => codeAction.command!,
@@ -97,7 +97,7 @@
   Future<void> verifyCommandEdits(
       Command command, String content, String expectedContent,
       {bool expectDocumentChanges = false,
-      Either2<num, String>? workDoneToken}) async {
+      Either2<int, String>? workDoneToken}) async {
     ApplyWorkspaceEditParams? editParams;
 
     final commandResponse = await handleExpectedRequest<Object?,
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index 9dbe5cc..cdc4cc8 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -499,7 +499,7 @@
   Future<void> test_initialize_invalidParams() async {
     final params = {'processId': 'invalid'};
     final request = RequestMessage(
-      id: Either2<num, String>.t1(1),
+      id: Either2<int, String>.t1(1),
       method: Method.initialize,
       params: params,
       jsonrpc: jsonRpcVersion,
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index e5ce594..4bdc585 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -571,7 +571,7 @@
   /// A progress token used in tests where the client-provides the token, which
   /// should not be validated as being created by the server first.
   final clientProvidedTestWorkDoneToken =
-      Either2<num, String>.t2('client-test');
+      Either2<int, String>.t2('client-test');
 
   int _id = 0;
   late String projectFolderPath,
@@ -804,7 +804,7 @@
   }
 
   Future<Object?> executeCommand(Command command,
-      {Either2<num, String>? workDoneToken}) async {
+      {Either2<int, String>? workDoneToken}) async {
     final request = makeRequest(
       Method.workspace_executeCommand,
       ExecuteCommandParams(
@@ -1334,7 +1334,7 @@
   }
 
   RequestMessage makeRequest(Method method, ToJsonable? params) {
-    final id = Either2<num, String>.t1(_id++);
+    final id = Either2<int, String>.t1(_id++);
     return RequestMessage(
         id: id, method: method, params: params, jsonrpc: jsonRpcVersion);
   }
diff --git a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
index c2715d7..f81b17a 100644
--- a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
+++ b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
@@ -91,7 +91,7 @@
 
     // Create a request that doesn't supply the query param.
     final request = RequestMessage(
-      id: Either2<num, String>.t1(1),
+      id: Either2<int, String>.t1(1),
       method: Method.workspace_symbol,
       params: <String, dynamic>{},
       jsonrpc: jsonRpcVersion,
diff --git a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
index add3ab4..824217e 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
@@ -20,7 +20,7 @@
 
     test('returns correct output for union types', () {
       final message = RequestMessage(
-          id: Either2<num, String>.t1(1),
+          id: Either2<int, String>.t1(1),
           method: Method.shutdown,
           jsonrpc: 'test');
       final output = json.encode(message.toJson());
@@ -113,7 +113,7 @@
     });
 
     test('ResponseMessage does not include an error with a result', () {
-      final id = Either2<num, String>.t1(1);
+      final id = Either2<int, String>.t1(1);
       final result = 'my result';
       final resp =
           ResponseMessage(id: id, result: result, jsonrpc: jsonRpcVersion);
@@ -302,7 +302,7 @@
     });
 
     test('ResponseMessage can include a null result', () {
-      final id = Either2<num, String>.t1(1);
+      final id = Either2<int, String>.t1(1);
       final resp = ResponseMessage(id: id, jsonrpc: jsonRpcVersion);
       final jsonMap = resp.toJson();
       expect(jsonMap, contains('result'));
@@ -310,7 +310,7 @@
     });
 
     test('ResponseMessage does not include a result for an error', () {
-      final id = Either2<num, String>.t1(1);
+      final id = Either2<int, String>.t1(1);
       final error =
           ResponseError(code: ErrorCodes.ParseError, message: 'Error');
       final resp =
@@ -321,7 +321,7 @@
     });
 
     test('ResponseMessage throws if both result and error are non-null', () {
-      final id = Either2<num, String>.t1(1);
+      final id = Either2<int, String>.t1(1);
       final result = 'my result';
       final error =
           ResponseError(code: ErrorCodes.ParseError, message: 'Error');
diff --git a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
index 3e5300d..66518f3 100644
--- a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
+++ b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
@@ -62,6 +62,14 @@
 
 TypeBase resolveTypeAlias(TypeBase type, {resolveEnumClasses = false}) {
   if (type is Type) {
+    // The LSP spec contains type aliases for `integer` and `uinteger` that map
+    // into the `number` type, with comments stating they must be integers. To
+    // preserve the improved typing, do _not_ resolve them to the `number`
+    // type.
+    if (type.name == 'integer' || type.name == 'uinteger') {
+      return type;
+    }
+
     final alias = _typeAliases[type.name];
     // Only follow the type if we're not an enum, or we wanted to follow enums.
     if (alias != null &&
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript.dart b/pkg/analysis_server/tool/lsp_spec/typescript.dart
index f857a6a..5ebb88d 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript.dart
@@ -118,16 +118,9 @@
     'ParameterInformation': {
       'label': 'String',
     },
-    'Position': {
-      'character': 'int',
-      'line': 'int',
-    },
     'ProgressParams': {
       'value': 'object',
     },
-    'SemanticTokens': {
-      'data': 'int[]',
-    },
     'ServerCapabilities': {
       'changeNotifications': 'bool',
     },
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
index 96f7c88..e3cc2c6 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
@@ -952,6 +952,8 @@
       'boolean': 'bool',
       'string': 'String',
       'number': 'num',
+      'integer': 'int',
+      'uinteger': 'int',
       'any': 'dynamic',
       'object': 'dynamic',
       // Simplify MarkedString from
diff --git a/pkg/analyzer/lib/src/error/must_call_super_verifier.dart b/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
index 7898133..31a85ca 100644
--- a/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
+++ b/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
@@ -21,13 +21,38 @@
     }
     var element = node.declaredElement!;
     var overridden = _findOverriddenMemberWithMustCallSuper(element);
-    if (overridden != null &&
-        _hasConcreteSuperMethod(element as MethodElement)) {
-      _SuperCallVerifier verifier = _SuperCallVerifier(overridden.name);
-      node.accept(verifier);
-      if (!verifier.superIsCalled) {
-        _errorReporter.reportErrorForNode(HintCode.MUST_CALL_SUPER, node.name,
-            [overridden.enclosingElement.name]);
+    if (overridden == null) {
+      return;
+    }
+
+    if (element is MethodElement && _hasConcreteSuperMethod(element)) {
+      _verifySuperIsCalled(
+          node, overridden.name, overridden.enclosingElement.name);
+      return;
+    }
+
+    var enclosingElement = element.enclosingElement as ClassElement;
+    if (element is PropertyAccessorElement && element.isGetter) {
+      var inheritedConcreteGetter = enclosingElement
+          .lookUpInheritedConcreteGetter(element.name, element.library);
+      if (inheritedConcreteGetter != null) {
+        _verifySuperIsCalled(
+            node, overridden.name, overridden.enclosingElement.name);
+      }
+      return;
+    }
+
+    if (element is PropertyAccessorElement && element.isSetter) {
+      var inheritedConcreteSetter = enclosingElement
+          .lookUpInheritedConcreteSetter(element.name, element.library);
+      if (inheritedConcreteSetter != null) {
+        var name = overridden.name;
+        // For a setter, give the name without the trailing '=' to the verifier,
+        // in order to check against property access.
+        if (name.endsWith('=')) {
+          name = name.substring(0, name.length - 1);
+        }
+        _verifySuperIsCalled(node, name, overridden.enclosingElement.name);
       }
     }
   }
@@ -67,6 +92,12 @@
       if (member is MethodElement && member.hasMustCallSuper) {
         return member;
       }
+      if (member is PropertyAccessorElement && member.hasMustCallSuper) {
+        // TODO(srawlins): What about a field annotated with `@mustCallSuper`?
+        // This might seem a legitimate case, but is not called out in the
+        // documentation of [mustCallSuper].
+        return member;
+      }
       superclasses
         ..addAll(ancestor.mixins.map((i) => i.element))
         ..addAll(ancestor.superclassConstraints.map((i) => i.element))
@@ -76,7 +107,7 @@
   }
 
   /// Returns whether [node] overrides a concrete method.
-  bool _hasConcreteSuperMethod(MethodElement element) {
+  bool _hasConcreteSuperMethod(ExecutableElement element) {
     var classElement = element.enclosingElement as ClassElement;
     String name = element.name;
 
@@ -99,6 +130,17 @@
 
     return false;
   }
+
+  void _verifySuperIsCalled(MethodDeclaration node, String methodName,
+      String? overriddenEnclosingName) {
+    _SuperCallVerifier verifier = _SuperCallVerifier(methodName);
+    node.accept(verifier);
+    if (!verifier.superIsCalled) {
+      _errorReporter.reportErrorForNode(
+          HintCode.MUST_CALL_SUPER, node.name, [overriddenEnclosingName]);
+    }
+    return;
+  }
 }
 
 /// Recursively visits an AST, looking for method invocations.
@@ -110,9 +152,22 @@
   _SuperCallVerifier(this.name);
 
   @override
+  void visitAssignmentExpression(AssignmentExpression node) {
+    var lhs = node.leftHandSide;
+    if (lhs is PropertyAccess) {
+      if (lhs.target is SuperExpression && lhs.propertyName.name == name) {
+        superIsCalled = true;
+        return;
+      }
+    }
+    super.visitAssignmentExpression(node);
+  }
+
+  @override
   void visitBinaryExpression(BinaryExpression node) {
     if (node.leftOperand is SuperExpression && node.operator.lexeme == name) {
       superIsCalled = true;
+      return;
     }
     super.visitBinaryExpression(node);
   }
@@ -121,7 +176,17 @@
   void visitMethodInvocation(MethodInvocation node) {
     if (node.target is SuperExpression && node.methodName.name == name) {
       superIsCalled = true;
+      return;
     }
     super.visitMethodInvocation(node);
   }
+
+  @override
+  void visitPropertyAccess(PropertyAccess node) {
+    if (node.target is SuperExpression && node.propertyName.name == name) {
+      superIsCalled = true;
+      return;
+    }
+    super.visitPropertyAccess(node);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
index 44f695f..ddc7589 100644
--- a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
@@ -113,6 +113,39 @@
     ]);
   }
 
+  test_fromExtendingClass_getter() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  int get a => 1;
+}
+class B extends A {
+  @override
+  int get a => 2;
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 122, 1),
+    ]);
+  }
+
+  test_fromExtendingClass_getter_containsSuperCall() async {
+    await assertNoErrorsInCode('''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  int get a => 1;
+}
+class B extends A {
+  @override
+  int get a {
+    super.a;
+    return 2;
+  }
+}
+''');
+  }
+
   test_fromExtendingClass_operator() async {
     await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
@@ -143,6 +176,38 @@
 ''');
   }
 
+  test_fromExtendingClass_setter() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  set a(int value) {}
+}
+class B extends A {
+  @override
+  set a(int value) {}
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 122, 1),
+    ]);
+  }
+
+  test_fromExtendingClass_setter_containsSuperCall() async {
+    await assertNoErrorsInCode('''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  set a(int value) {}
+}
+class B extends A {
+  @override
+  set a(int value) {
+    super.a = value;
+  }
+}
+''');
+  }
+
   test_fromInterface() async {
     await assertNoErrorsInCode(r'''
 import 'package:meta/meta.dart';
@@ -173,6 +238,22 @@
     ]);
   }
 
+  test_fromMixin_setter() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class Mixin {
+  @mustCallSuper
+  void set a(int value) {}
+}
+class C with Mixin {
+  @override
+  void set a(int value) {}
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 137, 1),
+    ]);
+  }
+
   test_fromMixin_throughExtendingClass() async {
     await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 9d0eb71..c3b3af8 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -14,21 +14,12 @@
   Map<NamingScope, TokenScope> _tokenScopes =
       new Maplet<NamingScope, TokenScope>();
 
-  // Some basic settings for smaller names
-  @override
-  String get isolateName => 'I';
-  @override
-  String get isolatePropertiesName => 'p';
   @override
   bool get shouldMinify => true;
 
   @override
   String get genericInstantiationPrefix => r'$I';
 
-  @override
-  jsAst.Name get staticsPropertyName =>
-      _staticsPropertyName ??= getFreshName(instanceScope, 'static');
-
   FrequencyBasedNamer(JClosedWorld closedWorld, FixedNames fixedNames)
       : super(closedWorld, fixedNames) {
     fieldRegistry = new _FieldNamingRegistry(this);
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index bf2f56c..0689113 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -20,10 +20,6 @@
   _FieldNamingRegistry fieldRegistry;
 
   @override
-  String get isolateName => 'I';
-  @override
-  String get isolatePropertiesName => 'p';
-  @override
   bool get shouldMinify => true;
   @override
   String get genericInstantiationPrefix => r'$I';
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 71a11cf..26707b5 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -419,15 +419,7 @@
     return _jsReserved;
   }
 
-  final String lazyGetterPrefix = r'$get$';
-  final String superPrefix = r'super$';
-  final String metadataField = '@';
   final String stubNameField = r'$stubName';
-  final String reflectionInfoField = r'$reflectionInfo';
-  final String reflectionNameField = r'$reflectionName';
-  final String metadataIndexField = r'$metadataIndex';
-  final String methodsWithOptionalArgumentsField =
-      r'$methodsWithOptionalArguments';
 
   @override
   final FixedNames fixedNames;
@@ -436,26 +428,17 @@
   static const String _callPrefixDollar = r'call$';
 
   static final jsAst.Name _literalDollar = new StringBackedName(r'$');
-  static final jsAst.Name literalPlus = new StringBackedName('+');
   static final jsAst.Name _literalDynamic = new StringBackedName("dynamic");
 
   jsAst.Name _literalGetterPrefix;
   jsAst.Name _literalSetterPrefix;
 
-  jsAst.Name _staticsPropertyName;
-
-  jsAst.Name get staticsPropertyName =>
-      _staticsPropertyName ??= new StringBackedName('static');
-
   jsAst.Name _rtiFieldJsName;
 
   @override
   jsAst.Name get rtiFieldJsName =>
       _rtiFieldJsName ??= new StringBackedName(fixedNames.rtiName);
 
-  // Name of property in a class description for the native dispatch metadata.
-  final String nativeSpecProperty = '%';
-
   static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$');
   static final RegExp NON_IDENTIFIER_CHAR = new RegExp(r'[^A-Za-z_0-9$]');
 
@@ -564,15 +547,8 @@
 
   NativeData get _nativeData => _closedWorld.nativeData;
 
-  String get deferredMetadataName => 'deferredMetadata';
-  String get deferredTypesName => 'deferredTypes';
-  String get isolateName => 'Isolate';
-  String get isolatePropertiesName => r'$isolateProperties';
   jsAst.Name get noSuchMethodName => invocationName(Selectors.noSuchMethod_);
 
-  /// Some closures must contain their name. The name is stored in
-  /// [STATIC_CLOSURE_NAME_NAME].
-  String get STATIC_CLOSURE_NAME_NAME => r'$name';
   String get closureInvocationSelectorName => Identifiers.call;
   bool get shouldMinify => false;
 
@@ -971,22 +947,6 @@
     return _newReference(newName);
   }
 
-  /// Returns the property name to use for a compiler-owner global variable,
-  /// i.e. one that does not correspond to any element but is used as a utility
-  /// global by code generation.
-  ///
-  /// [name] functions as both the proposed name for the global, and as a key
-  /// identifying the global. The [name] must not contain `$` symbols, since
-  /// the [Namer] uses those names internally.
-  ///
-  /// This provides an easy mechanism of avoiding a name-clash with user-space
-  /// globals, although the callers of must still take care not to accidentally
-  /// pass in the same [name] for two different internal globals.
-  jsAst.Name internalGlobal(String name) {
-    assert(!name.contains(r'$'));
-    return _disambiguateInternalGlobal(name);
-  }
-
   /// Generates a unique key for [library].
   ///
   /// Keys are meant to be used in maps and should not be visible in the output.
@@ -1493,18 +1453,6 @@
   // parts with the fast-startup emitter.
   String get typesOffsetName => r'typesOffset';
 
-  Map<FunctionType, jsAst.Name> functionTypeNameMap = {};
-
-  FunctionTypeNamer _functionTypeNamer;
-
-  jsAst.Name getFunctionTypeName(FunctionType functionType) {
-    return functionTypeNameMap.putIfAbsent(functionType, () {
-      _functionTypeNamer ??= new FunctionTypeNamer();
-      String proposedName = _functionTypeNamer.computeName(functionType);
-      return getFreshName(instanceScope, proposedName);
-    });
-  }
-
   @override
   jsAst.Name operatorIs(ClassEntity element) {
     // TODO(erikcorry): Reduce from $isx to ix when we are minifying.
@@ -2126,80 +2074,6 @@
   }
 }
 
-class FunctionTypeNamer extends BaseDartTypeVisitor {
-  StringBuffer sb;
-
-  FunctionTypeNamer();
-
-  String computeName(DartType type) {
-    sb = new StringBuffer();
-    visit(type);
-    return sb.toString();
-  }
-
-  @override
-  visit(DartType type, [_]) {
-    type.accept(this, null);
-  }
-
-  @override
-  visitType(DartType type, _) {}
-
-  @override
-  visitInterfaceType(InterfaceType type, _) {
-    sb.write(type.element.name);
-  }
-
-  @override
-  visitTypeVariableType(TypeVariableType type, _) {
-    sb.write(type.element.name);
-  }
-
-  bool _isSimpleFunctionType(FunctionType type) {
-    if (type.returnType is! DynamicType) return false;
-    if (!type.optionalParameterTypes.isEmpty) return false;
-    if (!type.namedParameterTypes.isEmpty) return false;
-    for (DartType parameter in type.parameterTypes) {
-      if (parameter is! DynamicType) return false;
-    }
-    return true;
-  }
-
-  @override
-  visitFunctionType(FunctionType type, _) {
-    if (_isSimpleFunctionType(type)) {
-      sb.write('args${type.parameterTypes.length}');
-      return;
-    }
-    visit(type.returnType);
-    sb.write('_');
-    for (DartType parameter in type.parameterTypes) {
-      sb.write('_');
-      visit(parameter);
-    }
-    bool first = false;
-    for (DartType parameter in type.optionalParameterTypes) {
-      if (!first) {
-        sb.write('_');
-      }
-      sb.write('_');
-      visit(parameter);
-      first = true;
-    }
-    if (!type.namedParameterTypes.isEmpty) {
-      first = false;
-      for (DartType parameter in type.namedParameterTypes) {
-        if (!first) {
-          sb.write('_');
-        }
-        sb.write('_');
-        visit(parameter);
-        first = true;
-      }
-    }
-  }
-}
-
 class NamingScope {
   /// Maps proposed names to *suggested* disambiguated names.
   ///
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index b72fbba..5e581c5 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -40,7 +40,8 @@
     args = args
         .where(
           (element) => !(element.contains('--observe') ||
-              element.contains('--enable-vm-service')),
+              element.contains('--enable-vm-service') ||
+              element.contains('--devtools')),
         )
         .toList();
   }
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index db32bfe..d996c3c 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -158,6 +158,10 @@
         hide: !verbose,
         negatable: false,
         help: 'Enables tracing of library and script loading.',
+      )
+      ..addFlag(
+        'debug-dds',
+        hide: true,
       );
     addExperimentalFlags(argParser, verbose);
   }
@@ -179,13 +183,18 @@
     String launchDdsArg = argResults['launch-dds'];
     String ddsHost = '';
     String ddsPort = '';
+
+    // TODO(bkonyi): allow for users to choose not to launch DevTools
+    // See https://github.com/dart-lang/sdk/issues/45867.
+    const bool launchDevTools = true;
     bool launchDds = false;
     if (launchDdsArg != null) {
       launchDds = true;
-      final ddsUrl = launchDdsArg.split(':');
+      final ddsUrl = launchDdsArg.split('\\:');
       ddsHost = ddsUrl[0];
       ddsPort = ddsUrl[1];
     }
+    final bool debugDds = argResults['debug-dds'];
 
     bool disableServiceAuthCodes = argResults['disable-service-auth-codes'];
 
@@ -198,7 +207,12 @@
     if (launchDds) {
       debugSession = _DebuggingSession();
       if (!await debugSession.start(
-          ddsHost, ddsPort, disableServiceAuthCodes)) {
+        ddsHost,
+        ddsPort,
+        disableServiceAuthCodes,
+        launchDevTools,
+        debugDds,
+      )) {
         return errorExitCode;
       }
     }
@@ -242,10 +256,19 @@
 
 class _DebuggingSession {
   Future<bool> start(
-      String host, String port, bool disableServiceAuthCodes) async {
-    final ddsSnapshot = (dirname(sdk.dart).endsWith('bin'))
+    String host,
+    String port,
+    bool disableServiceAuthCodes,
+    bool enableDevTools,
+    bool debugDds,
+  ) async {
+    final sdkDir = dirname(sdk.dart);
+    final fullSdk = sdkDir.endsWith('bin');
+    final ddsSnapshot = fullSdk
         ? sdk.ddsSnapshot
-        : absolute(dirname(sdk.dart), 'gen', 'dds.dart.snapshot');
+        : absolute(sdkDir, 'gen', 'dds.dart.snapshot');
+    final devToolsBinaries =
+        fullSdk ? sdk.devToolsBinaries : absolute(sdkDir, 'devtools');
     if (!Sdk.checkArtifactExists(ddsSnapshot)) {
       return false;
     }
@@ -256,30 +279,51 @@
       serviceInfo = await Service.getInfo();
     }
     final process = await Process.start(
-        sdk.dart,
-        [
-          if (dirname(sdk.dart).endsWith('bin'))
-            sdk.ddsSnapshot
-          else
-            absolute(dirname(sdk.dart), 'gen', 'dds.dart.snapshot'),
-          serviceInfo.serverUri.toString(),
-          host,
-          port,
-          disableServiceAuthCodes.toString(),
-        ],
-        mode: ProcessStartMode.detachedWithStdio);
+      sdk.dart,
+      [
+        if (debugDds) '--enable-vm-service=0',
+        ddsSnapshot,
+        serviceInfo.serverUri.toString(),
+        host,
+        port,
+        disableServiceAuthCodes.toString(),
+        enableDevTools.toString(),
+        devToolsBinaries,
+        debugDds.toString(),
+      ],
+      mode: ProcessStartMode.detachedWithStdio,
+    );
     final completer = Completer<void>();
-    StreamSubscription sub;
-    sub = process.stderr.transform(utf8.decoder).listen((event) {
-      if (event == 'DDS started') {
-        sub.cancel();
+    const devToolsMessagePrefix =
+        'The Dart DevTools debugger and profiler is available at:';
+    if (debugDds) {
+      StreamSubscription stdoutSub;
+      stdoutSub = process.stdout.transform(utf8.decoder).listen((event) {
+        if (event.startsWith(devToolsMessagePrefix)) {
+          final ddsDebuggingUri = event.split(' ').last;
+          print(
+            'A DevTools debugger for DDS is available at: $ddsDebuggingUri',
+          );
+          stdoutSub.cancel();
+        }
+      });
+    }
+    StreamSubscription stderrSub;
+    stderrSub = process.stderr.transform(utf8.decoder).listen((event) {
+      final result = json.decode(event) as Map<String, dynamic>;
+      final state = result['state'];
+      if (state == 'started') {
+        if (result.containsKey('devToolsUri')) {
+          final devToolsUri = result['devToolsUri'];
+          print('$devToolsMessagePrefix $devToolsUri');
+        }
+        stderrSub.cancel();
         completer.complete();
-      } else if (event.contains('Failed to start DDS')) {
-        sub.cancel();
-        completer.completeError(event.replaceAll(
-          'Failed to start DDS',
+      } else {
+        stderrSub.cancel();
+        completer.completeError(
           'Could not start Observatory HTTP server',
-        ));
+        );
       }
     });
     try {
diff --git a/pkg/dartdev/lib/src/sdk.dart b/pkg/dartdev/lib/src/sdk.dart
index 3e8a12a..426f810 100644
--- a/pkg/dartdev/lib/src/sdk.dart
+++ b/pkg/dartdev/lib/src/sdk.dart
@@ -68,6 +68,13 @@
         'dds.dart.snapshot',
       );
 
+  String get devToolsBinaries => path.absolute(
+        sdkPath,
+        'bin',
+        'resources',
+        'devtools',
+      );
+
   String get pubSnapshot => path.absolute(
         sdkPath,
         'bin',
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index b8cc5e8..58a4d56 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_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:async';
+import 'dart:convert';
 import 'dart:io';
 
 import 'package:path/path.dart' as path;
@@ -300,4 +302,61 @@
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
   });
+
+  group('DevTools', () {
+    const devToolsMessagePrefix =
+        'The Dart DevTools debugger and profiler is available at: http://127.0.0.1:';
+
+    test('spawn simple', () async {
+      p = project(mainSrc: "void main() { print('Hello World'); }");
+      ProcessResult result = p.runSync([
+        'run',
+        '--enable-vm-service',
+        p.relativeFilePath,
+      ]);
+      expect(result.stdout, contains(devToolsMessagePrefix));
+    });
+
+    test('implicit spawn', () async {
+      p = project(mainSrc: "void main() { print('Hello World'); }");
+      ProcessResult result = p.runSync([
+        '--enable-vm-service',
+        p.relativeFilePath,
+      ]);
+      expect(result.stdout, contains(devToolsMessagePrefix));
+    });
+
+    test(
+      'spawn via SIGQUIT',
+      () async {
+        p = project(
+          mainSrc:
+              'void main() { print("ready"); int i = 0; while(true) { i++; } }',
+        );
+        Process process = await p.start([
+          p.relativeFilePath,
+        ]);
+
+        final readyCompleter = Completer<void>();
+        final completer = Completer<void>();
+
+        StreamSubscription sub;
+        sub = process.stdout.transform(utf8.decoder).listen((event) async {
+          if (event.contains('ready')) {
+            readyCompleter.complete();
+          } else if (event.contains(devToolsMessagePrefix)) {
+            await sub.cancel();
+            completer.complete();
+          }
+        });
+        // Wait for process to start.
+        await readyCompleter.future;
+        process.kill(ProcessSignal.sigquit);
+        await completer.future;
+        process.kill();
+      },
+      // No support for SIGQUIT on Windows.
+      skip: Platform.isWindows,
+    );
+  });
 }
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md
index 3db7549..b39156e 100644
--- a/pkg/dds/CHANGELOG.md
+++ b/pkg/dds/CHANGELOG.md
@@ -1,4 +1,5 @@
-# 1.7.7-dev
+# 1.8.0-dev
+- Add support for launching DevTools from DDS.
 - Fixed issue where two clients subscribing to the same stream in close succession
   could result in DDS sending multiple `streamListen` requests to the VM service.
 
diff --git a/pkg/dds/bin/dds.dart b/pkg/dds/bin/dds.dart
index 9937d26..45673f5 100644
--- a/pkg/dds/bin/dds.dart
+++ b/pkg/dds/bin/dds.dart
@@ -4,6 +4,7 @@
 
 // @dart=2.10
 
+import 'dart:convert';
 import 'dart:io';
 
 import 'package:dds/dds.dart';
@@ -16,6 +17,9 @@
 ///   - DDS bind address
 ///   - DDS port
 ///   - Disable service authentication codes
+///   - Start DevTools
+///   - DevTools build directory
+///   - Enable logging
 Future<void> main(List<String> args) async {
   if (args.isEmpty) return;
 
@@ -37,16 +41,37 @@
     port: int.parse(args[2]),
   );
   final disableServiceAuthCodes = args[3] == 'true';
+
+  final startDevTools = args[4] == 'true';
+  Uri devToolsBuildDirectory;
+  if (args[5].isNotEmpty) {
+    devToolsBuildDirectory = Uri.file(args[5]);
+  }
+  final logRequests = args[6] == 'true';
   try {
     // TODO(bkonyi): add retry logic similar to that in vmservice_server.dart
     // See https://github.com/dart-lang/sdk/issues/43192.
-    await DartDevelopmentService.startDartDevelopmentService(
+    final dds = await DartDevelopmentService.startDartDevelopmentService(
       remoteVmServiceUri,
       serviceUri: serviceUri,
       enableAuthCodes: !disableServiceAuthCodes,
+      devToolsConfiguration: startDevTools
+          ? DevToolsConfiguration(
+              enable: startDevTools,
+              customBuildDirectoryPath: devToolsBuildDirectory,
+            )
+          : null,
+      logRequests: logRequests,
     );
-    stderr.write('DDS started');
-  } catch (e) {
-    stderr.writeln('Failed to start DDS:\n$e');
+    stderr.write(json.encode({
+      'state': 'started',
+      if (dds.devToolsUri != null) 'devToolsUri': dds.devToolsUri.toString(),
+    }));
+  } catch (e, st) {
+    stderr.write(json.encode({
+      'state': 'error',
+      'error': '$e',
+      'stacktrace': '$st',
+    }));
   }
 }
diff --git a/pkg/dds/lib/dds.dart b/pkg/dds/lib/dds.dart
index f7c7a05..f0e913b 100644
--- a/pkg/dds/lib/dds.dart
+++ b/pkg/dds/lib/dds.dart
@@ -44,6 +44,8 @@
     Uri serviceUri,
     bool enableAuthCodes = true,
     bool ipv6 = false,
+    DevToolsConfiguration devToolsConfiguration = const DevToolsConfiguration(),
+    bool logRequests = false,
   }) async {
     if (remoteVmServiceUri == null) {
       throw ArgumentError.notNull('remoteVmServiceUri');
@@ -80,6 +82,8 @@
       serviceUri,
       enableAuthCodes,
       ipv6,
+      devToolsConfiguration,
+      logRequests,
     );
     await service.startService();
     return service;
@@ -125,6 +129,11 @@
   /// Returns `null` if the service is not running.
   Uri get wsUri;
 
+  /// The HTTP [Uri] of the hosted DevTools instance.
+  ///
+  /// Returns `null` if DevTools is not running.
+  Uri get devToolsUri;
+
   /// Set to `true` if this instance of [DartDevelopmentService] is accepting
   /// requests.
   bool get isRunning;
@@ -168,3 +177,13 @@
   final int errorCode;
   final String message;
 }
+
+class DevToolsConfiguration {
+  const DevToolsConfiguration({
+    this.enable = false,
+    this.customBuildDirectoryPath,
+  });
+
+  final bool enable;
+  final Uri customBuildDirectoryPath;
+}
diff --git a/pkg/dds/lib/src/client.dart b/pkg/dds/lib/src/client.dart
index f81bd25..9ceb162 100644
--- a/pkg/dds/lib/src/client.dart
+++ b/pkg/dds/lib/src/client.dart
@@ -21,27 +21,25 @@
 /// Representation of a single DDS client which manages the connection and
 /// DDS request intercepting / forwarding.
 class DartDevelopmentServiceClient {
-  factory DartDevelopmentServiceClient.fromWebSocket(
+  DartDevelopmentServiceClient.fromWebSocket(
     DartDevelopmentService dds,
     WebSocketChannel ws,
     json_rpc.Peer vmServicePeer,
-  ) =>
-      DartDevelopmentServiceClient._(
-        dds,
-        ws,
-        vmServicePeer,
-      );
+  ) : this._(
+          dds,
+          ws,
+          vmServicePeer,
+        );
 
-  factory DartDevelopmentServiceClient.fromSSEConnection(
+  DartDevelopmentServiceClient.fromSSEConnection(
     DartDevelopmentService dds,
     SseConnection sse,
     json_rpc.Peer vmServicePeer,
-  ) =>
-      DartDevelopmentServiceClient._(
-        dds,
-        sse,
-        vmServicePeer,
-      );
+  ) : this._(
+          dds,
+          sse,
+          vmServicePeer,
+        );
 
   DartDevelopmentServiceClient._(
     this.dds,
diff --git a/pkg/dds/lib/src/constants.dart b/pkg/dds/lib/src/constants.dart
index 2466390..b69ae7c 100644
--- a/pkg/dds/lib/src/constants.dart
+++ b/pkg/dds/lib/src/constants.dart
@@ -16,6 +16,10 @@
   };
 }
 
+// Give connections time to reestablish before considering them closed.
+// Required to reestablish connections killed by UberProxy.
+const sseKeepAlive = Duration(seconds: 30);
+
 abstract class PauseTypeMasks {
   static const pauseOnStartMask = 1 << 0;
   static const pauseOnReloadMask = 1 << 1;
diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart
index db355fb..85be647 100644
--- a/pkg/dds/lib/src/dds_impl.dart
+++ b/pkg/dds/lib/src/dds_impl.dart
@@ -24,6 +24,8 @@
 import 'binary_compatible_peer.dart';
 import 'client.dart';
 import 'client_manager.dart';
+import 'constants.dart';
+import 'devtools/devtools_handler.dart';
 import 'expression_evaluator.dart';
 import 'isolate_manager.dart';
 import 'stream_manager.dart';
@@ -51,7 +53,13 @@
 
 class DartDevelopmentServiceImpl implements DartDevelopmentService {
   DartDevelopmentServiceImpl(
-      this._remoteVmServiceUri, this._uri, this._authCodesEnabled, this._ipv6) {
+    this._remoteVmServiceUri,
+    this._uri,
+    this._authCodesEnabled,
+    this._ipv6,
+    this._devToolsConfiguration,
+    this.shouldLogRequests,
+  ) {
     _clientManager = ClientManager(this);
     _expressionEvaluator = ExpressionEvaluator(this);
     _isolateManager = IsolateManager(this);
@@ -113,20 +121,26 @@
         (_ipv6 ? InternetAddress.loopbackIPv6 : InternetAddress.loopbackIPv4)
             .host;
     final port = uri?.port ?? 0;
-
+    final pipeline = const Pipeline();
+    if (shouldLogRequests) {
+      pipeline.addMiddleware(
+        logRequests(
+          logger: (String message, bool isError) {
+            print('Log: $message');
+          },
+        ),
+      );
+    }
+    pipeline.addMiddleware(_authCodeMiddleware);
+    final handler = pipeline.addHandler(_handlers().handler);
     // Start the DDS server.
-    _server = await io.serve(
-        const Pipeline()
-            .addMiddleware(_authCodeMiddleware)
-            .addHandler(_handlers().handler),
-        host,
-        port);
+    _server = await io.serve(handler, host, port);
 
     final tmpUri = Uri(
       scheme: 'http',
       host: host,
       port: _server.port,
-      path: '$_authCode/',
+      path: '$authCode/',
     );
 
     // Notify the VM service that this client is DDS and that it should close
@@ -157,7 +171,7 @@
       return;
     }
     _shuttingDown = true;
-    // Don't accept anymore HTTP requests.
+    // Don't accept any more HTTP requests.
     await _server?.close();
 
     // Close connections to clients.
@@ -197,7 +211,7 @@
             return forbidden;
           }
           final authToken = pathSegments[0];
-          if (authToken != _authCode) {
+          if (authToken != authCode) {
             return forbidden;
           }
           // Creates a new request with the authentication code stripped from
@@ -233,18 +247,12 @@
       });
 
   Handler _sseHandler() {
-    // Give connections time to reestablish before considering them closed.
-    // Required to reestablish connections killed by UberProxy.
-    const keepAlive = Duration(seconds: 30);
-    final handler = authCodesEnabled
-        ? SseHandler(
-            Uri.parse('/$_authCode/$_kSseHandlerPath'),
-            keepAlive: keepAlive,
-          )
-        : SseHandler(
-            Uri.parse('/$_kSseHandlerPath'),
-            keepAlive: keepAlive,
-          );
+    final handler = SseHandler(
+      authCodesEnabled
+          ? Uri.parse('/$authCode/$_kSseHandlerPath')
+          : Uri.parse('/$_kSseHandlerPath'),
+      keepAlive: sseKeepAlive,
+    );
 
     handler.connections.rest.listen((sseConnection) {
       final client = DartDevelopmentServiceClient.fromSSEConnection(
@@ -259,10 +267,18 @@
   }
 
   Handler _httpHandler() {
-    // DDS doesn't support any HTTP requests itself, so we just forward all of
-    // them to the VM service.
-    final cascade = Cascade().add(proxyHandler(remoteVmServiceUri));
-    return cascade.handler;
+    if (_devToolsConfiguration != null && _devToolsConfiguration.enable) {
+      // Install the DevTools handlers and forward any unhandled HTTP requests to
+      // the VM service.
+      final buildDir =
+          _devToolsConfiguration.customBuildDirectoryPath?.toFilePath();
+      return devtoolsHandler(
+        dds: this,
+        buildDir: buildDir,
+        notFoundHandler: proxyHandler(remoteVmServiceUri),
+      );
+    }
+    return proxyHandler(remoteVmServiceUri);
   }
 
   List<String> _cleanupPathSegments(Uri uri) {
@@ -296,14 +312,43 @@
     return uri.replace(scheme: 'sse', pathSegments: pathSegments);
   }
 
+  Uri _toDevTools(Uri uri) {
+    // The DevTools URI is a bit strange as the query parameters appear after
+    // the fragment. There's no nice way to encode the query parameters
+    // properly, so we create another Uri just to grab the formatted query.
+    // The result will need to have '/?' prepended when being used as the
+    // fragment to get the correct format.
+    final query = Uri(
+      queryParameters: {
+        'uri': wsUri.toString(),
+      },
+    ).query;
+    return Uri(
+      scheme: 'http',
+      host: uri.host,
+      port: uri.port,
+      pathSegments: [
+        ...uri.pathSegments.where(
+          (e) => e.isNotEmpty,
+        ),
+        'devtools',
+        '',
+      ],
+      fragment: '/?$query',
+    );
+  }
+
   String getNamespace(DartDevelopmentServiceClient client) =>
       clientManager.clients.keyOf(client);
 
   @override
   bool get authCodesEnabled => _authCodesEnabled;
   final bool _authCodesEnabled;
+  String get authCode => _authCode;
   String _authCode;
 
+  final bool shouldLogRequests;
+
   @override
   Uri get remoteVmServiceUri => _remoteVmServiceUri;
 
@@ -313,17 +358,21 @@
 
   @override
   Uri get uri => _uri;
+  Uri _uri;
 
   @override
   Uri get sseUri => _toSse(_uri);
 
   Uri get wsUri => _toWebSocket(_uri);
-  Uri _uri;
+
+  Uri get devToolsUri => _toDevTools(_uri);
 
   final bool _ipv6;
 
   bool get isRunning => _uri != null;
 
+  final DevToolsConfiguration _devToolsConfiguration;
+
   Future<void> get done => _done.future;
   Completer _done = Completer<void>();
   bool _shuttingDown = false;
diff --git a/pkg/dds/lib/src/devtools/devtools_client.dart b/pkg/dds/lib/src/devtools/devtools_client.dart
new file mode 100644
index 0000000..5f8670e
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/devtools_client.dart
@@ -0,0 +1,96 @@
+// 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:async';
+
+import 'package:json_rpc_2/src/server.dart' as json_rpc;
+import 'package:sse/src/server/sse_handler.dart';
+import 'package:stream_channel/stream_channel.dart';
+
+import 'server_api.dart';
+
+class LoggingMiddlewareSink<S> implements StreamSink<S> {
+  LoggingMiddlewareSink(this.sink);
+
+  @override
+  void add(S event) {
+    print('DevTools SSE response: $event');
+    sink.add(event);
+  }
+
+  @override
+  void addError(Object error, [StackTrace stackTrace]) {
+    print('DevTools SSE error response: $error');
+    sink.addError(error);
+  }
+
+  @override
+  Future addStream(Stream<S> stream) {
+    return sink.addStream(stream);
+  }
+
+  @override
+  Future close() => sink.close();
+
+  @override
+  Future get done => sink.done;
+
+  final StreamSink sink;
+}
+
+/// Represents a DevTools client connection to the DevTools server API.
+class DevToolsClient {
+  DevToolsClient.fromSSEConnection(
+    SseConnection sse,
+    bool loggingEnabled,
+  ) {
+    Stream<String> stream = sse.stream;
+    StreamSink sink = sse.sink;
+
+    if (loggingEnabled) {
+      stream = stream.map<String>((String e) {
+        print('DevTools SSE request: $e');
+        return e;
+      });
+      sink = LoggingMiddlewareSink(sink);
+    }
+
+    _server = json_rpc.Server(
+      StreamChannel(stream, sink),
+      strictProtocolChecks: false,
+    );
+    _registerJsonRpcMethods();
+    _server.listen();
+  }
+
+  void _registerJsonRpcMethods() {
+    _server.registerMethod('connected', (parameters) {
+      // Nothing to do here.
+    });
+
+    _server.registerMethod('currentPage', (parameters) {
+      // Nothing to do here.
+    });
+
+    _server.registerMethod('disconnected', (parameters) {
+      // Nothing to do here.
+    });
+
+    _server.registerMethod('getPreferenceValue', (parameters) {
+      final key = parameters['key'].asString;
+      final value = ServerApi.devToolsPreferences.properties[key];
+      return value;
+    });
+
+    _server.registerMethod('setPreferenceValue', (parameters) {
+      final key = parameters['key'].asString;
+      final value = parameters['value'].value;
+      ServerApi.devToolsPreferences.properties[key] = value;
+    });
+  }
+
+  json_rpc.Server _server;
+}
diff --git a/pkg/dds/lib/src/devtools/devtools_handler.dart b/pkg/dds/lib/src/devtools/devtools_handler.dart
new file mode 100644
index 0000000..a0a4bf1
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/devtools_handler.dart
@@ -0,0 +1,87 @@
+// 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:async';
+
+import 'package:dds/src/constants.dart';
+import 'package:meta/meta.dart';
+import 'package:shelf/shelf.dart';
+import 'package:shelf_static/shelf_static.dart';
+import 'package:sse/server/sse_handler.dart';
+
+import '../dds_impl.dart';
+import 'devtools_client.dart';
+import 'server_api.dart';
+
+/// Returns a [Handler] which handles serving DevTools and the DevTools server
+/// API under $DDS_URI/devtools/.
+///
+/// [buildDir] is the path to the pre-compiled DevTools instance to be served.
+///
+/// [notFoundHandler] is a [Handler] to which requests that could not be handled
+/// by the DevTools handler are forwarded (e.g., a proxy to the VM service).
+FutureOr<Handler> devtoolsHandler({
+  @required DartDevelopmentServiceImpl dds,
+  @required String buildDir,
+  @required Handler notFoundHandler,
+}) {
+  // Serves the web assets for DevTools.
+  final devtoolsAssetHandler = createStaticHandler(
+    buildDir,
+    defaultDocument: 'index.html',
+  );
+
+  // Support DevTools client-server interface via SSE.
+  // Note: the handler path needs to match the full *original* path, not the
+  // current request URL (we remove '/devtools' in the initial router but we
+  // need to include it here).
+  const devToolsSseHandlerPath = '/devtools/api/sse';
+  final devToolsApiHandler = SseHandler(
+    dds.authCodesEnabled
+        ? Uri.parse('/${dds.authCode}$devToolsSseHandlerPath')
+        : Uri.parse(devToolsSseHandlerPath),
+    keepAlive: sseKeepAlive,
+  );
+
+  devToolsApiHandler.connections.rest.listen(
+    (sseConnection) => DevToolsClient.fromSSEConnection(
+      sseConnection,
+      dds.shouldLogRequests,
+    ),
+  );
+
+  final devtoolsHandler = (Request request) {
+    // If the request isn't of the form api/<method> assume it's a request for
+    // DevTools assets.
+    if (request.url.pathSegments.length < 2 ||
+        request.url.pathSegments.first != 'api') {
+      return devtoolsAssetHandler(request);
+    }
+    final method = request.url.pathSegments[1];
+    if (method == 'ping') {
+      // Note: we have an 'OK' body response, otherwise the response has an
+      // incorrect status code (204 instead of 200).
+      return Response.ok('OK');
+    }
+    if (method == 'sse') {
+      return devToolsApiHandler.handler(request);
+    }
+    if (!ServerApi.canHandle(request)) {
+      return Response.notFound('$method is not a valid API');
+    }
+    return ServerApi.handle(request);
+  };
+
+  return (request) {
+    final pathSegments = request.url.pathSegments;
+    if (pathSegments.isEmpty || pathSegments.first != 'devtools') {
+      return notFoundHandler(request);
+    }
+    // Forward all requests to /devtools/* to the DevTools handler.
+    request = request.change(path: 'devtools');
+    return devtoolsHandler(request);
+  };
+}
diff --git a/pkg/dds/lib/src/devtools/file_system.dart b/pkg/dds/lib/src/devtools/file_system.dart
new file mode 100644
index 0000000..9a05de7
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/file_system.dart
@@ -0,0 +1,84 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @dart=2.9
+
+// TODO(bkonyi): remove once package:devtools_server_api is available
+// See https://github.com/flutter/devtools/issues/2958.
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:path/path.dart' as path;
+
+import 'usage.dart';
+
+class LocalFileSystem {
+  static String _userHomeDir() {
+    final String envKey =
+        Platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME';
+    final String value = Platform.environment[envKey];
+    return value == null ? '.' : value;
+  }
+
+  /// Returns the path to the DevTools storage directory.
+  static String devToolsDir() {
+    return path.join(_userHomeDir(), '.flutter-devtools');
+  }
+
+  /// Moves the .devtools file to ~/.flutter-devtools/.devtools if the .devtools file
+  /// exists in the user's home directory.
+  static void maybeMoveLegacyDevToolsStore() {
+    final file = File(path.join(_userHomeDir(), DevToolsUsage.storeName));
+    if (file.existsSync()) {
+      ensureDevToolsDirectory();
+      file.copySync(path.join(devToolsDir(), DevToolsUsage.storeName));
+      file.deleteSync();
+    }
+  }
+
+  /// Creates the ~/.flutter-devtools directory if it does not already exist.
+  static void ensureDevToolsDirectory() {
+    Directory('${LocalFileSystem.devToolsDir()}').createSync();
+  }
+
+  /// Returns a DevTools file from the given path.
+  ///
+  /// Only files within ~/.flutter-devtools/ can be accessed.
+  static File devToolsFileFromPath(String pathFromDevToolsDir) {
+    if (pathFromDevToolsDir.contains('..')) {
+      // The passed in path should not be able to walk up the directory tree
+      // outside of the ~/.flutter-devtools/ directory.
+      return null;
+    }
+    ensureDevToolsDirectory();
+    final file = File(path.join(devToolsDir(), pathFromDevToolsDir));
+    if (!file.existsSync()) {
+      return null;
+    }
+    return file;
+  }
+
+  /// Returns a DevTools file from the given path as encoded json.
+  ///
+  /// Only files within ~/.flutter-devtools/ can be accessed.
+  static String devToolsFileAsJson(String pathFromDevToolsDir) {
+    final file = devToolsFileFromPath(pathFromDevToolsDir);
+    if (file == null) return null;
+
+    final fileName = path.basename(file.path);
+    if (!fileName.endsWith('.json')) return null;
+
+    final content = file.readAsStringSync();
+    final json = jsonDecode(content);
+    json['lastModifiedTime'] = file.lastModifiedSync().toString();
+    return jsonEncode(json);
+  }
+
+  /// Whether the flutter store file exists.
+  static bool flutterStoreExists() {
+    final flutterStore = File('${_userHomeDir()}/.flutter');
+    return flutterStore.existsSync();
+  }
+}
diff --git a/pkg/dds/lib/src/devtools/server_api.dart b/pkg/dds/lib/src/devtools/server_api.dart
new file mode 100644
index 0000000..b866f44
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/server_api.dart
@@ -0,0 +1,230 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @dart=2.9
+
+// TODO(bkonyi): remove once package:devtools_server_api is available
+// See https://github.com/flutter/devtools/issues/2958.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:devtools_shared/devtools_shared.dart';
+import 'package:shelf/shelf.dart' as shelf;
+
+import 'file_system.dart';
+import 'usage.dart';
+
+/// The DevTools server API.
+///
+/// This defines endpoints that serve all requests that come in over api/.
+class ServerApi {
+  static const errorNoActiveSurvey = 'ERROR: setActiveSurvey not called.';
+
+  /// Determines whether or not [request] is an API call.
+  static bool canHandle(shelf.Request request) {
+    return request.url.path.startsWith(apiPrefix);
+  }
+
+  /// Handles all requests.
+  ///
+  /// To override an API call, pass in a subclass of [ServerApi].
+  static FutureOr<shelf.Response> handle(
+    shelf.Request request, [
+    ServerApi api,
+  ]) {
+    api ??= ServerApi();
+    switch (request.url.path) {
+      // ----- Flutter Tool GA store. -----
+      case apiGetFlutterGAEnabled:
+        // Is Analytics collection enabled?
+        return api.getCompleted(
+          request,
+          json.encode(FlutterUsage.doesStoreExist ? _usage.enabled : null),
+        );
+      case apiGetFlutterGAClientId:
+        // Flutter Tool GA clientId - ONLY get Flutter's clientId if enabled is
+        // true.
+        return (FlutterUsage.doesStoreExist)
+            ? api.getCompleted(
+                request,
+                json.encode(_usage.enabled ? _usage.clientId : null),
+              )
+            : api.getCompleted(
+                request,
+                json.encode(null),
+              );
+
+      // ----- DevTools GA store. -----
+
+      case apiResetDevTools:
+        _devToolsUsage.reset();
+        return api.getCompleted(request, json.encode(true));
+      case apiGetDevToolsFirstRun:
+        // Has DevTools been run first time? To bring up welcome screen.
+        return api.getCompleted(
+          request,
+          json.encode(_devToolsUsage.isFirstRun),
+        );
+      case apiGetDevToolsEnabled:
+        // Is DevTools Analytics collection enabled?
+        return api.getCompleted(request, json.encode(_devToolsUsage.enabled));
+      case apiSetDevToolsEnabled:
+        // Enable or disable DevTools analytics collection.
+        final queryParams = request.requestedUri.queryParameters;
+        if (queryParams.containsKey(devToolsEnabledPropertyName)) {
+          _devToolsUsage.enabled =
+              json.decode(queryParams[devToolsEnabledPropertyName]);
+        }
+        return api.setCompleted(request, json.encode(_devToolsUsage.enabled));
+
+      // ----- DevTools survey store. -----
+
+      case apiSetActiveSurvey:
+        // Assume failure.
+        bool result = false;
+
+        // Set the active survey used to store subsequent apiGetSurveyActionTaken,
+        // apiSetSurveyActionTaken, apiGetSurveyShownCount, and
+        // apiIncrementSurveyShownCount calls.
+        final queryParams = request.requestedUri.queryParameters;
+        if (queryParams.keys.length == 1 &&
+            queryParams.containsKey(activeSurveyName)) {
+          final String theSurveyName = queryParams[activeSurveyName];
+
+          // Set the current activeSurvey.
+          _devToolsUsage.activeSurvey = theSurveyName;
+          result = true;
+        }
+
+        return api.getCompleted(request, json.encode(result));
+      case apiGetSurveyActionTaken:
+        // Request setActiveSurvey has not been requested.
+        if (_devToolsUsage.activeSurvey == null) {
+          return api.badRequest('$errorNoActiveSurvey '
+              '- $apiGetSurveyActionTaken');
+        }
+        // SurveyActionTaken has the survey been acted upon (taken or dismissed)
+        return api.getCompleted(
+          request,
+          json.encode(_devToolsUsage.surveyActionTaken),
+        );
+      // TODO(terry): remove the query param logic for this request.
+      // setSurveyActionTaken should only be called with the value of true, so
+      // we can remove the extra complexity.
+      case apiSetSurveyActionTaken:
+        // Request setActiveSurvey has not been requested.
+        if (_devToolsUsage.activeSurvey == null) {
+          return api.badRequest('$errorNoActiveSurvey '
+              '- $apiSetSurveyActionTaken');
+        }
+        // Set the SurveyActionTaken.
+        // Has the survey been taken or dismissed..
+        final queryParams = request.requestedUri.queryParameters;
+        if (queryParams.containsKey(surveyActionTakenPropertyName)) {
+          _devToolsUsage.surveyActionTaken =
+              json.decode(queryParams[surveyActionTakenPropertyName]);
+        }
+        return api.setCompleted(
+          request,
+          json.encode(_devToolsUsage.surveyActionTaken),
+        );
+      case apiGetSurveyShownCount:
+        // Request setActiveSurvey has not been requested.
+        if (_devToolsUsage.activeSurvey == null) {
+          return api.badRequest('$errorNoActiveSurvey '
+              '- $apiGetSurveyShownCount');
+        }
+        // SurveyShownCount how many times have we asked to take survey.
+        return api.getCompleted(
+          request,
+          json.encode(_devToolsUsage.surveyShownCount),
+        );
+      case apiIncrementSurveyShownCount:
+        // Request setActiveSurvey has not been requested.
+        if (_devToolsUsage.activeSurvey == null) {
+          return api.badRequest('$errorNoActiveSurvey '
+              '- $apiIncrementSurveyShownCount');
+        }
+        // Increment the SurveyShownCount, we've asked about the survey.
+        _devToolsUsage.incrementSurveyShownCount();
+        return api.getCompleted(
+          request,
+          json.encode(_devToolsUsage.surveyShownCount),
+        );
+      case apiGetBaseAppSizeFile:
+        final queryParams = request.requestedUri.queryParameters;
+        if (queryParams.containsKey(baseAppSizeFilePropertyName)) {
+          final filePath = queryParams[baseAppSizeFilePropertyName];
+          final fileJson = LocalFileSystem.devToolsFileAsJson(filePath);
+          if (fileJson == null) {
+            return api.badRequest('No JSON file available at $filePath.');
+          }
+          return api.getCompleted(request, fileJson);
+        }
+        return api.badRequest('Request for base app size file does not '
+            'contain a query parameter with the expected key: '
+            '$baseAppSizeFilePropertyName');
+      case apiGetTestAppSizeFile:
+        final queryParams = request.requestedUri.queryParameters;
+        if (queryParams.containsKey(testAppSizeFilePropertyName)) {
+          final filePath = queryParams[testAppSizeFilePropertyName];
+          final fileJson = LocalFileSystem.devToolsFileAsJson(filePath);
+          if (fileJson == null) {
+            return api.badRequest('No JSON file available at $filePath.');
+          }
+          return api.getCompleted(request, fileJson);
+        }
+        return api.badRequest('Request for test app size file does not '
+            'contain a query parameter with the expected key: '
+            '$testAppSizeFilePropertyName');
+      default:
+        return api.notImplemented(request);
+    }
+  }
+
+  // Accessing Flutter usage file e.g., ~/.flutter.
+  // NOTE: Only access the file if it exists otherwise Flutter Tool hasn't yet
+  //       been run.
+  static final FlutterUsage _usage =
+      FlutterUsage.doesStoreExist ? FlutterUsage() : null;
+
+  // Accessing DevTools usage file e.g., ~/.devtools
+  static final DevToolsUsage _devToolsUsage = DevToolsUsage();
+
+  static DevToolsUsage get devToolsPreferences => _devToolsUsage;
+
+  /// Logs a page view in the DevTools server.
+  ///
+  /// In the open-source version of DevTools, Google Analytics handles this
+  /// without any need to involve the server.
+  FutureOr<shelf.Response> logScreenView(shelf.Request request) =>
+      notImplemented(request);
+
+  /// Return the value of the property.
+  FutureOr<shelf.Response> getCompleted(shelf.Request request, String value) =>
+      shelf.Response.ok('$value');
+
+  /// Return the value of the property after the property value has been set.
+  FutureOr<shelf.Response> setCompleted(shelf.Request request, String value) =>
+      shelf.Response.ok('$value');
+
+  /// A [shelf.Response] for API calls that encountered a request problem e.g.,
+  /// setActiveSurvey not called.
+  ///
+  /// This is a 400 Bad Request response.
+  FutureOr<shelf.Response> badRequest([String logError]) {
+    if (logError != null) print(logError);
+    return shelf.Response(HttpStatus.badRequest);
+  }
+
+  /// A [shelf.Response] for API calls that have not been implemented in this
+  /// server.
+  ///
+  /// This is a no-op 204 No Content response because returning 404 Not Found
+  /// creates unnecessary noise in the console.
+  FutureOr<shelf.Response> notImplemented(shelf.Request request) =>
+      shelf.Response(HttpStatus.noContent);
+}
diff --git a/pkg/dds/lib/src/devtools/usage.dart b/pkg/dds/lib/src/devtools/usage.dart
new file mode 100644
index 0000000..afa35d7
--- /dev/null
+++ b/pkg/dds/lib/src/devtools/usage.dart
@@ -0,0 +1,236 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @dart=2.9
+
+// TODO(bkonyi): remove once package:devtools_server_api is available
+// See https://github.com/flutter/devtools/issues/2958.
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:path/path.dart' as path;
+import 'package:usage/usage_io.dart';
+
+import 'file_system.dart';
+
+/// Access the file '~/.flutter'.
+class FlutterUsage {
+  /// Create a new Usage instance; [versionOverride] and [configDirOverride] are
+  /// used for testing.
+  FlutterUsage({
+    String settingsName = 'flutter',
+    String versionOverride,
+    String configDirOverride,
+  }) {
+    _analytics = AnalyticsIO('', settingsName, '');
+  }
+
+  Analytics _analytics;
+
+  /// Does the .flutter store exist?
+  static bool get doesStoreExist {
+    return LocalFileSystem.flutterStoreExists();
+  }
+
+  bool get isFirstRun => _analytics.firstRun;
+
+  bool get enabled => _analytics.enabled;
+
+  set enabled(bool value) => _analytics.enabled = value;
+
+  String get clientId => _analytics.clientId;
+}
+
+// Access the DevTools on disk store (~/.devtools/.devtools).
+class DevToolsUsage {
+  /// Create a new Usage instance; [versionOverride] and [configDirOverride] are
+  /// used for testing.
+  DevToolsUsage({
+    String versionOverride,
+    String configDirOverride,
+  }) {
+    LocalFileSystem.maybeMoveLegacyDevToolsStore();
+    properties = IOPersistentProperties(
+      storeName,
+      documentDirPath: LocalFileSystem.devToolsDir(),
+    );
+  }
+
+  static const storeName = '.devtools';
+
+  /// The activeSurvey is the property name of a top-level property
+  /// existing or created in the file ~/.devtools
+  /// If the property doesn't exist it is created with default survey values:
+  ///
+  ///   properties[activeSurvey]['surveyActionTaken'] = false;
+  ///   properties[activeSurvey]['surveyShownCount'] = 0;
+  ///
+  /// It is a requirement that the API apiSetActiveSurvey must be called before
+  /// calling any survey method on DevToolsUsage (addSurvey, rewriteActiveSurvey,
+  /// surveyShownCount, incrementSurveyShownCount, or surveyActionTaken).
+  String _activeSurvey;
+
+  IOPersistentProperties properties;
+
+  static const _surveyActionTaken = 'surveyActionTaken';
+  static const _surveyShownCount = 'surveyShownCount';
+
+  void reset() {
+    properties.remove('firstRun');
+    properties['enabled'] = false;
+  }
+
+  bool get isFirstRun {
+    properties['firstRun'] = properties['firstRun'] == null;
+    return properties['firstRun'];
+  }
+
+  bool get enabled {
+    if (properties['enabled'] == null) {
+      properties['enabled'] = false;
+    }
+
+    return properties['enabled'];
+  }
+
+  set enabled(bool value) {
+    properties['enabled'] = value;
+    return properties['enabled'];
+  }
+
+  bool surveyNameExists(String surveyName) => properties[surveyName] != null;
+
+  void _addSurvey(String surveyName) {
+    assert(activeSurvey != null);
+    assert(activeSurvey == surveyName);
+    rewriteActiveSurvey(false, 0);
+  }
+
+  String get activeSurvey => _activeSurvey;
+
+  set activeSurvey(String surveyName) {
+    assert(surveyName != null);
+    _activeSurvey = surveyName;
+
+    if (!surveyNameExists(activeSurvey)) {
+      // Create the survey if property is non-existent in ~/.devtools
+      _addSurvey(activeSurvey);
+    }
+  }
+
+  /// Need to rewrite the entire survey structure for property to be persisted.
+  void rewriteActiveSurvey(bool actionTaken, int shownCount) {
+    assert(activeSurvey != null);
+    properties[activeSurvey] = {
+      _surveyActionTaken: actionTaken,
+      _surveyShownCount: shownCount,
+    };
+  }
+
+  int get surveyShownCount {
+    assert(activeSurvey != null);
+    final prop = properties[activeSurvey];
+    if (prop[_surveyShownCount] == null) {
+      rewriteActiveSurvey(prop[_surveyActionTaken], 0);
+    }
+    return properties[activeSurvey][_surveyShownCount];
+  }
+
+  void incrementSurveyShownCount() {
+    assert(activeSurvey != null);
+    surveyShownCount; // Ensure surveyShownCount has been initialized.
+    final prop = properties[activeSurvey];
+    rewriteActiveSurvey(prop[_surveyActionTaken], prop[_surveyShownCount] + 1);
+  }
+
+  bool get surveyActionTaken {
+    assert(activeSurvey != null);
+    return properties[activeSurvey][_surveyActionTaken] == true;
+  }
+
+  set surveyActionTaken(bool value) {
+    assert(activeSurvey != null);
+    final prop = properties[activeSurvey];
+    rewriteActiveSurvey(value, prop[_surveyShownCount]);
+  }
+}
+
+abstract class PersistentProperties {
+  PersistentProperties(this.name);
+
+  final String name;
+
+  dynamic operator [](String key);
+
+  void operator []=(String key, dynamic value);
+
+  /// Re-read settings from the backing store.
+  ///
+  /// May be a no-op on some platforms.
+  void syncSettings();
+}
+
+const JsonEncoder _jsonEncoder = JsonEncoder.withIndent('  ');
+
+class IOPersistentProperties extends PersistentProperties {
+  IOPersistentProperties(
+    String name, {
+    String documentDirPath,
+  }) : super(name) {
+    final String fileName = name.replaceAll(' ', '_');
+    documentDirPath ??= LocalFileSystem.devToolsDir();
+    _file = File(path.join(documentDirPath, fileName));
+    if (!_file.existsSync()) {
+      _file.createSync(recursive: true);
+    }
+    syncSettings();
+  }
+
+  IOPersistentProperties.fromFile(File file) : super(path.basename(file.path)) {
+    _file = file;
+    if (!_file.existsSync()) {
+      _file.createSync(recursive: true);
+    }
+    syncSettings();
+  }
+
+  File _file;
+
+  Map _map;
+
+  @override
+  dynamic operator [](String key) => _map[key];
+
+  @override
+  void operator []=(String key, dynamic value) {
+    if (value == null && !_map.containsKey(key)) return;
+    if (_map[key] == value) return;
+
+    if (value == null) {
+      _map.remove(key);
+    } else {
+      _map[key] = value;
+    }
+
+    try {
+      _file.writeAsStringSync(_jsonEncoder.convert(_map) + '\n');
+    } catch (_) {}
+  }
+
+  @override
+  void syncSettings() {
+    try {
+      String contents = _file.readAsStringSync();
+      if (contents.isEmpty) contents = '{}';
+      _map = jsonDecode(contents);
+    } catch (_) {
+      _map = {};
+    }
+  }
+
+  void remove(String propertyName) {
+    _map.remove(propertyName);
+  }
+}
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 221e3df..a69236c 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: 1.7.6
+version: 1.8.0-dev
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds
 
@@ -12,18 +12,21 @@
 
 dependencies:
   async: ^2.4.1
+  devtools_shared: ^2.0.0
   json_rpc_2: ^2.2.0
   meta: ^1.1.8
+  path: ^1.8.0
   pedantic: ^1.7.0
   shelf: ^1.0.0
   shelf_proxy: ^1.0.0
+  shelf_static: ^1.0.0-dev
   shelf_web_socket: ^1.0.0
   sse: ^3.7.0
   stream_channel: ^2.0.0
+  usage: ^4.0.0
   vm_service: ^6.0.1-nullsafety.0
   web_socket_channel: ^2.0.0
 
 dev_dependencies:
-  shelf_static: ^1.0.0
   test: ^1.0.0
   webdriver: ^3.0.0
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 791ada2..b687d8c 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -94,6 +94,9 @@
   /// The class that is emitting its signature information, otherwise null.
   Class _classEmittingSignatures;
 
+  /// True when a class is emitting a deferred class hierarchy.
+  bool _emittingDeferredType = false;
+
   /// The current element being loaded.
   /// We can use this to determine if we're loading top-level code or not:
   ///
@@ -859,22 +862,38 @@
       return;
     }
 
-    js_ast.Expression emitDeferredType(DartType t) {
-      assert(isKnownDartTypeImplementor(t));
-      if (t is InterfaceType) {
-        _declareBeforeUse(t.classNode);
-        if (t.typeArguments.isNotEmpty) {
-          return _emitGenericClassType(
-              t, t.typeArguments.map(emitDeferredType));
+    js_ast.Expression emitDeferredType(DartType t,
+        {bool emitNullability = true}) {
+      js_ast.Expression _emitDeferredType(DartType t,
+          {bool emitNullability = true}) {
+        if (t is InterfaceType) {
+          _declareBeforeUse(t.classNode);
+          if (t.typeArguments.isNotEmpty) {
+            var typeRep = _emitGenericClassType(
+                t, t.typeArguments.map(_emitDeferredType));
+            return emitNullability
+                ? _emitNullabilityWrapper(typeRep, t.declaredNullability)
+                : typeRep;
+          }
+          return _emitInterfaceType(t, emitNullability: emitNullability);
+        } else if (t is FutureOrType) {
+          _declareBeforeUse(_coreTypes.deprecatedFutureOrClass);
+          // TODO(45870) Add nullability wrappers to FutureOr.
+          return _emitFutureOrTypeWithArgument(
+              _emitDeferredType(t.typeArgument));
+        } else if (t is TypeParameterType) {
+          return _emitTypeParameterType(t, emitNullability: emitNullability);
         }
-        return _emitInterfaceType(t, emitNullability: false);
-      } else if (t is FutureOrType) {
-        _declareBeforeUse(_coreTypes.deprecatedFutureOrClass);
-        return _emitFutureOrTypeWithArgument(emitDeferredType(t.typeArgument));
-      } else if (t is TypeParameterType) {
-        return _emitTypeParameterType(t, emitNullability: false);
+        return _emitType(t);
       }
-      return _emitType(t);
+
+      assert(isKnownDartTypeImplementor(t));
+      var savedEmittingDeferredType = _emittingDeferredType;
+      _emittingDeferredType = true;
+      var deferredClassRep =
+          _emitDeferredType(t, emitNullability: emitNullability);
+      _emittingDeferredType = savedEmittingDeferredType;
+      return deferredClassRep;
     }
 
     bool shouldDefer(InterfaceType t) {
@@ -921,7 +940,8 @@
 
     js_ast.Expression getBaseClass(int count) {
       var base = emitDeferredType(
-          c.getThisType(_coreTypes, c.enclosingLibrary.nonNullable));
+          c.getThisType(_coreTypes, c.enclosingLibrary.nonNullable),
+          emitNullability: false);
       while (--count >= 0) {
         base = js.call('#.__proto__', [base]);
       }
@@ -995,7 +1015,7 @@
       var originalSupertype = supertype;
       deferredSupertypes.add(() => runtimeStatement('setBaseClass(#, #)', [
             getBaseClass(isMixinAliasClass(c) ? 0 : mixinApplications.length),
-            emitDeferredType(originalSupertype),
+            emitDeferredType(originalSupertype, emitNullability: false),
           ]));
       // Refers to 'supertype' without type parameters. We remove these from
       // the 'extends' clause for generics for cyclic dependencies and append
@@ -1015,7 +1035,9 @@
 
       var m = c.mixedInType.asInterfaceType;
       var deferMixin = shouldDefer(m);
-      var mixinClass = deferMixin ? emitDeferredType(m) : emitClassRef(m);
+      var mixinClass = deferMixin
+          ? emitDeferredType(m, emitNullability: false)
+          : emitClassRef(m);
       var classExpr = deferMixin ? getBaseClass(0) : className;
 
       var mixinApplication =
@@ -1087,7 +1109,7 @@
       if (shouldDefer(mixinType)) {
         deferredSupertypes.add(() => runtimeStatement('applyMixin(#, #)', [
               getBaseClass(mixinApplications.length - i),
-              emitDeferredType(mixinType)
+              emitDeferredType(mixinType, emitNullability: false)
             ]));
       } else {
         body.add(runtimeStatement(
@@ -2909,7 +2931,9 @@
       _currentClass != null && identical(_currentClass, _classEmittingExtends);
 
   bool get _cacheTypes =>
-      !_emittingClassExtends && !_emittingClassSignatures ||
+      !_emittingDeferredType &&
+          !_emittingClassExtends &&
+          !_emittingClassSignatures ||
       _currentFunction != null;
 
   js_ast.Expression _emitGenericClassType(
diff --git a/pkg/front_end/test/binary_md_dill_reader.dart b/pkg/front_end/test/binary_md_dill_reader.dart
index d25607e..d9a3d0e 100644
--- a/pkg/front_end/test/binary_md_dill_reader.dart
+++ b/pkg/front_end/test/binary_md_dill_reader.dart
@@ -29,6 +29,7 @@
   Map _dillStringsPointer;
   int verboseLevel = 0;
   bool _ranSetup = false;
+  List<String> readingStack = [];
 
   BinaryMdDillReader(this._binaryMdContent, this._dillContent);
 
@@ -101,11 +102,13 @@
 
   int numLibs;
   int binaryOffsetForSourceTable;
+  int binaryOffsetForConstantTable;
+  int binaryOffsetForConstantTableIndex;
   int binaryOffsetForCanonicalNames;
   int binaryOffsetForMetadataPayloads;
   int binaryOffsetForMetadataMappings;
   int binaryOffsetForStringTable;
-  int binaryOffsetForConstantTable;
+  int binaryOffsetForStartOfComponentIndex;
   int mainMethodReference;
 
   /// Read the dill file data, parsing it into a Map.
@@ -119,11 +122,15 @@
 
     // Skip to the start of the index.
     _binaryOffset = _dillContent.length -
-        ((numLibs + 1) + 10 /* number of fixed fields */) * 4;
+        ((numLibs + 1) + 12 /* number of fixed fields */) * 4;
 
     // Read index.
     binaryOffsetForSourceTable = _peekUint32();
     _binaryOffset += 4;
+    binaryOffsetForConstantTable = _peekUint32();
+    _binaryOffset += 4;
+    binaryOffsetForConstantTableIndex = _peekUint32();
+    _binaryOffset += 4;
     binaryOffsetForCanonicalNames = _peekUint32();
     _binaryOffset += 4;
     binaryOffsetForMetadataPayloads = _peekUint32();
@@ -132,7 +139,7 @@
     _binaryOffset += 4;
     binaryOffsetForStringTable = _peekUint32();
     _binaryOffset += 4;
-    binaryOffsetForConstantTable = _peekUint32();
+    binaryOffsetForStartOfComponentIndex = _peekUint32();
     _binaryOffset += 4;
     mainMethodReference = _peekUint32();
     _binaryOffset += 4;
@@ -141,13 +148,13 @@
     _binaryOffset = binaryOffsetForStringTable;
     var saved = _readingInstructions["ComponentFile"];
     _readingInstructions["ComponentFile"] = ["StringTable strings;"];
-    _readBinary("ComponentFile");
+    _readBinary("ComponentFile", "");
     _readingInstructions["ComponentFile"] = saved;
     _binaryOffset = 0;
     _depth = 0;
     // Hack end.
 
-    Map componentFile = _readBinary("ComponentFile");
+    Map componentFile = _readBinary("ComponentFile", "");
     if (_binaryOffset != _dillContent.length) {
       throw "Didn't read the entire binary: "
           "Only read $_binaryOffset of ${_dillContent.length} bytes. "
@@ -384,7 +391,7 @@
 
   /// Actually read the binary dill file. Read type [what] at the current
   /// binary position as specified by field [_binaryOffset].
-  dynamic _readBinary(String what) {
+  dynamic _readBinary(String what, String callerInstruction) {
     ++_depth;
     what = _remapWhat(what);
 
@@ -417,6 +424,9 @@
       throw "Didn't find instructions for '$what'";
     }
 
+    readingStack.add(orgWhat);
+    readingStack.add(callerInstruction);
+
     Map<String, dynamic> vars = {};
     if (verboseLevel > 1) {
       print("".padLeft(_depth * 2) + " -> $what ($orgWhat @ $orgPosition)");
@@ -516,25 +526,36 @@
             count == "libraryCount + 1") {
           intCount = numLibs + 1;
         }
+        if (intCount < 0 &&
+            type == "UInt32" &&
+            _depth == 2 &&
+            count == "length" &&
+            readingStack.last == "RList<UInt32> constantsMapping;") {
+          int prevBinaryOffset = _binaryOffset;
+          // Hack: Use the ComponentIndex to go to the end and read the length.
+          _binaryOffset = binaryOffsetForCanonicalNames - 4;
+          intCount = _peekUint32();
+          _binaryOffset = prevBinaryOffset;
+        }
 
         if (intCount >= 0) {
           readNothingIsOk = intCount == 0;
           List<dynamic> value = new List.filled(intCount, null);
           for (int i = 0; i < intCount; ++i) {
             int oldOffset2 = _binaryOffset;
-            value[i] = _readBinary(type);
+            value[i] = _readBinary(type, instruction);
             if (_binaryOffset <= oldOffset2) {
               throw "Didn't read anything for $type @ $_binaryOffset";
             }
           }
           vars[name] = value;
         } else {
-          throw "Array of unknown size ($count)";
+          throw "Array of unknown size ($instruction, $type, $count)";
         }
       } else {
         // Not an array, read the single field recursively.
         type = _lookupGenericType(typeNames, type, types);
-        dynamic value = _readBinary(type);
+        dynamic value = _readBinary(type, instruction);
         vars[name] = value;
         _checkTag(instruction, value);
       }
@@ -551,6 +572,8 @@
     }
 
     --_depth;
+    readingStack.removeLast();
+    readingStack.removeLast();
     return vars;
   }
 
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index a7b97ca..a4ee9b7 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -940,6 +940,7 @@
 ratio
 rb
 rc
+rd
 re
 reach
 reachabilities
diff --git a/pkg/front_end/testcases/incremental.status b/pkg/front_end/testcases/incremental.status
index afed71c..57a86f3 100644
--- a/pkg/front_end/testcases/incremental.status
+++ b/pkg/front_end/testcases/incremental.status
@@ -6,3 +6,7 @@
 
 # http://dartbug.com/41812#issuecomment-684825703
 strongmode_mixins_2: Crash
+
+# http://dartbug.com/45899
+crash_05: Crash
+crash_06: Crash
diff --git a/pkg/front_end/testcases/incremental/crash_05.yaml b/pkg/front_end/testcases/incremental/crash_05.yaml
new file mode 100644
index 0000000..405d4f2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/crash_05.yaml
@@ -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.md file.
+
+# Reproduce a crash.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    experiments: non-nullable
+    sources:
+      main.dart: |
+        import 'dart:ffi';
+        import 'lib.dart';
+        class X extends Struct {
+          external Y xx;
+        }
+      lib.dart: |
+        import 'dart:ffi';
+        class Y extends Struct {
+          @Uint32()
+          external int yy;
+        }
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    experiments: non-nullable
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
+    expectsRebuildBodiesOnly: true
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental/crash_05.yaml.world.1.expect b/pkg/front_end/testcases/incremental/crash_05.yaml.world.1.expect
new file mode 100644
index 0000000..7b59748
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/crash_05.yaml.world.1.expect
@@ -0,0 +1,62 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "dart:ffi";
+
+  @#C6
+  class Y extends dart.ffi::Struct {
+    static final field dart.core::int* #sizeOf = (#C8).{dart.core::List::[]}(dart.ffi::_abi())/*isLegacy*/;
+    synthetic constructor •() → lib::Y
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → lib::Y
+      : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+      ;
+    @#C9
+    get yy() → dart.core::int
+      return dart.ffi::_loadUint32(this.{dart.ffi::_Compound::_typedDataBase}, (#C11).{dart.core::List::[]}(dart.ffi::_abi()));
+    @#C9
+    set yy(dart.core::int #externalFieldValue) → void
+      return dart.ffi::_storeUint32(this.{dart.ffi::_Compound::_typedDataBase}, (#C11).{dart.core::List::[]}(dart.ffi::_abi()), #externalFieldValue);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "dart:ffi";
+  import "org-dartlang-test:///lib.dart";
+
+  @#C15
+  class X extends dart.ffi::Struct {
+    static final field dart.core::int* #sizeOf = (#C8).{dart.core::List::[]}(dart.ffi::_abi())/*isLegacy*/;
+    synthetic constructor •() → main::X
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → main::X
+      : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+      ;
+    get xx() → lib::Y
+      return new lib::Y::#fromTypedDataBase( block {
+        dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase};
+        dart.core::int #offset = (#C11).{dart.core::List::[]}(dart.ffi::_abi());
+      } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<lib::Y>(#typedDataBase.{dart.ffi::Pointer::address}.{dart.core::num::+}(#offset)) : 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::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}.{dart.core::num::+}(#offset), (#C8).{dart.core::List::[]}(dart.ffi::_abi())));
+    set xx(lib::Y #externalFieldValue) → void
+      return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}, (#C11).{dart.core::List::[]}(dart.ffi::_abi()), #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}, #C10, (#C8).{dart.core::List::[]}(dart.ffi::_abi()));
+  }
+}
+constants  {
+  #C1 = "vm:ffi:struct-fields"
+  #C2 = TypeLiteralConstant(dart.ffi::Uint32)
+  #C3 = <dart.core::Type>[#C2]
+  #C4 = null
+  #C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C3, packing:#C4}
+  #C6 = dart.core::pragma {name:#C1, options:#C5}
+  #C7 = 4
+  #C8 = <dart.core::int*>[#C7, #C7, #C7]
+  #C9 = dart.ffi::Uint32 {}
+  #C10 = 0
+  #C11 = <dart.core::int*>[#C10, #C10, #C10]
+  #C12 = TypeLiteralConstant(lib::Y)
+  #C13 = <dart.core::Type>[#C12]
+  #C14 = dart.ffi::_FfiStructLayout {fieldTypes:#C13, packing:#C4}
+  #C15 = dart.core::pragma {name:#C1, options:#C14}
+}
diff --git a/pkg/front_end/testcases/incremental/crash_06.yaml b/pkg/front_end/testcases/incremental/crash_06.yaml
new file mode 100644
index 0000000..932a44d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/crash_06.yaml
@@ -0,0 +1,30 @@
+# Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Reproduce a crash.
+
+type: newworld
+worlds:
+  - entry: structs.dart
+    experiments: non-nullable
+    sources:
+      structs.dart: |
+        import 'dart:ffi';
+        class A extends Struct {
+          external Y yy;
+        }
+        class Y extends Struct {
+          external Z zz;
+        }
+    expectedLibraryCount: 1
+
+  - entry: structs.dart
+    experiments: non-nullable
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - structs.dart
+    expectedLibraryCount: 1
+    expectsRebuildBodiesOnly: true
+
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 1e83f7d..c891128 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -87,7 +87,7 @@
 }
 
 type ConstantReference {
-  UInt offset; // Byte offset into the Component's constants.
+  UInt index; // Index into [constantsMapping] and [constants].
 }
 
 type SourceInfo {
@@ -147,16 +147,17 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 63;
+  UInt32 formatVersion = 64;
   Byte[10] shortSdkHash;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
   UriSource sourceMap;
+  List<Constant> constants;
+  RList<UInt32> constantsMapping; // Byte offset into the Component's constants.
   List<CanonicalName> canonicalNames;
   MetadataPayload[] metadataPayloads;
   RList<MetadataMapping> metadataMappings;
   StringTable strings;
-  List<Constant> constants;
   ComponentIndex componentIndex;
 }
 
@@ -179,11 +180,13 @@
 type ComponentIndex {
   Byte[] 8bitAlignment; // 0-bytes to make the entire component (!) 8-byte aligned.
   UInt32 binaryOffsetForSourceTable;
+  UInt32 binaryOffsetForConstantTable;
+  UInt32 binaryOffsetForConstantTableIndex;
   UInt32 binaryOffsetForCanonicalNames;
   UInt32 binaryOffsetForMetadataPayloads;
   UInt32 binaryOffsetForMetadataMappings;
   UInt32 binaryOffsetForStringTable;
-  UInt32 binaryOffsetForConstantTable;
+  UInt32 binaryOffsetForStartOfComponentIndex;
   UInt32 mainMethodReference; // This is a ProcedureReference with a fixed-size integer.
   UInt32 compilationMode; // enum NonNullableByDefaultCompiledMode { Disabled = 0, Weak = 1, Strong = 2, Agnostic = 3 } with a fixed-size integer.
   UInt32[libraryCount + 1] libraryOffsets;
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 6c8a87d..039a81f 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -61,7 +61,7 @@
 }
 
 class _ComponentIndex {
-  static const int numberOfFixedFields = 10;
+  static const int numberOfFixedFields = 12;
 
   final int binaryOffsetForSourceTable;
   final int binaryOffsetForCanonicalNames;
@@ -69,6 +69,8 @@
   final int binaryOffsetForMetadataMappings;
   final int binaryOffsetForStringTable;
   final int binaryOffsetForConstantTable;
+  final int binaryOffsetForConstantTableIndex;
+  final int binaryOffsetForStartOfComponentIndex;
   final int mainMethodReference;
   final NonNullableByDefaultCompiledMode compiledMode;
   final List<int> libraryOffsets;
@@ -82,6 +84,8 @@
       required this.binaryOffsetForMetadataMappings,
       required this.binaryOffsetForStringTable,
       required this.binaryOffsetForConstantTable,
+      required this.binaryOffsetForConstantTableIndex,
+      required this.binaryOffsetForStartOfComponentIndex,
       required this.mainMethodReference,
       required this.compiledMode,
       required this.libraryOffsets,
@@ -122,7 +126,7 @@
   int _byteOffset = 0;
   List<String> _stringTable = const [];
   List<Uri> _sourceUriTable = const [];
-  Map<int, Constant> _constantTable = <int, Constant>{};
+  List<Constant> _constantTable = const <Constant>[];
   late List<CanonicalName> _linkTable;
   int _transformerFlags = 0;
   Library? _currentLibrary;
@@ -329,9 +333,12 @@
 
   void readConstantTable() {
     final int length = readUInt30();
-    final int startOffset = byteOffset;
+    // Because of "back-references" (e.g. the 10th constant referencing the 3rd
+    // constant) we can't use List.generate.
+    _constantTable =
+        new List<Constant>.filled(length, dummyConstant, growable: false);
     for (int i = 0; i < length; i++) {
-      _constantTable[byteOffset - startOffset] = readConstantTableEntry();
+      _constantTable[i] = readConstantTableEntry();
     }
   }
 
@@ -457,10 +464,11 @@
   }
 
   Constant readConstantReference() {
-    final int offset = readUInt30();
-    Constant? constant = _constantTable[offset];
-    assert(constant != null, "No constant found at offset $offset.");
-    return constant!;
+    final int index = readUInt30();
+    Constant constant = _constantTable[index];
+    assert(!identical(constant, dummyConstant),
+        "No constant found at index $index.");
+    return constant;
   }
 
   List<Constant> _readConstantReferenceList() {
@@ -702,11 +710,15 @@
 
     // Now read the component index.
     int binaryOffsetForSourceTable = _componentStartOffset + readUint32();
+    int binaryOffsetForConstantTable = _componentStartOffset + readUint32();
+    int binaryOffsetForConstantTableIndex =
+        _componentStartOffset + readUint32();
     int binaryOffsetForCanonicalNames = _componentStartOffset + readUint32();
     int binaryOffsetForMetadataPayloads = _componentStartOffset + readUint32();
     int binaryOffsetForMetadataMappings = _componentStartOffset + readUint32();
     int binaryOffsetForStringTable = _componentStartOffset + readUint32();
-    int binaryOffsetForConstantTable = _componentStartOffset + readUint32();
+    int binaryOffsetForStartOfComponentIndex =
+        _componentStartOffset + readUint32();
     int mainMethodReference = readUint32();
     NonNullableByDefaultCompiledMode compiledMode =
         NonNullableByDefaultCompiledMode.values[readUint32()];
@@ -726,6 +738,9 @@
         binaryOffsetForMetadataMappings: binaryOffsetForMetadataMappings,
         binaryOffsetForStringTable: binaryOffsetForStringTable,
         binaryOffsetForConstantTable: binaryOffsetForConstantTable,
+        binaryOffsetForConstantTableIndex: binaryOffsetForConstantTableIndex,
+        binaryOffsetForStartOfComponentIndex:
+            binaryOffsetForStartOfComponentIndex,
         mainMethodReference: mainMethodReference,
         compiledMode: compiledMode);
   }
@@ -804,6 +819,7 @@
 
     _byteOffset = index.binaryOffsetForConstantTable;
     readConstantTable();
+    // We don't need the constant table index on the dart side.
 
     int numberOfLibraries = index.libraryCount;
 
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 7252dcc..6602cc6 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -23,7 +23,7 @@
   SwitchCaseIndexer? _switchCaseIndexer;
   TypeParameterIndexer _typeParameterIndexer = new TypeParameterIndexer();
   final StringIndexer stringIndexer;
-  late ConstantIndexer _constantIndexer;
+  final ConstantIndexer _constantIndexer;
   final UriIndexer _sourceUriIndexer = new UriIndexer();
   bool _currentlyInNonimplementation = false;
   final List<bool> _sourcesFromRealImplementation = <bool>[];
@@ -36,8 +36,6 @@
 
   final BufferedSink _mainSink;
   final BufferedSink _metadataSink;
-  final BytesSink _constantsBytesSink;
-  late BufferedSink _constantsSink;
   late BufferedSink _sink;
   final bool includeSources;
   final bool includeOffsets;
@@ -51,9 +49,11 @@
   int _binaryOffsetForMetadataPayloads = -1;
   int _binaryOffsetForMetadataMappings = -1;
   int _binaryOffsetForStringTable = -1;
+  int _binaryOffsetForConstantTableIndex = -1;
   int _binaryOffsetForConstantTable = -1;
 
   late List<CanonicalName> _canonicalNameList;
+  bool _canonicalNameListDone = false;
   Set<CanonicalName> _knownCanonicalNameNonRootTops = new Set<CanonicalName>();
 
   Library? _currentLibrary;
@@ -69,10 +69,8 @@
       this.includeOffsets = true})
       : _mainSink = new BufferedSink(sink),
         _metadataSink = new BufferedSink(new BytesSink()),
-        _constantsBytesSink = new BytesSink(),
-        stringIndexer = stringIndexer ?? new StringIndexer() {
-    _constantsSink = new BufferedSink(_constantsBytesSink);
-    _constantIndexer = new ConstantIndexer(this.stringIndexer, this);
+        stringIndexer = stringIndexer ?? new StringIndexer(),
+        _constantIndexer = new ConstantIndexer() {
     _sink = _mainSink;
   }
 
@@ -181,21 +179,34 @@
     writeUInt30(_constantIndexer.put(constant));
   }
 
-  void writeConstantTable(ConstantIndexer indexer) {
+  void writeConstantTable() {
     _binaryOffsetForConstantTable = getBufferOffset();
 
-    writeUInt30(indexer.entries.length);
-    assert(identical(_sink, _mainSink));
-    _constantsSink.flushAndDestroy();
-    writeBytes(_constantsBytesSink.builder.takeBytes());
+    writeUInt30(_constantIndexer.entries.length);
+    assert(_constantIndexer.entries.length == _constantIndexer.offsets.length);
+    for (int i = 0; i < _constantIndexer.entries.length; i++) {
+      final Constant entry = _constantIndexer.entries[i];
+      _constantIndexer.offsets[i] =
+          getBufferOffset() - _binaryOffsetForConstantTable;
+      writeConstantTableEntry(entry);
+    }
   }
 
-  int writeConstantTableEntry(Constant constant) {
+  void writeConstantTableIndex() {
+    _binaryOffsetForConstantTableIndex = getBufferOffset();
+    assert(identical(_sink, _mainSink));
+    assert(_constantIndexer.entries.length == _constantIndexer.offsets.length);
+    for (int i = 0; i < _constantIndexer.offsets.length; i++) {
+      final int relativeOffset = _constantIndexer.offsets[i];
+      assert(relativeOffset >= 0);
+      writeUInt32(relativeOffset);
+    }
+    writeUInt32(_constantIndexer.entries.length);
+  }
+
+  void writeConstantTableEntry(Constant constant) {
     TypeParameterIndexer oldTypeParameterIndexer = _typeParameterIndexer;
     _typeParameterIndexer = new TypeParameterIndexer();
-    BufferedSink oldSink = _sink;
-    _sink = _constantsSink;
-    int initialOffset = _sink.offset;
     if (constant is NullConstant) {
       writeByte(ConstantTag.NullConstant);
     } else if (constant is BoolConstant) {
@@ -264,9 +275,7 @@
     } else {
       throw new ArgumentError('Unsupported constant $constant');
     }
-    _sink = oldSink;
     _typeParameterIndexer = oldTypeParameterIndexer;
-    return _constantsSink.offset - initialOffset;
   }
 
   void writeDartType(DartType type) {
@@ -491,6 +500,7 @@
   void writeLinkTable(Component component) {
     _binaryOffsetForLinkTable = getBufferOffset();
     writeList(_canonicalNameList, writeCanonicalNameEntry);
+    _canonicalNameListDone = true;
   }
 
   void indexLinkTable(Component component) {
@@ -506,6 +516,7 @@
 
   void _indexLinkTableInternal(CanonicalName node) {
     node.index = _canonicalNameList.length;
+    assert(!_canonicalNameListDone);
     _canonicalNameList.add(node);
     Iterable<CanonicalName>? children = node.childrenOrNull;
     if (children != null) {
@@ -557,10 +568,14 @@
       }
       writeLibraries(component);
       writeUriToSource(component.uriToSource);
+      // Writing constants can add both strings and canonical names.
+      writeConstantTable();
+      writeConstantTableIndex();
+      // Writing canonical names can add strings.
       writeLinkTable(component);
+      // Writing metadata sections can add strings.
       _writeMetadataSection(component);
       writeStringTable(stringIndexer);
-      writeConstantTable(_constantIndexer);
       List<Library> libraries = component.libraries;
       if (libraryFilter != null) {
         List<Library> librariesNew = <Library>[];
@@ -727,9 +742,10 @@
     const int kernelFileAlignment = 8;
 
     // Keep this in sync with number of writeUInt32 below.
-    int numComponentIndexEntries = 8 + libraryOffsets.length + 3;
+    int numComponentIndexEntries = 10 + libraryOffsets.length + 3;
+    int componentIndexOffset = getBufferOffset();
 
-    int unalignedSize = getBufferOffset() + numComponentIndexEntries * 4;
+    int unalignedSize = componentIndexOffset + numComponentIndexEntries * 4;
     int padding =
         ((unalignedSize + kernelFileAlignment - 1) & -kernelFileAlignment) -
             unalignedSize;
@@ -740,6 +756,10 @@
     // Fixed-size ints at the end used as an index.
     assert(_binaryOffsetForSourceTable >= 0);
     writeUInt32(_binaryOffsetForSourceTable);
+    assert(_binaryOffsetForConstantTable >= 0);
+    writeUInt32(_binaryOffsetForConstantTable);
+    assert(_binaryOffsetForConstantTableIndex >= 0);
+    writeUInt32(_binaryOffsetForConstantTableIndex);
     assert(_binaryOffsetForLinkTable >= 0);
     writeUInt32(_binaryOffsetForLinkTable);
     assert(_binaryOffsetForMetadataPayloads >= 0);
@@ -748,8 +768,8 @@
     writeUInt32(_binaryOffsetForMetadataMappings);
     assert(_binaryOffsetForStringTable >= 0);
     writeUInt32(_binaryOffsetForStringTable);
-    assert(_binaryOffsetForConstantTable >= 0);
-    writeUInt32(_binaryOffsetForConstantTable);
+    assert(componentIndexOffset >= 0);
+    writeUInt32(componentIndexOffset);
 
     Procedure? mainMethod = component.mainMethod;
     if (mainMethod == null) {
@@ -911,6 +931,7 @@
     }
     checkCanonicalName(node.parent!);
     node.index = _canonicalNameList.length;
+    assert(!_canonicalNameListDone);
     _canonicalNameList.add(node);
   }
 
@@ -2772,48 +2793,28 @@
 }
 
 class ConstantIndexer extends RecursiveResultVisitor {
-  final StringIndexer stringIndexer;
-
   final List<Constant> entries = <Constant>[];
-  final Map<Constant, int> offsets = <Constant, int>{};
-  int nextOffset = 0;
-
-  final BinaryPrinter _printer;
-
-  ConstantIndexer(this.stringIndexer, this._printer);
+  final List<int> offsets = <int>[];
+  final Map<Constant, int> index = <Constant, int>{};
 
   int put(Constant constant) {
-    final int? oldOffset = offsets[constant];
-    if (oldOffset != null) return oldOffset;
+    final int? oldIndex = index[constant];
+    if (oldIndex != null) return oldIndex;
 
     // Traverse DAG in post-order to ensure children have their offsets assigned
     // before the parent.
     constant.visitChildren(this);
 
-    if (constant is StringConstant) {
-      stringIndexer.put(constant.value);
-    } else if (constant is SymbolConstant) {
-      stringIndexer.put(constant.name);
-    } else if (constant is DoubleConstant) {
-      stringIndexer.put('${constant.value}');
-    } else if (constant is IntConstant) {
-      final int value = constant.value;
-      if ((value.abs() >> 30) != 0) {
-        stringIndexer.put('$value');
-      }
-    }
-
-    final int newOffset = nextOffset;
+    final int newIndex = entries.length;
     entries.add(constant);
-    nextOffset += _printer.writeConstantTableEntry(constant);
-    return offsets[constant] = newOffset;
+    offsets.add(-1); // placeholder.
+    assert(entries.length == offsets.length);
+    return index[constant] = newIndex;
   }
 
   defaultConstantReference(Constant node) {
     put(node);
   }
-
-  int? operator [](Constant node) => offsets[node];
 }
 
 class TypeParameterIndexer {
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 8fe71ec..832c230 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -174,7 +174,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 = 63;
+  static const int BinaryFormatVersion = 64;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index f4bc7eb..a08f107 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -789,11 +789,8 @@
 /// Contains all information collected by _FfiDefinitionTransformer that is
 /// needed in _FfiUseSiteTransformer.
 class FfiTransformerData {
-  final Map<Field, Procedure> replacedGetters;
-  final Map<Field, Procedure> replacedSetters;
   final Set<Class> emptyCompounds;
-  FfiTransformerData(
-      this.replacedGetters, this.replacedSetters, this.emptyCompounds);
+  FfiTransformerData(this.emptyCompounds);
 }
 
 /// Checks if any library depends on dart:ffi.
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index def3799..5c202a1 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -77,18 +77,17 @@
     // TODO: This check doesn't make sense: "dart:ffi" is always loaded/created
     // for the VM target.
     // If dart:ffi is not loaded, do not do the transformation.
-    return FfiTransformerData({}, {}, {});
+    return FfiTransformerData({});
   }
   if (index.tryGetClass('dart:ffi', 'NativeFunction') == null) {
     // If dart:ffi is not loaded (for real): do not do the transformation.
-    return FfiTransformerData({}, {}, {});
+    return FfiTransformerData({});
   }
   final transformer = new _FfiDefinitionTransformer(index, coreTypes, hierarchy,
       diagnosticReporter, referenceFromIndex, changedStructureNotifier);
   libraries.forEach(transformer.visitLibrary);
   transformer.manualVisitInTopologicalOrder();
-  return FfiTransformerData(transformer.replacedGetters,
-      transformer.replacedSetters, transformer.emptyCompounds);
+  return FfiTransformerData(transformer.emptyCompounds);
 }
 
 class CompoundDependencyGraph<T> implements Graph<T> {
@@ -109,8 +108,6 @@
   Map<Class, bool> fieldsValid = {};
   Map<Class, CompoundNativeTypeCfe> compoundCache = {};
 
-  Map<Field, Procedure> replacedGetters = {};
-  Map<Field, Procedure> replacedSetters = {};
   Set<Class> emptyCompounds = {};
 
   ChangedStructureNotifier changedStructureNotifier;
@@ -644,9 +641,6 @@
         ..isNonNullableByDefault = field.isNonNullableByDefault;
     }
 
-    replacedGetters[field] = getter;
-    replacedSetters[field] = setter;
-
     return [getter, if (setter != null) setter];
   }
 
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index a4383ed..a094f53 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -62,16 +62,12 @@
       hierarchy,
       diagnosticReporter,
       referenceFromIndex,
-      ffiTransformerData.replacedGetters,
-      ffiTransformerData.replacedSetters,
       ffiTransformerData.emptyCompounds);
   libraries.forEach(transformer.visitLibrary);
 }
 
 /// Checks and replaces calls to dart:ffi compound fields and methods.
 class _FfiUseSiteTransformer extends FfiTransformer {
-  final Map<Field, Procedure> replacedGetters;
-  final Map<Field, Procedure> replacedSetters;
   final Set<Class> emptyCompounds;
   StaticTypeContext _staticTypeContext;
 
@@ -87,8 +83,6 @@
       ClassHierarchy hierarchy,
       DiagnosticReporter diagnosticReporter,
       ReferenceFromIndex referenceFromIndex,
-      this.replacedGetters,
-      this.replacedSetters,
       this.emptyCompounds)
       : super(index, coreTypes, hierarchy, diagnosticReporter,
             referenceFromIndex) {}
@@ -146,31 +140,6 @@
   }
 
   @override
-  visitPropertyGet(PropertyGet node) {
-    super.visitPropertyGet(node);
-
-    final Procedure replacedWith = replacedGetters[node.interfaceTarget];
-    if (replacedWith != null) {
-      node = PropertyGet(node.receiver, replacedWith.name, replacedWith);
-    }
-
-    return node;
-  }
-
-  @override
-  visitPropertySet(PropertySet node) {
-    super.visitPropertySet(node);
-
-    final Procedure replacedWith = replacedSetters[node.interfaceTarget];
-    if (replacedWith != null) {
-      node = PropertySet(
-          node.receiver, replacedWith.name, node.value, replacedWith);
-    }
-
-    return node;
-  }
-
-  @override
   visitStaticInvocation(StaticInvocation node) {
     super.visitStaticInvocation(node);
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 67d9c2d..95c7166 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -553,13 +553,12 @@
     vm_service_server_port = 0;
   }
 
-  // We do not want to wait for DDS to advertise availability of VM service in the
-  // following scenarios:
-  // - When the VM service is disabled (can be started at a later time via SIGQUIT).
-  // - The DartDev CLI is disabled (CLI isolate starts DDS) and VM service is enabled.
-  bool wait_for_dds_to_advertise_service =
-    !Options::disable_dart_dev() && Options::enable_vm_service();
-
+  // We do not want to wait for DDS to advertise availability of VM service in
+  // the following scenarios:
+  // - The DartDev CLI is disabled (CLI isolate starts DDS) and VM service is
+  //   enabled.
+  // TODO(bkonyi): do we want to tie DevTools / DDS to the CLI in the long run?
+  bool wait_for_dds_to_advertise_service = !Options::disable_dart_dev();
   // Load embedder specific bits and return.
   if (!VmService::Setup(
           Options::disable_dart_dev() ? Options::vm_service_server_ip()
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index e60f6c8..77b794c 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -583,7 +583,7 @@
         run_command = true;
       }
       if (!Options::disable_dart_dev() && enable_vm_service_ && run_command) {
-        const char* dds_format_str = "--launch-dds=%s:%d";
+        const char* dds_format_str = "--launch-dds=%s\\:%d";
         size_t size =
             snprintf(nullptr, 0, dds_format_str, vm_service_server_ip(),
                      vm_service_server_port());
@@ -603,6 +603,7 @@
       first_option = false;
     }
   }
+
   // Verify consistency of arguments.
 
   // snapshot_depfile is an alias for depfile. Passing them both is an error.
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index dfbeeef..6705857 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -191,7 +191,7 @@
                                             const Instance& owner_mirror) {
   const Array& args = Array::Handle(Array::New(3));
   args.SetAt(0, param);
-  args.SetAt(1, String::Handle(param.name()));
+  args.SetAt(1, String::Handle(param.UserVisibleName()));
   args.SetAt(2, owner_mirror);
   return CreateMirror(Symbols::_TypeVariableMirror(), args);
 }
@@ -199,18 +199,17 @@
 // We create a list in native code and let Dart code create the type mirror
 // object and the ordered map.
 static InstancePtr CreateTypeVariableList(const Class& cls) {
-  const TypeArguments& args = TypeArguments::Handle(cls.type_parameters());
-  if (args.IsNull()) {
+  const intptr_t num_type_params = cls.NumTypeParameters();
+  if (num_type_params == 0) {
     return Object::empty_array().ptr();
   }
-  const Array& result = Array::Handle(Array::New(args.Length() * 2));
+  const Array& result = Array::Handle(Array::New(num_type_params * 2));
   TypeParameter& type = TypeParameter::Handle();
   String& name = String::Handle();
-  for (intptr_t i = 0; i < args.Length(); i++) {
-    type ^= args.TypeAt(i);
-    ASSERT(type.IsTypeParameter());
+  for (intptr_t i = 0; i < num_type_params; i++) {
+    type = cls.TypeParameterAt(i, Nullability::kLegacy);
     ASSERT(type.IsFinalized());
-    name = type.name();
+    name = type.UserVisibleName();
     result.SetAt(2 * i, name);
     result.SetAt(2 * i + 1, type);
   }
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 6b0e86c..fb999cf 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -449,18 +449,19 @@
   const Closure& closure =
       Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
   const Function& target = Function::Handle(zone, closure.function());
-  const TypeArguments& bounds =
-      TypeArguments::Handle(zone, target.type_parameters());
-
-  // Either the bounds are all-dynamic or the function is not generic.
-  if (bounds.IsNull()) return Object::null();
+  const TypeParameters& type_params =
+      TypeParameters::Handle(zone, target.type_parameters());
+  if (type_params.IsNull() || type_params.AllDynamicBounds()) {
+    // The function is not generic or the bounds are all dynamic.
+    return Object::null();
+  }
 
   const TypeArguments& type_args_to_check =
       TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(1));
 
   // This should be guaranteed by the front-end.
   ASSERT(type_args_to_check.IsNull() ||
-         bounds.Length() <= type_args_to_check.Length());
+         type_params.Length() <= type_args_to_check.Length());
 
   // The bounds on the closure may need instantiation.
   const TypeArguments& instantiator_type_args =
@@ -470,10 +471,8 @@
 
   AbstractType& supertype = AbstractType::Handle(zone);
   AbstractType& subtype = AbstractType::Handle(zone);
-  TypeParameter& parameter = TypeParameter::Handle(zone);
-  for (intptr_t i = 0; i < bounds.Length(); ++i) {
-    parameter ^= bounds.TypeAt(i);
-    supertype = parameter.bound();
+  for (intptr_t i = 0; i < type_params.Length(); ++i) {
+    supertype = type_params.BoundAt(i);
     subtype = type_args_to_check.IsNull() ? Object::dynamic_type().ptr()
                                           : type_args_to_check.TypeAt(i);
 
@@ -492,7 +491,7 @@
         ASSERT(caller_frame != NULL);
         location = caller_frame->GetTokenPos();
       }
-      String& parameter_name = String::Handle(zone, parameter.Name());
+      const auto& parameter_name = String::Handle(zone, type_params.NameAt(i));
       Exceptions::CreateAndThrowTypeError(location, subtype, supertype,
                                           parameter_name);
       UNREACHABLE();
diff --git a/runtime/vm/canonical_tables.cc b/runtime/vm/canonical_tables.cc
index 13c9470..bfdc140 100644
--- a/runtime/vm/canonical_tables.cc
+++ b/runtime/vm/canonical_tables.cc
@@ -40,11 +40,6 @@
     const Object& owner_b = Object::Handle(Field::Cast(b).Owner());
     return IsMatch(owner_a, owner_b);
   } else if (a.IsTypeParameter() && b.IsTypeParameter()) {
-    const String& name_a = String::Handle(TypeParameter::Cast(a).name());
-    const String& name_b = String::Handle(TypeParameter::Cast(b).name());
-    if (!name_a.Equals(name_b)) {
-      return false;
-    }
     if (TypeParameter::Cast(a).index() != TypeParameter::Cast(b).index() ||
         TypeParameter::Cast(a).base() != TypeParameter::Cast(b).base()) {
       return false;
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index e429842..eff5ead 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -294,31 +294,41 @@
   }
   IsolateGroup::Current()->heap()->Verify();
 }
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
 
-void ClassFinalizer::FinalizeTypeParameters(const Class& cls,
-                                            FinalizationKind finalization) {
+void ClassFinalizer::FinalizeTypeParameters(Zone* zone,
+                                            const Class& cls,
+                                            const FunctionType& signature,
+                                            FinalizationKind finalization,
+                                            PendingTypes* pending_types) {
   if (FLAG_trace_type_finalization) {
-    THR_Print("%s type parameters of '%s'\n",
-              String::Handle(cls.Name()).ToCString(),
-              finalization == kFinalize ? "Finalizing" : "Canonicalizing");
+    THR_Print(
+        "%s type parameters of %s '%s'\n",
+        finalization == kFinalize ? "Finalizing" : "Canonicalizing",
+        !cls.IsNull() ? "class" : "signature",
+        String::Handle(zone, !cls.IsNull() ? cls.Name() : signature.Name())
+            .ToCString());
   }
-  const TypeArguments& type_params =
-      TypeArguments::Handle(cls.type_parameters());
+  const TypeParameters& type_params =
+      TypeParameters::Handle(zone, !cls.IsNull() ? cls.type_parameters()
+                                                 : signature.type_parameters());
   if (!type_params.IsNull()) {
-    const intptr_t num_type_params = type_params.Length();
-    TypeParameter& type_param = TypeParameter::Handle();
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type_param ^= type_params.TypeAt(i);
-      if (!type_param.IsBeingFinalized()) {
-        type_param ^= FinalizeType(type_param, finalization);
-        type_params.SetTypeAt(i, type_param);
-      }
-    }
+    TypeArguments& type_args = TypeArguments::Handle(zone);
+
+    type_args = type_params.bounds();
+    type_args =
+        FinalizeTypeArguments(zone, type_args, finalization, pending_types);
+    type_params.set_bounds(type_args);
+
+    type_args = type_params.defaults();
+    type_args =
+        FinalizeTypeArguments(zone, type_args, finalization, pending_types);
+    type_params.set_defaults(type_args);
+
+    type_params.OptimizeFlags();
   }
 }
 
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
-
 // This function reports a compilation error if the recursive 'type' T being
 // finalized is a non-contractive type, i.e. if the induced type set S of P is
 // not finite, where P is the instantiation of T with its own type parameters.
@@ -407,9 +417,9 @@
 // Expand the type arguments of the given type and finalize its full type
 // argument vector. Return the number of type arguments (0 for a raw type).
 intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
+    Zone* zone,
     const AbstractType& type,
     PendingTypes* pending_types) {
-  Zone* zone = Thread::Current()->zone();
   // The type class does not need to be finalized in order to finalize the type.
   // Also, the type parameters of the type class must be finalized.
   Class& type_class = Class::Handle(zone, type.type_class());
@@ -483,8 +493,8 @@
       }
       if (offset > 0) {
         TrailPtr trail = new Trail(zone, 4);
-        FinalizeTypeArguments(type_class, full_arguments, offset, pending_types,
-                              trail);
+        FillAndFinalizeTypeArguments(zone, type_class, full_arguments, offset,
+                                     pending_types, trail);
       }
       if (full_arguments.IsRaw(0, num_type_arguments)) {
         // The parameterized_type is raw. Set its argument vector to null, which
@@ -535,22 +545,24 @@
 // same time. Canonicalization happens when pending types are processed.
 // The trail is required to correctly instantiate a recursive type argument
 // of the super type.
-void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
-                                           const TypeArguments& arguments,
-                                           intptr_t num_uninitialized_arguments,
-                                           PendingTypes* pending_types,
-                                           TrailPtr trail) {
+void ClassFinalizer::FillAndFinalizeTypeArguments(
+    Zone* zone,
+    const Class& cls,
+    const TypeArguments& arguments,
+    intptr_t num_uninitialized_arguments,
+    PendingTypes* pending_types,
+    TrailPtr trail) {
   ASSERT(arguments.Length() >= cls.NumTypeArguments());
   if (!cls.is_type_finalized()) {
 #if defined(DART_PRECOMPILED_RUNTIME)
     UNREACHABLE();
 #else
-    FinalizeTypeParameters(cls, kFinalize);
+    FinalizeTypeParameters(zone, cls, Object::null_function_type(), kFinalize);
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
   }
-  AbstractType& super_type = AbstractType::Handle(cls.super_type());
+  AbstractType& super_type = AbstractType::Handle(zone, cls.super_type());
   if (!super_type.IsNull()) {
-    const Class& super_class = Class::Handle(super_type.type_class());
+    const Class& super_class = Class::Handle(zone, super_type.type_class());
     const intptr_t num_super_type_params = super_class.NumTypeParameters();
     const intptr_t num_super_type_args = super_class.NumTypeArguments();
     if (!super_type.IsFinalized() && !super_type.IsBeingFinalized()) {
@@ -558,11 +570,12 @@
       cls.set_super_type(super_type);
     }
     TypeArguments& super_type_args =
-        TypeArguments::Handle(super_type.arguments());
+        TypeArguments::Handle(zone, super_type.arguments());
     // Offset of super type's type parameters in cls' type argument vector.
     const intptr_t super_offset = num_super_type_args - num_super_type_params;
     // If the super type is raw (i.e. super_type_args is null), set to dynamic.
-    AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType());
+    AbstractType& super_type_arg =
+        AbstractType::Handle(zone, Type::DynamicType());
     for (intptr_t i = super_offset; i < num_uninitialized_arguments; i++) {
       if (!super_type_args.IsNull()) {
         super_type_arg = super_type_args.TypeAt(i);
@@ -581,9 +594,10 @@
                 ASSERT(super_type_arg.IsFunctionType());
               }
               if (FLAG_trace_type_finalization) {
-                THR_Print("Creating TypeRef '%s': '%s'\n",
-                          String::Handle(super_type_arg.Name()).ToCString(),
-                          super_type_arg.ToCString());
+                THR_Print(
+                    "Creating TypeRef '%s': '%s'\n",
+                    String::Handle(zone, super_type_arg.Name()).ToCString(),
+                    super_type_arg.ToCString());
               }
               super_type_arg = TypeRef::New(super_type_arg);
             }
@@ -601,12 +615,12 @@
         // Instantiate super_type_arg with the current argument vector.
         if (!super_type_arg.IsInstantiated()) {
           if (FLAG_trace_type_finalization && super_type_arg.IsTypeRef()) {
-            AbstractType& ref_type =
-                AbstractType::Handle(TypeRef::Cast(super_type_arg).type());
+            AbstractType& ref_type = AbstractType::Handle(
+                zone, TypeRef::Cast(super_type_arg).type());
             THR_Print(
                 "Instantiating TypeRef '%s': '%s'\n"
                 "  instantiator: '%s'\n",
-                String::Handle(super_type_arg.Name()).ToCString(),
+                String::Handle(zone, super_type_arg.Name()).ToCString(),
                 ref_type.ToCString(), arguments.ToCString());
           }
           // In the typical case of an F-bounded type, the instantiation of the
@@ -628,7 +642,7 @@
             // The super_type_arg was instantiated from a type being finalized.
             // We need to finish finalizing its type arguments, unless it is a
             // type parameter, in which case there is nothing more to do.
-            AbstractType& unfinalized_type = AbstractType::Handle();
+            AbstractType& unfinalized_type = AbstractType::Handle(zone);
             if (super_type_arg.IsTypeRef()) {
               unfinalized_type = TypeRef::Cast(super_type_arg).type();
             } else {
@@ -636,18 +650,19 @@
               unfinalized_type = super_type_arg.ptr();
             }
             if (FLAG_trace_type_finalization) {
-              THR_Print("Instantiated unfinalized '%s': '%s'\n",
-                        String::Handle(unfinalized_type.Name()).ToCString(),
-                        unfinalized_type.ToCString());
+              THR_Print(
+                  "Instantiated unfinalized '%s': '%s'\n",
+                  String::Handle(zone, unfinalized_type.Name()).ToCString(),
+                  unfinalized_type.ToCString());
             }
             if (unfinalized_type.IsType()) {
               CheckRecursiveType(unfinalized_type, pending_types);
               pending_types->Add(unfinalized_type);
             }
             const Class& super_cls =
-                Class::Handle(unfinalized_type.type_class());
+                Class::Handle(zone, unfinalized_type.type_class());
             const TypeArguments& super_args =
-                TypeArguments::Handle(unfinalized_type.arguments());
+                TypeArguments::Handle(zone, unfinalized_type.arguments());
             // Mark as finalized before finalizing to avoid cycles.
             unfinalized_type.SetIsFinalized();
             // Although the instantiator is different between cls and super_cls,
@@ -655,25 +670,53 @@
             // divergence. Finalizing the type arguments of super_cls may indeed
             // recursively require instantiating the same type_refs already
             // present in the trail (see issue #29949).
-            FinalizeTypeArguments(
-                super_cls, super_args,
+            FillAndFinalizeTypeArguments(
+                zone, super_cls, super_args,
                 super_cls.NumTypeArguments() - super_cls.NumTypeParameters(),
                 pending_types, trail);
             if (FLAG_trace_type_finalization) {
-              THR_Print("Finalized instantiated '%s': '%s'\n",
-                        String::Handle(unfinalized_type.Name()).ToCString(),
-                        unfinalized_type.ToCString());
+              THR_Print(
+                  "Finalized instantiated '%s': '%s'\n",
+                  String::Handle(zone, unfinalized_type.Name()).ToCString(),
+                  unfinalized_type.ToCString());
             }
           }
         }
       }
       arguments.SetTypeAt(i, super_type_arg);
     }
-    FinalizeTypeArguments(super_class, arguments, super_offset, pending_types,
-                          trail);
+    FillAndFinalizeTypeArguments(zone, super_class, arguments, super_offset,
+                                 pending_types, trail);
   }
 }
 
+TypeArgumentsPtr ClassFinalizer::FinalizeTypeArguments(
+    Zone* zone,
+    const TypeArguments& type_args,
+    FinalizationKind finalization,
+    PendingTypes* pending_types) {
+  if (type_args.IsNull()) return TypeArguments::null();
+  ASSERT(type_args.ptr() != Object::empty_type_arguments().ptr());
+  const intptr_t len = type_args.Length();
+  AbstractType& type = AbstractType::Handle(zone);
+  AbstractType& finalized_type = AbstractType::Handle(zone);
+  for (intptr_t i = 0; i < len; i++) {
+    type = type_args.TypeAt(i);
+    if (type.IsBeingFinalized()) {
+      ASSERT(finalization < kCanonicalize);
+      continue;
+    }
+    finalized_type = FinalizeType(type, kFinalize, pending_types);
+    if (type.ptr() != finalized_type.ptr()) {
+      type_args.SetTypeAt(i, finalized_type);
+    }
+  }
+  if (finalization >= kCanonicalize) {
+    return type_args.Canonicalize(Thread::Current(), nullptr);
+  }
+  return type_args.ptr();
+}
+
 AbstractTypePtr ClassFinalizer::FinalizeType(const AbstractType& type,
                                              FinalizationKind finalization,
                                              PendingTypes* pending_types) {
@@ -701,8 +744,8 @@
     return type.ptr();
   }
 
-  // Recursive types must be processed in FinalizeTypeArguments() and cannot be
-  // encountered here.
+  // Recursive types must be processed in FillAndFinalizeTypeArguments() and
+  // cannot be encountered here.
   ASSERT(!type.IsBeingFinalized());
 
   // Mark the type as being finalized in order to detect self reference.
@@ -737,17 +780,20 @@
       type_parameter.set_parameterized_class_id(kClassCid);
     }
 
-    AbstractType& t = AbstractType::Handle(zone);
-    t = type_parameter.bound();
-    if (!t.IsBeingFinalized()) {
-      t = FinalizeType(t, kFinalize);
-      type_parameter.set_bound(t);
+    AbstractType& upper_bound = AbstractType::Handle(zone);
+    upper_bound = type_parameter.bound();
+    if (upper_bound.IsBeingFinalized()) {
+      if (upper_bound.IsTypeRef()) {
+        // Nothing to do.
+      } else {
+        upper_bound = TypeRef::New(upper_bound);
+        type_parameter.set_bound(upper_bound);
+        upper_bound = FinalizeType(upper_bound, kFinalize);
+      }
+    } else {
+      upper_bound = FinalizeType(upper_bound, kFinalize);
+      type_parameter.set_bound(upper_bound);
     }
-    t = type_parameter.default_argument();
-    // The default argument cannot create a cycle with the type parameter.
-    t = FinalizeType(t, kFinalize);
-    type_parameter.set_default_argument(t);
-
     type_parameter.SetIsFinalized();
 
     if (FLAG_trace_type_finalization) {
@@ -781,7 +827,7 @@
   pending_types->Add(type);
 
   const intptr_t num_expanded_type_arguments =
-      ExpandAndFinalizeTypeArguments(type, pending_types);
+      ExpandAndFinalizeTypeArguments(zone, type, pending_types);
 
   // Self referencing types may get finalized indirectly.
   if (!type.IsFinalized()) {
@@ -819,23 +865,12 @@
                                                   const FunctionType& signature,
                                                   FinalizationKind finalization,
                                                   PendingTypes* pending_types) {
+  // Finalize signature type parameter upper bounds and default args.
+  FinalizeTypeParameters(zone, Object::null_class(), signature, finalization,
+                         pending_types);
+
   AbstractType& type = AbstractType::Handle(zone);
   AbstractType& finalized_type = AbstractType::Handle(zone);
-  // Finalize signature type parameters, their upper bounds and default args.
-  const intptr_t num_type_params = signature.NumTypeParameters();
-  if (num_type_params > 0) {
-    TypeParameter& type_param = TypeParameter::Handle(zone);
-    const TypeArguments& type_params =
-        TypeArguments::Handle(zone, signature.type_parameters());
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type_param ^= type_params.TypeAt(i);
-      finalized_type ^= FinalizeType(type_param, kFinalize, pending_types);
-      if (type_param.ptr() != finalized_type.ptr()) {
-        type_params.SetTypeAt(i, TypeParameter::Cast(finalized_type));
-      }
-    }
-  }
-
   // Finalize result type.
   type = signature.result_type();
   finalized_type = FinalizeType(type, kFinalize, pending_types);
@@ -984,6 +1019,7 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
   UNREACHABLE();
 #else
+  Zone* zone = thread->zone();
   SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   if (cls.is_type_finalized()) {
     return;
@@ -993,24 +1029,24 @@
     THR_Print("Finalize types in %s\n", cls.ToCString());
   }
   // Finalize super class.
-  Class& super_class = Class::Handle(cls.SuperClass());
+  Class& super_class = Class::Handle(zone, cls.SuperClass());
   if (!super_class.IsNull()) {
     FinalizeTypesInClass(super_class);
   }
   // Finalize type parameters before finalizing the super type.
-  FinalizeTypeParameters(cls, kFinalize);
+  FinalizeTypeParameters(zone, cls, Object::null_function_type(),
+                         kCanonicalize);
   ASSERT(super_class.ptr() == cls.SuperClass());  // Not modified.
   ASSERT(super_class.IsNull() || super_class.is_type_finalized());
-  FinalizeTypeParameters(cls, kCanonicalize);
   // Finalize super type.
-  AbstractType& super_type = AbstractType::Handle(cls.super_type());
+  AbstractType& super_type = AbstractType::Handle(zone, cls.super_type());
   if (!super_type.IsNull()) {
     super_type = FinalizeType(super_type);
     cls.set_super_type(super_type);
   }
   // Finalize interface types (but not necessarily interface classes).
-  Array& interface_types = Array::Handle(cls.interfaces());
-  AbstractType& interface_type = AbstractType::Handle();
+  Array& interface_types = Array::Handle(zone, cls.interfaces());
+  AbstractType& interface_type = AbstractType::Handle(zone);
   for (intptr_t i = 0; i < interface_types.Length(); i++) {
     interface_type ^= interface_types.At(i);
     interface_type = FinalizeType(interface_type);
@@ -1343,8 +1379,7 @@
   error = cls.EnsureIsFinalized(thread);
   ASSERT(error.IsNull());
   ASSERT(cls.NumTypeParameters() == 1);
-  type_param ^= TypeParameter::RawCast(
-      TypeArguments::Handle(cls.type_parameters()).TypeAt(0));
+  type_param = cls.TypeParameterAt(0);
   ASSERT(Pointer::kNativeTypeArgPos == type_param.index());
 #endif
 }
@@ -1660,7 +1695,8 @@
   for (intptr_t i = 0; i < typeparams.Length(); i++) {
     typeparam ^= typeparams.At(i);
     bool present = typeparams_table.Insert(typeparam);
-    ASSERT(!present);
+    // Two recursive types with different topology (and hashes) may be equal.
+    ASSERT(!present || typeparam.IsRecursive());
   }
   object_store->set_canonical_type_parameters(typeparams_table.Release());
 
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index db2b973..3f7775d 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -79,6 +79,13 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
  private:
+  // Finalize given type argument vector.
+  static TypeArgumentsPtr FinalizeTypeArguments(
+      Zone* zone,
+      const TypeArguments& type_args,
+      FinalizationKind finalization = kCanonicalize,
+      PendingTypes* pending_types = NULL);
+
   // Finalize the types in the signature and the signature itself.
   static AbstractTypePtr FinalizeSignature(
       Zone* zone,
@@ -88,18 +95,24 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   static void AllocateEnumValues(const Class& enum_cls);
-  static void FinalizeTypeParameters(
-      const Class& cls,
-      FinalizationKind finalization = kCanonicalize);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-  static intptr_t ExpandAndFinalizeTypeArguments(const AbstractType& type,
+  static void FinalizeTypeParameters(
+      Zone* zone,
+      const Class& cls,
+      const FunctionType& signature,
+      FinalizationKind finalization = kCanonicalize,
+      PendingTypes* pending_types = NULL);
+
+  static intptr_t ExpandAndFinalizeTypeArguments(Zone* zone,
+                                                 const AbstractType& type,
                                                  PendingTypes* pending_types);
-  static void FinalizeTypeArguments(const Class& cls,
-                                    const TypeArguments& arguments,
-                                    intptr_t num_uninitialized_arguments,
-                                    PendingTypes* pending_types,
-                                    TrailPtr trail);
+  static void FillAndFinalizeTypeArguments(Zone* zone,
+                                           const Class& cls,
+                                           const TypeArguments& arguments,
+                                           intptr_t num_uninitialized_arguments,
+                                           PendingTypes* pending_types,
+                                           TrailPtr trail);
   static void CheckRecursiveType(const AbstractType& type,
                                  PendingTypes* pending_types);
 
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index cb1b9f0..5e2b4c7 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -21,6 +21,7 @@
   V(Class)                                                                     \
   V(PatchClass)                                                                \
   V(Function)                                                                  \
+  V(TypeParameters)                                                            \
   V(ClosureData)                                                               \
   V(FfiTrampolineData)                                                         \
   V(Field)                                                                     \
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 3de7da8..b99bc8a 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -533,8 +533,14 @@
         element ^= ptr;
         intptr_t entry = -1;
         const bool present = table.FindKeyOrDeletedOrUnused(element, &entry);
-        ASSERT(!present);
-        table.InsertKey(entry, element);
+        if (!present) {
+          table.InsertKey(entry, element);
+        } else {
+          // Two recursive types with different topology (and hashes)
+          // may be equal.
+          ASSERT(element.IsRecursive());
+          objects_[num_occupied++] = ptr;
+        }
       } else {
         objects_[num_occupied++] = ptr;
       }
@@ -686,6 +692,74 @@
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+class TypeParametersSerializationCluster : public SerializationCluster {
+ public:
+  TypeParametersSerializationCluster()
+      : SerializationCluster("TypeParameters",
+                             kTypeParametersCid,
+                             compiler::target::TypeParameters::InstanceSize()) {
+  }
+  ~TypeParametersSerializationCluster() {}
+
+  void Trace(Serializer* s, ObjectPtr object) {
+    TypeParametersPtr type_params = TypeParameters::RawCast(object);
+    objects_.Add(type_params);
+    PushFromTo(type_params);
+  }
+
+  void WriteAlloc(Serializer* s) {
+    const intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TypeParametersPtr type_params = objects_[i];
+      s->AssignRef(type_params);
+    }
+  }
+
+  void WriteFill(Serializer* s) {
+    const intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      TypeParametersPtr type_params = objects_[i];
+      AutoTraceObject(type_params);
+      WriteFromTo(type_params);
+    }
+  }
+
+ private:
+  GrowableArray<TypeParametersPtr> objects_;
+};
+#endif  // !DART_PRECOMPILED_RUNTIME
+
+class TypeParametersDeserializationCluster : public DeserializationCluster {
+ public:
+  TypeParametersDeserializationCluster()
+      : DeserializationCluster("TypeParameters") {}
+  ~TypeParametersDeserializationCluster() {}
+
+  void ReadAlloc(Deserializer* d) {
+    start_index_ = d->next_index();
+    PageSpace* old_space = d->heap()->old_space();
+    const intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(
+          AllocateUninitialized(old_space, TypeParameters::InstanceSize()));
+    }
+    stop_index_ = d->next_index();
+  }
+
+  void ReadFill(Deserializer* d, bool primary) {
+    ASSERT(!is_canonical());  // Never canonical.
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      TypeParametersPtr type_params =
+          static_cast<TypeParametersPtr>(d->Ref(id));
+      Deserializer::InitializeHeader(type_params, kTypeParametersCid,
+                                     TypeParameters::InstanceSize());
+      ReadFromTo(type_params);
+    }
+  }
+};
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
 class TypeArgumentsSerializationCluster
     : public CanonicalSetSerializationCluster<CanonicalTypeArgumentsSet,
                                               TypeArguments,
@@ -1088,7 +1162,6 @@
     }
     s->Push(data->untag()->parent_function());
     s->Push(data->untag()->closure());
-    s->Push(data->untag()->default_type_arguments());
   }
 
   void WriteAlloc(Serializer* s) {
@@ -1110,7 +1183,6 @@
       }
       WriteCompressedField(data, parent_function);
       WriteCompressedField(data, closure);
-      WriteCompressedField(data, default_type_arguments);
       s->WriteUnsigned(
           static_cast<intptr_t>(data->untag()->default_type_arguments_kind_));
     }
@@ -1151,8 +1223,6 @@
       }
       data->untag()->parent_function_ = static_cast<FunctionPtr>(d->ReadRef());
       data->untag()->closure_ = static_cast<InstancePtr>(d->ReadRef());
-      data->untag()->default_type_arguments_ =
-          static_cast<TypeArgumentsPtr>(d->ReadRef());
       data->untag()->default_type_arguments_kind_ =
           static_cast<ClosureData::DefaultTypeArgumentsKind>(d->ReadUnsigned());
     }
@@ -4218,8 +4288,8 @@
     AutoTraceObject(type);
     WriteFromTo(type);
     s->Write<int32_t>(type->untag()->parameterized_class_id_);
-    s->Write<uint16_t>(type->untag()->base_);
-    s->Write<uint16_t>(type->untag()->index_);
+    s->Write<uint8_t>(type->untag()->base_);
+    s->Write<uint8_t>(type->untag()->index_);
     ASSERT(type->untag()->flags_ < (1 << UntaggedTypeParameter::kFlagsBitSize));
     ASSERT(type->untag()->nullability_ < (1 << kNullabilityBitSize));
     static_assert(UntaggedTypeParameter::kFlagsBitSize + kNullabilityBitSize <=
@@ -4264,8 +4334,8 @@
                                      primary && is_canonical());
       ReadFromTo(type);
       type->untag()->parameterized_class_id_ = d->Read<int32_t>();
-      type->untag()->base_ = d->Read<uint16_t>();
-      type->untag()->index_ = d->Read<uint16_t>();
+      type->untag()->base_ = d->Read<uint8_t>();
+      type->untag()->index_ = d->Read<uint8_t>();
       const uint8_t combined = d->Read<uint8_t>();
       type->untag()->flags_ = combined >> kNullabilityBitSize;
       type->untag()->nullability_ = combined & kNullabilityBitMask;
@@ -6536,6 +6606,8 @@
   switch (cid) {
     case kClassCid:
       return new (Z) ClassSerializationCluster(num_cids_ + num_tlc_cids_);
+    case kTypeParametersCid:
+      return new (Z) TypeParametersSerializationCluster();
     case kTypeArgumentsCid:
       return new (Z) TypeArgumentsSerializationCluster(
           is_canonical, cluster_represents_canonical_set);
@@ -7388,6 +7460,8 @@
     case kClassCid:
       ASSERT(!is_canonical);
       return new (Z) ClassDeserializationCluster();
+    case kTypeParametersCid:
+      return new (Z) TypeParametersDeserializationCluster();
     case kTypeArgumentsCid:
       return new (Z)
           TypeArgumentsDeserializationCluster(is_canonical, !is_non_root_unit_);
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 22a4b28..56c13e8 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -962,7 +962,7 @@
     AddType(type);
   }
 
-  AddTypeArguments(TypeArguments::Handle(Z, cls.type_parameters()));
+  AddTypeParameters(TypeParameters::Handle(Z, cls.type_parameters()));
 
   type = cls.super_type();
   AddType(type);
@@ -991,15 +991,6 @@
   const FunctionType& signature = FunctionType::Handle(Z, function.signature());
   AddType(signature);
 
-  // At this point, ensure any cached default type arguments are canonicalized.
-  function.UpdateCachedDefaultTypeArguments(thread());
-  if (function.CachesDefaultTypeArguments()) {
-    const auto& defaults = TypeArguments::Handle(
-        Z, function.default_type_arguments(/*kind_out=*/nullptr));
-    ASSERT(defaults.IsCanonical());
-    AddTypeArguments(defaults);
-  }
-
   // A class may have all functions inlined except a local function.
   const Class& owner = Class::Handle(Z, function.Owner());
   AddTypesOf(owner);
@@ -1054,10 +1045,8 @@
     if (typeparams_to_retain_.HasKey(&param)) return;
     typeparams_to_retain_.Insert(&TypeParameter::ZoneHandle(Z, param.ptr()));
 
-    auto& type = AbstractType::Handle(Z, param.bound());
-    AddType(type);
-    type = param.default_argument();
-    AddType(type);
+    auto& bound = AbstractType::Handle(Z, param.bound());
+    AddType(bound);
     return;
   }
 
@@ -1067,7 +1056,7 @@
         FunctionType::ZoneHandle(Z, FunctionType::Cast(abstype).ptr());
     functiontypes_to_retain_.Insert(&signature);
 
-    AddTypeArguments(TypeArguments::Handle(Z, signature.type_parameters()));
+    AddTypeParameters(TypeParameters::Handle(Z, signature.type_parameters()));
 
     AbstractType& type = AbstractType::Handle(Z);
     type = signature.result_type();
@@ -1095,6 +1084,16 @@
   }
 }
 
+void Precompiler::AddTypeParameters(const TypeParameters& params) {
+  if (params.IsNull()) return;
+
+  TypeArguments& args = TypeArguments::Handle();
+  args = params.bounds();
+  AddTypeArguments(args);
+  args = params.defaults();
+  AddTypeArguments(args);
+}
+
 void Precompiler::AddTypeArguments(const TypeArguments& args) {
   if (args.IsNull()) return;
 
@@ -2479,16 +2478,6 @@
   Array& dict = Array::Handle(Z);
   Object& entry = Object::Handle(Z);
 
-  Array& scripts = Array::Handle(Z);
-  Script& script = Script::Handle(Z);
-  KernelProgramInfo& program_info = KernelProgramInfo::Handle(Z);
-  const TypedData& null_typed_data = TypedData::Handle(Z);
-  const KernelProgramInfo& null_info = KernelProgramInfo::Handle(Z);
-#if defined(PRODUCT)
-  auto& str = String::Handle(Z);
-  auto& wsr = WeakSerializationReference::Handle(Z);
-#endif
-
   for (intptr_t i = 0; i < libraries_.Length(); i++) {
     lib ^= libraries_.At(i);
 
@@ -2522,32 +2511,6 @@
       dict.SetAt(j, Object::null_object());
     }
 
-    scripts = lib.LoadedScripts();
-    if (!scripts.IsNull()) {
-      for (intptr_t i = 0; i < scripts.Length(); ++i) {
-        script = Script::RawCast(scripts.At(i));
-        program_info = script.kernel_program_info();
-        if (!program_info.IsNull()) {
-          program_info.set_constants(Array::null_array());
-          program_info.set_scripts(Array::null_array());
-          program_info.set_libraries_cache(Array::null_array());
-          program_info.set_classes_cache(Array::null_array());
-        }
-#if defined(PRODUCT)
-        str = script.resolved_url();
-        if (!str.IsNull()) {
-          wsr = WeakSerializationReference::New(str, String::null_string());
-          script.set_resolved_url(wsr);
-        }
-#endif  // defined(PRODUCT)
-        script.set_compile_time_constants(Array::null_array());
-        script.set_line_starts(null_typed_data);
-        script.set_debug_positions(Array::null_array());
-        script.set_kernel_program_info(null_info);
-        script.set_source(String::null_string());
-      }
-    }
-
     lib.RehashDictionary(dict, used * 4 / 3 + 1);
     if (!(retain_root_library_caches_ &&
           (lib.ptr() == IG->object_store()->root_library()))) {
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 24bebca..fba9413 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -298,6 +298,7 @@
   void AddType(const AbstractType& type);
   void AddTypesOf(const Class& cls);
   void AddTypesOf(const Function& function);
+  void AddTypeParameters(const TypeParameters& params);
   void AddTypeArguments(const TypeArguments& args);
   void AddCalleesOf(const Function& function, intptr_t gop_offset);
   void AddCalleesOfHelper(const Object& entry,
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index f6b9929..5737444 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -2694,7 +2694,6 @@
     case Slot::Kind::kClosure_function_type_arguments:
     case Slot::Kind::kClosure_instantiator_type_arguments:
     case Slot::Kind::kClosure_hash:
-    case Slot::Kind::kClosureData_default_type_arguments:
     case Slot::Kind::kCapturedVariable:
     case Slot::Kind::kDartField:
     case Slot::Kind::kFunction_data:
@@ -2705,8 +2704,11 @@
     case Slot::Kind::kPointerBase_data_field:
     case Slot::Kind::kType_arguments:
     case Slot::Kind::kTypeArgumentsIndex:
+    case Slot::Kind::kTypeParameters_names:
+    case Slot::Kind::kTypeParameters_flags:
+    case Slot::Kind::kTypeParameters_bounds:
+    case Slot::Kind::kTypeParameters_defaults:
     case Slot::Kind::kTypeParameter_bound:
-    case Slot::Kind::kTypeParameter_name:
     case Slot::Kind::kUnhandledException_exception:
     case Slot::Kind::kUnhandledException_stacktrace:
     case Slot::Kind::kWeakProperty_key:
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index a99374c..de02bc4 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -52,18 +52,14 @@
   return cls.ptr();
 }
 
-TypeParameterPtr GetClassTypeParameter(const Class& klass, const char* name) {
-  const auto& param = TypeParameter::Handle(
-      klass.LookupTypeParameter(String::Handle(String::New(name))));
+TypeParameterPtr GetClassTypeParameter(const Class& klass, intptr_t index) {
+  const auto& param = TypeParameter::Handle(klass.TypeParameterAt(index));
   EXPECT(!param.IsNull());
   return param.ptr();
 }
 
-TypeParameterPtr GetFunctionTypeParameter(const Function& fun,
-                                          const char* name) {
-  intptr_t fun_level = 0;
-  const auto& param = TypeParameter::Handle(
-      fun.LookupTypeParameter(String::Handle(String::New(name)), &fun_level));
+TypeParameterPtr GetFunctionTypeParameter(const Function& fun, intptr_t index) {
+  const auto& param = TypeParameter::Handle(fun.TypeParameterAt(index));
   EXPECT(!param.IsNull());
   return param.ptr();
 }
diff --git a/runtime/vm/compiler/backend/il_test_helper.h b/runtime/vm/compiler/backend/il_test_helper.h
index 7ef8db3..b42febd 100644
--- a/runtime/vm/compiler/backend/il_test_helper.h
+++ b/runtime/vm/compiler/backend/il_test_helper.h
@@ -58,9 +58,8 @@
 
 FunctionPtr GetFunction(const Library& lib, const char* name);
 ClassPtr GetClass(const Library& lib, const char* name);
-TypeParameterPtr GetClassTypeParameter(const Class& klass, const char* name);
-TypeParameterPtr GetFunctionTypeParameter(const Function& fun,
-                                          const char* name);
+TypeParameterPtr GetClassTypeParameter(const Class& klass, intptr_t index);
+TypeParameterPtr GetFunctionTypeParameter(const Function& fun, intptr_t index);
 
 ObjectPtr Invoke(const Library& lib, const char* name);
 
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 3992c8b..b65bdf1 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2797,7 +2797,6 @@
     case Slot::Kind::kClosure_function:
     case Slot::Kind::kClosure_function_type_arguments:
     case Slot::Kind::kClosure_instantiator_type_arguments:
-    case Slot::Kind::kClosureData_default_type_arguments:
     case Slot::Kind::kFunction_data:
     case Slot::Kind::kFunction_signature:
     case Slot::Kind::kFunctionType_parameter_names:
@@ -2807,8 +2806,11 @@
     case Slot::Kind::kTypedDataView_data:
     case Slot::Kind::kType_arguments:
     case Slot::Kind::kTypeArgumentsIndex:
+    case Slot::Kind::kTypeParameters_names:
+    case Slot::Kind::kTypeParameters_flags:
+    case Slot::Kind::kTypeParameters_bounds:
+    case Slot::Kind::kTypeParameters_defaults:
     case Slot::Kind::kTypeParameter_bound:
-    case Slot::Kind::kTypeParameter_name:
     case Slot::Kind::kUnhandledException_exception:
     case Slot::Kind::kUnhandledException_stacktrace:
     case Slot::Kind::kWeakProperty_key:
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 3292e7f..a9ff524 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -58,10 +58,13 @@
     FINAL)                                                                     \
   V(Closure, UntaggedClosure, delayed_type_arguments, TypeArguments, FINAL)    \
   V(Closure, UntaggedClosure, function_type_arguments, TypeArguments, FINAL)   \
-  V(ClosureData, UntaggedClosureData, default_type_arguments, TypeArguments,   \
-    FINAL_COMPRESSED)                                                          \
   V(Type, UntaggedType, arguments, TypeArguments, FINAL_COMPRESSED)            \
-  V(FunctionType, UntaggedFunctionType, type_parameters, TypeArguments,        \
+  V(FunctionType, UntaggedFunctionType, type_parameters, TypeParameters,       \
+    FINAL_COMPRESSED)                                                          \
+  V(TypeParameters, UntaggedTypeParameters, flags, Array, FINAL_COMPRESSED)    \
+  V(TypeParameters, UntaggedTypeParameters, bounds, TypeArguments,             \
+    FINAL_COMPRESSED)                                                          \
+  V(TypeParameters, UntaggedTypeParameters, defaults, TypeArguments,           \
     FINAL_COMPRESSED)                                                          \
   V(WeakProperty, UntaggedWeakProperty, key, Dynamic, VAR)                     \
   V(WeakProperty, UntaggedWeakProperty, value, Dynamic, VAR)
@@ -107,8 +110,8 @@
   V(ArgumentsDescriptor, UntaggedArray, size, Smi, FINAL)                      \
   V(PointerBase, UntaggedPointerBase, data_field, Dynamic, FINAL)              \
   V(TypeArguments, UntaggedTypeArguments, length, Smi, FINAL_COMPRESSED)       \
+  V(TypeParameters, UntaggedTypeParameters, names, Array, FINAL_COMPRESSED)    \
   V(TypeParameter, UntaggedTypeParameter, bound, Dynamic, FINAL_COMPRESSED)    \
-  V(TypeParameter, UntaggedTypeParameter, name, Dynamic, FINAL_COMPRESSED)     \
   V(UnhandledException, UntaggedUnhandledException, exception, Dynamic,        \
     FINAL_COMPRESSED)                                                          \
   V(UnhandledException, UntaggedUnhandledException, stacktrace, Dynamic,       \
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
index b75d8cb..572e967 100644
--- a/runtime/vm/compiler/frontend/constant_reader.cc
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -10,6 +10,10 @@
 #define Z (zone_)
 #define H (translation_helper_)
 
+// Note: If changing how the constants are saved in the binary (and thus how
+// they are read here) be aware that there's also some reading going on in
+// KernelLoader::ReadVMAnnotations which then also has to be updated!
+
 ConstantReader::ConstantReader(KernelReaderHelper* helper,
                                ActiveClass* active_class)
     : helper_(helper),
@@ -70,7 +74,7 @@
   return H.Canonicalize(metadata_values);
 }
 
-InstancePtr ConstantReader::ReadConstant(intptr_t constant_offset) {
+InstancePtr ConstantReader::ReadConstant(intptr_t constant_index) {
   ASSERT(!H.constants().IsNull());
   ASSERT(!H.constants_table().IsNull());  // raw bytes
 
@@ -84,30 +88,30 @@
     SafepointMutexLocker ml(
         H.thread()->isolate_group()->kernel_constants_mutex());
     KernelConstantsMap constant_map(H.info().constants());
-    result_ ^= constant_map.GetOrNull(constant_offset);
+    result_ ^= constant_map.GetOrNull(constant_index);
     ASSERT(constant_map.Release().ptr() == H.info().constants());
   }
 
   // On miss, evaluate, and insert value.
   if (result_.IsNull()) {
     LeaveCompilerScope cs(H.thread());
-    result_ = ReadConstantInternal(constant_offset);
+    result_ = ReadConstantInternal(constant_index);
     SafepointMutexLocker ml(
         H.thread()->isolate_group()->kernel_constants_mutex());
     KernelConstantsMap constant_map(H.info().constants());
-    auto insert = constant_map.InsertNewOrGetValue(constant_offset, result_);
+    auto insert = constant_map.InsertNewOrGetValue(constant_index, result_);
     ASSERT(insert == result_.ptr());
     H.info().set_constants(constant_map.Release());  // update!
   }
   return result_.ptr();
 }
 
-bool ConstantReader::IsInstanceConstant(intptr_t constant_offset,
+bool ConstantReader::IsInstanceConstant(intptr_t constant_index,
                                         const Class& clazz) {
-  // Get reader directly into raw bytes of constant table.
+  // Get reader directly into raw bytes of constant table/constant mapping.
   KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
-  reader.ReadUInt();  // skip variable-sized int for adjusted constant offset
-  reader.SetOffset(reader.ReaderOffset() + constant_offset);
+  NavigateToIndex(&reader, constant_index);
+
   // Peek for an instance of the given clazz.
   if (reader.ReadByte() == kInstanceConstant) {
     const NameIndex index = reader.ReadCanonicalNameReference();
@@ -116,12 +120,29 @@
   return false;
 }
 
-InstancePtr ConstantReader::ReadConstantInternal(intptr_t constant_offset) {
-  // Get reader directly into raw bytes of constant table.
+intptr_t ConstantReader::NavigateToIndex(KernelReaderHelper* reader,
+                                         intptr_t constant_index) {
+  // Get reader directly into raw bytes of constant table/constant mapping.
+  // Get the length of the constants (at the end of the mapping).
+  reader->SetOffset(reader->ReaderSize() - 4);
+  const intptr_t num_constants = reader->ReadUInt32();
+
+  // Get the binary offset of the constant at the wanted index.
+  reader->SetOffset(reader->ReaderSize() - 4 - (num_constants * 4) +
+                    (constant_index * 4));
+  const intptr_t constant_offset = reader->ReadUInt32();
+
+  reader->SetOffset(constant_offset);
+
+  return constant_offset;
+}
+
+InstancePtr ConstantReader::ReadConstantInternal(intptr_t constant_index) {
+  // Get reader directly into raw bytes of constant table/constant mapping.
   bool null_safety = H.thread()->isolate_group()->null_safety();
   KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
-  reader.ReadUInt();  // skip variable-sized int for adjusted constant offset
-  reader.SetOffset(reader.ReaderOffset() + constant_offset);
+  const intptr_t constant_offset = NavigateToIndex(&reader, constant_index);
+
   // No function types returned as part of any types built should reference
   // free parent type args, ensured by clearing the enclosing function type.
   ActiveEnclosingFunctionScope scope(active_class_, nullptr);
@@ -221,9 +242,9 @@
       for (intptr_t j = 0; j < length; ++j) {
         // Recurse into lazily evaluating all "sub" constants
         // needed to evaluate the current constant.
-        const intptr_t entry_offset = reader.ReadUInt();
-        ASSERT(entry_offset < constant_offset);  // DAG!
-        constant = ReadConstant(entry_offset);
+        const intptr_t entry_index = reader.ReadUInt();
+        ASSERT(entry_index < constant_offset);  // DAG!
+        constant = ReadConstant(entry_index);
         array.SetAt(j, constant);
       }
       instance = array.ptr();
@@ -273,9 +294,9 @@
             reader.ReadCanonicalNameReference());
         // Recurse into lazily evaluating all "sub" constants
         // needed to evaluate the current constant.
-        const intptr_t entry_offset = reader.ReadUInt();
-        ASSERT(entry_offset < constant_offset);  // DAG!
-        constant = ReadConstant(entry_offset);
+        const intptr_t entry_index = reader.ReadUInt();
+        ASSERT(entry_index < constant_offset);  // DAG!
+        constant = ReadConstant(entry_index);
         instance.SetField(field, constant);
       }
       break;
@@ -283,9 +304,9 @@
     case kPartialInstantiationConstant: {
       // Recurse into lazily evaluating the "sub" constant
       // needed to evaluate the current constant.
-      const intptr_t entry_offset = reader.ReadUInt();
-      ASSERT(entry_offset < constant_offset);  // DAG!
-      const auto& constant = Instance::Handle(Z, ReadConstant(entry_offset));
+      const intptr_t entry_index = reader.ReadUInt();
+      ASSERT(entry_index < constant_offset);  // DAG!
+      const auto& constant = Instance::Handle(Z, ReadConstant(entry_index));
       ASSERT(!constant.IsNull());
 
       // Build type from the raw bytes (needs temporary translator).
diff --git a/runtime/vm/compiler/frontend/constant_reader.h b/runtime/vm/compiler/frontend/constant_reader.h
index 94e8b3b..bb65f68 100644
--- a/runtime/vm/compiler/frontend/constant_reader.h
+++ b/runtime/vm/compiler/frontend/constant_reader.h
@@ -27,16 +27,17 @@
   InstancePtr ReadConstantExpression();
   ObjectPtr ReadAnnotations();
 
-  // Peeks to see if constant at the given offset will evaluate to
+  // Peeks to see if constant at the given index will evaluate to
   // instance of the given clazz.
-  bool IsInstanceConstant(intptr_t constant_offset, const Class& clazz);
+  bool IsInstanceConstant(intptr_t constant_index, const Class& clazz);
 
-  // Reads a constant at the given offset (possibly by recursing
+  // Reads a constant at the given index (possibly by recursing
   // into sub-constants).
-  InstancePtr ReadConstant(intptr_t constant_offset);
+  InstancePtr ReadConstant(intptr_t constant_index);
 
  private:
-  InstancePtr ReadConstantInternal(intptr_t constant_offset);
+  InstancePtr ReadConstantInternal(intptr_t constant_index);
+  intptr_t NavigateToIndex(KernelReaderHelper* reader, intptr_t constant_index);
 
   KernelReaderHelper* helper_;
   Zone* zone_;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 583f59b..123a0a2 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -3760,9 +3760,9 @@
     SkipDartType();
   }
   if (position != nullptr) *position = p;
-  const intptr_t constant_offset = ReadUInt();
+  const intptr_t constant_index = ReadUInt();
   Fragment result = Constant(
-      Object::ZoneHandle(Z, constant_reader_.ReadConstant(constant_offset)));
+      Object::ZoneHandle(Z, constant_reader_.ReadConstant(constant_index)));
   return result;
 }
 
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 3d4e86f..49b36d8 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1387,14 +1387,12 @@
         ASSERT(class_table->HasValidClassAt(kFfiPointerCid));
         const auto& pointer_class =
             Class::ZoneHandle(H.zone(), class_table->At(kFfiPointerCid));
-        const auto& pointer_type_args =
-            TypeArguments::Handle(pointer_class.type_parameters());
-        const auto& pointer_type_arg =
-            AbstractType::ZoneHandle(pointer_type_args.TypeAt(0));
+        const auto& pointer_type_param =
+            TypeParameter::ZoneHandle(pointer_class.TypeParameterAt(0));
 
         // But we type check it as a method on a generic class at runtime.
-        body += LoadLocal(arg_value);        // value.
-        body += Constant(pointer_type_arg);  // dst_type.
+        body += LoadLocal(arg_value);          // value.
+        body += Constant(pointer_type_param);  // dst_type.
         // We pass the Pointer type argument as instantiator_type_args.
         //
         // Call sites to this recognized method are guaranteed to pass a
@@ -1767,26 +1765,27 @@
     ASSERT(!forwarding_target->IsNull());
   }
 
-  TypeArguments& type_parameters = TypeArguments::Handle(Z);
+  TypeParameters& type_parameters = TypeParameters::Handle(Z);
   if (dart_function.IsFactory()) {
     type_parameters = Class::Handle(Z, dart_function.Owner()).type_parameters();
   } else {
     type_parameters = dart_function.type_parameters();
   }
-  intptr_t num_type_params = type_parameters.Length();
+  const intptr_t num_type_params = type_parameters.Length();
+  if (num_type_params == 0) return;
   if (forwarding_target != nullptr) {
     type_parameters = forwarding_target->type_parameters();
     ASSERT(type_parameters.Length() == num_type_params);
   }
-
+  if (type_parameters.AllDynamicBounds()) {
+    return;  // All bounds are dynamic.
+  }
   TypeParameter& type_param = TypeParameter::Handle(Z);
   String& name = String::Handle(Z);
   AbstractType& bound = AbstractType::Handle(Z);
   Fragment check_bounds;
   for (intptr_t i = 0; i < num_type_params; ++i) {
-    type_param ^= type_parameters.TypeAt(i);
-
-    bound = type_param.bound();
+    bound = type_parameters.BoundAt(i);
     if (bound.IsTopTypeForSubtyping()) {
       continue;
     }
@@ -1795,19 +1794,26 @@
       case TypeChecksToBuild::kCheckAllTypeParameterBounds:
         break;
       case TypeChecksToBuild::kCheckCovariantTypeParameterBounds:
-        if (!type_param.IsGenericCovariantImpl()) {
+        if (!type_parameters.IsGenericCovariantImplAt(i)) {
           continue;
         }
         break;
       case TypeChecksToBuild::kCheckNonCovariantTypeParameterBounds:
-        if (type_param.IsGenericCovariantImpl()) {
+        if (type_parameters.IsGenericCovariantImplAt(i)) {
           continue;
         }
         break;
     }
 
-    name = type_param.name();
+    name = type_parameters.NameAt(i);
 
+    if (forwarding_target != nullptr) {
+      type_param = forwarding_target->TypeParameterAt(i);
+    } else if (dart_function.IsFactory()) {
+      type_param = Class::Handle(Z, dart_function.Owner()).TypeParameterAt(i);
+    } else {
+      type_param = dart_function.TypeParameterAt(i);
+    }
     ASSERT(type_param.IsFinalized());
     check_bounds +=
         AssertSubtype(TokenPosition::kNoSource, type_param, bound, name);
@@ -2076,8 +2082,8 @@
   const ArgumentsDescriptor descriptor;
   ParsedFunction::DynamicClosureCallVars* const vars;
 
-  // Set up by BuildDynamicCallChecks() when needed. These values are
-  // read-only, so they don't need real local variables and are created
+  // Set up by BuildClosureCallDefaultTypeHandling() when needed. These values
+  // are read-only, so they don't need real local variables and are created
   // using MakeTemporary().
   LocalVariable* signature = nullptr;
   LocalVariable* num_fixed_params = nullptr;
@@ -2087,8 +2093,11 @@
   LocalVariable* parameter_names = nullptr;
   LocalVariable* parameter_types = nullptr;
   LocalVariable* type_parameters = nullptr;
+  LocalVariable* num_type_parameters = nullptr;
+  LocalVariable* type_parameter_flags = nullptr;
   LocalVariable* instantiator_type_args = nullptr;
   LocalVariable* parent_function_type_args = nullptr;
+  LocalVariable* num_parent_type_args = nullptr;
 };
 
 Fragment FlowGraphBuilder::TestClosureFunctionGeneric(
@@ -2239,8 +2248,8 @@
   store_default += BranchIfEqual(&can_share_instantiator, &can_share_function);
 
   Fragment instantiated(is_instantiated);
-  instantiated += LoadLocal(closure_data);
-  instantiated += LoadNativeField(Slot::ClosureData_default_type_arguments());
+  instantiated += LoadLocal(info.type_parameters);
+  instantiated += LoadNativeField(Slot::TypeParameters_defaults());
   instantiated += StoreLocal(info.vars->function_type_args);
   instantiated += Drop();
   instantiated += Goto(done);
@@ -2252,9 +2261,8 @@
   // can be used within the defaults).
   do_instantiation += LoadLocal(info.parent_function_type_args);
   // Load the default type arguments to instantiate.
-  do_instantiation += LoadLocal(closure_data);
-  do_instantiation +=
-      LoadNativeField(Slot::ClosureData_default_type_arguments());
+  do_instantiation += LoadLocal(info.type_parameters);
+  do_instantiation += LoadNativeField(Slot::TypeParameters_defaults());
   do_instantiation += InstantiateDynamicTypeArguments();
   do_instantiation += StoreLocal(info.vars->function_type_args);
   do_instantiation += Drop();
@@ -2433,7 +2441,8 @@
     check_type_args_length += BranchIfNull(&null, &not_null);
     check_type_args_length.current = not_null;  // Continue in non-error case.
     check_type_args_length += LoadLocal(info.type_parameters);
-    check_type_args_length += LoadNativeField(Slot::TypeArguments_length());
+    check_type_args_length += LoadNativeField(Slot::TypeParameters_names());
+    check_type_args_length += LoadNativeField(Slot::Array_length());
     check_type_args_length += IntConstant(info.descriptor.TypeArgsLen());
     TargetEntryInstr *equal, *not_equal;
     check_type_args_length += BranchIfEqual(&equal, &not_equal);
@@ -2522,6 +2531,16 @@
   // We assume that the value stored in :t_type_parameters is not null (i.e.,
   // the function stored in :t_function is generic).
   Fragment loop_init;
+
+  // A null bounds vector represents a vector of dynamic and no check is needed.
+  loop_init += LoadLocal(info.type_parameters);
+  loop_init += LoadNativeField(Slot::TypeParameters_bounds());
+  TargetEntryInstr *null_bounds, *non_null_bounds;
+  loop_init += BranchIfNull(&null_bounds, &non_null_bounds);
+
+  Fragment(null_bounds) + Goto(done);
+
+  loop_init.current = non_null_bounds;
   // Loop over the type parameters array.
   loop_init += IntConstant(0);
   loop_init += StoreLocal(info.vars->current_param_index);
@@ -2530,54 +2549,93 @@
 
   Fragment loop_check(loop);
   loop_check += LoadLocal(info.vars->current_param_index);
-  loop_check += LoadLocal(info.type_parameters);
-  loop_check += LoadNativeField(Slot::TypeArguments_length());
+  loop_check += LoadLocal(info.num_type_parameters);
   loop_check += SmiRelationalOp(Token::kLT);
   TargetEntryInstr *more, *no_more;
   loop_check += BranchIfTrue(&more, &no_more);
 
   Fragment(no_more) + Goto(done);
 
-  Fragment loop_body(more);
-  loop_body += LoadLocal(info.type_parameters);
-  loop_body += LoadLocal(info.vars->current_param_index);
-  loop_body += LoadIndexed(
-      kTypeArgumentsCid, /*index_scale*/ compiler::target::kCompressedWordSize);
-  LocalVariable* current_param = MakeTemporary("current_param");  // Read-only.
-
-  // One read-only local variable on stack (param) to drop after joining.
+  Fragment loop_test_flag(more);
   JoinEntryInstr* next = BuildJoinEntry();
+  JoinEntryInstr* check = BuildJoinEntry();
+  loop_test_flag += LoadLocal(info.type_parameter_flags);
+  TargetEntryInstr *null_flags, *non_null_flags;
+  loop_test_flag += BranchIfNull(&null_flags, &non_null_flags);
 
-  loop_body += LoadLocal(current_param);
-  loop_body += LoadNativeField(Slot::TypeParameter_flags());
-  loop_body += Box(kUnboxedUint8);
-  loop_body += IntConstant(
-      UntaggedTypeParameter::GenericCovariantImplBit::mask_in_place());
-  loop_body += SmiBinaryOp(Token::kBIT_AND);
-  loop_body += IntConstant(0);
+  Fragment(null_flags) + Goto(check);  // Check type if null (non-covariant).
+
+  loop_test_flag.current = non_null_flags;  // Test flags if not null.
+  loop_test_flag += LoadLocal(info.type_parameter_flags);
+  loop_test_flag += LoadLocal(info.vars->current_param_index);
+  loop_test_flag += IntConstant(TypeParameters::kFlagsPerSmiShift);
+  loop_test_flag += SmiBinaryOp(Token::kSHR);
+  loop_test_flag += LoadIndexed(kArrayCid);
+  loop_test_flag += LoadLocal(info.vars->current_param_index);
+  loop_test_flag += IntConstant(TypeParameters::kFlagsPerSmiMask);
+  loop_test_flag += SmiBinaryOp(Token::kBIT_AND);
+  loop_test_flag += SmiBinaryOp(Token::kSHR);
+  loop_test_flag += IntConstant(1);
+  loop_test_flag += SmiBinaryOp(Token::kBIT_AND);
+  loop_test_flag += IntConstant(0);
   TargetEntryInstr *is_noncovariant, *is_covariant;
-  loop_body += BranchIfEqual(&is_noncovariant, &is_covariant);
+  loop_test_flag += BranchIfEqual(&is_noncovariant, &is_covariant);
 
   Fragment(is_covariant) + Goto(next);  // Continue if covariant.
+  Fragment(is_noncovariant) + Goto(check);  // Check type if non-covariant.
 
-  loop_body.current = is_noncovariant;  // Type check if non-covariant.
-  loop_body += LoadLocal(info.instantiator_type_args);
-  loop_body += LoadLocal(info.vars->function_type_args);
-  // Load parameter.
-  loop_body += LoadLocal(current_param);
-  // Load bounds from parameter.
-  loop_body += LoadLocal(current_param);
-  loop_body += LoadNativeField(Slot::TypeParameter_bound());
-  // Load name from parameter.
-  loop_body += LoadLocal(current_param);
-  loop_body += LoadNativeField(Slot::TypeParameter_name());
-  // Assert that the type the parameter is instantiated as is consistent with
-  // the bounds of the parameter.
-  loop_body += AssertSubtype(TokenPosition::kNoSource);
-  loop_body += Goto(next);
+  Fragment loop_prep_type_param(check);
+  JoinEntryInstr* dynamic_type_param = BuildJoinEntry();
+  JoinEntryInstr* call = BuildJoinEntry();
+
+  // Load type argument already stored in function_type_args if non null.
+  loop_prep_type_param += LoadLocal(info.vars->function_type_args);
+  TargetEntryInstr *null_ftav, *non_null_ftav;
+  loop_prep_type_param += BranchIfNull(&null_ftav, &non_null_ftav);
+
+  Fragment(null_ftav) + Goto(dynamic_type_param);
+
+  loop_prep_type_param.current = non_null_ftav;
+  loop_prep_type_param += LoadLocal(info.vars->function_type_args);
+  loop_prep_type_param += LoadLocal(info.vars->current_param_index);
+  loop_prep_type_param += LoadLocal(info.num_parent_type_args);
+  loop_prep_type_param += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
+  loop_prep_type_param += LoadIndexed(
+      kTypeArgumentsCid, /*index_scale*/ compiler::target::kCompressedWordSize);
+  loop_prep_type_param += StoreLocal(info.vars->current_type_param);
+  loop_prep_type_param += Drop();
+  loop_prep_type_param += Goto(call);
+
+  Fragment loop_dynamic_type_param(dynamic_type_param);
+  // If function_type_args is null, the instantiated type param is dynamic.
+  loop_dynamic_type_param += Constant(Type::ZoneHandle(Type::DynamicType()));
+  loop_dynamic_type_param += StoreLocal(info.vars->current_type_param);
+  loop_dynamic_type_param += Drop();
+  loop_dynamic_type_param += Goto(call);
+
+  Fragment loop_call_check(call);
+  // Load instantiators.
+  loop_call_check += LoadLocal(info.instantiator_type_args);
+  loop_call_check += LoadLocal(info.vars->function_type_args);
+  // Load instantiated type parameter.
+  loop_call_check += LoadLocal(info.vars->current_type_param);
+  // Load bound from type parameters.
+  loop_call_check += LoadLocal(info.type_parameters);
+  loop_call_check += LoadNativeField(Slot::TypeParameters_bounds());
+  loop_call_check += LoadLocal(info.vars->current_param_index);
+  loop_call_check += LoadIndexed(
+      kTypeArgumentsCid, /*index_scale*/ compiler::target::kCompressedWordSize);
+  // Load (canonicalized) name of type parameter in signature.
+  loop_call_check += LoadLocal(info.type_parameters);
+  loop_call_check += LoadNativeField(Slot::TypeParameters_names());
+  loop_call_check += LoadLocal(info.vars->current_param_index);
+  loop_call_check += LoadIndexed(kArrayCid);
+  // Assert that the passed-in type argument is consistent with the bound of
+  // the corresponding type parameter.
+  loop_call_check += AssertSubtype(TokenPosition::kNoSource);
+  loop_call_check += Goto(next);
 
   Fragment loop_incr(next);
-  loop_incr += DropTemporary(&current_param);
   loop_incr += LoadLocal(info.vars->current_param_index);
   loop_incr += IntConstant(1);
   loop_incr += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
@@ -2717,23 +2775,38 @@
   // full set of function type arguments, then check the local function type
   // arguments against the closure function's type parameter bounds.
   Fragment generic;
+  // Calculate the number of parent type arguments and store them in
+  // info.num_parent_type_args.
+  generic += LoadLocal(info.signature);
+  generic += BuildExtractUnboxedSlotBitFieldIntoSmi<
+      UntaggedFunctionType::PackedNumParentTypeArguments>(
+      Slot::FunctionType_packed_fields());
+  info.num_parent_type_args = MakeTemporary("num_parent_type_args");
+
+  // Hoist number of type parameters.
+  generic += LoadLocal(info.type_parameters);
+  generic += LoadNativeField(Slot::TypeParameters_names());
+  generic += LoadNativeField(Slot::Array_length());
+  info.num_type_parameters = MakeTemporary("num_type_parameters");
+
+  // Hoist type parameter flags.
+  generic += LoadLocal(info.type_parameters);
+  generic += LoadNativeField(Slot::TypeParameters_flags());
+  info.type_parameter_flags = MakeTemporary("type_parameter_flags");
+
   // Calculate the local function type arguments and store them in
   // info.vars->function_type_args.
   generic += BuildClosureCallDefaultTypeHandling(info);
+
   // Load the local function type args.
   generic += LoadLocal(info.vars->function_type_args);
   // Load the parent function type args.
   generic += LoadLocal(info.parent_function_type_args);
   // Load the number of parent type parameters.
-  generic += LoadLocal(info.signature);
-  generic += BuildExtractUnboxedSlotBitFieldIntoSmi<
-      UntaggedFunctionType::PackedNumParentTypeArguments>(
-      Slot::FunctionType_packed_fields());
+  generic += LoadLocal(info.num_parent_type_args);
   // Load the number of total type parameters.
-  LocalVariable* num_parents = MakeTemporary();
-  generic += LoadLocal(info.type_parameters);
-  generic += LoadNativeField(Slot::TypeArguments_length());
-  generic += LoadLocal(num_parents);
+  generic += LoadLocal(info.num_parent_type_args);
+  generic += LoadLocal(info.num_type_parameters);
   generic += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
 
   // Call the static function for prepending type arguments.
@@ -2753,6 +2826,9 @@
   } else {
     generic += check_bounds;
   }
+  generic += DropTemporary(&info.type_parameter_flags);
+  generic += DropTemporary(&info.num_type_parameters);
+  generic += DropTemporary(&info.num_parent_type_args);
 
   // Call the appropriate fragment for setting up the function type arguments
   // and performing any needed type argument checking.
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 5808db3..f1db2d4 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -710,7 +710,18 @@
     type = klass.DeclarationType();
   } else {
     // Note that the type argument vector is not yet extended.
-    type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()));
+    TypeArguments& type_args = TypeArguments::Handle(Z);
+    const intptr_t num_type_params = klass.NumTypeParameters();
+    if (num_type_params > 0) {
+      type_args = TypeArguments::New(num_type_params);
+      TypeParameter& type_param = TypeParameter::Handle();
+      for (intptr_t i = 0; i < num_type_params; i++) {
+        type_param = klass.TypeParameterAt(i);
+        ASSERT(type_param.bound() != AbstractType::null());
+        type_args.SetTypeAt(i, type_param);
+      }
+    }
+    type = Type::New(klass, type_args, Nullability::kNonNullable);
   }
   return type;
 }
@@ -1717,10 +1728,10 @@
 
   const Object* constant_value = &Object::null_object();
   if ((flags & InferredTypeMetadata::kFlagConstant) != 0) {
-    const intptr_t constant_offset = helper_->ReadUInt();
+    const intptr_t constant_index = helper_->ReadUInt();
     if (read_constant) {
       constant_value = &Object::ZoneHandle(
-          H.zone(), constant_reader_->ReadConstant(constant_offset));
+          H.zone(), constant_reader_->ReadConstant(constant_index));
     }
   }
 
@@ -1958,6 +1969,10 @@
   return reader_.offset();
 }
 
+intptr_t KernelReaderHelper::ReaderSize() const {
+  return reader_.size();
+}
+
 void KernelReaderHelper::SetOffset(intptr_t offset) {
   reader_.set_offset(offset);
 }
@@ -2713,17 +2728,13 @@
   return position;
 }
 
-intptr_t KernelReaderHelper::SourceTableFieldCountFromFirstLibraryOffset() {
-  return SourceTableFieldCountFromFirstLibraryOffset41Plus;
-}
-
 intptr_t KernelReaderHelper::SourceTableSize() {
   AlternativeReadingScope alt(&reader_);
   intptr_t library_count = reader_.ReadFromIndexNoReset(
       reader_.size(), LibraryCountFieldCountFromEnd, 1, 0);
 
   const intptr_t count_from_first_library_offset =
-      SourceTableFieldCountFromFirstLibraryOffset();
+      SourceTableFieldCountFromFirstLibraryOffset;
 
   intptr_t source_table_offset = reader_.ReadFromIndexNoReset(
       reader_.size(),
@@ -2740,7 +2751,7 @@
       reader_.size(), LibraryCountFieldCountFromEnd, 1, 0);
 
   const intptr_t count_from_first_library_offset =
-      SourceTableFieldCountFromFirstLibraryOffset();
+      SourceTableFieldCountFromFirstLibraryOffset;
 
   intptr_t source_table_offset = reader_.ReadFromIndexNoReset(
       reader_.size(),
@@ -2835,19 +2846,13 @@
 intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) {
   ASSERT(member != NULL);
   if (member->IsFactory()) {
-    TypeArguments& class_types =
-        TypeArguments::Handle(zone, klass->type_parameters());
-    return class_types.Length();
+    return klass->NumTypeParameters();
   } else if (member->IsMethodExtractor()) {
     Function& extracted =
         Function::Handle(zone, member->extracted_method_closure());
-    TypeArguments& function_types =
-        TypeArguments::Handle(zone, extracted.type_parameters());
-    return function_types.Length();
+    return extracted.NumTypeParameters();
   } else {
-    TypeArguments& function_types =
-        TypeArguments::Handle(zone, member->type_parameters());
-    return function_types.Length();
+    return member->NumTypeParameters();
   }
 }
 
@@ -2856,17 +2861,15 @@
     const Function& innermost,
     const FunctionType* innermost_signature,
     Zone* Z)
-    : active_class_(active_class), saved_(*active_class) {
+    : active_class_(active_class), saved_(*active_class), zone_(Z) {
   active_class_->enclosing = innermost_signature;
 
   intptr_t num_params = 0;
 
   Function& f = Function::Handle(Z);
-  TypeArguments& f_params = TypeArguments::Handle(Z);
   for (f = innermost.ptr(); f.parent_function() != Object::null();
        f = f.parent_function()) {
-    f_params = f.type_parameters();
-    num_params += f_params.Length();
+    num_params += f.NumTypeParameters();
   }
   if (num_params == 0) return;
 
@@ -2876,9 +2879,10 @@
   intptr_t index = num_params;
   for (f = innermost.ptr(); f.parent_function() != Object::null();
        f = f.parent_function()) {
-    f_params = f.type_parameters();
-    for (intptr_t j = f_params.Length() - 1; j >= 0; --j) {
-      params.SetTypeAt(--index, AbstractType::Handle(Z, f_params.TypeAt(j)));
+    for (intptr_t j = f.NumTypeParameters() - 1; j >= 0; --j) {
+      const auto& type_param = TypeParameter::Handle(Z, f.TypeParameterAt(j));
+      params.SetTypeAt(--index, type_param);
+      active_class_->RecordDerivedTypeParameter(Z, type_param);
     }
   }
 
@@ -2888,32 +2892,55 @@
 ActiveTypeParametersScope::ActiveTypeParametersScope(
     ActiveClass* active_class,
     const FunctionType* innermost_signature,
-    const TypeArguments& new_params,
     Zone* Z)
-    : active_class_(active_class), saved_(*active_class) {
+    : active_class_(active_class), saved_(*active_class), zone_(Z) {
   active_class_->enclosing = innermost_signature;
 
-  if (new_params.IsNull()) return;
+  const intptr_t num_new_params =
+      innermost_signature == nullptr ? active_class->klass->NumTypeParameters()
+                                     : innermost_signature->NumTypeParameters();
+  if (num_new_params == 0) return;
 
   const TypeArguments* old_params = active_class->local_type_parameters;
   const intptr_t old_param_count =
       old_params == NULL ? 0 : old_params->Length();
   const TypeArguments& extended_params = TypeArguments::Handle(
-      Z, TypeArguments::New(old_param_count + new_params.Length()));
+      Z, TypeArguments::New(old_param_count + num_new_params));
 
   intptr_t index = 0;
   for (intptr_t i = 0; i < old_param_count; ++i) {
-    extended_params.SetTypeAt(
-        index++, AbstractType::ZoneHandle(Z, old_params->TypeAt(i)));
+    extended_params.SetTypeAt(index++,
+                              AbstractType::Handle(Z, old_params->TypeAt(i)));
   }
-  for (intptr_t i = 0; i < new_params.Length(); ++i) {
-    extended_params.SetTypeAt(
-        index++, AbstractType::ZoneHandle(Z, new_params.TypeAt(i)));
+  for (intptr_t i = 0; i < num_new_params; ++i) {
+    const auto& type_param =
+        TypeParameter::Handle(Z, innermost_signature == nullptr
+                                     ? active_class->klass->TypeParameterAt(i)
+                                     : innermost_signature->TypeParameterAt(i));
+    extended_params.SetTypeAt(index++, type_param);
+    active_class->RecordDerivedTypeParameter(Z, type_param);
   }
 
   active_class_->local_type_parameters = &extended_params;
 }
 
+ActiveTypeParametersScope::~ActiveTypeParametersScope() {
+  GrowableObjectArray* dropped = active_class_->derived_type_parameters;
+  const bool preserve_unpatched =
+      dropped != nullptr && saved_.derived_type_parameters == nullptr;
+  *active_class_ = saved_;
+  if (preserve_unpatched) {
+    // Preserve still unpatched derived type parameters that would be dropped.
+    auto& derived = TypeParameter::Handle(Z);
+    for (intptr_t i = 0, n = dropped->Length(); i < n; ++i) {
+      derived ^= dropped->At(i);
+      if (derived.bound() == AbstractType::null()) {
+        active_class_->RecordDerivedTypeParameter(Z, derived);
+      }
+    }
+  }
+}
+
 TypeTranslator::TypeTranslator(KernelReaderHelper* helper,
                                ConstantReader* constant_reader,
                                ActiveClass* active_class,
@@ -3054,14 +3081,12 @@
 
   if (!simple) {
     type_parameter_count = helper_->ReadListLength();
-    LoadAndSetupTypeParameters(
-        active_class_, Object::null_function(), Object::null_class(), signature,
-        type_parameter_count, active_class_->klass->nnbd_mode());
+    LoadAndSetupTypeParameters(active_class_, Object::null_function(),
+                               Object::null_class(), signature,
+                               type_parameter_count);
   }
 
-  ActiveTypeParametersScope scope(
-      active_class_, &signature,
-      TypeArguments::Handle(Z, signature.type_parameters()), Z);
+  ActiveTypeParametersScope scope(active_class_, &signature, Z);
 
   if (!simple) {
     LoadAndSetupBounds(active_class_, Object::null_function(),
@@ -3149,19 +3174,16 @@
   // If the type is from a constant, the parameter index isn't offset by the
   // enclosing context.
   if (!in_constant_context_) {
-    const TypeArguments& class_types =
-        TypeArguments::Handle(Z, active_class_->klass->type_parameters());
-    if (parameter_index < class_types.Length()) {
-      // The index of the type parameter in [parameters] is
-      // the same index into the `klass->type_parameters()` array.
-      const auto& type_param =
-          TypeParameter::CheckedHandle(Z, class_types.TypeAt(parameter_index));
-      result_ = type_param.ToNullability(nullability, Heap::kOld);
-      active_class_->RecordDerivedTypeParameter(Z, type_param,
+    const intptr_t class_type_parameter_count =
+        active_class_->klass->NumTypeParameters();
+    if (class_type_parameter_count > parameter_index) {
+      result_ =
+          active_class_->klass->TypeParameterAt(parameter_index, nullability);
+      active_class_->RecordDerivedTypeParameter(Z,
                                                 TypeParameter::Cast(result_));
       return;
     }
-    parameter_index -= class_types.Length();
+    parameter_index -= class_type_parameter_count;
 
     if (active_class_->HasMember()) {
       if (active_class_->MemberIsFactoryProcedure()) {
@@ -3182,33 +3204,32 @@
         //     static A.x<T'>() { return new B<T'>(); }
         //   }
         //
-        if (class_types.Length() > parameter_index) {
-          const auto& type_param = TypeParameter::CheckedHandle(
-              Z, class_types.TypeAt(parameter_index));
-          result_ = type_param.ToNullability(nullability, Heap::kOld);
+        if (class_type_parameter_count > parameter_index) {
+          result_ = active_class_->klass->TypeParameterAt(parameter_index,
+                                                          nullability);
           active_class_->RecordDerivedTypeParameter(
-              Z, type_param, TypeParameter::Cast(result_));
+              Z, TypeParameter::Cast(result_));
           return;
         }
-        parameter_index -= class_types.Length();
+        parameter_index -= class_type_parameter_count;
       }
       // Factory function should not be considered as procedure.
-      intptr_t procedure_type_parameter_count =
+      const intptr_t procedure_type_parameter_count =
           (active_class_->MemberIsProcedure() &&
            !active_class_->MemberIsFactoryProcedure())
               ? active_class_->MemberTypeParameterCount(Z)
               : 0;
       if (procedure_type_parameter_count > 0) {
         if (procedure_type_parameter_count > parameter_index) {
-          const auto& type_param = TypeParameter::CheckedHandle(
-              Z,
-              TypeArguments::Handle(Z, active_class_->member->type_parameters())
-                  .TypeAt(parameter_index));
-          result_ = type_param.ToNullability(nullability, Heap::kOld);
-          active_class_->RecordDerivedTypeParameter(
-              Z, type_param, TypeParameter::Cast(result_));
+          result_ = active_class_->member->TypeParameterAt(parameter_index,
+                                                           nullability);
           if (finalize_) {
+            ASSERT(TypeParameter::Cast(result_).bound() !=
+                   AbstractType::null());
             result_ = ClassFinalizer::FinalizeType(result_);
+          } else {
+            active_class_->RecordDerivedTypeParameter(
+                Z, TypeParameter::Cast(result_));
           }
           return;
         }
@@ -3221,10 +3242,12 @@
       const auto& type_param = TypeParameter::CheckedHandle(
           Z, active_class_->local_type_parameters->TypeAt(parameter_index));
       result_ = type_param.ToNullability(nullability, Heap::kOld);
-      active_class_->RecordDerivedTypeParameter(Z, type_param,
-                                                TypeParameter::Cast(result_));
       if (finalize_) {
+        ASSERT(TypeParameter::Cast(result_).bound() != AbstractType::null());
         result_ = ClassFinalizer::FinalizeType(result_);
+      } else {
+        active_class_->RecordDerivedTypeParameter(Z,
+                                                  TypeParameter::Cast(result_));
       }
       return;
     }
@@ -3300,8 +3323,7 @@
     const Function& function,
     const Class& parameterized_class,
     const FunctionType& parameterized_signature,
-    intptr_t type_parameter_count,
-    const NNBDMode nnbd_mode) {
+    intptr_t type_parameter_count) {
   ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());
   ASSERT(type_parameter_count >= 0);
   if (type_parameter_count == 0) {
@@ -3317,23 +3339,18 @@
 
   // First setup the type parameters, so if any of the following code uses it
   // (in a recursive way) we're fine.
-  TypeArguments& type_parameters = TypeArguments::Handle(Z);
-  TypeParameter& parameter = TypeParameter::Handle(Z);
+
+  // - Create a [ TypeParameters ] object.
+  const TypeParameters& type_parameters =
+      TypeParameters::Handle(Z, TypeParameters::New(type_parameter_count));
   const Type& null_bound = Type::Handle(Z);
 
-  const Nullability nullability = (nnbd_mode == NNBDMode::kOptedInLib)
-                                      ? Nullability::kNonNullable
-                                      : Nullability::kLegacy;
-
-  // - Create array of [TypeParameter] objects (without bound).
-  // - Create array of [String] objects.
-  type_parameters = TypeArguments::New(type_parameter_count);
   intptr_t offset = 0;
   if (!parameterized_class.IsNull()) {
-    ASSERT(parameterized_class.type_parameters() == TypeArguments::null());
+    ASSERT(parameterized_class.type_parameters() == TypeParameters::null());
     parameterized_class.set_type_parameters(type_parameters);
   } else {
-    ASSERT(parameterized_signature.type_parameters() == TypeArguments::null());
+    ASSERT(parameterized_signature.type_parameters() == TypeParameters::null());
     parameterized_signature.set_type_parameters(type_parameters);
     offset = parameterized_signature.NumParentTypeArguments();
     if (!function.IsNull()) {
@@ -3344,22 +3361,15 @@
   const Library& lib = Library::Handle(Z, active_class->klass->library());
   {
     AlternativeReadingScope alt(&helper_->reader_);
-    String& name = String::Handle(Z);
     for (intptr_t i = 0; i < type_parameter_count; i++) {
       TypeParameterHelper helper(helper_);
       helper.Finish();
-      if (parameterized_class.IsNull() && function.IsNull()) {
-        // Erase provided name and use a canonical one instead.
-        name = Symbols::NewFormatted(H.thread(), "X%" Pd, offset + i);
-      } else {
-        name = H.DartIdentifier(lib, helper.name_index_).ptr();
-      }
+      type_parameters.SetNameAt(i, H.DartIdentifier(lib, helper.name_index_));
+      type_parameters.SetIsGenericCovariantImplAt(
+          i, helper.IsGenericCovariantImpl());
       // Bounds are filled later in LoadAndSetupBounds as bound types may
       // reference type parameters which are not created yet.
-      parameter = TypeParameter::New(
-          parameterized_class, offset, offset + i, name, null_bound,
-          helper.IsGenericCovariantImpl(), nullability);
-      type_parameters.SetTypeAt(i, parameter);
+      type_parameters.SetBoundAt(i, null_bound);
     }
   }
 }
@@ -3376,52 +3386,45 @@
     return;
   }
 
-  const TypeArguments& type_parameters =
-      TypeArguments::Handle(Z, !parameterized_class.IsNull()
-                                   ? parameterized_class.type_parameters()
-                                   : parameterized_signature.type_parameters());
-  TypeParameter& parameter = TypeParameter::Handle(Z);
+  const TypeParameters& type_parameters = TypeParameters::Handle(
+      Z, !parameterized_class.IsNull()
+             ? parameterized_class.type_parameters()
+             : parameterized_signature.type_parameters());
 
   // Fill in the bounds and default arguments of all [TypeParameter]s.
   for (intptr_t i = 0; i < type_parameter_count; i++) {
     TypeParameterHelper helper(helper_);
     helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
 
-    parameter ^= type_parameters.TypeAt(i);
     AbstractType& bound = BuildTypeWithoutFinalization();  // read ith bound.
-    parameter.set_bound(bound);
+    ASSERT(!bound.IsNull());
+    type_parameters.SetBoundAt(i, bound);
     helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kDefaultType);
     AbstractType& default_arg = BuildTypeWithoutFinalization();
-    parameter.set_default_argument(default_arg);
+    ASSERT(!default_arg.IsNull());
+    type_parameters.SetDefaultAt(i, default_arg);
     helper.Finish();
   }
 
-  // Note that function.UpdateCachedDefaultTypeArguments() is called in
-  // function.set_signature() and is not required here.
-
-  // Fix bounds and default arguments in all derived type parameters (with
-  // different nullabilities).
+  // Fix bounds in all derived type parameters.
   const intptr_t offset = !parameterized_signature.IsNull()
                               ? parameterized_signature.NumParentTypeArguments()
                               : 0;
   if (active_class->derived_type_parameters != nullptr) {
     auto& derived = TypeParameter::Handle(Z);
-    auto& type = AbstractType::Handle(Z);
+    auto& bound = AbstractType::Handle(Z);
     for (intptr_t i = 0, n = active_class->derived_type_parameters->Length();
          i < n; ++i) {
       derived ^= active_class->derived_type_parameters->At(i);
       if (derived.bound() == AbstractType::null() &&
           ((!parameterized_class.IsNull() &&
-            derived.parameterized_class() == parameterized_class.ptr()) ||
+            derived.parameterized_class_id() == parameterized_class.id()) ||
            (!parameterized_signature.IsNull() &&
-            derived.parameterized_class() == Class::null() &&
+            derived.parameterized_class_id() == kFunctionCid &&
             derived.index() >= offset &&
             derived.index() < offset + type_parameter_count))) {
-        parameter ^= type_parameters.TypeAt(derived.index() - offset);
-        type = parameter.bound();
-        derived.set_bound(type);
-        type = parameter.default_argument();
-        derived.set_default_argument(type);
+        bound = type_parameters.BoundAt(derived.index() - offset);
+        derived.set_bound(bound);
       }
     }
   }
@@ -3435,8 +3438,18 @@
   if (finalize_ || klass.is_type_finalized()) {
     type = klass.DeclarationType();
   } else {
-    type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
-                     Nullability::kNonNullable);
+    TypeArguments& type_args = TypeArguments::Handle(Z);
+    const intptr_t num_type_params = klass.NumTypeParameters();
+    if (num_type_params > 0) {
+      type_args = TypeArguments::New(num_type_params);
+      TypeParameter& type_param = TypeParameter::Handle();
+      for (intptr_t i = 0; i < num_type_params; i++) {
+        type_param = klass.TypeParameterAt(i);
+        ASSERT(type_param.bound() != AbstractType::null());
+        type_args.SetTypeAt(i, type_param);
+      }
+    }
+    type = Type::New(klass, type_args, Nullability::kNonNullable);
   }
   return type;
 }
@@ -3550,8 +3563,8 @@
   if (!is_factory) {
     type_parameter_count = helper_->ReadListLength();
     LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z),
-                               signature, type_parameter_count,
-                               function.nnbd_mode());
+                               signature, type_parameter_count);
+    function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
   }
 
   ActiveTypeParametersScope scope(active_class_, function, &signature, Z);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 64c5c8d..1bed607 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -1204,6 +1204,7 @@
   }
 
   intptr_t ReaderOffset() const;
+  intptr_t ReaderSize() const;
   void SkipBytes(intptr_t skip);
   bool ReadBool();
   uint8_t ReadByte();
@@ -1252,7 +1253,6 @@
   Nullability ReadNullability();
   Variance ReadVariance();
 
-  intptr_t SourceTableFieldCountFromFirstLibraryOffset();
   intptr_t SourceTableSize();
   intptr_t GetOffsetForSourceInfo(intptr_t index);
   String& SourceTableUriFor(intptr_t index);
@@ -1344,11 +1344,8 @@
     return klass->NumTypeArguments();
   }
 
-  void RecordDerivedTypeParameter(Zone* zone,
-                                  const TypeParameter& original,
-                                  const TypeParameter& derived) {
-    if (original.ptr() != derived.ptr() &&
-        original.bound() == AbstractType::null()) {
+  void RecordDerivedTypeParameter(Zone* zone, const TypeParameter& derived) {
+    if (derived.bound() == AbstractType::null()) {
       if (derived_type_parameters == nullptr) {
         derived_type_parameters = &GrowableObjectArray::Handle(
             zone, GrowableObjectArray::New(Heap::kOld));
@@ -1442,14 +1439,14 @@
   // Also, the enclosing signature is set to 'signature'.
   ActiveTypeParametersScope(ActiveClass* active_class,
                             const FunctionType* innermost_signature,
-                            const TypeArguments& new_params,
                             Zone* Z);
 
-  ~ActiveTypeParametersScope() { *active_class_ = saved_; }
+  ~ActiveTypeParametersScope();
 
  private:
   ActiveClass* active_class_;
   ActiveClass saved_;
+  Zone* zone_;
 
   DISALLOW_COPY_AND_ASSIGN(ActiveTypeParametersScope);
 };
@@ -1476,8 +1473,7 @@
                                   const Function& function,
                                   const Class& parameterized_class,
                                   const FunctionType& parameterized_signature,
-                                  intptr_t type_parameter_count,
-                                  const NNBDMode nnbd_mode);
+                                  intptr_t type_parameter_count);
 
   void LoadAndSetupBounds(ActiveClass* active_class,
                           const Function& function,
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index c84b23c..b3edbc9 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -1180,6 +1180,10 @@
   return -kWordSize;
 }
 
+word TypeParameters::NextFieldOffset() {
+  return -kWordSize;
+}
+
 word TypeArguments::NextFieldOffset() {
   return -kWordSize;
 }
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 6c7d6db..c8cbc06 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -922,7 +922,6 @@
  public:
   static word bound_offset();
   static word flags_offset();
-  static word name_offset();
   static word InstanceSize();
   static word NextFieldOffset();
   static word parameterized_class_id_offset();
@@ -1303,7 +1302,6 @@
 
 class ClosureData : public AllStatic {
  public:
-  static word default_type_arguments_offset();
   static word default_type_arguments_kind_offset();
   static word InstanceSize();
   static word NextFieldOffset();
@@ -1373,6 +1371,16 @@
   static word NextFieldOffset();
 };
 
+class TypeParameters : public AllStatic {
+ public:
+  static word names_offset();
+  static word flags_offset();
+  static word bounds_offset();
+  static word defaults_offset();
+  static word InstanceSize();
+  static word NextFieldOffset();
+};
+
 class TypeArguments : public AllStatic {
  public:
   static word instantiations_offset();
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index abe8cc9..653ef92 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -134,9 +134,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 16;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 20;
+    ClosureData_default_type_arguments_kind_offset = 16;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -429,19 +427,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 12;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 32;
+    TypeParameter_parameterized_class_id_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 23;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    35;
+    25;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     16;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 34;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 12;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 4;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 12;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    16;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 16;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
@@ -473,7 +475,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 112;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     8;
@@ -536,7 +538,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word Type_InstanceSize = 28;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 36;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 28;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 20;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_HeaderSize = 12;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
@@ -670,9 +673,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 32;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 32;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -970,19 +971,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 56;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 60;
+    TypeParameter_parameterized_class_id_offset = 40;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 43;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    63;
+    45;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 16;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     32;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 62;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 24;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 16;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 24;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    32;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
@@ -1015,7 +1020,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 192;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 48;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     16;
@@ -1079,7 +1084,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word Type_InstanceSize = 56;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 64;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 48;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -1211,9 +1217,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 16;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 20;
+    ClosureData_default_type_arguments_kind_offset = 16;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -1506,19 +1510,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 12;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 32;
+    TypeParameter_parameterized_class_id_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 23;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    35;
+    25;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     16;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 34;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 12;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 4;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 12;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    16;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 16;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
@@ -1547,7 +1555,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 112;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     8;
@@ -1610,7 +1618,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word Type_InstanceSize = 28;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 36;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 28;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 20;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_HeaderSize = 12;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
@@ -1744,9 +1753,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 32;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 32;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -2044,19 +2051,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 56;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 60;
+    TypeParameter_parameterized_class_id_offset = 40;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 43;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    63;
+    45;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 16;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     32;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 62;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 24;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 16;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 24;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    32;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
@@ -2090,7 +2101,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 192;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 48;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     16;
@@ -2154,7 +2165,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word Type_InstanceSize = 56;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 64;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 48;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -2286,9 +2298,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 20;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 24;
+    ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -2586,19 +2596,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 20;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 36;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 40;
+    TypeParameter_parameterized_class_id_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    43;
+    33;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     20;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 42;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 20;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 12;
+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;
@@ -2631,7 +2645,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 120;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 32;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     16;
@@ -2695,7 +2709,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word Type_InstanceSize = 40;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 48;
+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 TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -2827,9 +2842,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 20;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 24;
+    ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -3127,19 +3140,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 20;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 36;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 40;
+    TypeParameter_parameterized_class_id_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    43;
+    33;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     20;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 42;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 20;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 12;
+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;
@@ -3173,7 +3190,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 120;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 32;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     16;
@@ -3237,7 +3254,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word Type_InstanceSize = 40;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 48;
+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 TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -3366,9 +3384,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 16;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 20;
+    ClosureData_default_type_arguments_kind_offset = 16;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -3660,19 +3676,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 12;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 32;
+    TypeParameter_parameterized_class_id_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 23;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    35;
+    25;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     16;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 34;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 12;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 4;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 12;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    16;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 16;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
@@ -3704,7 +3724,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 108;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     8;
@@ -3767,7 +3787,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word Type_InstanceSize = 28;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 36;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 28;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 20;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_HeaderSize = 12;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
@@ -3896,9 +3917,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 32;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 32;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -4195,19 +4214,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 56;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 60;
+    TypeParameter_parameterized_class_id_offset = 40;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 43;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    63;
+    45;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 16;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     32;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 62;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 24;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 16;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 24;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    32;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
@@ -4240,7 +4263,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 184;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 48;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     16;
@@ -4304,7 +4327,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word Type_InstanceSize = 56;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 64;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 48;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -4431,9 +4455,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 16;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 20;
+    ClosureData_default_type_arguments_kind_offset = 16;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -4725,19 +4747,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 12;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 32;
+    TypeParameter_parameterized_class_id_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 23;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    35;
+    25;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     16;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 34;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 12;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 4;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 12;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    16;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 16;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
@@ -4766,7 +4792,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 108;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     8;
@@ -4829,7 +4855,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word Type_InstanceSize = 28;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 36;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 28;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 20;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_HeaderSize = 12;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
@@ -4958,9 +4985,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 32;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 32;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -5257,19 +5282,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 56;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 60;
+    TypeParameter_parameterized_class_id_offset = 40;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 43;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    63;
+    45;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 16;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     32;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 62;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 24;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 16;
+static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 24;
+static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
+    32;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
@@ -5303,7 +5332,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 184;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 48;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     16;
@@ -5367,7 +5396,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word Type_InstanceSize = 56;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 64;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 48;
+static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -5494,9 +5524,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 20;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 24;
+    ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -5793,19 +5821,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 20;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 36;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 40;
+    TypeParameter_parameterized_class_id_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    43;
+    33;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     20;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 42;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 20;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 12;
+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;
@@ -5838,7 +5870,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 112;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 32;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     16;
@@ -5902,7 +5934,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word Type_InstanceSize = 40;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 48;
+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 TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -6029,9 +6062,7 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 20;
-static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_kind_offset = 24;
+    ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -6328,19 +6359,23 @@
 static constexpr dart::compiler::target::word
     FunctionType_type_parameters_offset = 20;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 36;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 40;
+    TypeParameter_parameterized_class_id_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    43;
+    33;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
 static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
     20;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 42;
-static constexpr dart::compiler::target::word TypeParameter_name_offset = 20;
+static constexpr dart::compiler::target::word TypeParameters_names_offset = 8;
+static constexpr dart::compiler::target::word TypeParameters_flags_offset = 12;
+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;
@@ -6374,7 +6409,7 @@
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word Class_InstanceSize = 112;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 32;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     16;
@@ -6438,7 +6473,8 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word Type_InstanceSize = 40;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 48;
+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 TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -6580,9 +6616,7 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 16;
-static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_kind_offset = 20;
+    AOT_ClosureData_default_type_arguments_kind_offset = 16;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 24;
@@ -6908,11 +6942,11 @@
 static constexpr dart::compiler::target::word
     AOT_FunctionType_type_parameters_offset = 12;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 28;
+    AOT_TypeParameter_parameterized_class_id_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    32;
+    23;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 35;
+    AOT_TypeParameter_nullability_offset = 25;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -6921,12 +6955,18 @@
     AOT_TypeArguments_nullability_offset = 16;
 static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
     20;
-static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    20;
-static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    34;
-static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
     12;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 16;
+static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
+    24;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     8;
@@ -6961,7 +7001,7 @@
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 92;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 8;
@@ -7033,7 +7073,9 @@
     AOT_TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    36;
+    28;
+static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
+    20;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 12;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -7176,9 +7218,7 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 32;
-static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_kind_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 32;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -7505,11 +7545,11 @@
 static constexpr dart::compiler::target::word
     AOT_FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 56;
+    AOT_TypeParameter_parameterized_class_id_offset = 40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    60;
+    43;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 63;
+    AOT_TypeParameter_nullability_offset = 45;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -7518,12 +7558,18 @@
     AOT_TypeArguments_nullability_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
     40;
-static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    40;
-static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    62;
-static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
     24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
+    32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
+    44;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -7560,7 +7606,7 @@
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 160;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 16;
@@ -7632,7 +7678,9 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    64;
+    48;
+static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
+    40;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -7778,9 +7826,7 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 32;
-static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_kind_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 32;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -8107,11 +8153,11 @@
 static constexpr dart::compiler::target::word
     AOT_FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 56;
+    AOT_TypeParameter_parameterized_class_id_offset = 40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    60;
+    43;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 63;
+    AOT_TypeParameter_nullability_offset = 45;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -8120,12 +8166,18 @@
     AOT_TypeArguments_nullability_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
     40;
-static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    40;
-static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    62;
-static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
     24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
+    32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
+    44;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -8163,7 +8215,7 @@
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 160;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 16;
@@ -8235,7 +8287,9 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    64;
+    48;
+static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
+    40;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -8378,9 +8432,7 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 20;
-static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_kind_offset = 24;
+    AOT_ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -8707,11 +8759,11 @@
 static constexpr dart::compiler::target::word
     AOT_FunctionType_type_parameters_offset = 20;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 36;
+    AOT_TypeParameter_parameterized_class_id_offset = 28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    40;
+    31;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 43;
+    AOT_TypeParameter_nullability_offset = 33;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -8720,12 +8772,18 @@
     AOT_TypeArguments_nullability_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
     24;
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    28;
+    24;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    42;
-static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
-    20;
+    32;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -8762,7 +8820,7 @@
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 96;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 16;
@@ -8834,7 +8892,9 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    48;
+    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_TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -8977,9 +9037,7 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 20;
-static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_kind_offset = 24;
+    AOT_ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -9306,11 +9364,11 @@
 static constexpr dart::compiler::target::word
     AOT_FunctionType_type_parameters_offset = 20;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 36;
+    AOT_TypeParameter_parameterized_class_id_offset = 28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    40;
+    31;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 43;
+    AOT_TypeParameter_nullability_offset = 33;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -9319,12 +9377,18 @@
     AOT_TypeArguments_nullability_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
     24;
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    28;
+    24;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    42;
-static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
-    20;
+    32;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -9362,7 +9426,7 @@
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 96;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 16;
@@ -9434,7 +9498,9 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    48;
+    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_TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -9573,9 +9639,7 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 16;
-static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_kind_offset = 20;
+    AOT_ClosureData_default_type_arguments_kind_offset = 16;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 24;
@@ -9899,11 +9963,11 @@
 static constexpr dart::compiler::target::word
     AOT_FunctionType_type_parameters_offset = 12;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 28;
+    AOT_TypeParameter_parameterized_class_id_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    32;
+    23;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 35;
+    AOT_TypeParameter_nullability_offset = 25;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -9912,12 +9976,18 @@
     AOT_TypeArguments_nullability_offset = 16;
 static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
     20;
-static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    20;
-static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    34;
-static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
     12;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 16;
+static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
+    24;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     8;
@@ -9952,7 +10022,7 @@
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 8;
@@ -10024,7 +10094,9 @@
     AOT_TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    36;
+    28;
+static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
+    20;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 12;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -10162,9 +10234,7 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 32;
-static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_kind_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 32;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -10489,11 +10559,11 @@
 static constexpr dart::compiler::target::word
     AOT_FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 56;
+    AOT_TypeParameter_parameterized_class_id_offset = 40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    60;
+    43;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 63;
+    AOT_TypeParameter_nullability_offset = 45;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -10502,12 +10572,18 @@
     AOT_TypeArguments_nullability_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
     40;
-static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    40;
-static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    62;
-static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
     24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
+    32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
+    44;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -10544,7 +10620,7 @@
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 136;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 16;
@@ -10616,7 +10692,9 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    64;
+    48;
+static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
+    40;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -10757,9 +10835,7 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 32;
-static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_kind_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 32;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -11084,11 +11160,11 @@
 static constexpr dart::compiler::target::word
     AOT_FunctionType_type_parameters_offset = 24;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 56;
+    AOT_TypeParameter_parameterized_class_id_offset = 40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    60;
+    43;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 63;
+    AOT_TypeParameter_nullability_offset = 45;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -11097,12 +11173,18 @@
     AOT_TypeArguments_nullability_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
     40;
-static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    40;
-static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    62;
-static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
     24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
+    32;
+static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
+    44;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -11140,7 +11222,7 @@
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 136;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 16;
@@ -11212,7 +11294,9 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    64;
+    48;
+static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
+    40;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -11350,9 +11434,7 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 20;
-static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_kind_offset = 24;
+    AOT_ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -11677,11 +11759,11 @@
 static constexpr dart::compiler::target::word
     AOT_FunctionType_type_parameters_offset = 20;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 36;
+    AOT_TypeParameter_parameterized_class_id_offset = 28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    40;
+    31;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 43;
+    AOT_TypeParameter_nullability_offset = 33;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -11690,12 +11772,18 @@
     AOT_TypeArguments_nullability_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
     24;
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    28;
+    24;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    42;
-static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
-    20;
+    32;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -11732,7 +11820,7 @@
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 88;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 16;
@@ -11804,7 +11892,9 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    48;
+    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_TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -11942,9 +12032,7 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 20;
-static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_kind_offset = 24;
+    AOT_ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -12269,11 +12357,11 @@
 static constexpr dart::compiler::target::word
     AOT_FunctionType_type_parameters_offset = 20;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 36;
+    AOT_TypeParameter_parameterized_class_id_offset = 28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    40;
+    31;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 43;
+    AOT_TypeParameter_nullability_offset = 33;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -12282,12 +12370,18 @@
     AOT_TypeArguments_nullability_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeArguments_types_offset =
     24;
+static constexpr dart::compiler::target::word AOT_TypeParameters_names_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_TypeParameters_flags_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_TypeParameters_bounds_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameters_defaults_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
-    28;
+    24;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    42;
-static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
-    20;
+    32;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -12325,7 +12419,7 @@
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 88;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 32;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 16;
@@ -12397,7 +12491,9 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    48;
+    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_TypedData_HeaderSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index 75e1b54..0af1b9e 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -110,7 +110,6 @@
   FIELD(Closure, function_type_arguments_offset)                               \
   FIELD(Closure, hash_offset)                                                  \
   FIELD(Closure, instantiator_type_arguments_offset)                           \
-  FIELD(ClosureData, default_type_arguments_offset)                            \
   FIELD(ClosureData, default_type_arguments_kind_offset)                       \
   FIELD(Code, object_pool_offset)                                              \
   FIELD(Code, saved_instructions_offset)                                       \
@@ -301,9 +300,12 @@
   FIELD(TypeArguments, length_offset)                                          \
   FIELD(TypeArguments, nullability_offset)                                     \
   FIELD(TypeArguments, types_offset)                                           \
+  FIELD(TypeParameters, names_offset)                                          \
+  FIELD(TypeParameters, flags_offset)                                          \
+  FIELD(TypeParameters, bounds_offset)                                         \
+  FIELD(TypeParameters, defaults_offset)                                       \
   FIELD(TypeParameter, bound_offset)                                           \
   FIELD(TypeParameter, flags_offset)                                           \
-  FIELD(TypeParameter, name_offset)                                            \
   FIELD(TypeRef, type_offset)                                                  \
   FIELD(TypedDataBase, length_offset)                                          \
   FIELD(TypedDataView, data_offset)                                            \
@@ -384,6 +386,7 @@
   SIZEOF(TransferableTypedData, InstanceSize, UntaggedTransferableTypedData)   \
   SIZEOF(Type, InstanceSize, UntaggedType)                                     \
   SIZEOF(TypeParameter, InstanceSize, UntaggedTypeParameter)                   \
+  SIZEOF(TypeParameters, InstanceSize, UntaggedTypeParameters)                 \
   SIZEOF(TypeRef, InstanceSize, UntaggedTypeRef)                               \
   SIZEOF(TypedData, HeaderSize, UntaggedTypedData)                             \
   SIZEOF(TypedDataBase, InstanceSize, UntaggedTypedDataBase)                   \
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index 604aeaa..2b5f9b2 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -597,7 +597,8 @@
     // Resolve the type parameter to its instantiated type and tail call the
     // instantiated type's TTS.
     __ LoadFieldFromOffset(TypeTestABI::kScratchReg, TypeTestABI::kDstTypeReg,
-                           target::TypeParameter::index_offset(), kTwoBytes);
+                           target::TypeParameter::index_offset(),
+                           kUnsignedByte);
     __ LoadIndexedCompressed(TypeTestABI::kScratchReg, tav,
                              target::TypeArguments::types_offset(),
                              TypeTestABI::kScratchReg);
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 9fc8ea7..dc9d048 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -77,7 +77,7 @@
       requested_column_number_(requested_column_number),
       code_token_pos_(TokenPosition::kNoSource) {
   ASSERT(scripts.length() > 0);
-  ASSERT(token_pos_.IsReal());
+  ASSERT(token_pos.IsReal());
   for (intptr_t i = 0; i < scripts.length(); ++i) {
     scripts_.Add(scripts.At(i).ptr());
   }
@@ -134,8 +134,8 @@
   ASSERT(!IsLatent());
   ASSERT(token_pos.IsWithin(func.token_pos(), func.end_token_pos()));
   ASSERT(func.is_debuggable());
-  token_pos_ = token_pos;
-  end_token_pos_ = token_pos;
+  token_pos_.store(token_pos);
+  end_token_pos_.store(token_pos);
   code_token_pos_ = token_pos;
 }
 
@@ -1328,20 +1328,19 @@
     intptr_t num_vars = function().NumTypeArguments();
     type_params_names.Grow(num_vars);
     type_params_names.SetLength(num_vars);
-    TypeArguments& type_params = TypeArguments::Handle();
-    TypeParameter& type_param = TypeParameter::Handle();
+    TypeParameters& type_params = TypeParameters::Handle();
     Function& current = Function::Handle(function().ptr());
     intptr_t mapping_offset = num_vars;
     for (intptr_t i = 0; !current.IsNull(); i += current.NumTypeParameters(),
                   current = current.parent_function()) {
       type_params = current.type_parameters();
+      if (type_params.IsNull()) continue;
       intptr_t size = current.NumTypeParameters();
-      ASSERT(size == 0 || type_params.Length() == size);
+      ASSERT(size > 0 && type_params.Length() == size);
       ASSERT(mapping_offset >= size);
       mapping_offset -= size;
       for (intptr_t j = 0; j < size; ++j) {
-        type_param = TypeParameter::RawCast(type_params.TypeAt(j));
-        name = type_param.name();
+        name = type_params.NameAt(j);
         // Write the names in backwards in terms of chain of functions.
         // But keep the order of names within the same function. so they
         // match up with the order of the types in 'type_arguments'.
@@ -2547,7 +2546,7 @@
 
 void GroupDebugger::MakeCodeBreakpointAt(const Function& func,
                                          BreakpointLocation* loc) {
-  ASSERT(loc->token_pos_.IsReal());
+  ASSERT(loc->token_pos().IsReal());
   ASSERT((loc != NULL) && loc->IsResolved());
   ASSERT(!func.HasOptimizedCode());
   ASSERT(func.HasCode());
@@ -2580,7 +2579,7 @@
     if (FLAG_verbose_debug) {
       OS::PrintErr("Setting code breakpoint at pos %s pc %#" Px " offset %#" Px
                    "\n",
-                   loc->token_pos_.ToCString(), lowest_pc,
+                   loc->token_pos().ToCString(), lowest_pc,
                    lowest_pc - code.PayloadStart());
     }
     RegisterCodeBreakpoint(code_bpt);
@@ -2589,10 +2588,12 @@
       OS::PrintErr(
           "Adding location to existing code breakpoint at pos %s pc %#" Px
           " offset %#" Px "\n",
-          loc->token_pos_.ToCString(), lowest_pc,
+          loc->token_pos().ToCString(), lowest_pc,
           lowest_pc - code.PayloadStart());
     }
-    code_bpt->AddBreakpointLocation(loc);
+    if (!code_bpt->HasBreakpointLocation(loc)) {
+      code_bpt->AddBreakpointLocation(loc);
+    }
   }
   if (loc->AnyEnabled()) {
     code_bpt->Enable();
@@ -3998,14 +3999,23 @@
     return Error::null();
   }
 
-  CodeBreakpoint* cbpt = nullptr;
-  BreakpointLocation* bpt_location =
-      group_debugger()->GetBreakpointLocationFor(this, top_frame->pc(), &cbpt);
-  if (bpt_location == nullptr) {
-    // There might be no breakpoint locations for this isolate/debugger.
-    return Error::null();
+  BreakpointLocation* bpt_location = nullptr;
+  const char* cbpt_tostring = nullptr;
+  {
+    SafepointReadRwLocker cbl(Thread::Current(),
+                              group_debugger()->code_breakpoints_lock());
+    CodeBreakpoint* cbpt = nullptr;
+    bpt_location = group_debugger()->GetBreakpointLocationFor(
+        this, top_frame->pc(), &cbpt);
+    if (bpt_location == nullptr) {
+      // There might be no breakpoint locations for this isolate/debugger.
+      return Error::null();
+    }
+    ASSERT(cbpt != nullptr);
+    if (FLAG_verbose_debug) {
+      cbpt_tostring = cbpt->ToCString();
+    }
   }
-  ASSERT(cbpt != nullptr);
 
   Breakpoint* bpt_hit = bpt_location->FindHitBreakpoint(top_frame);
   if (bpt_hit == nullptr) {
@@ -4023,7 +4033,7 @@
       OS::PrintErr(
           ">>> hit synthetic %s"
           " (func %s token %s address %#" Px " offset %#" Px ")\n",
-          cbpt->ToCString(),
+          cbpt_tostring,
           String::Handle(top_frame->QualifiedFunctionName()).ToCString(),
           bpt_location->token_pos().ToCString(), top_frame->pc(),
           top_frame->pc() - top_frame->code().PayloadStart());
@@ -4044,13 +4054,10 @@
   }
 
   if (FLAG_verbose_debug) {
-    // Lock is needed for CodeBreakpoint::ToCString().
-    SafepointReadRwLocker sl(Thread::Current(),
-                             group_debugger()->code_breakpoints_lock());
     OS::PrintErr(">>> hit %" Pd
                  " %s"
                  " (func %s token %s address %#" Px " offset %#" Px ")\n",
-                 bpt_hit->id(), cbpt->ToCString(),
+                 bpt_hit->id(), cbpt_tostring,
                  String::Handle(top_frame->QualifiedFunctionName()).ToCString(),
                  bpt_location->token_pos().ToCString(), top_frame->pc(),
                  top_frame->pc() - top_frame->code().PayloadStart());
@@ -4506,7 +4513,7 @@
   while (loc != NULL) {
     loc_url = loc->url();
     if (script_url.Equals(loc_url) &&
-        (!token_pos.IsReal() || (loc->token_pos_ == token_pos)) &&
+        (!token_pos.IsReal() || (loc->token_pos() == token_pos)) &&
         ((requested_line == -1) ||
          (loc->requested_line_number_ == requested_line)) &&
         ((requested_column == -1) ||
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index f02e84e..53fc598 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -151,9 +151,9 @@
 
   ~BreakpointLocation();
 
-  TokenPosition token_pos() const { return token_pos_; }
+  TokenPosition token_pos() const { return token_pos_.load(); }
   intptr_t line_number();
-  TokenPosition end_token_pos() const { return end_token_pos_; }
+  TokenPosition end_token_pos() const { return end_token_pos_.load(); }
 
   ScriptPtr script() const {
     if (scripts_.length() == 0) {
@@ -176,7 +176,7 @@
 
   bool AnyEnabled() const;
   bool IsResolved() const { return code_token_pos_.IsReal(); }
-  bool IsLatent() const { return !token_pos_.IsReal(); }
+  bool IsLatent() const { return !token_pos().IsReal(); }
 
   bool EnsureIsResolved(const Function& target_function,
                         TokenPosition exact_token_pos);
@@ -206,8 +206,8 @@
   StringPtr url_;
   std::unique_ptr<SafepointRwLock> line_number_lock_;
   intptr_t line_number_;  // lazily computed for token_pos_
-  TokenPosition token_pos_;
-  TokenPosition end_token_pos_;
+  std::atomic<TokenPosition> token_pos_;
+  std::atomic<TokenPosition> end_token_pos_;
   BreakpointLocation* next_;
   Breakpoint* conditions_;
   intptr_t requested_line_number_;
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index 442f8ce..1256780 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -703,15 +703,13 @@
   }
 
   const auto& type_params =
-      TypeArguments::Handle(zone, function.type_parameters());
+      TypeParameters::Handle(zone, function.type_parameters());
   if (!type_params.IsNull()) {
-    auto& type_param = TypeParameter::Handle(zone);
     auto& bound = AbstractType::Handle(zone);
     for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
-      type_param ^= type_params.TypeAt(i);
-      bound = type_param.bound();
+      bound = type_params.BoundAt(i);
       if (!bound.IsTopTypeForSubtyping() &&
-          !type_param.IsGenericCovariantImpl()) {
+          !type_params.IsGenericCovariantImplAt(i)) {
         return true;
       }
     }
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 32ecc7c..d9b9ddf 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -99,6 +99,7 @@
     return metadata_mappings_offset_;
   }
   intptr_t constant_table_offset() { return constant_table_offset_; }
+  intptr_t component_index_offset() { return component_index_offset_; }
   intptr_t library_count() { return library_count_; }
   NNBDCompiledMode compilation_mode() const { return compilation_mode_; }
 
@@ -122,6 +123,9 @@
   // The offset from the start of the binary to the start of the constant table.
   intptr_t constant_table_offset_;
 
+  // The offset from the start of the binary to the start of the ending-index.
+  intptr_t component_index_offset_;
+
   // The offset from the start of the binary to the canonical name table.
   intptr_t name_table_offset_;
 
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index 9e6e614..0e4cc79 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -171,17 +171,21 @@
   program->library_count_ = reader->ReadFromIndexNoReset(
       reader->size_, LibraryCountFieldCountFromEnd, 1, 0);
   intptr_t count_from_first_library_offset =
-      SourceTableFieldCountFromFirstLibraryOffset41Plus;
+      SourceTableFieldCountFromFirstLibraryOffset;
   program->source_table_offset_ = reader->ReadFromIndexNoReset(
       reader->size_,
       LibraryCountFieldCountFromEnd + 1 + program->library_count_ + 1 +
           count_from_first_library_offset,
       1, 0);
+  program->constant_table_offset_ = reader->ReadUInt32();
+  reader->ReadUInt32();  // offset for constant table index.
   program->name_table_offset_ = reader->ReadUInt32();
   program->metadata_payloads_offset_ = reader->ReadUInt32();
   program->metadata_mappings_offset_ = reader->ReadUInt32();
   program->string_table_offset_ = reader->ReadUInt32();
-  program->constant_table_offset_ = reader->ReadUInt32();
+  // The below includes any 8-bit alignment; denotes the end of the previous
+  // block.
+  program->component_index_offset_ = reader->ReadUInt32();
 
   program->main_method_reference_ = NameIndex(reader->ReadUInt32() - 1);
   NNBDCompiledMode compilation_mode =
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 38ca8fa..c7b1fe5 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 = 63;
-static const uint32_t kMaxSupportedKernelFormatVersion = 63;
+static const uint32_t kMinSupportedKernelFormatVersion = 64;
+static const uint32_t kMaxSupportedKernelFormatVersion = 64;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -217,8 +217,7 @@
 static const int SpecializedIntLiteralBias = 3;
 static const int LibraryCountFieldCountFromEnd = 1;
 static const int KernelFormatVersionOffset = 4;
-static const int SourceTableFieldCountFromFirstLibraryOffsetPre41 = 6;
-static const int SourceTableFieldCountFromFirstLibraryOffset41Plus = 7;
+static const int SourceTableFieldCountFromFirstLibraryOffset = 9;
 
 static const int HeaderSize = 8;  // 'magic', 'formatVersion'.
 
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index fb284d0..4b39508 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -399,11 +399,11 @@
       Z,
       reader.ExternalDataFromTo(reader.offset(), reader.offset() + end_offset));
 
-  // Create a view of the constants table. The trailing ComponentIndex is
-  // negligible in size.
+  // Create a view of the constants table (first part)
+  // and the constant table index (second part).
   const ExternalTypedData& constants_table = ExternalTypedData::Handle(
       Z, reader.ExternalDataFromTo(program_->constant_table_offset(),
-                                   program_->kernel_data_size()));
+                                   program_->name_table_offset()));
 
   // Copy the canonical names into the VM's heap.  Encode them as unsigned, so
   // the parent indexes are adjusted when extracted.
@@ -550,10 +550,10 @@
 
         // We have a candidate. Let's look if it's an instance of the
         // ExternalName class.
-        const intptr_t constant_table_offset = helper_.ReadUInt();
-        if (constant_reader.IsInstanceConstant(constant_table_offset,
+        const intptr_t constant_table_index = helper_.ReadUInt();
+        if (constant_reader.IsInstanceConstant(constant_table_index,
                                                external_name_class_)) {
-          constant = constant_reader.ReadConstant(constant_table_offset);
+          constant = constant_reader.ReadConstant(constant_table_index);
           ASSERT(constant.clazz() == external_name_class_.ptr());
           // We found the annotation, let's flag the function as native and
           // set the native name!
@@ -667,10 +667,10 @@
 
         // We have a candidate. Let's look if it's an instance of the
         // ExternalName class.
-        const intptr_t constant_table_offset = helper_.ReadUInt();
-        if (constant_reader.IsInstanceConstant(constant_table_offset,
+        const intptr_t constant_table_index = helper_.ReadUInt();
+        if (constant_reader.IsInstanceConstant(constant_table_index,
                                                external_name_class_)) {
-          constant = constant_reader.ReadConstant(constant_table_offset);
+          constant = constant_reader.ReadConstant(constant_table_index);
           ASSERT(constant.clazz() == external_name_class_.ptr());
           uri_path ^= constant.GetField(external_name_field_);
         }
@@ -830,6 +830,18 @@
 
   function.set_owner(real_class);
 
+  ASSERT(real_class.is_finalized());
+  // The owner class has already been marked as finalized so the signature of
+  // this added function must be finalized here, since finalization of member
+  // types will not be called anymore.
+  FunctionType& signature = FunctionType::Handle(Z, function.signature());
+  if (!function.is_static()) {
+    // Patch the illegal receiver type (type class with kIllegalCid) to dynamic.
+    signature.SetParameterTypeAt(0, Object::dynamic_type());
+  }
+  signature ^= ClassFinalizer::FinalizeType(signature);
+  function.set_signature(signature);
+
   return function.ptr();
 }
 
@@ -1425,7 +1437,9 @@
   // Set type parameters.
   T.LoadAndSetupTypeParameters(&active_class_, Object::null_function(), *klass,
                                Object::null_function_type(),
-                               type_parameter_count, klass->nnbd_mode());
+                               type_parameter_count);
+
+  ActiveTypeParametersScope scope(&active_class_, nullptr, Z);
 
   T.LoadAndSetupBounds(&active_class_, Object::null_function(), *klass,
                        Object::null_function_type(), type_parameter_count);
@@ -1899,7 +1913,7 @@
         helper_.ReadByte();      // Skip the tag.
         helper_.ReadPosition();  // Skip fileOffset.
         helper_.SkipDartType();  // Skip type.
-        const intptr_t offset_in_constant_table = helper_.ReadUInt();
+        const intptr_t index_in_constant_table = helper_.ReadUInt();
 
         AlternativeReadingScopeWithNewData scope(
             &helper_.reader_,
@@ -1909,8 +1923,18 @@
 
         // Seek into the position within the constant table where we can inspect
         // this constant's Kernel representation.
-        helper_.ReadUInt();  // skip constant table size
-        helper_.SkipBytes(offset_in_constant_table);
+
+        // Get the length of the constants (at the end of the mapping).
+        helper_.SetOffset(helper_.ReaderSize() - 4);
+        const intptr_t num_constants = helper_.ReadUInt32();
+
+        // Get the binary offset of the constant at the wanted index.
+        helper_.SetOffset(helper_.ReaderSize() - 4 - (num_constants * 4) +
+                          (index_in_constant_table * 4));
+        const intptr_t constant_offset = helper_.ReadUInt32();
+
+        helper_.SetOffset(constant_offset);
+
         uint8_t tag = helper_.ReadTag();
         if (tag == kInstanceConstant) {
           *has_pragma_annotation =
@@ -1937,15 +1961,15 @@
           helper_.ReadPosition();  // Skip fileOffset.
           helper_.SkipDartType();  // Skip type.
         }
-        const intptr_t constant_table_offset = helper_.ReadUInt();
+        const intptr_t constant_table_index = helper_.ReadUInt();
         // We have a candidate. Let's look if it's an instance of the
         // ExternalName or Pragma class.
-        if (constant_reader.IsInstanceConstant(constant_table_offset,
+        if (constant_reader.IsInstanceConstant(constant_table_index,
                                                external_name_class_)) {
-          constant = constant_reader.ReadConstant(constant_table_offset);
+          constant = constant_reader.ReadConstant(constant_table_index);
           ASSERT(constant.clazz() == external_name_class_.ptr());
           *native_name ^= constant.GetField(external_name_field_);
-        } else if (constant_reader.IsInstanceConstant(constant_table_offset,
+        } else if (constant_reader.IsInstanceConstant(constant_table_index,
                                                       pragma_class_)) {
           *has_pragma_annotation = true;
         }
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ade7623..d7c6b01 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -143,6 +143,7 @@
 ClassPtr Object::class_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::dynamic_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::void_class_ = static_cast<ClassPtr>(RAW_NULL);
+ClassPtr Object::type_parameters_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::type_arguments_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::patch_class_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::function_class_ = static_cast<ClassPtr>(RAW_NULL);
@@ -785,6 +786,9 @@
   }
 
   // Allocate the remaining VM internal classes.
+  cls = Class::New<TypeParameters, RTN::TypeParameters>(isolate_group);
+  type_parameters_class_ = cls.ptr();
+
   cls = Class::New<TypeArguments, RTN::TypeArguments>(isolate_group);
   type_arguments_class_ = cls.ptr();
 
@@ -1236,6 +1240,7 @@
   class_class_ = static_cast<ClassPtr>(RAW_NULL);
   dynamic_class_ = static_cast<ClassPtr>(RAW_NULL);
   void_class_ = static_cast<ClassPtr>(RAW_NULL);
+  type_parameters_class_ = static_cast<ClassPtr>(RAW_NULL);
   type_arguments_class_ = static_cast<ClassPtr>(RAW_NULL);
   patch_class_class_ = static_cast<ClassPtr>(RAW_NULL);
   function_class_ = static_cast<ClassPtr>(RAW_NULL);
@@ -1336,6 +1341,7 @@
   SET_CLASS_NAME(class, Class);
   SET_CLASS_NAME(dynamic, Dynamic);
   SET_CLASS_NAME(void, Void);
+  SET_CLASS_NAME(type_parameters, TypeParameters);
   SET_CLASS_NAME(type_arguments, TypeArguments);
   SET_CLASS_NAME(patch_class, PatchClass);
   SET_CLASS_NAME(function, Function);
@@ -2169,6 +2175,7 @@
     type.SetIsFinalized();
     type ^= type.Canonicalize(thread, nullptr);
     object_store->set_null_type(type);
+    cls.set_declaration_type(type);
     ASSERT(type.IsNullable());
 
     // Consider removing when/if Null becomes an ordinary class.
@@ -3152,7 +3159,7 @@
   untag()->set_library(value.ptr());
 }
 
-void Class::set_type_parameters(const TypeArguments& value) const {
+void Class::set_type_parameters(const TypeParameters& value) const {
   ASSERT((num_type_arguments() == kUnknownNumTypeArguments) ||
          is_prefinalized());
   untag()->set_type_parameters(value.ptr());
@@ -3187,11 +3194,11 @@
     }
     return 0;
   }
-  if (type_parameters() == TypeArguments::null()) {
+  if (type_parameters() == TypeParameters::null()) {
     return 0;
   }
   REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
-  TypeArguments& type_params = thread->TypeArgumentsHandle();
+  TypeParameters& type_params = thread->TypeParametersHandle();
   type_params = type_parameters();
   return type_params.Length();
 }
@@ -3289,31 +3296,13 @@
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
-static TypeArgumentsPtr InstantiateTypeArgumentsToBounds(
-    Thread* thread,
-    const TypeArguments& parameters) {
-  ASSERT(thread != nullptr);
-  if (parameters.IsNull()) {
-    return Object::empty_type_arguments().ptr();
-  }
-  auto const zone = thread->zone();
-  const auto& result = TypeArguments::Handle(
-      zone, TypeArguments::New(parameters.Length(), Heap::kNew));
-  auto& param = TypeParameter::Handle(zone);
-  auto& type = AbstractType::Handle(zone);
-  for (intptr_t i = 0, n = parameters.Length(); i < n; i++) {
-    param ^= parameters.TypeAt(i);
-    type = param.default_argument();
-    ASSERT(type.IsFinalized());
-    result.SetTypeAt(i, type);
-  }
-  return result.Canonicalize(thread);
-}
-
 TypeArgumentsPtr Class::InstantiateToBounds(Thread* thread) const {
   const auto& type_params =
-      TypeArguments::Handle(thread->zone(), type_parameters());
-  return InstantiateTypeArgumentsToBounds(thread, type_params);
+      TypeParameters::Handle(thread->zone(), type_parameters());
+  if (type_params.IsNull()) {
+    return Object::empty_type_arguments().ptr();
+  }
+  return type_params.defaults();
 }
 
 ClassPtr Class::SuperClass(bool original_classes) const {
@@ -3341,28 +3330,19 @@
   untag()->set_super_type(value.ptr());
 }
 
-TypeParameterPtr Class::LookupTypeParameter(const String& type_name) const {
-  ASSERT(!type_name.IsNull());
-  Thread* thread = Thread::Current();
-  REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
-  REUSABLE_TYPE_PARAMETER_HANDLESCOPE(thread);
-  REUSABLE_STRING_HANDLESCOPE(thread);
-  TypeArguments& type_params = thread->TypeArgumentsHandle();
-  TypeParameter& type_param = thread->TypeParameterHandle();
-  String& type_param_name = thread->StringHandle();
-
-  type_params = type_parameters();
-  if (!type_params.IsNull()) {
-    const intptr_t num_type_params = type_params.Length();
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type_param ^= type_params.TypeAt(i);
-      type_param_name = type_param.name();
-      if (type_param_name.Equals(type_name)) {
-        return type_param.ptr();
-      }
-    }
+TypeParameterPtr Class::TypeParameterAt(intptr_t index,
+                                        Nullability nullability) const {
+  ASSERT(index >= 0 && index < NumTypeParameters());
+  const TypeParameters& type_params = TypeParameters::Handle(type_parameters());
+  const TypeArguments& bounds = TypeArguments::Handle(type_params.bounds());
+  const AbstractType& bound = AbstractType::Handle(
+      bounds.IsNull() ? Type::DynamicType() : bounds.TypeAt(index));
+  TypeParameter& type_param = TypeParameter::Handle(
+      TypeParameter::New(*this, 0, index, bound, nullability));
+  if (is_type_finalized()) {
+    type_param ^= ClassFinalizer::FinalizeType(type_param);
   }
-  return TypeParameter::null();
+  return type_param.ptr();
 }
 
 UnboxedFieldBitmap Class::CalculateFieldOffsets() const {
@@ -3403,9 +3383,7 @@
   // parameterized, introduce a new type_arguments field.
   if (host_type_args_field_offset == kNoTypeArguments) {
     ASSERT(target_type_args_field_offset == RTN::Class::kNoTypeArguments);
-    const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
-    if (!type_params.IsNull()) {
-      ASSERT(type_params.Length() > 0);
+    if (IsGeneric()) {
       // The instance needs a type_arguments field.
       host_type_args_field_offset = host_offset;
       target_type_args_field_offset = target_offset;
@@ -4869,6 +4847,8 @@
       return Symbols::Never().ToCString();
     case kClassCid:
       return Symbols::Class().ToCString();
+    case kTypeParametersCid:
+      return Symbols::TypeParameters().ToCString();
     case kTypeArgumentsCid:
       return Symbols::TypeArguments().ToCString();
     case kPatchClassCid:
@@ -5195,9 +5175,18 @@
     // DeclarationType without checking its nullability. Therefore, we
     // consistently cache the kNonNullable version of the type.
     // The exception is type Null which is stored as kNullable.
+    TypeArguments& type_args = TypeArguments::Handle();
+    const intptr_t num_type_params = NumTypeParameters();
+    if (num_type_params > 0) {
+      type_args = TypeArguments::New(num_type_params);
+      TypeParameter& type_param = TypeParameter::Handle();
+      for (intptr_t i = 0; i < num_type_params; i++) {
+        type_param = TypeParameterAt(i);
+        type_args.SetTypeAt(i, type_param);
+      }
+    }
     Type& type =
-        Type::Handle(Type::New(*this, TypeArguments::Handle(type_parameters()),
-                               Nullability::kNonNullable));
+        Type::Handle(Type::New(*this, type_args, Nullability::kNonNullable));
     type ^= ClassFinalizer::FinalizeType(type);
     set_declaration_type(type);
     return type.ptr();
@@ -6021,6 +6010,191 @@
   return result;
 }
 
+intptr_t TypeParameters::Length() const {
+  if (IsNull() || untag()->names() == Array::null()) return 0;
+  return Smi::Value(untag()->names()->untag()->length());
+}
+
+void TypeParameters::set_names(const Array& value) const {
+  ASSERT(!value.IsNull());
+  untag()->set_names(value.ptr());
+}
+
+StringPtr TypeParameters::NameAt(intptr_t index) const {
+  const Array& names_array = Array::Handle(names());
+  return String::RawCast(names_array.At(index));
+}
+
+void TypeParameters::SetNameAt(intptr_t index, const String& value) const {
+  const Array& names_array = Array::Handle(names());
+  names_array.SetAt(index, value);
+}
+
+void TypeParameters::set_flags(const Array& value) const {
+  untag()->set_flags(value.ptr());
+}
+
+void TypeParameters::set_bounds(const TypeArguments& value) const {
+  // A null value represents a vector of dynamic.
+  untag()->set_bounds(value.ptr());
+}
+
+AbstractTypePtr TypeParameters::BoundAt(intptr_t index) const {
+  const TypeArguments& upper_bounds = TypeArguments::Handle(bounds());
+  return upper_bounds.IsNull() ? Type::DynamicType()
+                               : upper_bounds.TypeAt(index);
+}
+
+void TypeParameters::SetBoundAt(intptr_t index,
+                                const AbstractType& value) const {
+  const TypeArguments& upper_bounds = TypeArguments::Handle(bounds());
+  upper_bounds.SetTypeAt(index, value);
+}
+
+bool TypeParameters::AllDynamicBounds() const {
+  return bounds() == TypeArguments::null();
+}
+
+void TypeParameters::set_defaults(const TypeArguments& value) const {
+  // The null value represents a vector of dynamic.
+  untag()->set_defaults(value.ptr());
+}
+
+AbstractTypePtr TypeParameters::DefaultAt(intptr_t index) const {
+  const TypeArguments& default_type_args = TypeArguments::Handle(defaults());
+  return default_type_args.IsNull() ? Type::DynamicType()
+                                    : default_type_args.TypeAt(index);
+}
+
+void TypeParameters::SetDefaultAt(intptr_t index,
+                                  const AbstractType& value) const {
+  const TypeArguments& default_type_args = TypeArguments::Handle(defaults());
+  default_type_args.SetTypeAt(index, value);
+}
+
+bool TypeParameters::AllDynamicDefaults() const {
+  return defaults() == TypeArguments::null();
+}
+
+void TypeParameters::AllocateFlags(Heap::Space space) const {
+  const intptr_t len = (Length() + kFlagsPerSmiMask) >> kFlagsPerSmiShift;
+  const Array& flags_array = Array::Handle(Array::New(len, space));
+  // Initialize flags to 0.
+  const Smi& zero = Smi::Handle(Smi::New(0));
+  for (intptr_t i = 0; i < len; i++) {
+    flags_array.SetAt(i, zero);
+  }
+  set_flags(flags_array);
+}
+
+void TypeParameters::OptimizeFlags() const {
+  if (untag()->flags() == Array::null()) return;  // Already optimized.
+  const intptr_t len = (Length() + kFlagsPerSmiMask) >> kFlagsPerSmiShift;
+  const Array& flags_array = Array::Handle(flags());
+  const Smi& zero = Smi::Handle(Smi::New(0));
+  for (intptr_t i = 0; i < len; i++) {
+    if (flags_array.At(i) != zero.ptr()) return;
+  }
+  set_flags(Object::null_array());
+}
+
+bool TypeParameters::IsGenericCovariantImplAt(intptr_t index) const {
+  if (untag()->flags() == Array::null()) return false;
+  const intptr_t flag = Smi::Value(
+      Smi::RawCast(Array::Handle(flags()).At(index >> kFlagsPerSmiShift)));
+  return (flag >> (index & kFlagsPerSmiMask)) != 0;
+}
+
+void TypeParameters::SetIsGenericCovariantImplAt(intptr_t index,
+                                                 bool value) const {
+  const Array& flg = Array::Handle(flags());
+  intptr_t flag = Smi::Value(Smi::RawCast(flg.At(index >> kFlagsPerSmiShift)));
+  if (value) {
+    flag |= 1 << (index % kFlagsPerSmiMask);
+  } else {
+    flag &= ~(1 << (index % kFlagsPerSmiMask));
+  }
+  flg.SetAt(index >> kFlagsPerSmiShift, Smi::Handle(Smi::New(flag)));
+}
+
+void TypeParameters::Print(Thread* thread,
+                           Zone* zone,
+                           bool are_class_type_parameters,
+                           intptr_t base,
+                           NameVisibility name_visibility,
+                           BaseTextBuffer* printer) const {
+  String& name = String::Handle(zone);
+  AbstractType& type = AbstractType::Handle(zone);
+  const intptr_t num_type_params = Length();
+  for (intptr_t i = 0; i < num_type_params; i++) {
+    if (are_class_type_parameters) {
+      name = NameAt(i);
+      printer->AddString(name.ToCString());
+    } else {
+      printer->AddString(TypeParameter::CanonicalNameCString(
+          are_class_type_parameters, base, base + i));
+    }
+    if (!AllDynamicBounds()) {
+      type = BoundAt(i);
+      // Do not print default bound or non-nullable Object bound in weak mode.
+      if (!type.IsNull() &&
+          (!type.IsObjectType() ||
+           (thread->isolate_group()->null_safety() && type.IsNonNullable()))) {
+        printer->AddString(" extends ");
+        type.PrintName(name_visibility, printer);
+        if (FLAG_show_internal_names && !AllDynamicDefaults()) {
+          type = DefaultAt(i);
+          if (!type.IsNull() && !type.IsDynamicType()) {
+            printer->AddString(" defaults to ");
+            type.PrintName(name_visibility, printer);
+          }
+        }
+      }
+    }
+    if (i != num_type_params - 1) {
+      printer->AddString(", ");
+    }
+  }
+}
+
+const char* TypeParameters::ToCString() const {
+  if (IsNull()) {
+    return "TypeParameters: null";
+  }
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  ZoneTextBuffer buffer(zone);
+  buffer.AddString("TypeParameters: ");
+  Print(thread, zone, true, 0, kInternalName, &buffer);
+  return buffer.buffer();
+}
+
+TypeParametersPtr TypeParameters::New(Heap::Space space) {
+  ASSERT(Object::type_parameters_class() != Class::null());
+  ObjectPtr ptr = Object::Allocate(TypeParameters::kClassId,
+                                   TypeParameters::InstanceSize(), space,
+                                   /*compressed*/ false);
+  return static_cast<TypeParametersPtr>(ptr);
+}
+
+TypeParametersPtr TypeParameters::New(intptr_t count, Heap::Space space) {
+  const TypeParameters& result =
+      TypeParameters::Handle(TypeParameters::New(space));
+  // Create an [ Array ] of [ String ] objects to represent the names.
+  // Create a [ TypeArguments ] vector representing the bounds.
+  // Create a [ TypeArguments ] vector representing the defaults.
+  // Create an [ Array ] of [ Smi] objects to represent the flags.
+  const Array& names_array = Array::Handle(Array::New(count, space));
+  result.set_names(names_array);
+  TypeArguments& type_args = TypeArguments::Handle();
+  type_args = TypeArguments::New(count, Heap::kNew);  // Will get canonicalized.
+  result.set_bounds(type_args);
+  type_args = TypeArguments::New(count, Heap::kNew);  // Will get canonicalized.
+  result.set_defaults(type_args);
+  result.AllocateFlags(space);  // Will get optimized.
+  return result.ptr();
+}
+
 intptr_t TypeArguments::ComputeNullability() const {
   if (IsNull()) return 0;
   const intptr_t num_types = Length();
@@ -7145,97 +7319,47 @@
 TypeArgumentsPtr Function::InstantiateToBounds(
     Thread* thread,
     DefaultTypeArgumentsKind* kind_out) const {
-  if (CachesDefaultTypeArguments()) {
-    // Always use the cached version, even if the type parameters are null,
-    // to catch cases where the cache isn't properly initialized.
-    return default_type_arguments(kind_out);
-  }
-  // No cached version, so just retrieve from the type parameters and return
-  // a canonicalized version..
-  if (type_parameters() == TypeArguments::null()) {
+  if (type_parameters() == TypeParameters::null()) {
     if (kind_out != nullptr) {
       *kind_out = DefaultTypeArgumentsKind::kIsInstantiated;
     }
     return Object::empty_type_arguments().ptr();
   }
-  auto& result = TypeArguments::Handle(thread->zone(), type_parameters());
-  result = InstantiateTypeArgumentsToBounds(thread, result);
+  auto& type_params = TypeParameters::Handle(thread->zone(), type_parameters());
+  auto& result = TypeArguments::Handle(thread->zone(), type_params.defaults());
   if (kind_out != nullptr) {
-    // We just return is/is not instantiated if the value isn't cached, as
-    // the other checks may be more overhead at runtime than just doing the
-    // instantiation.
-    *kind_out = result.IsNull() || result.IsInstantiated()
-                    ? DefaultTypeArgumentsKind::kIsInstantiated
-                    : DefaultTypeArgumentsKind::kNeedsInstantiation;
+    if (IsClosureFunction()) {
+      *kind_out = default_type_arguments_kind();
+    } else {
+      // We just return is/is not instantiated if the value isn't cached, as
+      // the other checks may be more overhead at runtime than just doing the
+      // instantiation.
+      *kind_out = result.IsNull() || result.IsInstantiated()
+                      ? DefaultTypeArgumentsKind::kIsInstantiated
+                      : DefaultTypeArgumentsKind::kNeedsInstantiation;
+    }
   }
   return result.ptr();
 }
 
-void Function::UpdateCachedDefaultTypeArguments(Thread* thread) const {
-  auto const zone = thread->zone();
-  auto& closure_function = Function::Handle(zone);
-  if (HasImplicitClosureFunction()) {
-    closure_function = ImplicitClosureFunction();
-  }
-  if (CachesDefaultTypeArguments()) {
-    auto defaults = &Object::empty_type_arguments();
-    const FunctionType& sig = FunctionType::Handle(zone, signature());
-    if (sig.NumTypeParameters(thread) > 0) {
-      const auto& params = TypeArguments::Handle(zone, sig.type_parameters());
-      const intptr_t num_params = params.Length();
-      auto& new_defaults = TypeArguments::Handle(
-          zone, TypeArguments::New(num_params, Heap::kNew));
-      // Only canonicalize the result if all the default arguments have been
-      // canonicalized, to avoid premature canonicalization of the arguments.
-      bool all_canonical = true;
-      auto& type = AbstractType::Handle(zone);
-      for (intptr_t i = 0; i < num_params; i++) {
-        type = params.TypeAt(i);
-        type = TypeParameter::Cast(type).default_argument();
-        if (!type.IsCanonical()) {
-          all_canonical = false;
-        }
-        new_defaults.SetTypeAt(i, type);
-      }
-      if (all_canonical) {
-        new_defaults = new_defaults.Canonicalize(thread);
-      }
-      defaults = &new_defaults;
-    }
-    set_default_type_arguments(*defaults);
-    if (!closure_function.IsNull()) {
-      closure_function.set_default_type_arguments(*defaults);
-    }
-  } else if (!closure_function.IsNull()) {
-    closure_function.UpdateCachedDefaultTypeArguments(thread);
-  }
-}
-
-TypeArgumentsPtr Function::default_type_arguments(
-    DefaultTypeArgumentsKind* kind_out) const {
-  if (!CachesDefaultTypeArguments()) {
+Function::DefaultTypeArgumentsKind Function::default_type_arguments_kind()
+    const {
+  if (!IsClosureFunction()) {
     UNREACHABLE();
   }
   const auto& closure_data = ClosureData::Handle(ClosureData::RawCast(data()));
   ASSERT(!closure_data.IsNull());
-  if (kind_out != nullptr) {
-    *kind_out = closure_data.default_type_arguments_kind();
-  }
-  return closure_data.default_type_arguments();
+  return closure_data.default_type_arguments_kind();
 }
 
-void Function::set_default_type_arguments(const TypeArguments& value) const {
-  if (!CachesDefaultTypeArguments()) {
+void Function::set_default_type_arguments_kind(
+    Function::DefaultTypeArgumentsKind value) const {
+  if (!IsClosureFunction()) {
     UNREACHABLE();
   }
   const auto& closure_data = ClosureData::Handle(ClosureData::RawCast(data()));
   ASSERT(!closure_data.IsNull());
-  auto kind = DefaultTypeArgumentsKindFor(value);
-  ASSERT(kind != DefaultTypeArgumentsKind::kInvalid);
-  closure_data.set_default_type_arguments_kind(kind);
-  // We could just store null for the ksharesFunction/kSharesInstantiator cases,
-  // assuming all clients retrieve the DefaultTypeArgumentsKind to distinguish.
-  closure_data.set_default_type_arguments(value);
+  closure_data.set_default_type_arguments_kind(value);
 }
 
 Function::DefaultTypeArgumentsKind Function::DefaultTypeArgumentsKindFor(
@@ -7514,10 +7638,32 @@
   untag()->set_signature(value.ptr());
   if (!value.IsNull()) {
     ASSERT(NumImplicitParameters() == value.num_implicit_parameters());
-    UpdateCachedDefaultTypeArguments(Thread::Current());
+    if (IsClosureFunction() && value.IsGeneric()) {
+      const TypeParameters& type_params =
+          TypeParameters::Handle(value.type_parameters());
+      const TypeArguments& defaults =
+          TypeArguments::Handle(type_params.defaults());
+      auto kind = DefaultTypeArgumentsKindFor(defaults);
+      ASSERT(kind != DefaultTypeArgumentsKind::kInvalid);
+      set_default_type_arguments_kind(kind);
+    }
   }
 }
 
+TypeParameterPtr FunctionType::TypeParameterAt(intptr_t index,
+                                               Nullability nullability) const {
+  ASSERT(index >= 0 && index < NumTypeParameters());
+  const TypeParameters& type_params = TypeParameters::Handle(type_parameters());
+  const AbstractType& bound = AbstractType::Handle(type_params.BoundAt(index));
+  TypeParameter& type_param = TypeParameter::Handle(
+      TypeParameter::New(Object::null_class(), NumParentTypeArguments(),
+                         NumParentTypeArguments() + index, bound, nullability));
+  if (IsFinalized()) {
+    type_param ^= ClassFinalizer::FinalizeType(type_param);
+  }
+  return type_param.ptr();
+}
+
 void FunctionType::set_result_type(const AbstractType& value) const {
   ASSERT(!value.IsNull());
   untag()->set_result_type(value.ptr());
@@ -7705,7 +7851,7 @@
   }
 }
 
-void FunctionType::set_type_parameters(const TypeArguments& value) const {
+void FunctionType::set_type_parameters(const TypeParameters& value) const {
   untag()->set_type_parameters(value.ptr());
 }
 
@@ -7749,11 +7895,11 @@
 }
 
 intptr_t FunctionType::NumTypeParameters(Thread* thread) const {
-  if (type_parameters() == TypeArguments::null()) {
+  if (type_parameters() == TypeParameters::null()) {
     return 0;
   }
-  REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
-  TypeArguments& type_params = thread->TypeArgumentsHandle();
+  REUSABLE_TYPE_PARAMETERS_HANDLESCOPE(thread);
+  TypeParameters& type_params = thread->TypeParametersHandle();
   type_params = type_parameters();
   // We require null to represent a non-generic signature.
   ASSERT(type_params.Length() != 0);
@@ -7766,45 +7912,10 @@
   return FunctionType::Handle(signature()).NumParentTypeArguments();
 }
 
-TypeParameterPtr Function::LookupTypeParameter(const String& type_name,
-                                               intptr_t* function_level) const {
-  ASSERT(!type_name.IsNull());
-  Thread* thread = Thread::Current();
-  REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
-  REUSABLE_TYPE_PARAMETER_HANDLESCOPE(thread);
-  REUSABLE_STRING_HANDLESCOPE(thread);
-  REUSABLE_FUNCTION_HANDLESCOPE(thread);
-  TypeArguments& type_params = thread->TypeArgumentsHandle();
-  TypeParameter& type_param = thread->TypeParameterHandle();
-  String& type_param_name = thread->StringHandle();
-  Function& function = thread->FunctionHandle();
-
-  function = this->ptr();
-  while (!function.IsNull()) {
-    if (function.signature() != FunctionType::null()) {
-      type_params = function.type_parameters();
-      if (!type_params.IsNull()) {
-        const intptr_t num_type_params = type_params.Length();
-        for (intptr_t i = 0; i < num_type_params; i++) {
-          type_param ^= type_params.TypeAt(i);
-          type_param_name = type_param.name();
-          if (type_param_name.Equals(type_name)) {
-            return type_param.ptr();
-          }
-        }
-      }
-    }
-    if (function.IsImplicitClosureFunction()) {
-      // The parent function is not the enclosing function, but the closurized
-      // function with identical type parameters.
-      break;
-    }
-    function = function.parent_function();
-    if (function_level != NULL) {
-      (*function_level)--;
-    }
-  }
-  return TypeParameter::null();
+TypeParameterPtr Function::TypeParameterAt(intptr_t index,
+                                           Nullability nullability) const {
+  const FunctionType& sig = FunctionType::Handle(signature());
+  return sig.TypeParameterAt(index, nullability);
 }
 
 void Function::set_kind(UntaggedFunction::Kind value) const {
@@ -8086,7 +8197,6 @@
     const Function& function,
     const Instance& receiver,
     const TypeArguments& instantiator_type_args,
-    const TypeArguments& type_params,
     const Array& args,
     const ArgumentsDescriptor& args_desc) {
   ASSERT(!function.IsNull());
@@ -8218,11 +8328,10 @@
     receiver ^= args.At(args_desc.FirstArgIndex());
   }
 
-  const auto& params = TypeArguments::Handle(zone, type_parameters());
   const auto& function_type_arguments = TypeArguments::Handle(
       zone, RetrieveFunctionTypeArguments(thread, zone, *this, receiver,
-                                          instantiator_type_arguments, params,
-                                          args, args_desc));
+                                          instantiator_type_arguments, args,
+                                          args_desc));
   return Function::DoArgumentTypesMatch(
       args, args_desc, instantiator_type_arguments, function_type_arguments);
 }
@@ -8248,23 +8357,29 @@
     const intptr_t kNumParentTypeArgs = NumParentTypeArguments();
     ASSERT(function_type_arguments.HasCount(kNumParentTypeArgs +
                                             kNumLocalTypeArgs));
-    const auto& params = TypeArguments::Handle(zone, type_parameters());
-    auto& parameter = TypeParameter::Handle(zone);
-    auto& type = AbstractType::Handle(zone);
-    auto& bound = AbstractType::Handle(zone);
-    for (intptr_t i = 0; i < kNumLocalTypeArgs; i++) {
-      parameter ^= params.TypeAt(i);
-      type = parameter.ptr();
-      bound = parameter.bound();
-      // Only perform non-covariant checks where the bound is not the top type.
-      if (parameter.IsGenericCovariantImpl() || bound.IsTopTypeForSubtyping()) {
-        continue;
-      }
-      if (!AbstractType::InstantiateAndTestSubtype(&type, &bound,
-                                                   instantiator_type_arguments,
-                                                   function_type_arguments)) {
-        const auto& name = String::Handle(zone, parameter.name());
-        return Error::RawCast(ThrowTypeError(token_pos(), type, bound, name));
+    const auto& params = TypeParameters::Handle(zone, type_parameters());
+    // No checks are needed if all bounds are dynamic.
+    if (!params.AllDynamicBounds()) {
+      auto& param = AbstractType::Handle(zone);
+      auto& bound = AbstractType::Handle(zone);
+      for (intptr_t i = 0; i < kNumLocalTypeArgs; i++) {
+        bound = params.BoundAt(i);
+        // Only perform non-covariant checks where the bound is not
+        // the top type.
+        if (params.IsGenericCovariantImplAt(i) ||
+            bound.IsTopTypeForSubtyping()) {
+          continue;
+        }
+        param = TypeParameterAt(i);
+        if (!AbstractType::InstantiateAndTestSubtype(
+                &param, &bound, instantiator_type_arguments,
+                function_type_arguments)) {
+          const auto& names = Array::Handle(zone, params.names());
+          auto& name = String::Handle(zone);
+          name ^= names.At(i);
+          return Error::RawCast(
+              ThrowTypeError(token_pos(), param, bound, name));
+        }
       }
     }
   } else {
@@ -8484,49 +8599,35 @@
       FunctionType::New(remaining_parent_type_params, nullability(), space));
   AbstractType& type = AbstractType::Handle(zone);
 
-  // Copy the type parameters and instantiate their bounds (if necessary).
+  // Copy the type parameters and instantiate their bounds and defaults.
   if (!delete_type_parameters) {
-    const TypeArguments& type_params =
-        TypeArguments::Handle(zone, type_parameters());
+    const TypeParameters& type_params =
+        TypeParameters::Handle(zone, type_parameters());
     if (!type_params.IsNull()) {
-      TypeArguments& instantiated_type_params = TypeArguments::Handle(zone);
-      TypeParameter& type_param = TypeParameter::Handle(zone);
-      String& param_name = String::Handle(zone);
-      for (intptr_t i = 0; i < type_params.Length(); ++i) {
-        type_param ^= type_params.TypeAt(i);
-        ASSERT(type_param.index() == num_parent_type_args + i);
-        type = type_param.bound();
-        if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
-          type = type.InstantiateFrom(instantiator_type_arguments,
-                                      function_type_arguments,
-                                      num_free_fun_type_params, space, trail);
-          // A returned null type indicates a failed instantiation in dead code
-          // that must be propagated up to the caller, the optimizing compiler.
-          if (type.IsNull()) {
-            return FunctionType::null();
-          }
-          ASSERT(type_param.IsFinalized());
-          param_name = type_param.name();
-          type_param = TypeParameter::New(
-              Object::null_class(), type_param.base(), type_param.index(),
-              param_name, type, type_param.IsGenericCovariantImpl(),
-              type_param.nullability());
-          type_param.SetIsFinalized();
-          if (instantiated_type_params.IsNull()) {
-            instantiated_type_params = TypeArguments::New(type_params.Length());
-            for (intptr_t j = 0; j < i; ++j) {
-              type = type_params.TypeAt(j);
-              instantiated_type_params.SetTypeAt(j, type);
-            }
-          }
-          instantiated_type_params.SetTypeAt(i, type_param);
-        } else if (!instantiated_type_params.IsNull()) {
-          instantiated_type_params.SetTypeAt(i, type_param);
-        }
+      const TypeParameters& sig_type_params =
+          TypeParameters::Handle(zone, TypeParameters::New());
+      // No need to set names that are ignored in a signature, however, the
+      // length of the names array defines the number of type parameters.
+      sig_type_params.set_names(Array::Handle(zone, type_params.names()));
+      sig_type_params.set_flags(Array::Handle(zone, type_params.flags()));
+      TypeArguments& type_args = TypeArguments::Handle(zone);
+      type_args = type_params.bounds();
+      if (!type_args.IsNull() &&
+          !type_args.IsInstantiated(kAny, num_free_fun_type_params)) {
+        type_args = type_args.InstantiateFrom(
+            instantiator_type_arguments, function_type_arguments,
+            num_free_fun_type_params, space, trail);
       }
-      sig.set_type_parameters(instantiated_type_params.IsNull()
-                                  ? type_params
-                                  : instantiated_type_params);
+      sig_type_params.set_bounds(type_args);
+      type_args = type_params.defaults();
+      if (!type_args.IsNull() &&
+          !type_args.IsInstantiated(kAny, num_free_fun_type_params)) {
+        type_args = type_args.InstantiateFrom(
+            instantiator_type_arguments, function_type_arguments,
+            num_free_fun_type_params, space, trail);
+      }
+      sig_type_params.set_defaults(type_args);
+      sig.set_type_parameters(sig_type_params);
     }
   }
 
@@ -8609,20 +8710,56 @@
     return false;
   }
   if (num_type_params > 0) {
-    const TypeArguments& type_params =
-        TypeArguments::Handle(zone, type_parameters());
+    const TypeParameters& type_params =
+        TypeParameters::Handle(zone, type_parameters());
     ASSERT(!type_params.IsNull());
-    const TypeArguments& other_type_params =
-        TypeArguments::Handle(zone, other.type_parameters());
+    const TypeParameters& other_type_params =
+        TypeParameters::Handle(zone, other.type_parameters());
     ASSERT(!other_type_params.IsNull());
-    TypeParameter& type_param = TypeParameter::Handle(zone);
-    TypeParameter& other_type_param = TypeParameter::Handle(zone);
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type_param ^= type_params.TypeAt(i);
-      other_type_param ^= other_type_params.TypeAt(i);
-      if (!type_param.IsEquivalent(other_type_param, kind, trail)) {
+    if (kind == TypeEquality::kInSubtypeTest) {
+      if (!type_params.AllDynamicBounds() ||
+          !other_type_params.AllDynamicBounds()) {
+        AbstractType& bound = AbstractType::Handle(zone);
+        AbstractType& other_bound = AbstractType::Handle(zone);
+        for (intptr_t i = 0; i < num_type_params; i++) {
+          bound = type_params.BoundAt(i);
+          other_bound = other_type_params.BoundAt(i);
+          // Bounds that are mutual subtypes are considered equal.
+          if (!bound.IsSubtypeOf(other_bound, Heap::kOld) ||
+              !other_bound.IsSubtypeOf(bound, Heap::kOld)) {
+            return false;
+          }
+        }
+      }
+    } else {
+      if (NumParentTypeArguments() != other.NumParentTypeArguments()) {
         return false;
       }
+      const TypeArguments& bounds =
+          TypeArguments::Handle(zone, type_params.bounds());
+      const TypeArguments& other_bounds =
+          TypeArguments::Handle(zone, other_type_params.bounds());
+      if (!bounds.IsEquivalent(other_bounds, kind, trail)) {
+        return false;
+      }
+      if (kind == TypeEquality::kCanonical) {
+        // Compare default arguments.
+        const TypeArguments& defaults =
+            TypeArguments::Handle(zone, type_params.defaults());
+        const TypeArguments& other_defaults =
+            TypeArguments::Handle(zone, other_type_params.defaults());
+        if (defaults.IsNull()) {
+          if (!other_defaults.IsNull()) {
+            return false;
+          }
+        } else if (!defaults.IsEquivalent(other_defaults, kind, trail)) {
+          return false;
+        }
+      }
+    }
+    // Compare flags (IsGenericCovariantImpl).
+    if (!Array::Equals(type_params.flags(), other_type_params.flags())) {
+      return false;
     }
   }
   return true;
@@ -8814,11 +8951,6 @@
     // in new space.
     ASSERT(space == Heap::kOld);
   }
-  if (result.CachesDefaultTypeArguments()) {
-    // Make sure the default type arguments are set consistently with the
-    // function type parameters (currently null).
-    result.set_default_type_arguments(Object::empty_type_arguments());
-  }
 
   // Force-optimized functions are not debuggable because they cannot
   // deoptimize.
@@ -8934,9 +9066,8 @@
   // 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.set_type_parameters(
-      TypeArguments::Handle(zone, type_parameters()));
+      TypeParameters::Handle(zone, type_parameters()));
   closure_function.SetNumTypeParameters(NumTypeParameters());
-  closure_function.UpdateCachedDefaultTypeArguments(thread);
 
   // Set closure function's result type to this result type.
   closure_signature.set_result_type(AbstractType::Handle(zone, result_type()));
@@ -9170,39 +9301,15 @@
   }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  auto isolate_group = thread->isolate_group();
-  const TypeArguments& type_params =
-      TypeArguments::Handle(zone, type_parameters());
+  const TypeParameters& type_params =
+      TypeParameters::Handle(zone, type_parameters());
   if (!type_params.IsNull()) {
-    const intptr_t num_type_params = type_params.Length();
-    ASSERT(num_type_params > 0);
-    TypeParameter& type_param = TypeParameter::Handle(zone);
-    String& name = String::Handle(zone);
-    AbstractType& bound = AbstractType::Handle(zone);
     printer->AddString("<");
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type_param ^= type_params.TypeAt(i);
-      name = type_param.name();
-      printer->AddString(name.ToCString());
-      bound = type_param.bound();
-      // Do not print default bound or non-nullable Object bound in weak mode.
-      if (!bound.IsNull() &&
-          (!bound.IsObjectType() ||
-           (isolate_group->null_safety() && bound.IsNonNullable()))) {
-        printer->AddString(" extends ");
-        bound.PrintName(name_visibility, printer);
-        if (FLAG_show_internal_names) {
-          bound = type_param.default_argument();
-          if (!bound.IsNull() && !bound.IsDynamicType()) {
-            printer->AddString(" defaults to ");
-            bound.PrintName(name_visibility, printer);
-          }
-        }
-      }
-      if (i < num_type_params - 1) {
-        printer->AddString(", ");
-      }
-    }
+    const intptr_t base = NumParentTypeArguments();
+    const bool kIsClassTypeParameter = false;
+    // Type parameter names are meaningless after canonicalization.
+    type_params.Print(thread, zone, kIsClassTypeParameter, base,
+                      name_visibility, printer);
     printer->AddString(">");
   }
   printer->AddString("(");
@@ -9250,13 +9357,16 @@
       return false;
     }
   }
-  TypeArguments& type_params = TypeArguments::Handle(type_parameters());
-  TypeParameter& type_param = TypeParameter::Handle();
-  for (intptr_t i = 0; i < type_params.Length(); ++i) {
-    type_param ^= type_params.TypeAt(i);
-    type = type_param.bound();
-    if (!type.IsInstantiated(genericity, num_free_fun_type_params, trail)) {
-      return false;
+  const intptr_t num_type_params = NumTypeParameters();
+  if (num_type_params > 0) {
+    TypeParameters& type_params = TypeParameters::Handle(type_parameters());
+    if (!type_params.AllDynamicBounds()) {
+      for (intptr_t i = 0; i < type_params.Length(); ++i) {
+        type = type_params.BoundAt(i);
+        if (!type.IsInstantiated(genericity, num_free_fun_type_params, trail)) {
+          return false;
+        }
+      }
     }
   }
   return true;
@@ -9950,10 +10060,6 @@
                       value, *original));
 }
 
-void ClosureData::set_default_type_arguments(const TypeArguments& value) const {
-  untag()->set_default_type_arguments(value.ptr());
-}
-
 ClosureData::DefaultTypeArgumentsKind ClosureData::default_type_arguments_kind()
     const {
   return LoadNonPointer(&untag()->default_type_arguments_kind_);
@@ -9988,13 +10094,6 @@
   }
   buffer.Printf(" implicit_static_closure: 0x%" Px "",
                 static_cast<uword>(implicit_static_closure()));
-  buffer.AddString(" default_type_arguments: ");
-  if (default_type_arguments() == TypeArguments::null()) {
-    buffer.AddString("null");
-  } else {
-    buffer.AddString(
-        TypeArguments::Handle(zone, default_type_arguments()).ToCString());
-  }
   return buffer.buffer();
 }
 
@@ -11556,15 +11655,9 @@
   untag()->set_url(value.ptr());
 }
 
-#if defined(DART_PRECOMPILER)
-void Script::set_resolved_url(const Object& value) const {
-  untag()->set_resolved_url(value.ptr());
-}
-#else
 void Script::set_resolved_url(const String& value) const {
   untag()->set_resolved_url(value.ptr());
 }
-#endif
 
 void Script::set_source(const String& value) const {
   untag()->set_source(value.ptr());
@@ -19584,16 +19677,9 @@
   } else {
     const intptr_t len = (*trail)->length();
     ASSERT((len % 2) == 0);
-    const bool this_is_typeref = IsTypeRef();
-    const bool buddy_is_typeref = buddy.IsTypeRef();
-    // Note that at least one of 'this' and 'buddy' should be a typeref, with
-    // one exception, when the class of the 'this' type implements the 'call'
-    // method, thereby possibly creating a recursive type (see regress_29405).
     for (intptr_t i = 0; i < len; i += 2) {
-      if ((((*trail)->At(i).ptr() == this->ptr()) ||
-           (buddy_is_typeref && (*trail)->At(i).Equals(*this))) &&
-          (((*trail)->At(i + 1).ptr() == buddy.ptr()) ||
-           (this_is_typeref && (*trail)->At(i + 1).Equals(buddy)))) {
+      if ((*trail)->At(i).ptr() == this->ptr() &&
+          (*trail)->At(i + 1).ptr() == buddy.ptr()) {
         return true;
       }
     }
@@ -19705,7 +19791,8 @@
   Class& cls = Class::Handle(zone);
   if (IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(*this);
-    printer->AddString(String::Handle(type_param.name()).ToCString());
+    // Type parameter names are meaningless after canonicalization.
+    printer->AddString(type_param.CanonicalNameCString());
     printer->AddString(NullabilitySuffix(name_visibility));
     return;
   }
@@ -19943,10 +20030,6 @@
     }
     const AbstractType& bound = AbstractType::Handle(zone, type_param.bound());
     ASSERT(bound.IsFinalized());
-    // Avoid cycles with F-bounded types.
-    if (TestAndAddBuddyToTrail(&trail, other)) {
-      return true;
-    }
     if (bound.IsSubtypeOf(other, space, trail)) {
       return true;
     }
@@ -20773,12 +20856,12 @@
   AbstractType& type = AbstractType::Handle();
   const intptr_t num_type_params = NumTypeParameters();
   if (num_type_params > 0) {
-    const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type = type_params.TypeAt(i);
-      type = TypeParameter::Cast(type).bound();
-      result = CombineHashes(result, type.Hash());
-    }
+    const TypeParameters& type_params =
+        TypeParameters::Handle(type_parameters());
+    const TypeArguments& bounds = TypeArguments::Handle(type_params.bounds());
+    result = CombineHashes(result, bounds.Hash());
+    // Since the default arguments are ignored when comparing two generic
+    // function types for type equality, the hash does not depend on them.
   }
   type = result_type();
   result = CombineHashes(result, type.Hash());
@@ -20867,17 +20950,20 @@
 }
 
 bool FunctionType::IsRecursive(TrailPtr trail) const {
-  AbstractType& type = AbstractType::Handle();
-  const intptr_t num_type_params = NumTypeParameters();
-  if (num_type_params > 0) {
-    const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type = type_params.TypeAt(i);
-      if (type.IsRecursive(trail)) {
-        return true;
-      }
+  if (IsGeneric()) {
+    const TypeParameters& type_params =
+        TypeParameters::Handle(type_parameters());
+    TypeArguments& type_args = TypeArguments::Handle();
+    type_args = type_params.bounds();
+    if (type_args.IsRecursive(trail)) {
+      return true;
+    }
+    type_args = type_params.defaults();
+    if (type_args.IsRecursive(trail)) {
+      return true;
     }
   }
+  AbstractType& type = AbstractType::Handle();
   type = result_type();
   if (type.IsRecursive(trail)) {
     return true;
@@ -20902,23 +20988,23 @@
     // its signature.
     return false;
   }
-  AbstractType& type = AbstractType::Handle(zone);
   const intptr_t num_type_params = NumTypeParameters();
   if (num_type_params > 0) {
-    const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
-    TypeParameter& type_param = TypeParameter::Handle(zone);
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type_param ^= type_params.TypeAt(i);
-      type = type_param.bound();
-      if (type.RequireConstCanonicalTypeErasure(zone, trail)) {
-        return true;
-      }
-      type = type_param.default_argument();
-      if (type.RequireConstCanonicalTypeErasure(zone, trail)) {
-        return true;
-      }
+    const TypeParameters& type_params =
+        TypeParameters::Handle(type_parameters());
+    TypeArguments& type_args = TypeArguments::Handle();
+    type_args = type_params.bounds();
+    if (type_args.RequireConstCanonicalTypeErasure(zone, 0, num_type_params,
+                                                   trail)) {
+      return true;
+    }
+    type_args = type_params.defaults();
+    if (type_args.RequireConstCanonicalTypeErasure(zone, 0, num_type_params,
+                                                   trail)) {
+      return true;
     }
   }
+  AbstractType& type = AbstractType::Handle(zone);
   type = result_type();
   if (type.RequireConstCanonicalTypeErasure(zone, trail)) {
     return true;
@@ -20940,18 +21026,19 @@
   if (IsCanonical()) {
 #ifdef DEBUG
     // Verify that all fields are allocated in old space and are canonical.
-    AbstractType& type = AbstractType::Handle(zone);
-    const intptr_t num_type_params = NumTypeParameters();
-    if (num_type_params > 0) {
-      const TypeArguments& type_params =
-          TypeArguments::Handle(zone, type_parameters());
+    if (IsGeneric()) {
+      const TypeParameters& type_params =
+          TypeParameters::Handle(zone, type_parameters());
       ASSERT(type_params.IsOld());
-      for (intptr_t i = 0; i < num_type_params; i++) {
-        type = type_params.TypeAt(i);
-        ASSERT(type.IsOld());
-        ASSERT(type.IsCanonical());
-      }
+      TypeArguments& type_args = TypeArguments::Handle(zone);
+      type_args = type_params.bounds();
+      ASSERT(type_args.IsOld());
+      ASSERT(type_args.IsCanonical());
+      type_args = type_params.defaults();
+      ASSERT(type_args.IsOld());
+      ASSERT(type_args.IsCanonical());
     }
+    AbstractType& type = AbstractType::Handle(zone);
     type = result_type();
     ASSERT(type.IsOld());
     ASSERT(type.IsCanonical());
@@ -20979,19 +21066,22 @@
   if (sig.IsNull()) {
     // The function type was not found in the table. It is not canonical yet.
     // Canonicalize its type parameters and types.
-    const intptr_t num_type_params = NumTypeParameters();
-    if (num_type_params > 0) {
-      const TypeArguments& type_params =
-          TypeArguments::Handle(zone, type_parameters());
+    if (IsGeneric()) {
+      const TypeParameters& type_params =
+          TypeParameters::Handle(zone, type_parameters());
       ASSERT(type_params.IsOld());
-      TypeParameter& type_param = TypeParameter::Handle(zone);
-      for (intptr_t i = 0; i < num_type_params; i++) {
-        type_param ^= type_params.TypeAt(i);
-        if (!type_param.IsCanonical()) {
-          type_param ^= type_param.Canonicalize(thread, trail);
-          type_params.SetTypeAt(i, type_param);
-          SetHash(0);
-        }
+      TypeArguments& type_args = TypeArguments::Handle(zone);
+      type_args = type_params.bounds();
+      if (!type_args.IsCanonical()) {
+        type_args = type_args.Canonicalize(thread, trail);
+        type_params.set_bounds(type_args);
+        SetHash(0);
+      }
+      type_args = type_params.defaults();
+      if (!type_args.IsCanonical()) {
+        type_args = type_args.Canonicalize(thread, trail);
+        type_params.set_defaults(type_args);
+        SetHash(0);
       }
     }
     AbstractType& type = AbstractType::Handle(zone);
@@ -21143,7 +21233,7 @@
 }
 
 void TypeRef::set_type(const AbstractType& value) const {
-  ASSERT(value.IsNull() || value.IsType() || value.IsFunctionType());
+  ASSERT(!value.IsTypeRef());
   untag()->set_type(value.ptr());
 }
 
@@ -21194,7 +21284,14 @@
   //    type arguments are set).
   const AbstractType& ref_type = AbstractType::Handle(type());
   ASSERT(!ref_type.IsNull());
-  uint32_t result = ref_type.type_class_id();
+  uint32_t result;
+  if (ref_type.IsTypeParameter()) {
+    result = TypeParameter::Cast(ref_type).parameterized_class_id();
+    result = CombineHashes(result, TypeParameter::Cast(ref_type).index());
+  } else {
+    ASSERT(ref_type.IsType() || ref_type.IsFunctionType());
+    result = ref_type.type_class_id();
+  }
   // A legacy type should have the same hash as its non-nullable version to be
   // consistent with the definition of type equality in Dart code.
   Nullability ref_type_nullability = ref_type.nullability();
@@ -21250,11 +21347,6 @@
       UntaggedTypeParameter::BeingFinalizedBit::update(true, untag()->flags_));
 }
 
-void TypeParameter::SetGenericCovariantImpl(bool value) const {
-  set_flags(UntaggedTypeParameter::GenericCovariantImplBit::update(
-      value, untag()->flags_));
-}
-
 void TypeParameter::set_nullability(Nullability value) const {
   StoreNonPointer(&untag()->nullability_, static_cast<uint8_t>(value));
 }
@@ -21294,15 +21386,9 @@
   }
   // Although the type parameter is instantiated, its bound may not be.
   const AbstractType& upper_bound = AbstractType::Handle(bound());
-  ASSERT(!upper_bound.IsTypeRef());
-  if (upper_bound.IsTypeParameter() || upper_bound.IsFunctionType() ||
-      upper_bound.arguments() != TypeArguments::null()) {
-    // Use trail to break cycles created by bound referring to type parameter.
-    if (!TestAndAddToTrail(&trail) &&
-        !upper_bound.IsInstantiated(genericity, num_free_fun_type_params,
-                                    trail)) {
-      return false;
-    }
+  if (!upper_bound.IsInstantiated(genericity, num_free_fun_type_params,
+                                  trail)) {
+    return false;
   }
   return true;
 }
@@ -21353,34 +21439,11 @@
           index() != other_type_param.index()) {
         return false;
       }
-      // Compare bounds.
-      if (TestAndAddBuddyToTrail(&trail, other_type_param)) {
-        return true;
-      }
       AbstractType& type = AbstractType::Handle(bound());
       AbstractType& other_type = AbstractType::Handle(other_type_param.bound());
       if (!type.IsEquivalent(other_type, kind, trail)) {
         return false;
       }
-      if (kind == TypeEquality::kCanonical) {
-        // Compare names.
-        if (name() != other_type_param.name()) {
-          return false;
-        }
-        // Compare default arguments.
-        type = default_argument();
-        other_type = other_type_param.default_argument();
-        if (type.IsNull()) {
-          if (!other_type.IsNull()) {
-            return false;
-          }
-        } else if (!type.IsEquivalent(other_type, kind, trail)) {
-          return false;
-        }
-      }
-    }
-    if (IsGenericCovariantImpl() != other_type_param.IsGenericCovariantImpl()) {
-      return false;
     }
   } else {
     if (!other_type_param.IsClassTypeParameter()) {
@@ -21393,8 +21456,7 @@
         return false;
       }
       if (base() != other_type_param.base() ||
-          index() != other_type_param.index() ||
-          name() != other_type_param.name()) {
+          index() != other_type_param.index()) {
         return false;
       }
     } else {
@@ -21402,10 +21464,6 @@
         return false;
       }
     }
-    // Compare bounds.
-    if (TestAndAddBuddyToTrail(&trail, other_type_param)) {
-      return true;
-    }
     AbstractType& upper_bound = AbstractType::Handle(bound());
     AbstractType& other_type_param_upper_bound =
         AbstractType::Handle(other_type_param.bound());
@@ -21441,16 +21499,7 @@
 }
 
 bool TypeParameter::IsRecursive(TrailPtr trail) const {
-  if (TestAndAddToTrail(&trail)) {
-    return true;
-  }
-  AbstractType& type = AbstractType::Handle();
-  type = bound();
-  if (type.IsRecursive(trail)) {
-    return true;
-  }
-  type = default_argument();
-  if (type.IsRecursive(trail)) {
+  if (AbstractType::Handle(bound()).IsRecursive(trail)) {
     return true;
   }
   return false;
@@ -21494,21 +21543,11 @@
   StoreNonPointer(&untag()->index_, value);
 }
 
-void TypeParameter::set_name(const String& value) const {
-  ASSERT(value.IsSymbol());
-  untag()->set_name(value.ptr());
-}
-
 void TypeParameter::set_bound(const AbstractType& value) const {
   ASSERT(!IsCanonical());
   untag()->set_bound(value.ptr());
 }
 
-void TypeParameter::set_default_argument(const AbstractType& value) const {
-  ASSERT(!IsCanonical());
-  untag()->set_default_argument(value.ptr());
-}
-
 AbstractTypePtr TypeParameter::GetFromTypeArguments(
     const TypeArguments& instantiator_type_arguments,
     const TypeArguments& function_type_arguments) const {
@@ -21534,13 +21573,6 @@
       AbstractType& upper_bound = AbstractType::Handle(bound());
       if (!upper_bound.IsInstantiated(kAny, num_free_fun_type_params,
                                       nullptr)) {
-        // Use trail to break cycles created by bound referring to type param.
-        // The instantiation trail must contain pairs, so add itself as buddy.
-        if (TestAndAddBuddyToTrail(&trail, *this)) {
-          // If the type parameter is already in the trail, it is returned
-          // unchanged here and will be processed when returning from recursion.
-          return ptr();
-        }
         upper_bound = upper_bound.InstantiateFrom(
             instantiator_type_arguments, function_type_arguments,
             num_free_fun_type_params, space, trail);
@@ -21590,13 +21622,9 @@
   if (IsCanonical()) {
 #ifdef DEBUG
     // Verify that all fields are allocated in old space and are canonical.
-    AbstractType& type = AbstractType::Handle(zone);
-    type = bound();
-    ASSERT(type.IsOld());
-    ASSERT(type.IsCanonical());
-    type = default_argument();
-    ASSERT(type.IsOld());
-    ASSERT(type.IsCanonical());
+    const AbstractType& upper_bound = AbstractType::Handle(zone, bound());
+    ASSERT(upper_bound.IsOld());
+    ASSERT(upper_bound.IsCanonical() || upper_bound.IsTypeRef());
 #endif
     return this->ptr();
   }
@@ -21611,33 +21639,15 @@
     ASSERT(object_store->canonical_type_parameters() == table.Release().ptr());
   }
   if (type_parameter.IsNull()) {
-    // The type parameter was not found in the table. It is not canonical yet.
-    // Canonicalize its bound and default argument.
-    // However, if the type parameter is already being canonicalized, it is part
-    // of a cycle via its bound. Return it now and let the caller finish
-    // canonicalizing it.
-    if (TestAndAddToTrail(&trail)) {
-      return ptr();
-    }
-    AbstractType& type = AbstractType::Handle(zone);
-    type = bound();
-    type = type.Canonicalize(thread, trail);
+    AbstractType& upper_bound = AbstractType::Handle(zone, bound());
+    upper_bound = upper_bound.Canonicalize(thread, trail);
     if (IsCanonical()) {
-      // Canonicalizing bound or default argument canonicalized this type
-      // parameter as a side effect.
+      // Canonicalizing the bound canonicalized this type parameter
+      // as a side effect.
       ASSERT(IsRecursive());  // Self-referring bound or default argument.
       return ptr();
     }
-    set_bound(type);
-    type = default_argument();
-    type = type.Canonicalize(thread, trail);
-    if (IsCanonical()) {
-      // Canonicalizing bound or default argument canonicalized this type
-      // parameter as a side effect.
-      ASSERT(IsRecursive());  // Self-referring bound or default argument.
-      return this->ptr();
-    }
-    set_default_argument(type);
+    set_bound(upper_bound);
     // Check to see if the type parameter got added to canonical table as part
     // of the canonicalization of its bound and default argument.
     SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
@@ -21663,6 +21673,9 @@
 
 #if defined(DEBUG)
 bool TypeParameter::CheckIsCanonical(Thread* thread) const {
+  if (IsRecursive()) {
+    return true;
+  }
   Zone* zone = thread->zone();
   auto isolate_group = thread->isolate_group();
 
@@ -21682,23 +21695,10 @@
 uword TypeParameter::ComputeHash() const {
   ASSERT(IsFinalized() || IsBeingFinalized());  // Bound may not be finalized.
   uint32_t result = parameterized_class_id();
-  // Hashing the bound reduces collisions, but may also create cycles.
-  // Therefore, we only hash the type_class_id of the bound,
-  // and do not use its full hash, as we do for TypeRef.
   const AbstractType& upper_bound = AbstractType::Handle(bound());
-  if (upper_bound.IsTypeParameter()) {
-    ASSERT(upper_bound.IsFinalized() || upper_bound.IsBeingFinalized());
-    result = CombineHashes(result, TypeParameter::Cast(upper_bound).index());
-  } else {
-    // Note that the bound may not be finalized yet.
-    result = CombineHashes(result, upper_bound.type_class_id());
-  }
-  // Since the default argument is ignored when comparing two generic function
-  // types for type equality, the hash does not depend on it.
-  result = CombineHashes(result, IsGenericCovariantImpl() ? 1 : 0);
+  result = CombineHashes(result, upper_bound.Hash());  // May be a TypeRef.
   result = CombineHashes(result, base());
   result = CombineHashes(result, index());
-  result = CombineHashes(result, String::Handle(name()).Hash());
   // A legacy type should have the same hash as its non-nullable version to be
   // consistent with the definition of type equality in Dart code.
   Nullability type_param_nullability = nullability();
@@ -21721,21 +21721,16 @@
 TypeParameterPtr TypeParameter::New(const Class& parameterized_class,
                                     intptr_t base,
                                     intptr_t index,
-                                    const String& name,
                                     const AbstractType& bound,
-                                    bool is_generic_covariant_impl,
                                     Nullability nullability) {
   Zone* Z = Thread::Current()->zone();
   const TypeParameter& result = TypeParameter::Handle(Z, TypeParameter::New());
   result.set_parameterized_class(parameterized_class);
   result.set_base(base);
   result.set_index(index);
-  result.set_name(name);
   result.set_bound(bound);
-  result.set_default_argument(Object::dynamic_type());
   result.set_flags(0);
   result.set_nullability(nullability);
-  result.SetGenericCovariantImpl(is_generic_covariant_impl);
   result.SetHash(0);
 
   result.SetTypeTestingStub(
@@ -21747,12 +21742,28 @@
   StoreNonPointer(&untag()->flags_, flags);
 }
 
-const char* TypeParameter::ToCString() const {
+const char* TypeParameter::CanonicalNameCString(bool is_class_type_parameter,
+                                                intptr_t base,
+                                                intptr_t index) {
   Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  ZoneTextBuffer printer(zone);
+  ZoneTextBuffer printer(thread->zone());
+  const char* base_fmt = is_class_type_parameter ? "C%" Pd : "F%" Pd;
+  const char* index_fmt = is_class_type_parameter ? "X%" Pd : "Y%" Pd;
+  if (base != 0) {
+    printer.Printf(base_fmt, base);
+  }
+  printer.Printf(index_fmt, index - base);
+  return printer.buffer();
+}
+
+const char* TypeParameter::ToCString() const {
+  if (IsNull()) {
+    return "TypeParameter: null";
+  }
+  Thread* thread = Thread::Current();
+  ZoneTextBuffer printer(thread->zone());
   printer.Printf("TypeParameter: ");
-  printer.AddString(String::Handle(zone, name()).ToCString());
+  printer.AddString(CanonicalNameCString());
   printer.AddString(NullabilitySuffix(kInternalName));
   printer.Printf("; bound: ");
   const AbstractType& upper_bound = AbstractType::Handle(bound());
@@ -21761,15 +21772,6 @@
   } else {
     upper_bound.PrintName(kInternalName, &printer);
   }
-  if (FLAG_show_internal_names) {
-    printer.Printf("; default: ");
-    const AbstractType& default_arg = AbstractType::Handle(default_argument());
-    if (default_arg.IsNull()) {
-      printer.AddString("<null>");
-    } else {
-      default_arg.PrintName(kInternalName, &printer);
-    }
-  }
   return printer.buffer();
 }
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 75bab66..29ed4b3 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -460,6 +460,7 @@
   static ClassPtr class_class() { return class_class_; }
   static ClassPtr dynamic_class() { return dynamic_class_; }
   static ClassPtr void_class() { return void_class_; }
+  static ClassPtr type_parameters_class() { return type_parameters_class_; }
   static ClassPtr type_arguments_class() { return type_arguments_class_; }
   static ClassPtr patch_class_class() { return patch_class_class_; }
   static ClassPtr function_class() { return function_class_; }
@@ -774,13 +775,14 @@
   static BoolPtr true_;
   static BoolPtr false_;
 
-  static ClassPtr class_class_;           // Class of the Class vm object.
-  static ClassPtr dynamic_class_;         // Class of the 'dynamic' type.
-  static ClassPtr void_class_;            // Class of the 'void' type.
-  static ClassPtr type_arguments_class_;  // Class of TypeArguments vm object.
-  static ClassPtr patch_class_class_;     // Class of the PatchClass vm object.
-  static ClassPtr function_class_;        // Class of the Function vm object.
-  static ClassPtr closure_data_class_;    // Class of ClosureData vm obj.
+  static ClassPtr class_class_;            // Class of the Class vm object.
+  static ClassPtr dynamic_class_;          // Class of the 'dynamic' type.
+  static ClassPtr void_class_;             // Class of the 'void' type.
+  static ClassPtr type_parameters_class_;  // Class of TypeParameters vm object.
+  static ClassPtr type_arguments_class_;   // Class of TypeArguments vm object.
+  static ClassPtr patch_class_class_;      // Class of the PatchClass vm object.
+  static ClassPtr function_class_;         // Class of the Function vm object.
+  static ClassPtr closure_data_class_;     // Class of ClosureData vm obj.
   static ClassPtr ffi_trampoline_data_class_;  // Class of FfiTrampolineData
                                                // vm obj.
   static ClassPtr field_class_;                // Class of the Field vm object.
@@ -1103,21 +1105,22 @@
   LibraryPtr library() const { return untag()->library(); }
   void set_library(const Library& value) const;
 
-  // The type parameters (and their bounds) are specified as an array of
-  // TypeParameter.
-  TypeArgumentsPtr type_parameters() const {
+  // The formal type parameters and their bounds (no defaults), are specified as
+  // an object of type TypeParameters.
+  TypeParametersPtr type_parameters() const {
     ASSERT(is_declaration_loaded());
     return untag()->type_parameters();
   }
-  void set_type_parameters(const TypeArguments& value) const;
+  void set_type_parameters(const TypeParameters& value) const;
   intptr_t NumTypeParameters(Thread* thread) const;
   intptr_t NumTypeParameters() const {
     return NumTypeParameters(Thread::Current());
   }
 
-  // Return a TypeParameter if the type_name is a type parameter of this class.
-  // Return null otherwise.
-  TypeParameterPtr LookupTypeParameter(const String& type_name) const;
+  // Return the type parameter declared at index.
+  TypeParameterPtr TypeParameterAt(
+      intptr_t index,
+      Nullability nullability = Nullability::kNonNullable) const;
 
   // The type argument vector is flattened and includes the type arguments of
   // the super class.
@@ -2614,9 +2617,9 @@
   // are packed into SMIs, but omitted if they're 0.
   bool IsRequiredAt(intptr_t index) const;
 
-  // The type parameters (and their bounds) are specified as an array of
-  // TypeParameter stored in the signature. They are part of the function type.
-  TypeArgumentsPtr type_parameters() const {
+  // The formal type parameters, their bounds, and defaults, are specified as an
+  // object of type TypeParameters stored in the signature.
+  TypeParametersPtr type_parameters() const {
     return untag()->signature()->untag()->type_parameters();
   }
 
@@ -2635,12 +2638,10 @@
     return NumParentTypeArguments() + NumTypeParameters();
   }
 
-  // Return a TypeParameter if the type_name is a type parameter of this
-  // function or of one of its parent functions.
-  // Unless NULL, adjust function_level accordingly (in and out parameter).
-  // Return null otherwise.
-  TypeParameterPtr LookupTypeParameter(const String& type_name,
-                                       intptr_t* function_level) const;
+  // 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.
@@ -2735,21 +2736,9 @@
       Thread* thread,
       DefaultTypeArgumentsKind* kind_out = nullptr) const;
 
-  // Whether this function should have a cached type arguments vector for the
-  // instantiated-to-bounds version of the type parameters.
-  bool CachesDefaultTypeArguments() const { return IsClosureFunction(); }
-
-  // Updates the cached default type arguments vector for this function if it
-  // caches and for its implicit closure function if it has one. If the
-  // default arguments are all canonical, the cached default type arguments
-  // vector is canonicalized. Should be run any time the type parameters vector
-  // is changed or if the default arguments of any type parameters are updated.
-  void UpdateCachedDefaultTypeArguments(Thread* thread) const;
-
-  // These are only usable for functions that cache the default type arguments.
-  TypeArgumentsPtr default_type_arguments(
-      DefaultTypeArgumentsKind* kind_out = nullptr) const;
-  void set_default_type_arguments(const TypeArguments& value) const;
+  // Only usable for closure functions.
+  DefaultTypeArgumentsKind default_type_arguments_kind() const;
+  void set_default_type_arguments_kind(DefaultTypeArgumentsKind value) const;
 
   // Enclosing outermost function of this local function.
   FunctionPtr GetOutermostFunction() const;
@@ -3787,9 +3776,6 @@
     return RoundedAllocationSize(sizeof(UntaggedClosureData));
   }
 
-  static intptr_t default_type_arguments_offset() {
-    return OFFSET_OF(UntaggedClosureData, default_type_arguments_);
-  }
   static intptr_t default_type_arguments_kind_offset() {
     return OFFSET_OF(UntaggedClosureData, default_type_arguments_kind_);
   }
@@ -3816,11 +3802,6 @@
   }
   void set_implicit_static_closure(const Instance& closure) const;
 
-  TypeArgumentsPtr default_type_arguments() const {
-    return untag()->default_type_arguments();
-  }
-  void set_default_type_arguments(const TypeArguments& value) const;
-
   DefaultTypeArgumentsKind default_type_arguments_kind() const;
   void set_default_type_arguments_kind(DefaultTypeArgumentsKind value) const;
 
@@ -4222,7 +4203,7 @@
   // Returns false if any value read from this field is guaranteed to be
   // not null.
   // Internally we is_nullable_ field contains either kNullCid (nullable) or
-  // kInvalidCid (non-nullable) instead of boolean. This is done to simplify
+  // kIllegalCid (non-nullable) instead of boolean. This is done to simplify
   // guarding sequence in the generated code.
   bool is_nullable() const;
   void set_is_nullable(bool val) const {
@@ -4531,11 +4512,7 @@
   void SetCachedMaxPosition(intptr_t value) const;
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-#if defined(DART_PRECOMPILER)
-  void set_resolved_url(const Object& value) const;
-#else
   void set_resolved_url(const String& value) const;
-#endif
   void set_source(const String& value) const;
   void set_load_timestamp(int64_t value) const;
   ArrayPtr debug_positions() const;
@@ -7487,6 +7464,90 @@
   friend class Class;
 };
 
+// TypeParameters represents a list of formal type parameters with their bounds
+// and their default values as calculated by CFE.
+class TypeParameters : public Object {
+ public:
+  intptr_t Length() const;
+
+  static intptr_t names_offset() {
+    return OFFSET_OF(UntaggedTypeParameters, names_);
+  }
+  StringPtr NameAt(intptr_t index) const;
+  void SetNameAt(intptr_t index, const String& value) const;
+
+  static intptr_t flags_offset() {
+    return OFFSET_OF(UntaggedTypeParameters, flags_);
+  }
+
+  static intptr_t bounds_offset() {
+    return OFFSET_OF(UntaggedTypeParameters, bounds_);
+  }
+  AbstractTypePtr BoundAt(intptr_t index) const;
+  void SetBoundAt(intptr_t index, const AbstractType& value) const;
+  bool AllDynamicBounds() const;
+
+  static intptr_t defaults_offset() {
+    return OFFSET_OF(UntaggedTypeParameters, defaults_);
+  }
+  AbstractTypePtr DefaultAt(intptr_t index) const;
+  void SetDefaultAt(intptr_t index, const AbstractType& value) const;
+  bool AllDynamicDefaults() const;
+
+  // The isGenericCovariantImpl bits are packed into SMIs in the flags array,
+  // but omitted if they're 0.
+  bool IsGenericCovariantImplAt(intptr_t index) const;
+  void SetIsGenericCovariantImplAt(intptr_t index, bool value) const;
+
+  // The number of flags per Smi should be a power of 2 in order to simplify the
+  // generated code accessing the flags array.
+#if !defined(DART_COMPRESSED_POINTERS)
+  static const intptr_t kFlagsPerSmiShift = kBitsPerWordLog2 - 1;
+#else
+  static const intptr_t kFlagsPerSmiShift = kBitsPerWordLog2 - 2;
+#endif
+  static const intptr_t kFlagsPerSmi = 1LL << kFlagsPerSmiShift;
+  COMPILE_ASSERT(kFlagsPerSmi < kSmiBits);
+  static const intptr_t kFlagsPerSmiMask = kFlagsPerSmi - 1;
+
+  void Print(Thread* thread,
+             Zone* zone,
+             bool are_class_type_parameters,
+             intptr_t base,
+             NameVisibility name_visibility,
+             BaseTextBuffer* printer) const;
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(UntaggedTypeParameters));
+  }
+
+  static TypeParametersPtr New(Heap::Space space = Heap::kOld);
+  static TypeParametersPtr New(intptr_t count, Heap::Space space = Heap::kOld);
+
+ private:
+  ArrayPtr names() const { return untag()->names(); }
+  void set_names(const Array& value) const;
+  ArrayPtr flags() const { return untag()->flags(); }
+  void set_flags(const Array& value) const;
+  TypeArgumentsPtr bounds() const { return untag()->bounds(); }
+  void set_bounds(const TypeArguments& value) const;
+  TypeArgumentsPtr defaults() const { return untag()->defaults(); }
+  void set_defaults(const TypeArguments& value) const;
+
+  // Allocate and initialize the flags array to zero.
+  void AllocateFlags(Heap::Space space) const;
+  // Reset the flags array to null if all flags are zero.
+  void OptimizeFlags() const;
+
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeParameters, Object);
+  friend class Class;
+  friend class ClassFinalizer;
+  friend class Function;
+  friend class FunctionType;
+  friend class Object;
+  friend class Precompiler;
+};
+
 // A TypeArguments is an array of AbstractType.
 class TypeArguments : public Instance {
  public:
@@ -8311,6 +8372,8 @@
   }
 
   // Reexported so they can be used by the flow graph builders.
+  using PackedNumParentTypeArguments =
+      UntaggedFunctionType::PackedNumParentTypeArguments;
   using PackedHasNamedOptionalParameters =
       UntaggedFunctionType::PackedHasNamedOptionalParameters;
   using PackedNumFixedParameters =
@@ -8318,6 +8381,11 @@
   using PackedNumOptionalParameters =
       UntaggedFunctionType::PackedNumOptionalParameters;
 
+  // Return the type parameter declared at index.
+  TypeParameterPtr TypeParameterAt(
+      intptr_t index,
+      Nullability nullability = Nullability::kNonNullable) const;
+
   AbstractTypePtr result_type() const { return untag()->result_type(); }
   void set_result_type(const AbstractType& value) const;
 
@@ -8373,12 +8441,12 @@
   // parameters don't have flags.
   static intptr_t NameArrayLengthIncludingFlags(intptr_t num_parameters);
 
-  // The type parameters (and their bounds) are specified as an array of
-  // TypeParameter.
-  TypeArgumentsPtr type_parameters() const {
+  // The formal type parameters, their bounds, and defaults, are specified as an
+  // object of type TypeParameters.
+  TypeParametersPtr type_parameters() const {
     return untag()->type_parameters();
   }
-  void set_type_parameters(const TypeArguments& value) const;
+  void set_type_parameters(const TypeParameters& value) const;
   static intptr_t type_parameters_offset() {
     return OFFSET_OF(UntaggedFunctionType, type_parameters_);
   }
@@ -8540,11 +8608,6 @@
     return UntaggedTypeParameter::BeingFinalizedBit::decode(untag()->flags_);
   }
   virtual void SetIsBeingFinalized() const;
-  bool IsGenericCovariantImpl() const {
-    return UntaggedTypeParameter::GenericCovariantImplBit::decode(
-        untag()->flags_);
-  }
-  void SetGenericCovariantImpl(bool value) const;
   static intptr_t flags_offset() {
     return OFFSET_OF(UntaggedTypeParameter, flags_);
   }
@@ -8579,21 +8642,12 @@
     return OFFSET_OF(UntaggedTypeParameter, index_);
   }
 
-  StringPtr name() const { return untag()->name(); }
-  static intptr_t name_offset() {
-    return OFFSET_OF(UntaggedTypeParameter, name_);
-  }
   AbstractTypePtr bound() const { return untag()->bound(); }
   void set_bound(const AbstractType& value) const;
   static intptr_t bound_offset() {
     return OFFSET_OF(UntaggedTypeParameter, bound_);
   }
 
-  AbstractTypePtr default_argument() const {
-    return untag()->default_argument();
-  }
-  void set_default_argument(const AbstractType& value) const;
-
   virtual bool IsInstantiated(Genericity genericity = kAny,
                               intptr_t num_free_fun_type_params = kAllFree,
                               TrailPtr trail = nullptr) const;
@@ -8629,6 +8683,15 @@
       const TypeArguments& instantiator_type_arguments,
       const TypeArguments& function_type_arguments) const;
 
+  // Return a constructed name for this nameless type parameter.
+  const char* CanonicalNameCString() const {
+    return CanonicalNameCString(IsClassTypeParameter(), base(), index());
+  }
+
+  static const char* CanonicalNameCString(bool is_class_type_parameter,
+                                          intptr_t base,
+                                          intptr_t index);
+
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(UntaggedTypeParameter));
   }
@@ -8637,9 +8700,7 @@
   static TypeParameterPtr New(const Class& parameterized_class,
                               intptr_t base,
                               intptr_t index,
-                              const String& name,
                               const AbstractType& bound,
-                              bool is_generic_covariant_impl,
                               Nullability nullability);
 
  private:
@@ -8997,6 +9058,8 @@
     return GetCachedHash(ptr()) != 0;
   }
 
+  bool IsRecursive() const { return false; }  // Required by HashSet templates.
+
   static intptr_t hash_offset() {
 #if defined(HASH_IN_OBJECT_HEADER)
     COMPILE_ASSERT(UntaggedObject::kHashTagPos % kBitsPerByte == 0);
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 7f3da19..cc858f5 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -169,6 +169,15 @@
   }
 }
 
+void TypeParameters::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  JSONObject jsobj(stream);
+  jsobj.AddProperty("kind", "TypeParameters");
+  jsobj.AddProperty("flags", Array::Handle(flags()));
+  jsobj.AddProperty("names", Array::Handle(names()));
+  jsobj.AddProperty("bounds", TypeArguments::Handle(bounds()));
+  jsobj.AddProperty("defaults", TypeArguments::Handle(defaults()));
+}
+
 void TypeArguments::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   // The index in the canonical_type_arguments table cannot be used as part of
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 2aa73d8..0916e2a 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -244,6 +244,7 @@
   V(current_function, Function, CurrentFunction)                               \
   V(current_num_processed, Smi, CurrentNumProcessed)                           \
   V(current_param_index, Smi, CurrentParamIndex)                               \
+  V(current_type_param, Dynamic, CurrentTypeParam)                             \
   V(function_type_args, Dynamic, FunctionTypeArgs)
 
 #define DEFINE_FIELD(Name, _, __) LocalVariable* Name = nullptr;
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index d99acc8..1cdaff0 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -572,6 +572,7 @@
 COMPRESSED_VISITOR(UserTag)
 REGULAR_VISITOR(SubtypeTestCache)
 COMPRESSED_VISITOR(LoadingUnit)
+COMPRESSED_VISITOR(TypeParameters)
 VARIABLE_COMPRESSED_VISITOR(TypeArguments,
                             Smi::Value(raw_obj->untag()->length()))
 VARIABLE_COMPRESSED_VISITOR(LocalVarDescriptors, raw_obj->untag()->num_entries_)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index f386161..50f35b8 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -948,8 +948,7 @@
   COMPRESSED_POINTER_FIELD(ArrayPtr, interfaces)  // Array of AbstractType.
   COMPRESSED_POINTER_FIELD(ScriptPtr, script)
   COMPRESSED_POINTER_FIELD(LibraryPtr, library)
-  // Array of TypeParameter.
-  COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_parameters)
+  COMPRESSED_POINTER_FIELD(TypeParametersPtr, type_parameters)
   COMPRESSED_POINTER_FIELD(AbstractTypePtr, super_type)
   // Canonicalized const instances of this class.
   COMPRESSED_POINTER_FIELD(ArrayPtr, constants)
@@ -1352,9 +1351,7 @@
 #endif
   // Closure object for static implicit closures.
   COMPRESSED_POINTER_FIELD(InstancePtr, closure)
-  // Instantiate-to-bounds TAV for use when no TAV is provided.
-  COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, default_type_arguments)
-  VISIT_TO(CompressedObjectPtr, default_type_arguments)
+  VISIT_TO(CompressedObjectPtr, closure)
 
   enum class DefaultTypeArgumentsKind : uint8_t {
     // Only here to make sure it's explicitly set appropriately.
@@ -1452,7 +1449,7 @@
   TokenPosition end_token_pos_;
   ClassIdTagType guarded_cid_;
   ClassIdTagType is_nullable_;  // kNullCid if field can contain null value and
-                                // kInvalidCid otherwise.
+                                // kIllegalCid otherwise.
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   uint32_t kernel_offset_;
@@ -1486,13 +1483,7 @@
 
   VISIT_FROM(CompressedObjectPtr, url)
   COMPRESSED_POINTER_FIELD(StringPtr, url)
-#if defined(DART_PRECOMPILER)
-  // We use WSRs to keep the information available to the DWARF writer
-  // without being actually serialized.
-  COMPRESSED_POINTER_FIELD(ObjectPtr, resolved_url)
-#else
   COMPRESSED_POINTER_FIELD(StringPtr, resolved_url)
-#endif
   COMPRESSED_POINTER_FIELD(ArrayPtr, compile_time_constants)
   COMPRESSED_POINTER_FIELD(TypedDataPtr, line_starts)
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
@@ -2503,6 +2494,25 @@
   friend class SnapshotReader;
 };
 
+class UntaggedTypeParameters : public UntaggedObject {
+ private:
+  RAW_HEAP_OBJECT_IMPLEMENTATION(TypeParameters);
+
+  VISIT_FROM(CompressedObjectPtr, names)
+  // Length of names reflects the number of type parameters.
+  COMPRESSED_POINTER_FIELD(ArrayPtr, names)
+  // flags: isGenericCovariantImpl and (todo) variance.
+  COMPRESSED_POINTER_FIELD(ArrayPtr, flags)
+  COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, bounds)
+  // defaults is the instantiation to bounds (calculated by CFE).
+  COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, defaults)
+  VISIT_TO(CompressedObjectPtr, defaults)
+  CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
+
+  friend class Object;
+  friend class SnapshotReader;
+};
+
 class UntaggedAbstractType : public UntaggedInstance {
  public:
   enum TypeState {
@@ -2551,8 +2561,7 @@
   RAW_HEAP_OBJECT_IMPLEMENTATION(FunctionType);
 
   VISIT_FROM(CompressedObjectPtr, type_test_stub)
-  // Array of TypeParameter.
-  COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_parameters)
+  COMPRESSED_POINTER_FIELD(TypeParametersPtr, type_parameters)
   COMPRESSED_POINTER_FIELD(AbstractTypePtr, result_type)
   COMPRESSED_POINTER_FIELD(ArrayPtr, parameter_types)
   COMPRESSED_POINTER_FIELD(ArrayPtr, parameter_names);
@@ -2624,21 +2633,13 @@
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypeParameter);
 
   VISIT_FROM(CompressedObjectPtr, type_test_stub)
-  COMPRESSED_POINTER_FIELD(StringPtr, name)
   COMPRESSED_POINTER_FIELD(SmiPtr, hash)
   // ObjectType if no explicit bound specified.
   COMPRESSED_POINTER_FIELD(AbstractTypePtr, bound)
-  // The instantiation to bounds of this parameter as calculated by the CFE.
-  //
-  // TODO(dartbug.com/43901): Once a separate TypeParameters class has been
-  // added, move these there and remove them from TypeParameter objects.
-  COMPRESSED_POINTER_FIELD(AbstractTypePtr, default_argument)
-  VISIT_TO(CompressedObjectPtr, default_argument)
+  VISIT_TO(CompressedObjectPtr, bound)
   ClassIdTagType parameterized_class_id_;  // Or kFunctionCid for function tp.
-  // TODO(regis): Can we use uint8_t twice below? Or keep uint16_t?
-  // Warning: BuildTypeParameterTypeTestStub assumes uint16_t.
-  uint16_t base_;  // Number of enclosing function type parameters.
-  uint16_t index_;
+  uint8_t base_;   // Number of enclosing function type parameters.
+  uint8_t index_;  // Keep size in sync with BuildTypeParameterTypeTestStub.
   uint8_t flags_;
   uint8_t nullability_;
 
@@ -2646,9 +2647,7 @@
   using BeingFinalizedBit = BitField<decltype(flags_), bool, 0, 1>;
   using FinalizedBit =
       BitField<decltype(flags_), bool, BeingFinalizedBit::kNextBit, 1>;
-  using GenericCovariantImplBit =
-      BitField<decltype(flags_), bool, FinalizedBit::kNextBit, 1>;
-  static constexpr intptr_t kFlagsBitSize = GenericCovariantImplBit::kNextBit;
+  static constexpr intptr_t kFlagsBitSize = FinalizedBit::kNextBit;
 
  private:
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index faea10f..629d62b 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -136,9 +136,12 @@
   F(TypeRef, type_test_stub_)                                                  \
   F(TypeRef, type_)                                                            \
   F(TypeParameter, type_test_stub_)                                            \
-  F(TypeParameter, name_)                                                      \
   F(TypeParameter, hash_)                                                      \
   F(TypeParameter, bound_)                                                     \
+  F(TypeParameters, names_)                                                    \
+  F(TypeParameters, flags_)                                                    \
+  F(TypeParameters, bounds_)                                                   \
+  F(TypeParameters, defaults_)                                                 \
   F(Closure, instantiator_type_arguments_)                                     \
   F(Closure, function_type_arguments_)                                         \
   F(Closure, delayed_type_arguments_)                                          \
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 924f0a4..606d930 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -230,6 +230,8 @@
   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));
@@ -279,8 +281,8 @@
   writer->WriteTags(writer->GetObjectTags(this));
 
   // Write out all the non object pointer fields.
-  writer->Write<uint16_t>(base_);
-  writer->Write<uint16_t>(index_);
+  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));
@@ -296,6 +298,43 @@
   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,
diff --git a/runtime/vm/reusable_handles.h b/runtime/vm/reusable_handles.h
index 5b05ecc..e2ac116 100644
--- a/runtime/vm/reusable_handles.h
+++ b/runtime/vm/reusable_handles.h
@@ -109,6 +109,8 @@
   ReusableSmiHandleScope reused_smi_handle(thread);
 #define REUSABLE_STRING_HANDLESCOPE(thread)                                    \
   ReusableStringHandleScope reused_string_handle(thread);
+#define REUSABLE_TYPE_PARAMETERS_HANDLESCOPE(thread)                           \
+  ReusableTypeArgumentsHandleScope reused_type_parameters_handle(thread);
 #define REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread)                            \
   ReusableTypeArgumentsHandleScope reused_type_arguments_handle(thread);
 #define REUSABLE_TYPE_PARAMETER_HANDLESCOPE(thread)                            \
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index ba3f9a9..2eb5417 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -416,6 +416,7 @@
   friend class Type;
   friend class FunctionType;
   friend class TypedDataView;
+  friend class TypeParameters;
   friend class TypeArguments;
   friend class TypeParameter;
   friend class TypeRef;
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index fd790e9..ef0270b 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -106,6 +106,7 @@
   V(DynamicCallCurrentNumProcessedVar, ":dyn_call_current_num_processed")      \
   V(DynamicCallCurrentFunctionVar, ":dyn_call_current_function")               \
   V(DynamicCallCurrentParamIndexVar, ":dyn_call_current_param_index")          \
+  V(DynamicCallCurrentTypeParamVar, ":dyn_call_current_type_param")            \
   V(DynamicCallFunctionTypeArgsVar, ":dyn_call_function_type_args")            \
   V(DynamicPrefix, "dyn:")                                                     \
   V(EntryPointsTemp, ":entry_points_temp")                                     \
@@ -286,6 +287,7 @@
   V(TypeArguments, "TypeArguments")                                            \
   V(TypeArgumentsParameter, ":type_arguments")                                 \
   V(TypeError, "_TypeError")                                                   \
+  V(TypeParameters, "TypeParameters")                                          \
   V(TypeQuote, "type '")                                                       \
   V(Uint16List, "Uint16List")                                                  \
   V(Uint32List, "Uint32List")                                                  \
diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h
index 4df36b4..582e207 100644
--- a/runtime/vm/tagged_pointer.h
+++ b/runtime/vm/tagged_pointer.h
@@ -324,6 +324,7 @@
 DEFINE_TAGGED_POINTER(Instance, Object)
 DEFINE_TAGGED_POINTER(LibraryPrefix, Instance)
 DEFINE_TAGGED_POINTER(TypeArguments, Instance)
+DEFINE_TAGGED_POINTER(TypeParameters, Object)
 DEFINE_TAGGED_POINTER(AbstractType, Instance)
 DEFINE_TAGGED_POINTER(Type, AbstractType)
 DEFINE_TAGGED_POINTER(FunctionType, AbstractType)
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 9b4dfe3..abbddba 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -83,6 +83,7 @@
   V(PcDescriptors)                                                             \
   V(Smi)                                                                       \
   V(String)                                                                    \
+  V(TypeParameters)                                                            \
   V(TypeArguments)                                                             \
   V(TypeParameter)
 
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 165c7b5..d0ff2d8 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -69,8 +69,8 @@
 
     return concatenated;
   } else if (type.IsTypeParameter()) {
-    string_ = TypeParameter::Cast(type).name();
-    return AssemblerSafeName(OS::SCreate(Z, "%s", string_.ToCString()));
+    return AssemblerSafeName(
+        OS::SCreate(Z, "%s", TypeParameter::Cast(type).CanonicalNameCString()));
   } else {
     return AssemblerSafeName(OS::SCreate(Z, "%s", type.ToCString()));
   }
@@ -316,18 +316,13 @@
   } else {
     ASSERT(hi->CanUseGenericSubtypeRangeCheckFor(type));
 
-    const intptr_t num_type_parameters = type_class.NumTypeParameters();
     const intptr_t num_type_arguments = type_class.NumTypeArguments();
 
-    const TypeArguments& tp =
-        TypeArguments::Handle(type_class.type_parameters());
-    ASSERT(tp.Length() == num_type_parameters);
-
     const TypeArguments& ta = TypeArguments::Handle(type.arguments());
     ASSERT(ta.Length() == num_type_arguments);
 
     BuildOptimizedSubclassRangeCheckWithTypeArguments(assembler, hi, type,
-                                                      type_class, tp, ta);
+                                                      type_class, ta);
   }
 
   if (Instance::NullIsAssignableTo(type)) {
@@ -368,7 +363,6 @@
         HierarchyInfo* hi,
         const Type& type,
         const Class& type_class,
-        const TypeArguments& tp,
         const TypeArguments& ta) {
   // a) First we make a quick sub*class* cid-range check.
   compiler::Label check_failed;
@@ -898,7 +892,6 @@
     TypeParameterSet* parameters_tested_against) {
   Class& klass = Class::Handle(zone_);
   TypeParameter& param = TypeParameter::Handle(zone_);
-  TypeArguments& params = TypeArguments::Handle(zone_);
   AbstractType& type = AbstractType::Handle(zone_);
 
   // Because Object/dynamic are common values for type parameters, we add them
@@ -918,9 +911,8 @@
     }
 
     const intptr_t num_parameters = klass.NumTypeParameters();
-    params = klass.type_parameters();
     for (intptr_t i = 0; i < num_parameters; ++i) {
-      param ^= params.TypeAt(i);
+      param = klass.TypeParameterAt(i);
       if (parameters_tested_against->HasKey(&param)) {
         TypeArgumentsSet& ta_set = instance_creation_arguments_[cid];
         auto it = ta_set.GetIterator();
diff --git a/runtime/vm/type_testing_stubs.h b/runtime/vm/type_testing_stubs.h
index d8307b8..7f97d5d 100644
--- a/runtime/vm/type_testing_stubs.h
+++ b/runtime/vm/type_testing_stubs.h
@@ -80,7 +80,6 @@
       HierarchyInfo* hi,
       const Type& type,
       const Class& type_class,
-      const TypeArguments& type_parameters,
       const TypeArguments& type_arguments);
 
   static void BuildOptimizedSubclassRangeCheckWithTypeArguments(
@@ -88,7 +87,6 @@
       HierarchyInfo* hi,
       const Type& type,
       const Class& type_class,
-      const TypeArguments& type_parameters,
       const TypeArguments& type_arguments,
       const Register class_id_reg,
       const Register instance_type_args_reg);
diff --git a/runtime/vm/type_testing_stubs_test.cc b/runtime/vm/type_testing_stubs_test.cc
index 18c90d1..15c1682 100644
--- a/runtime/vm/type_testing_stubs_test.cc
+++ b/runtime/vm/type_testing_stubs_test.cc
@@ -461,7 +461,7 @@
   auto& tav_dynamic_t = TypeArguments::Handle(TypeArguments::New(2));
   tav_dynamic_t.SetTypeAt(0, type_dynamic);
   tav_dynamic_t.SetTypeAt(
-      1, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
+      1, TypeParameter::Handle(GetClassTypeParameter(class_base, 0)));
   CanonicalizeTAV(&tav_dynamic_t);
 
   // We will generate specialized TTS for instantiated interface types
@@ -750,7 +750,7 @@
   // <...> as Base<T>  with T instantiantiator type parameter (T == int)
   const auto& tav_baset = TypeArguments::Handle(TypeArguments::New(1));
   tav_baset.SetTypeAt(
-      0, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
+      0, TypeParameter::Handle(GetClassTypeParameter(class_base, 0)));
   auto& type_base_t = AbstractType::Handle(Type::New(class_base, tav_baset));
   FinalizeAndCanonicalize(&type_base_t);
   RunTTSTest(obj_base_int, type_base_t, tav_int, tav_null,
@@ -761,7 +761,7 @@
   // <...> as Base<B>  with B function type parameter
   const auto& tav_baseb = TypeArguments::Handle(TypeArguments::New(1));
   tav_baseb.SetTypeAt(
-      0, TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, "B")));
+      0, TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, 1)));
   auto& type_base_b = AbstractType::Handle(Type::New(class_base, tav_baseb));
   FinalizeAndCanonicalize(&type_base_b);
   // With B == int
@@ -797,8 +797,8 @@
 
   //   <...> as Base<A2<T>>
   const auto& tav_t = TypeArguments::Handle(TypeArguments::New(1));
-  tav_t.SetTypeAt(
-      0, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
+  tav_t.SetTypeAt(0,
+                  TypeParameter::Handle(GetClassTypeParameter(class_base, 0)));
   auto& type_a2_t = Type::Handle(Type::New(class_a2, tav_t));
   type_a2_t = type_a2_t.ToNullability(Nullability::kLegacy, Heap::kNew);
   FinalizeAndCanonicalize(&type_a2_t);
@@ -855,7 +855,7 @@
   // dst_type = B<T>
   const auto& dst_tav = TypeArguments::Handle(TypeArguments::New(1));
   dst_tav.SetTypeAt(0,
-                    TypeParameter::Handle(GetClassTypeParameter(class_b, "T")));
+                    TypeParameter::Handle(GetClassTypeParameter(class_b, 0)));
   auto& dst_type = Type::Handle(Type::New(class_b, dst_tav));
   FinalizeAndCanonicalize(&dst_type);
   const auto& cint_tav =
@@ -891,10 +891,10 @@
       Function::Handle(GetFunction(root_library, "genericFun"));
 
   const auto& dst_type_t =
-      TypeParameter::Handle(GetClassTypeParameter(class_a, "T"));
+      TypeParameter::Handle(GetClassTypeParameter(class_a, 0));
 
   const auto& dst_type_h =
-      TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, "H"));
+      TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, 0));
 
   const auto& aint = Object::Handle(Invoke(root_library, "createAInt"));
   const auto& astring = Object::Handle(Invoke(root_library, "createAString"));
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 15a1abf..1390092 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -252,6 +252,18 @@
   },
 ]
 
+# This rule copies the pre-built DevTools application to
+# bin/resources/devtools/
+copy_tree_specs += [
+  {
+    target = "copy_prebuilt_devtools"
+    visibility = [ ":create_common_sdk" ]
+    source = "../third_party/devtools/web"
+    dest = "$root_out_dir/dart-sdk/bin/resources/devtools"
+    ignore_patterns = "{}"
+  },
+]
+
 # This loop generates rules to copy libraries to lib/
 foreach(library, _full_sdk_libraries) {
   copy_tree_specs += [
@@ -811,6 +823,7 @@
     ":copy_libraries_dart",
     ":copy_libraries_specification",
     ":copy_license",
+    ":copy_prebuilt_devtools",
     ":copy_readme",
     ":copy_vm_dill_files",
     ":write_dartdoc_options",
diff --git a/sdk/lib/_internal/vm/bin/vmservice_io.dart b/sdk/lib/_internal/vm/bin/vmservice_io.dart
index d1f8a5d..833e5a2 100644
--- a/sdk/lib/_internal/vm/bin/vmservice_io.dart
+++ b/sdk/lib/_internal/vm/bin/vmservice_io.dart
@@ -43,6 +43,7 @@
 // HTTP server.
 Server? server;
 Future<Server>? serverFuture;
+_DebuggingSession? ddsInstance;
 
 Server _lazyServerBoot() {
   var localServer = server;
@@ -58,6 +59,90 @@
   return localServer;
 }
 
+/// Responsible for launching a DevTools instance when the service is started
+/// via SIGQUIT.
+class _DebuggingSession {
+  Future<bool> start(
+    String host,
+    String port,
+    bool disableServiceAuthCodes,
+    bool enableDevTools,
+  ) async {
+    final dartPath = Uri.parse(Platform.resolvedExecutable);
+    final dartDir = [
+      '', // Include leading '/'
+      ...dartPath.pathSegments.sublist(
+        0,
+        dartPath.pathSegments.length - 1,
+      ),
+    ].join('/');
+
+    final fullSdk = dartDir.endsWith('bin');
+
+    final ddsSnapshot = [
+      dartDir,
+      fullSdk ? 'snapshots' : 'gen',
+      'dds.dart.snapshot',
+    ].join('/');
+
+    final devToolsBinaries = [
+      dartDir,
+      if (fullSdk) 'resources',
+      'devtools',
+    ].join('/');
+
+    const enableLogging = false;
+    _process = await Process.start(
+      dartPath.toString(),
+      [
+        ddsSnapshot,
+        server!.serverAddress!.toString(),
+        host,
+        port,
+        disableServiceAuthCodes.toString(),
+        enableDevTools.toString(),
+        devToolsBinaries,
+        enableLogging.toString(),
+      ],
+      mode: ProcessStartMode.detachedWithStdio,
+    );
+    final completer = Completer<void>();
+    late StreamSubscription stderrSub;
+    stderrSub = _process!.stderr.transform(utf8.decoder).listen((event) {
+      final result = json.decode(event) as Map<String, dynamic>;
+      final state = result['state'];
+      if (state == 'started') {
+        if (result.containsKey('devToolsUri')) {
+          // NOTE: update pkg/dartdev/lib/src/commands/run.dart if this message
+          // is changed to ensure consistency.
+          const devToolsMessagePrefix =
+              'The Dart DevTools debugger and profiler is available at:';
+          final devToolsUri = result['devToolsUri'];
+          print('$devToolsMessagePrefix $devToolsUri');
+        }
+        stderrSub.cancel();
+        completer.complete();
+      } else {
+        stderrSub.cancel();
+        completer.completeError(
+          'Could not start Observatory HTTP server',
+        );
+      }
+    });
+    try {
+      await completer.future;
+      return true;
+    } catch (e) {
+      stderr.write(e);
+      return false;
+    }
+  }
+
+  void shutdown() => _process!.kill();
+
+  Process? _process;
+}
+
 Future cleanupCallback() async {
   // Cancel the sigquit subscription.
   if (_signalSubscription != null) {
@@ -221,10 +306,6 @@
   _server.acceptNewWebSocketConnections = enable;
 }
 
-void _clearFuture(_) {
-  serverFuture = null;
-}
-
 _onSignal(ProcessSignal signal) {
   if (serverFuture != null) {
     // Still waiting.
@@ -233,9 +314,21 @@
   final _server = _lazyServerBoot();
   // Toggle HTTP server.
   if (_server.running) {
-    _server.shutdown(true).then(_clearFuture);
+    _server.shutdown(true).then((_) async {
+      ddsInstance?.shutdown();
+      await VMService().clearState();
+      serverFuture = null;
+    });
   } else {
-    _server.startup().then(_clearFuture);
+    _server.startup().then((_) {
+      ddsInstance = _DebuggingSession()
+        ..start(
+          _server._ip,
+          _server._port.toString(),
+          false,
+          true,
+        );
+    });
   }
 }
 
diff --git a/sdk/lib/_internal/vm/bin/vmservice_server.dart b/sdk/lib/_internal/vm/bin/vmservice_server.dart
index 69aa7f8..f5742ed 100644
--- a/sdk/lib/_internal/vm/bin/vmservice_server.dart
+++ b/sdk/lib/_internal/vm/bin/vmservice_server.dart
@@ -26,9 +26,9 @@
     socket.done.then((_) => close());
   }
 
-  disconnect() {
+  Future<void> disconnect() async {
     if (socket != null) {
-      socket.close();
+      await socket.close();
     }
   }
 
@@ -102,8 +102,8 @@
   HttpRequestClient(this.request, VMService service)
       : super(service, sendEvents: false);
 
-  disconnect() {
-    request.response.close();
+  Future<void> disconnect() async {
+    await request.response.close();
     close();
   }
 
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index a3f7e8b..d492dcf 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -411,6 +411,16 @@
     replyPort.send(bytes);
   }
 
+  Future<void> clearState() async {
+    // Create a copy of the set as a list because client.disconnect() will
+    // alter the connected clients set.
+    final clientsList = clients.toList();
+    for (final client in clientsList) {
+      await client.disconnect();
+    }
+    devfs.cleanup();
+  }
+
   Future _exit() async {
     isExiting = true;
 
@@ -423,14 +433,7 @@
     // Close receive ports.
     isolateControlPort.close();
     scriptLoadPort.close();
-
-    // Create a copy of the set as a list because client.disconnect() will
-    // alter the connected clients set.
-    final clientsList = clients.toList();
-    for (final client in clientsList) {
-      client.disconnect();
-    }
-    devfs.cleanup();
+    await clearState();
     final cleanup = VMServiceEmbedderHooks.cleanup;
     if (cleanup != null) {
       await cleanup();
diff --git a/tests/language/generic/regress_45767_test.dart b/tests/language/generic/regress_45767_test.dart
new file mode 100644
index 0000000..953c966
--- /dev/null
+++ b/tests/language/generic/regress_45767_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+// Regression test for https://github.com/dart-lang/sdk/issues/45767.
+
+class I<T> {}
+
+class F<E extends F<E>> extends I<E> {}
+
+// Extending F forces DDC to defer the superclass and trigger the bug
+class A<T> extends F<A<Object?>> {}
+
+class B<T> extends F<B<T?>> {}
+
+void main() {
+  Expect.isTrue(A<bool>() is I<A<Object?>>);
+  Expect.equals(!hasSoundNullSafety, A<bool>() is I<A<Object>>);
+  Expect.isTrue(B<bool>() is I<B<bool?>>);
+  Expect.equals(!hasSoundNullSafety, B<bool>() is I<B<bool>>);
+}
diff --git a/tests/language/regress/regress45763_test.dart b/tests/language/regress/regress45763_test.dart
new file mode 100644
index 0000000..1efd68d
--- /dev/null
+++ b/tests/language/regress/regress45763_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=generic-metadata
+
+import "package:expect/expect.dart";
+
+Type? capturedTypeArgument;
+Type typeOf<X>() => X;
+
+X captureTypeArgument<X>() {
+  capturedTypeArgument = X;
+  throw "";
+}
+
+typedef check = void Function<T>();
+
+void main() {
+  void f(check Function<T>() g) => g();
+  try {
+    f(<T>() => captureTypeArgument());
+  } catch (e) {}
+  Expect.equals(typeOf<void Function<T>()>(), capturedTypeArgument);
+}
diff --git a/tests/lib/mirrors/class_mirror_type_variables_expect.dart b/tests/lib/mirrors/class_mirror_type_variables_expect.dart
index 847bd7f..3326b08 100644
--- a/tests/lib/mirrors/class_mirror_type_variables_expect.dart
+++ b/tests/lib/mirrors/class_mirror_type_variables_expect.dart
@@ -96,9 +96,6 @@
   values.forEach((e) {
     Expect.equals(true, e is TypeVariableMirror);
   });
-  Expect.equals(#R, values.elementAt(0).simpleName);
-  Expect.equals(#S, values.elementAt(1).simpleName);
-  Expect.equals(#T, values.elementAt(2).simpleName);
 }
 
 void testE(Env env) {
diff --git a/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart b/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart
index 46e731f..fd7c9e9 100644
--- a/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart
+++ b/tests/lib/mirrors/generic_bounded_by_type_parameter_test.dart
@@ -50,13 +50,6 @@
   Expect.equals(reflectClass(Object), xFromGeneric.upperBound); // //# 02: continued
   Expect.equals(reflectClass(Object), yFromGeneric.upperBound); // //# 02: continued
 
-  typeParameters(superDecl, [#T, #R]);
-  typeParameters(superOfNumAndInt, [#T, #R]);
-  typeParameters(genericDecl, [#X, #Y]); // //# 02: continued
-  typeParameters(superOfXAndY, [#T, #R]); // //# 02: continued
-  typeParameters(genericOfNumAndDouble, [#X, #Y]); // //# 02: continued
-  typeParameters(superOfNumAndDouble, [#T, #R]); // //# 02: continued
-
   typeArguments(superDecl, []);
   typeArguments(superOfNumAndInt, [reflectClass(num), reflectClass(int)]);
   typeArguments(genericDecl, []); // //# 02: continued
diff --git a/tests/lib/mirrors/generic_bounded_test.dart b/tests/lib/mirrors/generic_bounded_test.dart
index 01301fb..062780e 100644
--- a/tests/lib/mirrors/generic_bounded_test.dart
+++ b/tests/lib/mirrors/generic_bounded_test.dart
@@ -49,14 +49,6 @@
   Expect.equals(reflectClass(num), tFromSuper.upperBound);
   Expect.equals(reflectClass(Object), rFromGeneric.upperBound); // //# 02: continued
 
-  typeParameters(superDecl, [#T]);
-  typeParameters(superOfInt, [#T]);
-  typeParameters(genericDecl, [#R]); // //# 02: continued
-  typeParameters(superOfR, [#T]); // //# 02: continued
-  typeParameters(genericOfDouble, [#R]); // //# 02: continued
-  typeParameters(superOfDouble, [#T]); // //# 02: continued
-  typeParameters(superOfString, [#T]); // //# 01: continued
-
   typeArguments(superDecl, []);
   typeArguments(superOfInt, [reflectClass(int)]);
   typeArguments(genericDecl, []); // //# 02: continued
diff --git a/tests/lib/mirrors/generic_class_declaration_test.dart b/tests/lib/mirrors/generic_class_declaration_test.dart
index 79ebee1..2a2e4c6 100644
--- a/tests/lib/mirrors/generic_class_declaration_test.dart
+++ b/tests/lib/mirrors/generic_class_declaration_test.dart
@@ -81,14 +81,4 @@
           .where((dm) => dm is MethodMirror && dm.isConstructor)
           .map(stringify),
       'constructors');
-
-  Expect.setEquals(
-      [
-        'TypeVariable(s(T) in s(A), upperBound = Class(s(Object) in '
-            's(dart.core), top-level))'
-      ],
-      cm.declarations.values
-          .where((dm) => dm is TypeVariableMirror)
-          .map(stringify),
-      'type variables');
 }
diff --git a/tests/lib/mirrors/generic_f_bounded_test.dart b/tests/lib/mirrors/generic_f_bounded_test.dart
index 5f84435..408a8a3 100644
--- a/tests/lib/mirrors/generic_f_bounded_test.dart
+++ b/tests/lib/mirrors/generic_f_bounded_test.dart
@@ -43,13 +43,8 @@
   Expect.equals(magnitudeDecl, magnitudeOfR.originalDeclaration);
   Expect.equals(rFromSorter, magnitudeOfR.typeArguments.single);
 
-  typeParameters(magnitudeDecl, [#T]);
   typeParameters(realDecl, []);
-  typeParameters(sorterDecl, [#R]);
   typeParameters(realSorterDecl, []);
-  typeParameters(magnitudeOfReal, [#T]);
-  typeParameters(sorterOfReal, [#R]);
-  typeParameters(magnitudeOfR, [#T]);
 
   typeArguments(magnitudeDecl, []);
   typeArguments(realDecl, []);
diff --git a/tests/lib/mirrors/generic_interface_test.dart b/tests/lib/mirrors/generic_interface_test.dart
index 8b38a3b..061685d 100644
--- a/tests/lib/mirrors/generic_interface_test.dart
+++ b/tests/lib/mirrors/generic_interface_test.dart
@@ -91,21 +91,6 @@
   Expect.equals(reflectClass(Object), xFromGenericMixinApplication.upperBound);
   Expect.equals(reflectClass(Object), yFromGenericClass.upperBound);
 
-  typeParameters(interfaceDecl, [#T]);
-  typeParameters(boundedDecl, [#S]);
-  typeParameters(interfaceOfInt, [#T]);
-  typeParameters(interfaceOfR, [#T]);
-  typeParameters(interfaceOfBool, [#T]);
-  typeParameters(boundedOfInt, [#S]);
-  typeParameters(boundedOfString, [#S]); // //# 01: continued
-  typeParameters(interfaceOfFBounded, [#T]);
-  typeParameters(interfaceOfInt2, [#T]);
-  typeParameters(interfaceOfX, [#T]);
-  typeParameters(interfaceOfDouble, [#T]);
-  typeParameters(interfaceOfInt3, [#T]);
-  typeParameters(interfaceOfY, [#T]);
-  typeParameters(interfaceOfDouble2, [#T]);
-
   typeArguments(interfaceDecl, []);
   typeArguments(boundedDecl, []);
   typeArguments(interfaceOfInt, [reflectClass(int)]);
diff --git a/tests/lib/mirrors/generic_mixin_test.dart b/tests/lib/mirrors/generic_mixin_test.dart
index 238689b..c52c756 100644
--- a/tests/lib/mirrors/generic_mixin_test.dart
+++ b/tests/lib/mirrors/generic_mixin_test.dart
@@ -35,30 +35,6 @@
 main() {
   TypeMirror dynamicMirror = currentMirrorSystem().dynamicType;
 
-  typeParameters(reflectClass(NonGenericMixinApplication1).mixin, [#M]);
-  typeParameters(reflectClass(NonGenericMixinApplication2).mixin, [#M]);
-  typeParameters(reflectClass(GenericMixinApplication1).mixin, [#M]);
-  typeParameters(reflectClass(GenericMixinApplication2).mixin, [#M]);
-  typeParameters(reflectClass(NonGenericClass1).mixin, []);
-  typeParameters(reflectClass(NonGenericClass2).mixin, []);
-  typeParameters(reflectClass(GenericClass1).mixin, [#C]);
-  typeParameters(reflectClass(GenericClass2).mixin, [#C]);
-  typeParameters(reflectClass(NonGenericClass1).superclass!.mixin, [#M]);
-  typeParameters(reflectClass(NonGenericClass2).superclass!.mixin, [#M]);
-  typeParameters(reflectClass(GenericClass1).superclass!.mixin, [#M]);
-  typeParameters(reflectClass(GenericClass2).superclass!.mixin, [#M]);
-  typeParameters(reflectClass(GenericMultipleMixins).mixin, [#A, #B, #C]);
-  typeParameters(reflectClass(GenericMultipleMixins).superclass!.mixin, [#N]);
-  typeParameters(
-      reflectClass(GenericMultipleMixins).superclass!.superclass!.mixin, [#M]);
-  typeParameters(
-      reflectClass(GenericMultipleMixins)
-          .superclass!
-          .superclass!
-          .superclass!
-          .mixin,
-      [#S]);
-
   typeArguments(
       reflectClass(NonGenericMixinApplication1).mixin, [dynamicMirror]);
   typeArguments(
@@ -93,46 +69,8 @@
           .mixin,
       [reflectClass(GenericMultipleMixins).typeVariables[0]]);
 
-  typeParameters(reflect(new NonGenericMixinApplication1()).type.mixin, [#M]);
-  typeParameters(reflect(new NonGenericMixinApplication2()).type.mixin, [#M]);
-  typeParameters(
-      reflect(new GenericMixinApplication1<bool>()).type.mixin, [#M]);
-  typeParameters(
-      reflect(new GenericMixinApplication2<bool>()).type.mixin, [#M]);
   typeParameters(reflect(new NonGenericClass1()).type.mixin, []);
   typeParameters(reflect(new NonGenericClass2()).type.mixin, []);
-  typeParameters(reflect(new GenericClass1<bool>()).type.mixin, [#C]);
-  typeParameters(reflect(new GenericClass2<bool>()).type.mixin, [#C]);
-  typeParameters(reflect(new NonGenericClass1()).type.superclass!.mixin, [#M]);
-  typeParameters(reflect(new NonGenericClass2()).type.superclass!.mixin, [#M]);
-  typeParameters(
-      reflect(new GenericClass1<bool>()).type.superclass!.mixin, [#M]);
-  typeParameters(
-      reflect(new GenericClass2<bool>()).type.superclass!.mixin, [#M]);
-  typeParameters(
-      reflect(new GenericMultipleMixins<bool, String, int>()).type.mixin,
-      [#A, #B, #C]);
-  typeParameters(
-      reflect(new GenericMultipleMixins<bool, String, int>())
-          .type
-          .superclass!
-          .mixin,
-      [#N]);
-  typeParameters(
-      reflect(new GenericMultipleMixins<bool, String, int>())
-          .type
-          .superclass!
-          .superclass!
-          .mixin,
-      [#M]);
-  typeParameters(
-      reflect(new GenericMultipleMixins<bool, String, int>())
-          .type
-          .superclass!
-          .superclass!
-          .superclass!
-          .mixin,
-      [#S]);
 
   typeArguments(
       reflect(new NonGenericMixinApplication1()).type.mixin, [dynamicMirror]);
diff --git a/tests/lib/mirrors/generics_substitution_test.dart b/tests/lib/mirrors/generics_substitution_test.dart
index 9c2c0ae..6ca6c54 100644
--- a/tests/lib/mirrors/generics_substitution_test.dart
+++ b/tests/lib/mirrors/generics_substitution_test.dart
@@ -36,18 +36,12 @@
   Symbol t(ClassMirror cm) =>
       (cm.declarations[#t] as MethodMirror).returnType.simpleName;
 
-  Expect.equals(#T, r(genericDecl.superclass!));
   Expect.equals(#int, s(genericDecl.superclass!));
-  Expect.equals(#T, t(genericDecl));
 
   Expect.equals(#String, r(genericOfString.superclass!));
   Expect.equals(#int, s(genericOfString.superclass!));
   Expect.equals(#String, t(genericOfString));
 
-  Expect.equals(#R, r(superGenericDecl));
-  Expect.equals(#S, s(superGenericDecl));
-
-  Expect.equals(#T, r(superOfTAndInt));
   Expect.equals(#int, s(superOfTAndInt));
 
   Expect.equals(#String, r(superOfStringAndInt));
diff --git a/tests/lib/mirrors/generics_test.dart b/tests/lib/mirrors/generics_test.dart
index ce9d8f0..be1ea8a 100644
--- a/tests/lib/mirrors/generics_test.dart
+++ b/tests/lib/mirrors/generics_test.dart
@@ -33,15 +33,11 @@
 
 main() {
   // Declarations.
-  typeParameters(reflectClass(A), [#T]);
   typeParameters(reflectClass(G), []);
   typeParameters(reflectClass(B), []);
   typeParameters(reflectClass(C), []);
   typeParameters(reflectClass(D), []);
-  typeParameters(reflectClass(E), [#S]);
-  typeParameters(reflectClass(F), [#R]);
   typeParameters(reflectClass(G), []);
-  typeParameters(reflectClass(H), [#A, #B, #C]);
   typeParameters(reflectClass(I), []);
 
   typeArguments(reflectClass(A), []);
@@ -75,14 +71,10 @@
   Expect.equals(reflectClass(I), reflectClass(I).originalDeclaration);
 
   // Instantiations.
-  typeParameters(reflect(new A<num>()).type, [#T]);
   typeParameters(reflect(new B()).type, []);
   typeParameters(reflect(new C()).type, []);
   typeParameters(reflect(new D()).type, []);
-  typeParameters(reflect(new E()).type, [#S]);
-  typeParameters(reflect(new F<num>()).type, [#R]);
   typeParameters(reflect(new G()).type, []);
-  typeParameters(reflect(new H()).type, [#A, #B, #C]);
   typeParameters(reflect(new I()).type, []);
 
   var numMirror = reflectClass(num);
diff --git a/tests/lib/mirrors/parameter_test.dart b/tests/lib/mirrors/parameter_test.dart
index 2a5eff6..2d9418f 100644
--- a/tests/lib/mirrors/parameter_test.dart
+++ b/tests/lib/mirrors/parameter_test.dart
@@ -180,24 +180,7 @@
 
   MethodMirror fooInC = cm.declarations[#foo] as MethodMirror;
   expect('Method(s(foo) in s(C))', fooInC);
-  expect(
-      '[Parameter(s(a) in s(foo),'
-      ' type = Class(s(int) in s(dart.core), top-level)), '
-      'Parameter(s(b) in s(foo),'
-      ' type = TypeVariable(s(S) in s(Null),'
-      ' upperBound = Class(s(int) in s(dart.core), top-level)))]',
-      fooInC.parameters);
 
   MethodMirror barInC = cm.declarations[#bar] as MethodMirror;
   expect('Method(s(bar) in s(C))', barInC);
-  expect(
-      '[Parameter(s(a) in s(bar),'
-      ' type = TypeVariable(s(S) in s(Null),'
-      ' upperBound = Class(s(int) in s(dart.core), top-level))), '
-      'Parameter(s(b) in s(bar),'
-      ' type = TypeVariable(s(T) in s(Null),'
-      ' upperBound = Class(s(Object) in s(dart.core), top-level))), '
-      'Parameter(s(c) in s(bar),'
-      ' type = Class(s(num) in s(dart.core), top-level))]',
-      barInC.parameters);
 }
diff --git a/tests/lib/mirrors/type_argument_is_type_variable_test.dart b/tests/lib/mirrors/type_argument_is_type_variable_test.dart
index 2aa7118..d26d803 100644
--- a/tests/lib/mirrors/type_argument_is_type_variable_test.dart
+++ b/tests/lib/mirrors/type_argument_is_type_variable_test.dart
@@ -27,14 +27,6 @@
   TypeVariableMirror ssFromSuperSuper =
       superOfSuperOfGeneric.typeVariables.single;
 
-  Expect.equals(#G, gFromGeneric.simpleName);
-  Expect.equals(#S, sFromSuper.simpleName);
-  Expect.equals(#SS, ssFromSuperSuper.simpleName);
-
-  typeParameters(generic, [#G]);
-  typeParameters(superOfGeneric, [#S]);
-  typeParameters(superOfSuperOfGeneric, [#SS]);
-
   typeArguments(generic, []);
   typeArguments(superOfGeneric, [gFromGeneric]);
   typeArguments(superOfSuperOfGeneric, [gFromGeneric]);
@@ -44,10 +36,6 @@
   ClassMirror superOfGenericWithInt = genericWithInt.superclass!;
   ClassMirror superOfSuperOfGenericWithInt = superOfGenericWithInt.superclass!;
 
-  typeParameters(genericWithInt, [#G]);
-  typeParameters(superOfGenericWithInt, [#S]);
-  typeParameters(superOfSuperOfGenericWithInt, [#SS]);
-
   typeArguments(genericWithInt, [reflectClass(int)]);
   typeArguments(superOfGenericWithInt, [reflectClass(int)]);
   typeArguments(superOfSuperOfGenericWithInt, [reflectClass(int)]);
diff --git a/tests/lib_2/mirrors/class_mirror_type_variables_expect.dart b/tests/lib_2/mirrors/class_mirror_type_variables_expect.dart
index cf30d1c..5adbd2d 100644
--- a/tests/lib_2/mirrors/class_mirror_type_variables_expect.dart
+++ b/tests/lib_2/mirrors/class_mirror_type_variables_expect.dart
@@ -98,9 +98,9 @@
   values.forEach((e) {
     Expect.equals(true, e is TypeVariableMirror);
   });
-  Expect.equals(#R, values.elementAt(0).simpleName);
-  Expect.equals(#S, values.elementAt(1).simpleName);
-  Expect.equals(#T, values.elementAt(2).simpleName);
+
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
 }
 
 void testE(Env env) {
diff --git a/tests/lib_2/mirrors/generic_bounded_by_type_parameter_test.dart b/tests/lib_2/mirrors/generic_bounded_by_type_parameter_test.dart
index 8edb952..c4dbb66 100644
--- a/tests/lib_2/mirrors/generic_bounded_by_type_parameter_test.dart
+++ b/tests/lib_2/mirrors/generic_bounded_by_type_parameter_test.dart
@@ -52,12 +52,8 @@
   Expect.equals(reflectClass(Object), xFromGeneric.upperBound); // //# 02: continued
   Expect.equals(reflectClass(Object), yFromGeneric.upperBound); // //# 02: continued
 
-  typeParameters(superDecl, [#T, #R]);
-  typeParameters(superOfNumAndInt, [#T, #R]);
-  typeParameters(genericDecl, [#X, #Y]); // //# 02: continued
-  typeParameters(superOfXAndY, [#T, #R]); // //# 02: continued
-  typeParameters(genericOfNumAndDouble, [#X, #Y]); // //# 02: continued
-  typeParameters(superOfNumAndDouble, [#T, #R]); // //# 02: continued
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
 
   typeArguments(superDecl, []);
   typeArguments(superOfNumAndInt, [reflectClass(num), reflectClass(int)]);
diff --git a/tests/lib_2/mirrors/generic_bounded_test.dart b/tests/lib_2/mirrors/generic_bounded_test.dart
index 4e47e13..3cd16fa 100644
--- a/tests/lib_2/mirrors/generic_bounded_test.dart
+++ b/tests/lib_2/mirrors/generic_bounded_test.dart
@@ -51,13 +51,8 @@
   Expect.equals(reflectClass(num), tFromSuper.upperBound);
   Expect.equals(reflectClass(Object), rFromGeneric.upperBound); // //# 02: continued
 
-  typeParameters(superDecl, [#T]);
-  typeParameters(superOfInt, [#T]);
-  typeParameters(genericDecl, [#R]); // //# 02: continued
-  typeParameters(superOfR, [#T]); // //# 02: continued
-  typeParameters(genericOfDouble, [#R]); // //# 02: continued
-  typeParameters(superOfDouble, [#T]); // //# 02: continued
-  typeParameters(superOfString, [#T]); // //# 01: continued
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
 
   typeArguments(superDecl, []);
   typeArguments(superOfInt, [reflectClass(int)]);
diff --git a/tests/lib_2/mirrors/generic_class_declaration_test.dart b/tests/lib_2/mirrors/generic_class_declaration_test.dart
index 76b1c19..353b48f 100644
--- a/tests/lib_2/mirrors/generic_class_declaration_test.dart
+++ b/tests/lib_2/mirrors/generic_class_declaration_test.dart
@@ -84,13 +84,6 @@
           .map(stringify),
       'constructors');
 
-  Expect.setEquals(
-      [
-        'TypeVariable(s(T) in s(A), upperBound = Class(s(Object) in '
-            's(dart.core), top-level))'
-      ],
-      cm.declarations.values
-          .where((dm) => dm is TypeVariableMirror)
-          .map(stringify),
-      'type variables');
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
 }
diff --git a/tests/lib_2/mirrors/generic_f_bounded_test.dart b/tests/lib_2/mirrors/generic_f_bounded_test.dart
index ff86355..ccde8ae 100644
--- a/tests/lib_2/mirrors/generic_f_bounded_test.dart
+++ b/tests/lib_2/mirrors/generic_f_bounded_test.dart
@@ -45,13 +45,14 @@
   Expect.equals(magnitudeDecl, magnitudeOfR.originalDeclaration);
   Expect.equals(rFromSorter, magnitudeOfR.typeArguments.single);
 
-  typeParameters(magnitudeDecl, [#T]);
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
+
   typeParameters(realDecl, []);
-  typeParameters(sorterDecl, [#R]);
   typeParameters(realSorterDecl, []);
-  typeParameters(magnitudeOfReal, [#T]);
-  typeParameters(sorterOfReal, [#R]);
-  typeParameters(magnitudeOfR, [#T]);
+
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
 
   typeArguments(magnitudeDecl, []);
   typeArguments(realDecl, []);
diff --git a/tests/lib_2/mirrors/generic_interface_test.dart b/tests/lib_2/mirrors/generic_interface_test.dart
index a9ad011..7480523 100644
--- a/tests/lib_2/mirrors/generic_interface_test.dart
+++ b/tests/lib_2/mirrors/generic_interface_test.dart
@@ -93,20 +93,8 @@
   Expect.equals(reflectClass(Object), xFromGenericMixinApplication.upperBound);
   Expect.equals(reflectClass(Object), yFromGenericClass.upperBound);
 
-  typeParameters(interfaceDecl, [#T]);
-  typeParameters(boundedDecl, [#S]);
-  typeParameters(interfaceOfInt, [#T]);
-  typeParameters(interfaceOfR, [#T]);
-  typeParameters(interfaceOfBool, [#T]);
-  typeParameters(boundedOfInt, [#S]);
-  typeParameters(boundedOfString, [#S]); // //# 01: continued
-  typeParameters(interfaceOfFBounded, [#T]);
-  typeParameters(interfaceOfInt2, [#T]);
-  typeParameters(interfaceOfX, [#T]);
-  typeParameters(interfaceOfDouble, [#T]);
-  typeParameters(interfaceOfInt3, [#T]);
-  typeParameters(interfaceOfY, [#T]);
-  typeParameters(interfaceOfDouble2, [#T]);
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
 
   typeArguments(interfaceDecl, []);
   typeArguments(boundedDecl, []);
diff --git a/tests/lib_2/mirrors/generic_mixin_test.dart b/tests/lib_2/mirrors/generic_mixin_test.dart
index 7ea8b4e..ccde91b 100644
--- a/tests/lib_2/mirrors/generic_mixin_test.dart
+++ b/tests/lib_2/mirrors/generic_mixin_test.dart
@@ -37,29 +37,8 @@
 main() {
   TypeMirror dynamicMirror = currentMirrorSystem().dynamicType;
 
-  typeParameters(reflectClass(NonGenericMixinApplication1).mixin, [#M]);
-  typeParameters(reflectClass(NonGenericMixinApplication2).mixin, [#M]);
-  typeParameters(reflectClass(GenericMixinApplication1).mixin, [#M]);
-  typeParameters(reflectClass(GenericMixinApplication2).mixin, [#M]);
-  typeParameters(reflectClass(NonGenericClass1).mixin, []);
-  typeParameters(reflectClass(NonGenericClass2).mixin, []);
-  typeParameters(reflectClass(GenericClass1).mixin, [#C]);
-  typeParameters(reflectClass(GenericClass2).mixin, [#C]);
-  typeParameters(reflectClass(NonGenericClass1).superclass.mixin, [#M]);
-  typeParameters(reflectClass(NonGenericClass2).superclass.mixin, [#M]);
-  typeParameters(reflectClass(GenericClass1).superclass.mixin, [#M]);
-  typeParameters(reflectClass(GenericClass2).superclass.mixin, [#M]);
-  typeParameters(reflectClass(GenericMultipleMixins).mixin, [#A, #B, #C]);
-  typeParameters(reflectClass(GenericMultipleMixins).superclass.mixin, [#N]);
-  typeParameters(
-      reflectClass(GenericMultipleMixins).superclass.superclass.mixin, [#M]);
-  typeParameters(
-      reflectClass(GenericMultipleMixins)
-          .superclass
-          .superclass
-          .superclass
-          .mixin,
-      [#S]);
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
 
   typeArguments(
       reflectClass(NonGenericMixinApplication1).mixin, [dynamicMirror]);
@@ -94,46 +73,8 @@
           .mixin,
       [reflectClass(GenericMultipleMixins).typeVariables[0]]);
 
-  typeParameters(reflect(new NonGenericMixinApplication1()).type.mixin, [#M]);
-  typeParameters(reflect(new NonGenericMixinApplication2()).type.mixin, [#M]);
-  typeParameters(
-      reflect(new GenericMixinApplication1<bool>()).type.mixin, [#M]);
-  typeParameters(
-      reflect(new GenericMixinApplication2<bool>()).type.mixin, [#M]);
   typeParameters(reflect(new NonGenericClass1()).type.mixin, []);
   typeParameters(reflect(new NonGenericClass2()).type.mixin, []);
-  typeParameters(reflect(new GenericClass1<bool>()).type.mixin, [#C]);
-  typeParameters(reflect(new GenericClass2<bool>()).type.mixin, [#C]);
-  typeParameters(reflect(new NonGenericClass1()).type.superclass.mixin, [#M]);
-  typeParameters(reflect(new NonGenericClass2()).type.superclass.mixin, [#M]);
-  typeParameters(
-      reflect(new GenericClass1<bool>()).type.superclass.mixin, [#M]);
-  typeParameters(
-      reflect(new GenericClass2<bool>()).type.superclass.mixin, [#M]);
-  typeParameters(
-      reflect(new GenericMultipleMixins<bool, String, int>()).type.mixin,
-      [#A, #B, #C]);
-  typeParameters(
-      reflect(new GenericMultipleMixins<bool, String, int>())
-          .type
-          .superclass
-          .mixin,
-      [#N]);
-  typeParameters(
-      reflect(new GenericMultipleMixins<bool, String, int>())
-          .type
-          .superclass
-          .superclass
-          .mixin,
-      [#M]);
-  typeParameters(
-      reflect(new GenericMultipleMixins<bool, String, int>())
-          .type
-          .superclass
-          .superclass
-          .superclass
-          .mixin,
-      [#S]);
 
   typeArguments(
       reflect(new NonGenericMixinApplication1()).type.mixin, [dynamicMirror]);
diff --git a/tests/lib_2/mirrors/generics_substitution_test.dart b/tests/lib_2/mirrors/generics_substitution_test.dart
index 8c89b03..b07f509 100644
--- a/tests/lib_2/mirrors/generics_substitution_test.dart
+++ b/tests/lib_2/mirrors/generics_substitution_test.dart
@@ -38,18 +38,15 @@
   Symbol t(ClassMirror cm) =>
       (cm.declarations[#t] as MethodMirror).returnType.simpleName;
 
-  Expect.equals(#T, r(genericDecl.superclass));
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
+
   Expect.equals(#int, s(genericDecl.superclass));
-  Expect.equals(#T, t(genericDecl));
 
   Expect.equals(#String, r(genericOfString.superclass));
   Expect.equals(#int, s(genericOfString.superclass));
   Expect.equals(#String, t(genericOfString));
 
-  Expect.equals(#R, r(superGenericDecl));
-  Expect.equals(#S, s(superGenericDecl));
-
-  Expect.equals(#T, r(superOfTAndInt));
   Expect.equals(#int, s(superOfTAndInt));
 
   Expect.equals(#String, r(superOfStringAndInt));
diff --git a/tests/lib_2/mirrors/generics_test.dart b/tests/lib_2/mirrors/generics_test.dart
index c0ec7fa..a9dfb79 100644
--- a/tests/lib_2/mirrors/generics_test.dart
+++ b/tests/lib_2/mirrors/generics_test.dart
@@ -35,15 +35,15 @@
 
 main() {
   // Declarations.
-  typeParameters(reflectClass(A), [#T]);
+
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
+
   typeParameters(reflectClass(G), []);
   typeParameters(reflectClass(B), []);
   typeParameters(reflectClass(C), []);
   typeParameters(reflectClass(D), []);
-  typeParameters(reflectClass(E), [#S]);
-  typeParameters(reflectClass(F), [#R]);
   typeParameters(reflectClass(G), []);
-  typeParameters(reflectClass(H), [#A, #B, #C]);
   typeParameters(reflectClass(I), []);
 
   typeArguments(reflectClass(A), []);
@@ -77,14 +77,10 @@
   Expect.equals(reflectClass(I), reflectClass(I).originalDeclaration);
 
   // Instantiations.
-  typeParameters(reflect(new A<num>()).type, [#T]);
   typeParameters(reflect(new B()).type, []);
   typeParameters(reflect(new C()).type, []);
   typeParameters(reflect(new D()).type, []);
-  typeParameters(reflect(new E()).type, [#S]);
-  typeParameters(reflect(new F<num>()).type, [#R]);
   typeParameters(reflect(new G()).type, []);
-  typeParameters(reflect(new H()).type, [#A, #B, #C]);
   typeParameters(reflect(new I()).type, []);
 
   var numMirror = reflectClass(num);
diff --git a/tests/lib_2/mirrors/parameter_test.dart b/tests/lib_2/mirrors/parameter_test.dart
index 47095dd..fe1b77a 100644
--- a/tests/lib_2/mirrors/parameter_test.dart
+++ b/tests/lib_2/mirrors/parameter_test.dart
@@ -182,24 +182,11 @@
 
   MethodMirror fooInC = cm.declarations[#foo] as MethodMirror;
   expect('Method(s(foo) in s(C))', fooInC);
-  expect(
-      '[Parameter(s(a) in s(foo),'
-      ' type = Class(s(int) in s(dart.core), top-level)), '
-      'Parameter(s(b) in s(foo),'
-      ' type = TypeVariable(s(S) in s(Null),'
-      ' upperBound = Class(s(int) in s(dart.core), top-level)))]',
-      fooInC.parameters);
+
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
+
 
   MethodMirror barInC = cm.declarations[#bar] as MethodMirror;
   expect('Method(s(bar) in s(C))', barInC);
-  expect(
-      '[Parameter(s(a) in s(bar),'
-      ' type = TypeVariable(s(S) in s(Null),'
-      ' upperBound = Class(s(int) in s(dart.core), top-level))), '
-      'Parameter(s(b) in s(bar),'
-      ' type = TypeVariable(s(T) in s(Null),'
-      ' upperBound = Class(s(Object) in s(dart.core), top-level))), '
-      'Parameter(s(c) in s(bar),'
-      ' type = Class(s(num) in s(dart.core), top-level))]',
-      barInC.parameters);
 }
diff --git a/tests/lib_2/mirrors/type_argument_is_type_variable_test.dart b/tests/lib_2/mirrors/type_argument_is_type_variable_test.dart
index ca11b17..733e575 100644
--- a/tests/lib_2/mirrors/type_argument_is_type_variable_test.dart
+++ b/tests/lib_2/mirrors/type_argument_is_type_variable_test.dart
@@ -29,13 +29,8 @@
   TypeVariableMirror ssFromSuperSuper =
       superOfSuperOfGeneric.typeVariables.single;
 
-  Expect.equals(#G, gFromGeneric.simpleName);
-  Expect.equals(#S, sFromSuper.simpleName);
-  Expect.equals(#SS, ssFromSuperSuper.simpleName);
-
-  typeParameters(generic, [#G]);
-  typeParameters(superOfGeneric, [#S]);
-  typeParameters(superOfSuperOfGeneric, [#SS]);
+  // Names of type variables are not preserved after type canonicalization
+  // and are therefore not compared to expected names.
 
   typeArguments(generic, []);
   typeArguments(superOfGeneric, [gFromGeneric]);
@@ -46,10 +41,6 @@
   ClassMirror superOfGenericWithInt = genericWithInt.superclass;
   ClassMirror superOfSuperOfGenericWithInt = superOfGenericWithInt.superclass;
 
-  typeParameters(genericWithInt, [#G]);
-  typeParameters(superOfGenericWithInt, [#S]);
-  typeParameters(superOfSuperOfGenericWithInt, [#SS]);
-
   typeArguments(genericWithInt, [reflectClass(int)]);
   typeArguments(superOfGenericWithInt, [reflectClass(int)]);
   typeArguments(superOfSuperOfGenericWithInt, [reflectClass(int)]);
diff --git a/third_party/devtools/update.sh b/third_party/devtools/update.sh
index a69f6ee..077d758 100755
--- a/third_party/devtools/update.sh
+++ b/third_party/devtools/update.sh
@@ -30,12 +30,11 @@
 # to serve from DDS.
 mkdir cipd_package
 cp -R packages/devtools/build/ cipd_package/web
-cp -r packages/devtools_server cipd_package
 cp -r packages/devtools_shared cipd_package
 
 cipd create \
   -name dart/third_party/flutter/devtools \
   -in cipd_package \
   -install-mode copy \
-  -tag revision:$1
+  -tag git_revision:$1
 
diff --git a/tools/VERSION b/tools/VERSION
index 19e4d49..547d936c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 76
+PRERELEASE 77
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index be5f821..bfa020b 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -322,6 +322,7 @@
       "xcodebuild/ReleaseSIMARM64C/",
       "xcodebuild/ReleaseX64/",
       "xcodebuild/ReleaseX64C/",
+      "pkg/",
       "samples/",
       "samples_2/",
       "samples-dev/",
@@ -329,6 +330,7 @@
       "third_party/android_tools/sdk/platform-tools/adb",
       "third_party/android_tools/ndk/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip",
       "third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip",
+      "third_party/devtools/",
       "third_party/webdriver/",
       "third_party/pkg/",
       "third_party/pkg_tested/",
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index babc89d..4cf47e0 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -57,6 +57,8 @@
     packageDirectory(
         'runtime/observatory_2/tests/service_2/observatory_test_package_2'),
     packageDirectory('sdk/lib/_internal/sdk_library_metadata'),
+    packageDirectory('third_party/devtools/devtools_server'),
+    packageDirectory('third_party/devtools/devtools_shared'),
     packageDirectory('third_party/pkg/protobuf/protobuf'),
     packageDirectory('tools/package_deps'),
   ];
diff --git a/utils/dartdev/BUILD.gn b/utils/dartdev/BUILD.gn
index 7f33d99..3ce3bc3 100644
--- a/utils/dartdev/BUILD.gn
+++ b/utils/dartdev/BUILD.gn
@@ -2,12 +2,14 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+import("../../build/dart/copy_tree.gni")
 import("../application_snapshot.gni")
 
 group("dartdev") {
   public_deps = [
     ":copy_dartdev_kernel",
     ":copy_dartdev_snapshot",
+    ":copy_prebuilt_devtools",
   ]
 }
 
@@ -39,3 +41,15 @@
   deps = [ "../dds:dds" ]
   output = "$root_gen_dir/dartdev.dart.snapshot"
 }
+
+copy_trees("copy_prebuilt_devtools") {
+  sources = [
+    {
+      target = "copy_prebuilt_devtools"
+      visibility = [ ":dartdev" ]
+      source = "../../third_party/devtools/web"
+      dest = "$root_out_dir/devtools"
+      ignore_patterns = "{}"
+    },
+  ]
+}