[VM/runtime] Refactor the representation of type parameters in the VM.

This introduces a new VM internal class 'TypeParameters' representing the declaration of a list of type parameters, either in a class or function.
The reference to (or use of) a type parameter is still represented by the existing 'TypeParameter' class.

Fixes https://github.com/dart-lang/sdk/issues/43901
Fixes https://github.com/dart-lang/sdk/issues/45763

TEST=existing ones and a regression test

Change-Id: I1fde808bf753cc1cb829f2c4383c1836651cee80
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/189942
Commit-Queue: RĂ©gis Crelier <regis@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
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 1910b15..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;
 
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/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 f786a81..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;
 }
@@ -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 087b9c1..1bed607 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -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 6d1de7d..dc9d048 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -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'.
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_loader.cc b/runtime/vm/kernel_loader.cc
index f48bdaf..4b39508 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -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);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index f241a57..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();
 }
 
@@ -19578,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;
       }
     }
@@ -19699,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;
   }
@@ -19937,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;
     }
@@ -20767,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());
@@ -20861,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;
@@ -20896,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;
@@ -20934,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());
@@ -20973,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);
@@ -21137,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());
 }
 
@@ -21188,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();
@@ -21244,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));
 }
@@ -21288,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;
 }
@@ -21347,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()) {
@@ -21387,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 {
@@ -21396,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());
@@ -21435,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;
@@ -21488,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 {
@@ -21528,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);
@@ -21584,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();
   }
@@ -21605,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());
@@ -21657,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();
 
@@ -21676,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();
@@ -21715,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(
@@ -21741,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());
@@ -21755,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 0a54c9d..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 {
@@ -7483,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:
@@ -8307,6 +8372,8 @@
   }
 
   // Reexported so they can be used by the flow graph builders.
+  using PackedNumParentTypeArguments =
+      UntaggedFunctionType::PackedNumParentTypeArguments;
   using PackedHasNamedOptionalParameters =
       UntaggedFunctionType::PackedHasNamedOptionalParameters;
   using PackedNumFixedParameters =
@@ -8314,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;
 
@@ -8369,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_);
   }
@@ -8536,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_);
   }
@@ -8575,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;
@@ -8625,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));
   }
@@ -8633,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:
@@ -8993,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 a50a643..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_;
@@ -2497,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 {
@@ -2545,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);
@@ -2618,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_;
 
@@ -2640,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/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)]);