[kernel] readAndPushTypeParameterList takes useGrowableLists into account

This means that when useGrowableLists is false all empty TypeParameter
lists are the same (unmodifiable) empty list.

When running dart2js in its "linker scenario" on a large internal app
this saves something along the lines of 30MB of memory.

Change-Id: Iee31016d238650de19db584a5617ca4a16889fe7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/186940
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index af89d14..47f4628 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -13378,6 +13378,11 @@
 final List<NamedType> emptyListOfNamedType =
     List.filled(0, dummyNamedType, growable: false);
 
+/// Almost const <TypeParameter>[], but not const in an attempt to avoid
+/// polymorphism. See https://dart-review.googlesource.com/c/sdk/+/185828.
+final List<TypeParameter> emptyListOfTypeParameter =
+    List.filled(0, dummyTypeParameter, growable: false);
+
 /// Non-nullable [DartType] dummy value.
 ///
 /// This is used as the removal sentinel in [RemovingTransformer] and can be
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 4f9b333..911ea5a 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -2944,7 +2944,14 @@
   List<TypeParameter> readAndPushTypeParameterList(
       [List<TypeParameter> list, TreeNode parent]) {
     int length = readUInt30();
-    if (length == 0) return list ?? <TypeParameter>[];
+    if (length == 0) {
+      if (list != null) return list;
+      if (useGrowableLists) {
+        return <TypeParameter>[];
+      } else {
+        return emptyListOfTypeParameter;
+      }
+    }
     if (list == null) {
       list = new List<TypeParameter>.generate(
           length, (_) => new TypeParameter(null, null)..parent = parent,