Version 2.10.0-39.0.dev

Merge commit '538e2e47789184e66e2792d7a90830d9d78a4ddc' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2ac349f..3325b41 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,7 +19,19 @@
 *   Introduces `Dart_FinalizableHandle`s. They do auto-delete, and the weakly
     referred object cannot be accessed through them.
 
+### Dart2JS
+
+*   Adds support for deferred loading of types seperately from classes. This
+    enables dart2js to make better optimization choices when deferred loading.
+    This work is necessary to address unsoundness in the deferred loading
+    algorithm. Currently, fixing this unsoundness would result in code bloat,
+    but loading types seperately from classes will allow us to fix the
+    unsoundness with only a minimal regression. To explicitly disable
+    deferred loading of types, pass `--no-defer-class-types`. See the original
+    post on the [unsoundness in the deferred loading algorithm][].
+
 [#42982]: https://github.com/dart-lang/sdk/issues/42982
+[unsoundness in the deferred loading algorithm]: https://github.com/dart-lang/sdk/blob/302ad7ab2cd2de936254850550aad128ae76bbb7/CHANGELOG.md#dart2js-3
 
 ### Tools
 
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 41b46d5..c1bfac7 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -112,7 +112,7 @@
   int codegenShard;
   int codegenShards;
   List<String> bazelPaths;
-  List<String> multiRoots;
+  List<Uri> multiRoots;
   String multiRootScheme = 'org-dartlang-app';
   Uri packageConfig = null;
   List<String> options = new List<String>();
@@ -200,8 +200,8 @@
 
   void setMultiRoots(String argument) {
     String paths = extractParameter(argument);
-    multiRoots ??= <String>[];
-    multiRoots.addAll(paths.split(','));
+    multiRoots ??= <Uri>[];
+    multiRoots.addAll(paths.split(',').map(fe.nativeToUri));
   }
 
   void setMultiRootScheme(String argument) {
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 6cd91f3..2871956 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -158,7 +158,7 @@
   bool reportInvalidInferredDeferredTypes = false;
 
   /// Whether to defer load class types.
-  bool deferClassTypes = false; // default value.
+  bool deferClassTypes = true; // default value.
   bool _deferClassTypes = false;
   bool _noDeferClassTypes = false;
 
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index e227a7d..f8b1da3 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -602,8 +602,7 @@
   final List<Uri> roots;
   final String markerScheme;
 
-  MultiRootInputProvider(this.markerScheme, List<String> searchPaths)
-      : roots = searchPaths.map(Uri.base.resolve).toList();
+  MultiRootInputProvider(this.markerScheme, this.roots);
 
   @override
   Future<api.Input<List<int>>> readFromUri(Uri uri,
diff --git a/pkg/compiler/test/codegen/class_codegen_test.dart b/pkg/compiler/test/codegen/class_codegen_test.dart
index a4f0c3d..6236208 100644
--- a/pkg/compiler/test/codegen/class_codegen_test.dart
+++ b/pkg/compiler/test/codegen/class_codegen_test.dart
@@ -26,6 +26,8 @@
 main() {
   new A();
   new B();
+  String c = '';
+  print(c);
 }
 """;
 
@@ -34,6 +36,8 @@
 class A { }
 
 main() {
+  String c = '';
+  print(c);
   new B();
   new A();
 }
diff --git a/pkg/compiler/test/deferred/not_in_main_test.dart b/pkg/compiler/test/deferred/not_in_main_test.dart
index d66079a..9550547 100644
--- a/pkg/compiler/test/deferred/not_in_main_test.dart
+++ b/pkg/compiler/test/deferred/not_in_main_test.dart
@@ -18,6 +18,9 @@
     print('--test from kernel------------------------------------------------');
     await deferredTest1();
     await deferredTest2();
+    await deferredTest3();
+    await deferredTest4();
+    await deferredTest5();
   });
 }
 
@@ -45,12 +48,75 @@
   var closedWorld = compiler.backendClosedWorldForTesting;
   var env = closedWorld.elementEnvironment;
   var outputUnitForClass = closedWorld.outputUnitData.outputUnitForClass;
+  var outputUnitForClassType =
+      closedWorld.outputUnitData.outputUnitForClassType;
+  lookupLibrary(name) => env.lookupLibrary(Uri.parse(name));
+  dynamic shared = lookupLibrary("memory:shared.dart");
+  var a = env.lookupClass(shared, "A");
+
+  Expect.equals("OutputUnit(1, {import(def: deferred)})",
+      outputUnitForClass(a).toString());
+  Expect.equals("OutputUnit(1, {import(def: deferred)})",
+      outputUnitForClassType(a).toString());
+}
+
+deferredTest3() async {
+  CompilationResult result = await runCompiler(memorySourceFiles: TEST3);
+
+  Compiler compiler = result.compiler;
+  var closedWorld = compiler.backendClosedWorldForTesting;
+  var env = closedWorld.elementEnvironment;
+  var outputUnitForClass = closedWorld.outputUnitData.outputUnitForClass;
+  var outputUnitForClassType =
+      closedWorld.outputUnitData.outputUnitForClassType;
   var mainOutputUnit = closedWorld.outputUnitData.mainOutputUnit;
   lookupLibrary(name) => env.lookupLibrary(Uri.parse(name));
   dynamic shared = lookupLibrary("memory:shared.dart");
   var a = env.lookupClass(shared, "A");
 
   Expect.equals(mainOutputUnit, outputUnitForClass(a));
+  Expect.equals(mainOutputUnit, outputUnitForClassType(a));
+}
+
+deferredTest4() async {
+  CompilationResult result = await runCompiler(memorySourceFiles: TEST4);
+
+  Compiler compiler = result.compiler;
+  var closedWorld = compiler.backendClosedWorldForTesting;
+  var env = closedWorld.elementEnvironment;
+  var outputUnitForClass = closedWorld.outputUnitData.outputUnitForClass;
+  var outputUnitForClassType =
+      closedWorld.outputUnitData.outputUnitForClassType;
+  var mainOutputUnit = closedWorld.outputUnitData.mainOutputUnit;
+  lookupLibrary(name) => env.lookupLibrary(Uri.parse(name));
+  dynamic shared = lookupLibrary("memory:shared.dart");
+  var a = env.lookupClass(shared, "A");
+
+  Expect.equals("OutputUnit(1, {import(def: deferred)})",
+      outputUnitForClass(a).toString());
+  Expect.equals(mainOutputUnit, outputUnitForClassType(a));
+}
+
+deferredTest5() async {
+  CompilationResult result = await runCompiler(memorySourceFiles: TEST5);
+
+  Compiler compiler = result.compiler;
+  var closedWorld = compiler.backendClosedWorldForTesting;
+  var env = closedWorld.elementEnvironment;
+  var outputUnitForClass = closedWorld.outputUnitData.outputUnitForClass;
+  var outputUnitForClassType =
+      closedWorld.outputUnitData.outputUnitForClassType;
+  lookupLibrary(name) => env.lookupLibrary(Uri.parse(name));
+  dynamic shared = lookupLibrary("memory:shared.dart");
+  var a = env.lookupClass(shared, "A");
+  Expect.equals(
+      "OutputUnit(1, {import(def2: deferred), import(def3: deferred)})",
+      outputUnitForClass(a).toString());
+  Expect.equals(
+      "OutputUnit(2, {import(def1: deferred), "
+      "import(def2: deferred), "
+      "import(def3: deferred)})",
+      outputUnitForClassType(a).toString());
 }
 
 // lib1 imports lib2 deferred. But mainlib never uses DeferredLibrary.
@@ -81,8 +147,7 @@
 """,
 };
 
-// main indirectly uses class A from shared. A should still be included in the
-// main fragment.
+// A's type should be in main.
 const Map<String, String> TEST2 = const {
   "main.dart": """
 import 'def.dart' deferred as def;
@@ -108,3 +173,94 @@
 foo(B b) => null;
 """,
 };
+
+// main directly uses class A from shared. A should be included in the
+// main fragment.
+const Map<String, String> TEST3 = const {
+  "main.dart": """
+import 'def.dart' deferred as def;
+import 'shared.dart';
+
+main() {
+  print(A());
+  def.loadLibrary().then((_) {
+    def.toto();
+  });
+}
+""",
+  "def.dart": """
+import 'shared.dart';
+
+toto() { print(new A()); }
+""",
+  "shared.dart": """
+class A {}
+class B extends A {}
+""",
+};
+
+// main directly uses class A's type from shared. A's type but not class
+// should be included in main.
+const Map<String, String> TEST4 = const {
+  "main.dart": """
+import 'def.dart' deferred as def;
+import 'shared.dart';
+
+main() {
+  print(5 is A);
+  def.loadLibrary().then((_) {
+    def.toto();
+  });
+}
+""",
+  "def.dart": """
+import 'shared.dart';
+
+toto() { print(new A()); }
+""",
+  "shared.dart": """
+class A {}
+""",
+};
+
+// main doesn't directly use A's class or type, but does so indirectly.
+const Map<String, String> TEST5 = const {
+  "main.dart": """
+import 'def1.dart' deferred as def1;
+import 'def2.dart' deferred as def2;
+import 'def3.dart' deferred as def3;
+
+main() {
+  def1.loadLibrary().then((_) {
+    def2.loadLibrary().then((_) {
+      def3.loadLibrary().then((_) {
+        def1.toto(null);
+        def2.toto();
+        def3.toto(null);
+      });
+    });
+  });
+}
+""",
+  "def1.dart": """
+import 'shared.dart';
+
+toto(x) => x is A;
+""",
+  "def2.dart": """
+import 'shared.dart';
+
+toto() { print(A()); }
+""",
+  "def3.dart": """
+import 'shared.dart';
+
+toto(x) {
+  print(new A());
+  return x is A;
+}
+""",
+  "shared.dart": """
+class A {}
+""",
+};
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_class/lib.dart b/pkg/compiler/test/deferred_loading/data/deferred_class/lib.dart
index 7e98e7b..faac240 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_class/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_class/lib.dart
@@ -8,7 +8,7 @@
 
 library deferred_class_library;
 
-/*class: MyClass:OutputUnit(1, {lib})*/
+/*class: MyClass:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class MyClass {
   /*member: MyClass.:OutputUnit(1, {lib})*/
   const MyClass();
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant1/lib3.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant1/lib3.dart
index 8283665..5d63ed2 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant1/lib3.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant1/lib3.dart
@@ -6,7 +6,7 @@
 
 library deferred_constants1_lib3;
 
-/*class: C:OutputUnit(main, {})*/
+/*class: C:OutputUnit(main, {}), type=OutputUnit(main, {})*/
 class C {
   /*member: C.value:OutputUnit(main, {})*/
   final value;
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant2/lib.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant2/lib.dart
index db36de5..9d06cea 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant2/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant2/lib.dart
@@ -6,7 +6,7 @@
 
 library deferred_constants2_lib;
 
-/*class: Constant:OutputUnit(1, {lib})*/
+/*class: Constant:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class Constant {
   /*member: Constant.value:OutputUnit(1, {lib})*/
   final value;
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant3/shared.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant3/shared.dart
index 401e946..57c860b 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant3/shared.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant3/shared.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*class: C:OutputUnit(main, {})*/
+/*class: C:OutputUnit(main, {}), type=OutputUnit(main, {})*/
 class C {
   const C(this.x);
 
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/deferred_overlapping_lib3.dart b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/deferred_overlapping_lib3.dart
index 839af93..a4170a9 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/deferred_overlapping_lib3.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/deferred_overlapping_lib3.dart
@@ -4,6 +4,6 @@
 
 // @dart = 2.7
 
-/*class: C3:OutputUnit(1, {lib1, lib2})*/
+/*class: C3:OutputUnit(1, {lib1, lib2}), type=OutputUnit(1, {lib1, lib2})*/
 /*member: C3.:OutputUnit(1, {lib1, lib2})*/
 class C3 {}
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib1.dart b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib1.dart
index 6172db7..1f1586c 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib1.dart
@@ -6,6 +6,6 @@
 
 import "deferred_overlapping_lib3.dart";
 
-/*class: C1:OutputUnit(2, {lib1})*/
+/*class: C1:OutputUnit(2, {lib1}), type=OutputUnit(2, {lib1})*/
 /*member: C1.:OutputUnit(2, {lib1})*/
 class C1 extends C3 {}
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib2.dart b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib2.dart
index c8cd0e6..748d2cd 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib2.dart
@@ -6,6 +6,6 @@
 
 import "deferred_overlapping_lib3.dart";
 
-/*class: C2:OutputUnit(3, {lib2})*/
+/*class: C2:OutputUnit(3, {lib2}), type=OutputUnit(3, {lib2})*/
 /*member: C2.:OutputUnit(3, {lib2})*/
 class C2 extends C3 {}
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_typed_map/lib1.dart b/pkg/compiler/test/deferred_loading/data/deferred_typed_map/lib1.dart
index f5a9c26..0c7ae5a 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_typed_map/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_typed_map/lib1.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*class: M:OutputUnit(1, {lib})*/
+/*class: M:none, type=OutputUnit(1, {lib})*/
 class M {}
 
 typedef dynamic FF({M b});
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_typedef/lib1.dart b/pkg/compiler/test/deferred_loading/data/deferred_typedef/lib1.dart
index a5bc5f9..e1a6bb8 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_typedef/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_typedef/lib1.dart
@@ -6,7 +6,7 @@
 
 library deferred_typedef_lib1;
 
-/*class: C:OutputUnit(1, {lib1})*/
+/*class: C:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
 class C {
   /*member: C.a:OutputUnit(1, {lib1})*/
   final a;
diff --git a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/exported_main.dart b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/exported_main.dart
index 35834d4..2fcc514 100644
--- a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/exported_main.dart
+++ b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/exported_main.dart
@@ -9,7 +9,7 @@
 
 const c = "string3";
 
-/*class: C:OutputUnit(main, {})*/
+/*class: C:OutputUnit(main, {}), type=OutputUnit(main, {})*/
 class C {
   /*member: C.p:OutputUnit(main, {})*/
   final p;
diff --git a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib1.dart b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib1.dart
index 8e5690c..c017966 100644
--- a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib1.dart
@@ -15,7 +15,7 @@
 
 const C2b = const C(1010);
 
-/*class: D:null*/
+/*class: D:none, type=none*/
 class D {
   static const C3 = "string2";
 
diff --git a/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/lib.dart b/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/lib.dart
index f920e6b..f305b51 100644
--- a/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/lib.dart
@@ -16,7 +16,7 @@
 /*member: d:OutputUnit(1, {lib})*/
 d() => print("123");
 
-/*class: B:OutputUnit(1, {lib})*/
+/*class: B:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class B {
   /*member: B.:OutputUnit(1, {lib})*/
   B() {
@@ -24,14 +24,14 @@
   }
 }
 
-/*class: B2:OutputUnit(1, {lib})*/
+/*class: B2:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: B2.:OutputUnit(1, {lib})*/
 class B2 extends B {
   // No constructor creates a synthetic constructor that has an implicit
   // super-call.
 }
 
-/*class: A:OutputUnit(1, {lib})*/
+/*class: A:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class A {
   /*member: A.:OutputUnit(1, {lib})*/
   A() {
@@ -39,17 +39,17 @@
   }
 }
 
-/*class: A2:OutputUnit(1, {lib})*/
+/*class: A2:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class A2 extends A {
   // Implicit super call.
   /*member: A2.:OutputUnit(1, {lib})*/
   A2();
 }
 
-/*class: C1:OutputUnit(1, {lib})*/
+/*class: C1:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class C1 {}
 
-/*class: C2:OutputUnit(1, {lib})*/
+/*class: C2:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class C2 {
   /*member: C2.:OutputUnit(1, {lib})*/
   C2() {
@@ -57,33 +57,33 @@
   }
 }
 
-/*class: C2p:null*/
+/*class: C2p:none, type=none*/
 class C2p {
   C2() {
     c();
   }
 }
 
-/*class: C3:OutputUnit(1, {lib})*/
+/*class: C3:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: C3.:OutputUnit(1, {lib})*/
 class C3 extends C2 with C1 {
   // Implicit redirecting "super" call via mixin.
 }
 
-/*class: E:OutputUnit(1, {lib})*/
+/*class: E:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class E {}
 
-/*class: F:OutputUnit(1, {lib})*/
+/*class: F:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class F {}
 
-/*class: G:OutputUnit(1, {lib})*/
+/*class: G:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: G.:OutputUnit(1, {lib})*/
 class G extends C3 with C1, E, F {}
 
-/*class: D1:OutputUnit(1, {lib})*/
+/*class: D1:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class D1 {}
 
-/*class: D2:OutputUnit(1, {lib})*/
+/*class: D2:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class D2 {
   /*member: D2.:OutputUnit(1, {lib})*/
   D2(x) {
@@ -92,5 +92,5 @@
 }
 
 // Implicit redirecting "super" call with a parameter via mixin.
-/*class: D3:OutputUnit(1, {lib})*/
+/*class: D3:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 class D3 = D2 with D1;
diff --git a/pkg/compiler/test/deferred_loading/data/future_or/lib2.dart b/pkg/compiler/test/deferred_loading/data/future_or/lib2.dart
index fde4bbc..d222767 100644
--- a/pkg/compiler/test/deferred_loading/data/future_or/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/future_or/lib2.dart
@@ -4,10 +4,10 @@
 
 // @dart = 2.7
 
-/*class: A:OutputUnit(main, {})*/
+/*class: A:OutputUnit(1, {lib1}), type=OutputUnit(main, {})*/
 class A {
   const A();
 
-  /*member: A.method:OutputUnit(main, {})*/
+  /*member: A.method:OutputUnit(1, {lib1})*/
   method() {}
 }
diff --git a/pkg/compiler/test/deferred_loading/data/future_or/main.dart b/pkg/compiler/test/deferred_loading/data/future_or/main.dart
index deb3dc9..ed02ff6 100644
--- a/pkg/compiler/test/deferred_loading/data/future_or/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/future_or/main.dart
@@ -8,10 +8,7 @@
 import 'lib1.dart' deferred as lib1;
 import 'lib2.dart' as lib2;
 
-/*member: main:
- OutputUnit(main, {}),
- constants=[ConstructedConstant(A())=OutputUnit(1, {lib1})]
-*/
+/*member: main:OutputUnit(main, {}),constants=[ConstructedConstant(A())=OutputUnit(1, {lib1})]*/
 main() async {
   await lib1.loadLibrary();
   lib1.field is FutureOr<lib2.A>;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart
index 07c483a..0b94d3a 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart
@@ -6,8 +6,8 @@
 
 // Test instantiation used only in a deferred library.
 
-/*class: global#Instantiation:OutputUnit(1, {b})*/
-/*class: global#Instantiation1:OutputUnit(1, {b})*/
+/*class: global#Instantiation:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
+/*class: global#Instantiation1:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
 
 import 'lib1.dart' deferred as b;
 
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart
index 8f40a89..2e0e4ef 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart
@@ -7,9 +7,9 @@
 // Test instantiations with different type argument count used only in two
 // deferred libraries.
 
-/*class: global#Instantiation:OutputUnit(2, {b, c})*/
-/*class: global#Instantiation1:OutputUnit(1, {b})*/
-/*class: global#Instantiation2:OutputUnit(3, {c})*/
+/*class: global#Instantiation:OutputUnit(2, {b, c}), type=OutputUnit(2, {b, c})*/
+/*class: global#Instantiation1:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
+/*class: global#Instantiation2:OutputUnit(3, {c}), type=OutputUnit(3, {c})*/
 
 import 'lib1.dart' deferred as b;
 import 'lib2.dart' deferred as c;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart
index 9c4fb76..70dc5f6 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart
@@ -7,8 +7,8 @@
 // Test instantiations with the same type argument count used only in two
 // deferred libraries.
 
-/*class: global#Instantiation:OutputUnit(1, {b, c})*/
-/*class: global#Instantiation1:OutputUnit(1, {b, c})*/
+/*class: global#Instantiation:OutputUnit(1, {b, c}), type=OutputUnit(1, {b, c})*/
+/*class: global#Instantiation1:OutputUnit(1, {b, c}), type=OutputUnit(1, {b, c})*/
 
 import 'lib1.dart' deferred as b;
 import 'lib2.dart' deferred as c;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart
index dad30c1..3cb4f5a 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart
@@ -6,8 +6,8 @@
 
 // Test instantiation used only in a deferred library.
 
-/*class: global#Instantiation:OutputUnit(1, {b})*/
-/*class: global#Instantiation1:OutputUnit(1, {b})*/
+/*class: global#Instantiation:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
+/*class: global#Instantiation1:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
 
 /*member: global#instantiate1:OutputUnit(1, {b})*/
 
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart
index 7f641b8..4359611 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart
@@ -9,10 +9,7 @@
 
 typedef dynamic G<T>(T v);
 
-/*member: m:
- OutputUnit(1, {b}),
- constants=[FunctionConstant(getFoo)=OutputUnit(1, {b})]
-*/
+/*member: m:OutputUnit(1, {b}),constants=[FunctionConstant(getFoo)=OutputUnit(1, {b})]*/
 m(int x, {G<int> f}) {
   f ??= getFoo;
   print(f(x));
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart
index 302e331..361d35a 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart
@@ -7,9 +7,9 @@
 // Test instantiations with different type argument count used only in two
 // deferred libraries.
 
-/*class: global#Instantiation:OutputUnit(2, {b, c})*/
-/*class: global#Instantiation1:OutputUnit(1, {b})*/
-/*class: global#Instantiation2:OutputUnit(3, {c})*/
+/*class: global#Instantiation:OutputUnit(2, {b, c}), type=OutputUnit(2, {b, c})*/
+/*class: global#Instantiation1:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
+/*class: global#Instantiation2:OutputUnit(3, {c}), type=OutputUnit(3, {c})*/
 
 /*member: global#instantiate1:OutputUnit(1, {b})*/
 /*member: global#instantiate2:OutputUnit(3, {c})*/
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart
index ba9004e..9f270b1 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart
@@ -7,8 +7,8 @@
 // Test instantiations with the same type argument count used only in two
 // deferred libraries.
 
-/*class: global#Instantiation:OutputUnit(1, {b, c})*/
-/*class: global#Instantiation1:OutputUnit(1, {b, c})*/
+/*class: global#Instantiation:OutputUnit(1, {b, c}), type=OutputUnit(1, {b, c})*/
+/*class: global#Instantiation1:OutputUnit(1, {b, c}), type=OutputUnit(1, {b, c})*/
 
 /*member: global#instantiate1:OutputUnit(1, {b, c})*/
 
diff --git a/pkg/compiler/test/deferred_loading/data/inteface_type_variable/lib.dart b/pkg/compiler/test/deferred_loading/data/inteface_type_variable/lib.dart
index 97e8353..95c9a26 100644
--- a/pkg/compiler/test/deferred_loading/data/inteface_type_variable/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/inteface_type_variable/lib.dart
@@ -4,35 +4,35 @@
 
 // @dart = 2.7
 
-/*class: A:OutputUnit(1, {lib})*/
+/*class: A:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: A.:OutputUnit(1, {lib})*/
 class A {}
 
-/*class: I:OutputUnit(1, {lib})*/
+/*class: I:none, type=OutputUnit(1, {lib})*/
 class I<T> {}
 
-/*class: J:OutputUnit(1, {lib})*/
+/*class: J:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: J.:OutputUnit(1, {lib})*/
 class J<T> {}
 
 // C needs to include "N", otherwise checking for `is I<A>` will likely cause
 // problems
-/*class: C:OutputUnit(1, {lib})*/
+/*class: C:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: C.:OutputUnit(1, {lib})*/
 class C extends A implements I<N> {}
 
-/*class: C1:OutputUnit(1, {lib})*/
+/*class: C1:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: C1.:OutputUnit(1, {lib})*/
 class C1 extends J<M> implements A {}
 
-/*class: C2:OutputUnit(1, {lib})*/
+/*class: C2:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: C2.:OutputUnit(1, {lib})*/
 class C2 extends J<M> implements I<N> {}
 
-/*class: N:OutputUnit(1, {lib})*/
+/*class: N:none, type=OutputUnit(1, {lib})*/
 class N extends A {}
 
-/*class: M:OutputUnit(1, {lib})*/
+/*class: M:none, type=OutputUnit(1, {lib})*/
 class M extends A {}
 
 /*member: doCheck1:OutputUnit(1, {lib})*/
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart
index f8a57c2..3e9dbdf 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart
@@ -4,24 +4,24 @@
 
 // @dart = 2.7
 
-/*class: Foo:OutputUnit(1, {libA, libB, libC})*/
+/*class: Foo:OutputUnit(1, {libB}), type=OutputUnit(3, {libA, libB, libC})*/
 class Foo {
-  /*member: Foo.x:OutputUnit(1, {libA, libB, libC})*/
+  /*member: Foo.x:OutputUnit(1, {libB})*/
   int x;
-  /*member: Foo.:OutputUnit(3, {libB})*/
+  /*member: Foo.:OutputUnit(1, {libB})*/
   Foo() {
     x = DateTime.now().millisecond;
   }
-  /*member: Foo.method:OutputUnit(1, {libA, libB, libC})*/
+  /*member: Foo.method:OutputUnit(1, {libB})*/
   int method() => x;
 }
 
-/*member: isFoo:OutputUnit(1, {libA, libB, libC})*/
+/*member: isFoo:OutputUnit(3, {libA, libB, libC})*/
 bool isFoo(o) {
   return o is Foo;
 }
 
-/*member: callFooMethod:OutputUnit(3, {libB})*/
+/*member: callFooMethod:OutputUnit(1, {libB})*/
 int callFooMethod() {
   return Foo().method();
 }
@@ -29,58 +29,58 @@
 typedef int FunFoo(Foo a);
 typedef int FunFunFoo(FunFoo b, int c);
 
-/*member: isFunFunFoo:OutputUnit(1, {libA, libB, libC})*/
+/*member: isFunFunFoo:OutputUnit(3, {libA, libB, libC})*/
 bool isFunFunFoo(o) {
   return o is FunFunFoo;
 }
 
-/*class: Aoo:OutputUnit(4, {libB, libC})*/
+/*class: Aoo:none, type=OutputUnit(2, {libC})*/
 class Aoo<T> {}
 
-/*class: Boo:OutputUnit(4, {libB, libC})*/
+/*class: Boo:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
 class Boo<T> implements Aoo<T> {}
 
-/*class: Coo:OutputUnit(4, {libB, libC})*/
-/*member: Coo.:OutputUnit(6, {libC})*/
+/*class: Coo:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
+/*member: Coo.:OutputUnit(2, {libC})*/
 class Coo<T> {}
 
-/*class: Doo:OutputUnit(4, {libB, libC})*/
-/*member: Doo.:OutputUnit(6, {libC})*/
+/*class: Doo:OutputUnit(2, {libC}), type=OutputUnit(5, {libB, libC})*/
+/*member: Doo.:OutputUnit(2, {libC})*/
 class Doo<T> extends Coo<T> with Boo<T> {}
 
-/*member: createDooFunFunFoo:OutputUnit(6, {libC})*/
+/*member: createDooFunFunFoo:OutputUnit(2, {libC})*/
 createDooFunFunFoo() => Doo<FunFunFoo>();
 
-/*class: B:OutputUnit(2, {libA, libC})*/
-/*member: B.:OutputUnit(6, {libC})*/
+/*class: B:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
+/*member: B.:OutputUnit(2, {libC})*/
 class B {}
 
-/*class: B2:OutputUnit(2, {libA, libC})*/
-/*member: B2.:OutputUnit(6, {libC})*/
+/*class: B2:OutputUnit(2, {libC}), type=OutputUnit(4, {libA, libC})*/
+/*member: B2.:OutputUnit(2, {libC})*/
 class B2 extends B {}
 
-/*class: C1:OutputUnit(2, {libA, libC})*/
+/*class: C1:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
 class C1 {}
 
-/*class: C2:OutputUnit(2, {libA, libC})*/
-/*member: C2.:OutputUnit(6, {libC})*/
+/*class: C2:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
+/*member: C2.:OutputUnit(2, {libC})*/
 class C2 {}
 
-/*class: C3:OutputUnit(2, {libA, libC})*/
-/*member: C3.:OutputUnit(6, {libC})*/
+/*class: C3:OutputUnit(2, {libC}), type=OutputUnit(4, {libA, libC})*/
+/*member: C3.:OutputUnit(2, {libC})*/
 class C3 extends C2 with C1 {}
 
-/*class: D1:OutputUnit(2, {libA, libC})*/
+/*class: D1:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
 class D1 {}
 
-/*class: D2:OutputUnit(2, {libA, libC})*/
-/*member: D2.:OutputUnit(6, {libC})*/
+/*class: D2:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
+/*member: D2.:OutputUnit(2, {libC})*/
 class D2 {}
 
-/*class: D3:OutputUnit(2, {libA, libC})*/
+/*class: D3:OutputUnit(2, {libC}), type=OutputUnit(4, {libA, libC})*/
 class D3 = D2 with D1;
 
-/*member: isMega:OutputUnit(5, {libA})*/
+/*member: isMega:OutputUnit(6, {libA})*/
 bool isMega(o) {
   return o is B2 || o is C3 || o is D3;
 }
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/liba.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/liba.dart
index a712114..5601618 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/liba.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/liba.dart
@@ -6,11 +6,11 @@
 
 import 'lib.dart' as lib;
 
-/*member: isFoo:OutputUnit(5, {libA})*/
+/*member: isFoo:OutputUnit(6, {libA})*/
 bool isFoo(o) => lib.isFoo(o);
 
-/*member: isFunFunFoo:OutputUnit(5, {libA})*/
+/*member: isFunFunFoo:OutputUnit(6, {libA})*/
 bool isFunFunFoo(o) => lib.isFunFunFoo(o);
 
-/*member: isMega:OutputUnit(5, {libA})*/
+/*member: isMega:OutputUnit(6, {libA})*/
 bool isMega(o) => lib.isMega(o);
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/libb.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/libb.dart
index 591fe47..2b28333 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/libb.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/libb.dart
@@ -6,14 +6,14 @@
 
 import 'lib.dart' as lib;
 
-/*member: callFooMethod:OutputUnit(3, {libB})*/
+/*member: callFooMethod:OutputUnit(1, {libB})*/
 int callFooMethod() => lib.callFooMethod();
 
-/*member: isFoo:OutputUnit(3, {libB})*/
+/*member: isFoo:OutputUnit(1, {libB})*/
 bool isFoo(o) => lib.isFoo(o);
 
-/*member: isFunFunFoo:OutputUnit(3, {libB})*/
+/*member: isFunFunFoo:OutputUnit(1, {libB})*/
 bool isFunFunFoo(o) => lib.isFunFunFoo(o);
 
-/*member: isDooFunFunFoo:OutputUnit(3, {libB})*/
+/*member: isDooFunFunFoo:OutputUnit(1, {libB})*/
 bool isDooFunFunFoo(o) => o is lib.Doo<lib.FunFunFoo>;
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/libc.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/libc.dart
index 1c04601..8e9708b 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/libc.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/libc.dart
@@ -6,20 +6,20 @@
 
 import 'lib.dart' as lib;
 
-/*member: isFoo:OutputUnit(6, {libC})*/
+/*member: isFoo:OutputUnit(2, {libC})*/
 bool isFoo(o) => lib.isFoo(o);
 
-/*member: isFunFunFoo:OutputUnit(6, {libC})*/
+/*member: isFunFunFoo:OutputUnit(2, {libC})*/
 bool isFunFunFoo(o) => lib.isFunFunFoo(o);
 
-/*member: createB2:OutputUnit(6, {libC})*/
+/*member: createB2:OutputUnit(2, {libC})*/
 createB2() => new lib.B2();
 
-/*member: createC3:OutputUnit(6, {libC})*/
+/*member: createC3:OutputUnit(2, {libC})*/
 createC3() => new lib.C3();
 
-/*member: createD3:OutputUnit(6, {libC})*/
+/*member: createD3:OutputUnit(2, {libC})*/
 createD3() => new lib.D3();
 
-/*member: createDooFunFunFoo:OutputUnit(6, {libC})*/
+/*member: createDooFunFunFoo:OutputUnit(2, {libC})*/
 createDooFunFunFoo() => lib.createDooFunFunFoo();
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart
index 885e32e..541070c 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart
@@ -8,7 +8,7 @@
 import 'libb.dart' deferred as libB;
 import 'libc.dart' deferred as libC;
 
-/*member: foo:OutputUnit(main, {}),constants=[FunctionConstant(callFooMethod)=OutputUnit(3, {libB}),FunctionConstant(createB2)=OutputUnit(6, {libC}),FunctionConstant(createC3)=OutputUnit(6, {libC}),FunctionConstant(createD3)=OutputUnit(6, {libC}),FunctionConstant(createDooFunFunFoo)=OutputUnit(6, {libC}),FunctionConstant(isDooFunFunFoo)=OutputUnit(3, {libB}),FunctionConstant(isFoo)=OutputUnit(3, {libB}),FunctionConstant(isFoo)=OutputUnit(5, {libA}),FunctionConstant(isFoo)=OutputUnit(6, {libC}),FunctionConstant(isFunFunFoo)=OutputUnit(3, {libB}),FunctionConstant(isFunFunFoo)=OutputUnit(5, {libA}),FunctionConstant(isFunFunFoo)=OutputUnit(6, {libC}),FunctionConstant(isMega)=OutputUnit(5, {libA})]*/
+/*member: foo:OutputUnit(main, {}),constants=[FunctionConstant(callFooMethod)=OutputUnit(1, {libB}),FunctionConstant(createB2)=OutputUnit(2, {libC}),FunctionConstant(createC3)=OutputUnit(2, {libC}),FunctionConstant(createD3)=OutputUnit(2, {libC}),FunctionConstant(createDooFunFunFoo)=OutputUnit(2, {libC}),FunctionConstant(isDooFunFunFoo)=OutputUnit(1, {libB}),FunctionConstant(isFoo)=OutputUnit(1, {libB}),FunctionConstant(isFoo)=OutputUnit(2, {libC}),FunctionConstant(isFoo)=OutputUnit(6, {libA}),FunctionConstant(isFunFunFoo)=OutputUnit(1, {libB}),FunctionConstant(isFunFunFoo)=OutputUnit(2, {libC}),FunctionConstant(isFunFunFoo)=OutputUnit(6, {libA}),FunctionConstant(isMega)=OutputUnit(6, {libA})]*/
 void foo() async {
   await libA.loadLibrary();
   await libB.loadLibrary();
diff --git a/pkg/compiler/test/deferred_loading/data/regress_43055/libb.dart b/pkg/compiler/test/deferred_loading/data/regress_43055/libb.dart
index 1d38a5c..bb954ec 100644
--- a/pkg/compiler/test/deferred_loading/data/regress_43055/libb.dart
+++ b/pkg/compiler/test/deferred_loading/data/regress_43055/libb.dart
@@ -6,6 +6,6 @@
 
 import 'libc.dart';
 
-/*class: C1:OutputUnit(1, {libb})*/
+/*class: C1:OutputUnit(1, {libb}), type=OutputUnit(1, {libb})*/
 /*member: C1.:OutputUnit(1, {libb})*/
 class C1 extends C2 implements C3 {}
diff --git a/pkg/compiler/test/deferred_loading/data/regress_43055/libc.dart b/pkg/compiler/test/deferred_loading/data/regress_43055/libc.dart
index 6133cf2..a1300e3 100644
--- a/pkg/compiler/test/deferred_loading/data/regress_43055/libc.dart
+++ b/pkg/compiler/test/deferred_loading/data/regress_43055/libc.dart
@@ -4,9 +4,9 @@
 
 // @dart = 2.7
 
-/*class: C2:OutputUnit(main, {})*/
+/*class: C2:OutputUnit(1, {libb}), type=OutputUnit(main, {})*/
 /*member: C2.:OutputUnit(1, {libb})*/
 class C2 {}
 
-/*class: C3:OutputUnit(main, {})*/
+/*class: C3:none, type=OutputUnit(main, {})*/
 class C3 {}
diff --git a/pkg/compiler/test/deferred_loading/data/shared_constant/lib_c.dart b/pkg/compiler/test/deferred_loading/data/shared_constant/lib_c.dart
index ffc3796..71f2233 100644
--- a/pkg/compiler/test/deferred_loading/data/shared_constant/lib_c.dart
+++ b/pkg/compiler/test/deferred_loading/data/shared_constant/lib_c.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*class: C:OutputUnit(1, {s1, s2})*/
+/*class: C:OutputUnit(1, {s1, s2}), type=OutputUnit(1, {s1, s2})*/
 class C {
   const C();
 
diff --git a/pkg/compiler/test/deferred_loading/data/static_separate/lib1.dart b/pkg/compiler/test/deferred_loading/data/static_separate/lib1.dart
index c9489f7..ebec04b 100644
--- a/pkg/compiler/test/deferred_loading/data/static_separate/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/static_separate/lib1.dart
@@ -6,7 +6,7 @@
 
 library lib1;
 
-/*class: ConstClass:OutputUnit(2, {lib1, lib2})*/
+/*class: ConstClass:OutputUnit(2, {lib1, lib2}), type=OutputUnit(2, {lib1, lib2})*/
 class ConstClass {
   /*member: ConstClass.x:OutputUnit(2, {lib1, lib2})*/
   final x;
@@ -20,7 +20,7 @@
 */
 var x = const ConstClass(const ConstClass(1));
 
-/*class: C:OutputUnit(1, {lib1})*/
+/*class: C:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
 class C {
   /*member: C.foo:OutputUnit(3, {lib2})*/
   static foo() {
@@ -38,7 +38,7 @@
   }
 }
 
-/*class: C1:null*/
+/*class: C1:none, type=none*/
 class C1 {
   /*member: C1.foo:
    OutputUnit(3, {lib2}),
@@ -48,7 +48,7 @@
   var bar = const {};
 }
 
-/*class: C2:OutputUnit(1, {lib1})*/
+/*class: C2:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
 class C2 {
   /*member: C2.foo:OutputUnit(3, {lib2})*/
   static var foo = new Map<int, int>.from({1: 2});
@@ -60,7 +60,7 @@
   C2();
 }
 
-/*class: C3:OutputUnit(1, {lib1})*/
+/*class: C3:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
 class C3 {
   /*member: C3.foo:
    OutputUnit(3, {lib2}),
@@ -78,7 +78,7 @@
   C3();
 }
 
-/*class: C4:OutputUnit(1, {lib1})*/
+/*class: C4:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
 class C4 {
   /*member: C4.foo:OutputUnit(3, {lib2})*/
   static final foo = new Map<ConstClass, ConstClass>.from({x: x});
@@ -90,7 +90,7 @@
   C4();
 }
 
-/*class: C5:OutputUnit(1, {lib1})*/
+/*class: C5:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
 class C5 {
   static const foo = const [
     const {1: 3}
diff --git a/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib2.dart b/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib2.dart
index bfa82bf..d6a1146 100644
--- a/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib2.dart
@@ -4,13 +4,13 @@
 
 // @dart = 2.7
 
-/*class: A:OutputUnit(main, {})*/
+/*class: A:OutputUnit(1, {c}), type=OutputUnit(1, {c})*/
 class A {
   /*member: A.:OutputUnit(1, {c})*/
   A();
 }
 
-/*class: B:OutputUnit(main, {})*/
+/*class: B:none, type=OutputUnit(main, {})*/
 class B extends A {}
 
 /*member: createA:OutputUnit(1, {c})*/
diff --git a/pkg/compiler/test/deferred_loading/data/type_arguments/lib1.dart b/pkg/compiler/test/deferred_loading/data/type_arguments/lib1.dart
index 052d852..1886af2 100644
--- a/pkg/compiler/test/deferred_loading/data/type_arguments/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_arguments/lib1.dart
@@ -6,12 +6,12 @@
 
 import 'lib3.dart';
 
-/*class: A:OutputUnit(1, {lib1})*/
+/*class: A:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
 class A<T> {
   const A();
 }
 
-/*class: B:OutputUnit(1, {lib1})*/
+/*class: B:none, type=OutputUnit(1, {lib1})*/
 class B {}
 
 const dynamic field1 = const A<B>();
diff --git a/pkg/compiler/test/deferred_loading/data/type_arguments/lib2.dart b/pkg/compiler/test/deferred_loading/data/type_arguments/lib2.dart
index f2d4c91..3f18084 100644
--- a/pkg/compiler/test/deferred_loading/data/type_arguments/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_arguments/lib2.dart
@@ -4,12 +4,12 @@
 
 // @dart = 2.7
 
-/*class: C:OutputUnit(main, {})*/
+/*class: C:OutputUnit(main, {}), type=OutputUnit(main, {})*/
 class C<T> {
   const C();
 }
 
-/*class: D:OutputUnit(main, {})*/
+/*class: D:none, type=OutputUnit(main, {})*/
 class D {}
 
 const dynamic field = const C<D>();
diff --git a/pkg/compiler/test/deferred_loading/data/type_arguments/lib3.dart b/pkg/compiler/test/deferred_loading/data/type_arguments/lib3.dart
index d9e5e24..8e2f533 100644
--- a/pkg/compiler/test/deferred_loading/data/type_arguments/lib3.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_arguments/lib3.dart
@@ -4,12 +4,12 @@
 
 // @dart = 2.7
 
-/*class: E:OutputUnit(3, {lib3})*/
+/*class: E:OutputUnit(2, {lib3}), type=OutputUnit(2, {lib3})*/
 class E<T> {
   const E();
 }
 
-/*class: F:OutputUnit(2, {lib1, lib3})*/
+/*class: F:none, type=OutputUnit(3, {lib1, lib3})*/
 class F {}
 
 const dynamic field = const E<F>();
diff --git a/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart b/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart
index 08b4d39..2e5f732 100644
--- a/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart
@@ -8,7 +8,7 @@
 import 'lib2.dart' as lib2;
 import 'lib3.dart' deferred as lib3;
 
-/*member: main:OutputUnit(main, {}),constants=[ConstructedConstant(A<B*>())=OutputUnit(1, {lib1}),ConstructedConstant(A<F*>())=OutputUnit(1, {lib1}),ConstructedConstant(C<D*>())=OutputUnit(main, {}),ConstructedConstant(E<F*>())=OutputUnit(3, {lib3})]*/
+/*member: main:OutputUnit(main, {}),constants=[ConstructedConstant(A<B*>())=OutputUnit(1, {lib1}),ConstructedConstant(A<F*>())=OutputUnit(1, {lib1}),ConstructedConstant(C<D*>())=OutputUnit(main, {}),ConstructedConstant(E<F*>())=OutputUnit(2, {lib3})]*/
 main() async {
   await lib1.loadLibrary();
   lib1.field1;
diff --git a/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/lib.dart b/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/lib.dart
index 0379450..51880ac 100644
--- a/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/lib.dart
@@ -7,25 +7,25 @@
 // All of these types are considered instantiated because we create an instance
 // of [C].
 
-/*class: A:OutputUnit(1, {lib})*/
+/*class: A:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: A.:OutputUnit(1, {lib})*/
 class A {}
 
-/*class: Box:OutputUnit(1, {lib})*/
+/*class: Box:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: Box.:OutputUnit(1, {lib})*/
 class Box<T> {
   /*member: Box.value:OutputUnit(1, {lib})*/
   int value;
 }
 
-/*class: B:OutputUnit(1, {lib})*/
+/*class: B:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: B.:OutputUnit(1, {lib})*/
 class B<T> extends A {
   /*member: B.box:OutputUnit(1, {lib})*/
   final box = new Box<T>();
 }
 
-/*class: C:OutputUnit(1, {lib})*/
+/*class: C:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
 /*member: C.:OutputUnit(1, {lib})*/
 class C extends B<N> {}
 
@@ -35,5 +35,5 @@
 // to the main output unit. However, A is in the output unit of C so we fail
 // when trying to finalize the declaration of N while loading the main output
 // unit.
-/*class: N:OutputUnit(1, {lib})*/
+/*class: N:none, type=OutputUnit(1, {lib})*/
 class N extends A {}
diff --git a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
index f25018a..e2ad132 100644
--- a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
+++ b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
@@ -49,7 +49,7 @@
 /// Create a consistent string representation of [OutputUnit]s for both
 /// KImportEntities and ImportElements.
 String outputUnitString(OutputUnit unit) {
-  if (unit == null) return 'null';
+  if (unit == null) return 'none';
   StringBuffer sb = new StringBuffer();
   bool first = true;
   for (ImportEntity import in unit.importsForTesting) {
@@ -139,8 +139,12 @@
 
   @override
   String computeClassValue(Id id, ir.Class node) {
-    return outputUnitString(
-        _data.outputUnitForClassForTesting(_elementMap.getClass(node)));
+    var cls = _elementMap.getClass(node);
+    StringBuffer sb = new StringBuffer();
+    sb.write(outputUnitString(_data.outputUnitForClassForTesting(cls)));
+    sb.write(', type=');
+    sb.write(outputUnitString(_data.outputUnitForClassTypeForTesting(cls)));
+    return sb.toString();
   }
 
   @override
diff --git a/pkg/compiler/test/rti/disable_rti_test.dart b/pkg/compiler/test/rti/disable_rti_test.dart
index 6bbeb2f..e993dc6 100644
--- a/pkg/compiler/test/rti/disable_rti_test.dart
+++ b/pkg/compiler/test/rti/disable_rti_test.dart
@@ -25,7 +25,7 @@
 class F<T> extends B<List<T>>{}
 class G {
   call() {}
-} 
+}
 class H implements G {
   call() {}
 }
@@ -108,7 +108,7 @@
       elementEnvironment.forEachLocalClassMember(element, processMember);
 
       List<String> expectedIsChecks = expectedIsChecksMap[element.name];
-      if (expectedIsChecks != null) {
+      if (!expectedIsChecks.isEmpty) {
         Class cls = programLookup.getClass(element);
         List<String> isChecks = cls.isChecks.map((m) => m.name.key).toList();
         if (cls.functionTypeIndex != null) {
diff --git a/pkg/compiler/test/rti/emission/arguments.dart b/pkg/compiler/test/rti/emission/arguments.dart
index 7089270..9c13328 100644
--- a/pkg/compiler/test/rti/emission/arguments.dart
+++ b/pkg/compiler/test/rti/emission/arguments.dart
@@ -4,10 +4,10 @@
 
 // @dart = 2.7
 
-/*class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: A:checkedTypeArgument,typeArgument*/
 class A {}
 
-/*class: B:checks=[],onlyForRti,typeArgument*/
+/*class: B:typeArgument*/
 class B {}
 
 /*class: C:checkedInstance,checks=[],instance*/
diff --git a/pkg/compiler/test/rti/emission/dynamic_instance.dart b/pkg/compiler/test/rti/emission/dynamic_instance.dart
index 14284f7..5afac9b 100644
--- a/pkg/compiler/test/rti/emission/dynamic_instance.dart
+++ b/pkg/compiler/test/rti/emission/dynamic_instance.dart
@@ -6,7 +6,7 @@
 
 import 'package:expect/expect.dart';
 
-/*class: B:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: B:checkedInstance,typeArgument*/
 class B {}
 
 /*class: C:checks=[],instance*/
diff --git a/pkg/compiler/test/rti/emission/dynamic_type_argument.dart b/pkg/compiler/test/rti/emission/dynamic_type_argument.dart
index 5da881f..6d21d6e 100644
--- a/pkg/compiler/test/rti/emission/dynamic_type_argument.dart
+++ b/pkg/compiler/test/rti/emission/dynamic_type_argument.dart
@@ -9,7 +9,7 @@
 /*class: A:checkedInstance,checks=[],instance*/
 class A<T> {}
 
-/*class: B:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: B:checkedTypeArgument,typeArgument*/
 class B {}
 
 /*class: C:checks=[],instance*/
@@ -21,10 +21,10 @@
   method2<T>() => new A<T>();
 }
 
-/*class: D:checks=[],onlyForRti,typeArgument*/
+/*class: D:typeArgument*/
 class D extends B {}
 
-/*class: E:checks=[],onlyForRti,typeArgument*/
+/*class: E:typeArgument*/
 class E {}
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/emission/dynamic_type_literal.dart b/pkg/compiler/test/rti/emission/dynamic_type_literal.dart
index a635a06..04c8efc 100644
--- a/pkg/compiler/test/rti/emission/dynamic_type_literal.dart
+++ b/pkg/compiler/test/rti/emission/dynamic_type_literal.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*class: global#Type:checks=[],instance,onlyForRti,typeLiteral*/
+/*class: global#Type:instance,typeLiteral*/
 
 import "package:expect/expect.dart";
 
diff --git a/pkg/compiler/test/rti/emission/fixed_type_argument.dart b/pkg/compiler/test/rti/emission/fixed_type_argument.dart
index 5ae24b0..dc8a7b5 100644
--- a/pkg/compiler/test/rti/emission/fixed_type_argument.dart
+++ b/pkg/compiler/test/rti/emission/fixed_type_argument.dart
@@ -4,12 +4,12 @@
 
 // @dart = 2.7
 
-/*spec.class: A:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: A:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: A:checkedTypeArgument,typeArgument*/
 class A {}
 
-/*spec.class: B:checkedInstance,checks=[$isA],onlyForRti,typeArgument*/
-/*prod.class: B:checks=[$isA],onlyForRti,typeArgument*/
+/*spec.class: B:checkedInstance,typeArgument*/
+/*prod.class: B:typeArgument*/
 class B implements A {}
 
 /*class: C:checks=[],indirectInstance*/
diff --git a/pkg/compiler/test/rti/emission/fixed_type_argument_implements.dart b/pkg/compiler/test/rti/emission/fixed_type_argument_implements.dart
index a6a9c1b..216d416 100644
--- a/pkg/compiler/test/rti/emission/fixed_type_argument_implements.dart
+++ b/pkg/compiler/test/rti/emission/fixed_type_argument_implements.dart
@@ -7,11 +7,10 @@
 // Test that we emit the relation between B and A even when B is only live
 // as a type argument through the supertype of D.
 
-/*spec.class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: A:checkedTypeArgument,typeArgument*/
 class A {}
 
-/*spec.class: B:checks=[$isA],onlyForRti,typeArgument*/
-/*prod.class: B:checks=[],onlyForRti,typeArgument*/
+/*class: B:typeArgument*/
 class B implements A {}
 
 /*spec.class: C:checkedInstance*/
diff --git a/pkg/compiler/test/rti/emission/function_typed_arguments.dart b/pkg/compiler/test/rti/emission/function_typed_arguments.dart
index 69e8ad7..b09784a 100644
--- a/pkg/compiler/test/rti/emission/function_typed_arguments.dart
+++ b/pkg/compiler/test/rti/emission/function_typed_arguments.dart
@@ -18,10 +18,10 @@
   test6();
 }
 
-/*class: B1:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: B1:checkedTypeArgument,typeArgument*/
 class B1<T> {}
 
-/*class: C1:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: C1:checkedTypeArgument,typeArgument*/
 class C1 extends B1<int> {}
 
 @pragma('dart2js:noInline')
@@ -34,10 +34,10 @@
 @pragma('dart2js:noInline')
 _test1(f) => f is A<void Function(C1)>;
 
-/*class: B2:checks=[],onlyForRti,typeArgument*/
+/*class: B2:typeArgument*/
 class B2<T> {}
 
-/*class: C2:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: C2:checkedTypeArgument,typeArgument*/
 class C2 extends B2<int> {}
 
 @pragma('dart2js:noInline')
@@ -50,10 +50,10 @@
 @pragma('dart2js:noInline')
 _test2(f) => f is A<C2 Function()>;
 
-/*class: B3:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: B3:checkedTypeArgument,typeArgument*/
 class B3<T> {}
 
-/*class: C3:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: C3:checkedTypeArgument,typeArgument*/
 class C3 extends B3<int> {}
 
 @pragma('dart2js:noInline')
@@ -66,10 +66,10 @@
 @pragma('dart2js:noInline')
 _test3(f) => f is A<void Function(B3<int>)>;
 
-/*class: B4:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: B4:checkedTypeArgument,typeArgument*/
 class B4<T> {}
 
-/*class: C4:checks=[],onlyForRti,typeArgument*/
+/*class: C4:typeArgument*/
 class C4 extends B4<int> {}
 
 @pragma('dart4js:noInline')
@@ -82,10 +82,10 @@
 @pragma('dart4js:noInline')
 _test4(f) => f is A<B4<int> Function()>;
 
-/*class: B5:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: B5:checkedTypeArgument,typeArgument*/
 class B5<T> {}
 
-/*class: C5:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: C5:checkedTypeArgument,typeArgument*/
 class C5 extends B5<int> {}
 
 @pragma('dart2js:noInline')
@@ -98,10 +98,10 @@
 @pragma('dart2js:noInline')
 _test5(f) => f is A<void Function(C5 Function())>;
 
-/*class: B6:checks=[],onlyForRti,typeArgument*/
+/*class: B6:typeArgument*/
 class B6<T> {}
 
-/*class: C6:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: C6:checkedTypeArgument,typeArgument*/
 class C6 extends B6<int> {}
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/emission/future_or_as_type_argument.dart b/pkg/compiler/test/rti/emission/future_or_as_type_argument.dart
index 9b2fcd45..a746358 100644
--- a/pkg/compiler/test/rti/emission/future_or_as_type_argument.dart
+++ b/pkg/compiler/test/rti/emission/future_or_as_type_argument.dart
@@ -6,15 +6,15 @@
 
 import 'dart:async';
 
-/*class: global#Future:checks=[],onlyForRti,typeArgument*/
+/*class: global#Future:typeArgument*/
 
 /*class: A:checkedInstance,checks=[],instance*/
 class A<T> {}
 
-/*class: B:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: B:checkedTypeArgument,typeArgument*/
 class B {}
 
-/*class: C:checks=[],onlyForRti,typeArgument*/
+/*class: C:typeArgument*/
 class C {}
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/emission/future_or_future_or_generic.dart b/pkg/compiler/test/rti/emission/future_or_future_or_generic.dart
index 989c8de..629d268 100644
--- a/pkg/compiler/test/rti/emission/future_or_future_or_generic.dart
+++ b/pkg/compiler/test/rti/emission/future_or_future_or_generic.dart
@@ -18,10 +18,10 @@
 /*class: B:checkedInstance,checkedTypeArgument,checks=[],instance,typeArgument*/
 class B<T> {}
 
-/*class: C:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: C:checkedInstance,checkedTypeArgument,typeArgument*/
 class C {}
 
-/*class: D:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: D:checkedInstance,checkedTypeArgument,typeArgument*/
 class D {}
 
 main() {
diff --git a/pkg/compiler/test/rti/emission/future_or_generic.dart b/pkg/compiler/test/rti/emission/future_or_generic.dart
index c4ece54..7576c46 100644
--- a/pkg/compiler/test/rti/emission/future_or_generic.dart
+++ b/pkg/compiler/test/rti/emission/future_or_generic.dart
@@ -20,7 +20,7 @@
 
 // TODO(johnniwinther): Do we need the implied `checkedTypeArgument` from
 // the `Future<C>` test in `A.m`?
-/*class: C:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: C:checkedInstance,typeArgument*/
 class C {}
 
 /*class: FutureMock:checks=[$isFuture],instance*/
diff --git a/pkg/compiler/test/rti/emission/future_or_generic2.dart b/pkg/compiler/test/rti/emission/future_or_generic2.dart
index 5fa8720..ae3dc31 100644
--- a/pkg/compiler/test/rti/emission/future_or_generic2.dart
+++ b/pkg/compiler/test/rti/emission/future_or_generic2.dart
@@ -18,10 +18,10 @@
 /*class: B:checkedInstance,checkedTypeArgument,checks=[],instance,typeArgument*/
 class B<T> {}
 
-/*class: C:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: C:checkedInstance,typeArgument*/
 class C {}
 
-/*class: D:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: D:checkedInstance,typeArgument*/
 class D {}
 
 main() {
diff --git a/pkg/compiler/test/rti/emission/future_or_type_argument.dart b/pkg/compiler/test/rti/emission/future_or_type_argument.dart
index c225b61..b095626 100644
--- a/pkg/compiler/test/rti/emission/future_or_type_argument.dart
+++ b/pkg/compiler/test/rti/emission/future_or_type_argument.dart
@@ -7,15 +7,15 @@
 import 'dart:async';
 import 'package:expect/expect.dart';
 
-/*class: global#Future:checks=[],onlyForRti,typeArgument*/
+/*class: global#Future:typeArgument*/
 
 /*class: A:checkedInstance,checks=[],instance*/
 class A<T> {}
 
-/*class: B:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: B:checkedTypeArgument,typeArgument*/
 class B {}
 
-/*class: C:checks=[],onlyForRti,typeArgument*/
+/*class: C:typeArgument*/
 class C {}
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/emission/generic_instanceof4.dart b/pkg/compiler/test/rti/emission/generic_instanceof4.dart
index 48b6274..5d0756b 100644
--- a/pkg/compiler/test/rti/emission/generic_instanceof4.dart
+++ b/pkg/compiler/test/rti/emission/generic_instanceof4.dart
@@ -12,7 +12,7 @@
   }
 }
 
-/*class: BB:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: BB:checkedInstance,typeArgument*/
 class BB {}
 
 /*class: B:checks=[$isBB],instance*/
diff --git a/pkg/compiler/test/rti/emission/generic_methods_dynamic_02.dart b/pkg/compiler/test/rti/emission/generic_methods_dynamic_02.dart
index c4db1f9..07a44ed 100644
--- a/pkg/compiler/test/rti/emission/generic_methods_dynamic_02.dart
+++ b/pkg/compiler/test/rti/emission/generic_methods_dynamic_02.dart
@@ -8,7 +8,7 @@
 
 library generic_methods_dynamic_test;
 
-/*spec.class: A:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*spec.class: A:checkedInstance,typeArgument*/
 class A {}
 
 /*spec.class: B:checks=[],instance*/
diff --git a/pkg/compiler/test/rti/emission/indirect_through_static.dart b/pkg/compiler/test/rti/emission/indirect_through_static.dart
index 848e578..0bd13be 100644
--- a/pkg/compiler/test/rti/emission/indirect_through_static.dart
+++ b/pkg/compiler/test/rti/emission/indirect_through_static.dart
@@ -4,10 +4,10 @@
 
 // @dart = 2.7
 
-/*class: A:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: A:checkedInstance,typeArgument*/
 abstract class A {}
 
-/*class: B:checks=[$isA],onlyForRti,typeArgument*/
+/*class: B:typeArgument*/
 class B implements A {}
 
 /*class: C:checkedInstance,checks=[],instance,typeArgument*/
diff --git a/pkg/compiler/test/rti/emission/jsinterop_generic_factory_args.dart b/pkg/compiler/test/rti/emission/jsinterop_generic_factory_args.dart
index c7dc08b..897ffea 100644
--- a/pkg/compiler/test/rti/emission/jsinterop_generic_factory_args.dart
+++ b/pkg/compiler/test/rti/emission/jsinterop_generic_factory_args.dart
@@ -7,15 +7,15 @@
 @JS()
 library foo;
 
-/*class: global#JavaScriptObject:checks=[$isA],onlyForRti*/
+/*class: global#JavaScriptObject:*/
 
 import 'package:expect/expect.dart';
 import 'package:js/js.dart';
 
 @JS()
 @anonymous
-/*spec.class: A:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: A:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: A:checkedTypeArgument,typeArgument*/
 class A<T> {
   external factory A();
 }
diff --git a/pkg/compiler/test/rti/emission/list.dart b/pkg/compiler/test/rti/emission/list.dart
index 5c1199c..276c2c5 100644
--- a/pkg/compiler/test/rti/emission/list.dart
+++ b/pkg/compiler/test/rti/emission/list.dart
@@ -9,12 +9,12 @@
 
 /*class: global#Iterable:checkedInstance*/
 
-/*spec.class: A:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: A:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: A:checkedTypeArgument,typeArgument*/
 class A {}
 
-/*spec.class: B:checkedInstance,checks=[],onlyForRti,typeArgument*/
-/*prod.class: B:checks=[],onlyForRti,typeArgument*/
+/*spec.class: B:checkedInstance,typeArgument*/
+/*prod.class: B:typeArgument*/
 class B {}
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/emission/map_literal.dart b/pkg/compiler/test/rti/emission/map_literal.dart
index b89ceec..c2b86d0 100644
--- a/pkg/compiler/test/rti/emission/map_literal.dart
+++ b/pkg/compiler/test/rti/emission/map_literal.dart
@@ -9,7 +9,7 @@
 /*class: global#LinkedHashMap:*/
 /*class: global#JsLinkedHashMap:checks=[],instance*/
 
-/*spec.class: global#double:checkedInstance,checks=[],instance,onlyForRti,typeArgument*/
+/*spec.class: global#double:checkedInstance,instance,typeArgument*/
 
 /*class: global#JSDouble:checks=[],instance*/
 
diff --git a/pkg/compiler/test/rti/emission/mixin_subtype.dart b/pkg/compiler/test/rti/emission/mixin_subtype.dart
index adf0e05..57b30b3 100644
--- a/pkg/compiler/test/rti/emission/mixin_subtype.dart
+++ b/pkg/compiler/test/rti/emission/mixin_subtype.dart
@@ -12,19 +12,19 @@
 
 // A mixin with multiple super-types and implemented types.
 
-/*class: A:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: A:checkedInstance,typeArgument*/
 class A {}
 
-/*class: B:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: B:checkedInstance,typeArgument*/
 class B {}
 
-/*class: I:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: I:checkedInstance,typeArgument*/
 class I {}
 
-/*class: J:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: J:checkedInstance,typeArgument*/
 class J {}
 
-/*class: M1:checkedInstance,checks=[$isA,$isB,$isI,$isJ],onlyForRti,typeArgument*/
+/*class: M1:checkedInstance,typeArgument*/
 mixin M1 on A, B implements I, J {}
 
 /*class: M2:checkedInstance,checks=[$isA,$isB,$isI,$isJ],typeArgument*/
@@ -42,13 +42,13 @@
 /*class: C:checkedInstance,checks=[$isA,$isB],indirectInstance,typeArgument*/
 class C implements A, B {}
 
-/*class: D1:checkedInstance,checks=[$isI,$isJ,$isM1],onlyForRti,typeArgument*/
+/*class: D1:checkedInstance,typeArgument*/
 class D1 = C with M1;
 
 /*class: D2:checkedInstance,checks=[$isI,$isJ],instance,typeArgument*/
 class D2 = C with M2;
 
-/*class: D3:checkedInstance,checks=[$isI,$isJ,$isM3],onlyForRti,typeArgument*/
+/*class: D3:checkedInstance,typeArgument*/
 class D3 = C with M3;
 
 /*class: D4:checkedInstance,checks=[$isI,$isJ],instance,typeArgument*/
@@ -61,25 +61,25 @@
 class E5 extends D5 {}
 
 // Same, with generics.
-/*class: GA:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: GA:checkedInstance,typeArgument*/
 class GA<T> {}
 
-/*class: GB:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: GB:checkedInstance,typeArgument*/
 class GB<T> {}
 
-/*class: GI:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: GI:checkedInstance,typeArgument*/
 class GI<T> {}
 
-/*class: GJ:checkedInstance,checks=[],onlyForRti,typeArgument*/
+/*class: GJ:checkedInstance,typeArgument*/
 class GJ<T> {}
 
-/*class: GM:checkedInstance,checks=[$isGA,$isGB,$isGI,$isGJ],onlyForRti,typeArgument*/
+/*class: GM:checkedInstance,typeArgument*/
 mixin GM<T> on GA<T>, GB<List<T>> implements GI<Iterable<T>>, GJ<Set<T>> {}
 
-/*class: GC:checkedInstance,checks=[$isGA,$isGB],onlyForRti,typeArgument*/
+/*class: GC:checkedInstance,typeArgument*/
 class GC<T> implements GA<T>, GB<List<T>> {}
 
-/*class: GD:checkedInstance,checks=[$isGI,$isGJ,$isGM],onlyForRti,typeArgument*/
+/*class: GD:checkedInstance,typeArgument*/
 class GD<T> = GC<T> with GM<T>;
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/emission/mixin_type_arguments.dart b/pkg/compiler/test/rti/emission/mixin_type_arguments.dart
index dd2a28b..eced8f0 100644
--- a/pkg/compiler/test/rti/emission/mixin_type_arguments.dart
+++ b/pkg/compiler/test/rti/emission/mixin_type_arguments.dart
@@ -6,22 +6,22 @@
 
 import 'package:expect/expect.dart' show Expect;
 
-/*class: A:checks=[],onlyForRti,typeArgument*/
+/*class: A:typeArgument*/
 class A {}
 
-/*class: B:checks=[],onlyForRti,typeArgument*/
+/*class: B:typeArgument*/
 class B {}
 
-/*class: C:checks=[],onlyForRti,typeArgument*/
+/*class: C:typeArgument*/
 class C {}
 
-/*class: D:checks=[],onlyForRti,typeArgument*/
+/*class: D:typeArgument*/
 class D {}
 
-/*class: E:checks=[],onlyForRti,typeArgument*/
+/*class: E:typeArgument*/
 class E {}
 
-/*class: F:checks=[],onlyForRti,typeArgument*/
+/*class: F:typeArgument*/
 class F {}
 
 /*class: M1:checks=[]*/
diff --git a/pkg/compiler/test/rti/emission/optimized_is_check.dart b/pkg/compiler/test/rti/emission/optimized_is_check.dart
index e652518..726440d 100644
--- a/pkg/compiler/test/rti/emission/optimized_is_check.dart
+++ b/pkg/compiler/test/rti/emission/optimized_is_check.dart
@@ -24,10 +24,10 @@
 /*class: DeferredAndRemoved:checks=[],onlyForConstructor*/
 class DeferredAndRemoved {} // allocated after first check and removed
 
-/*class: UsedAsTypeParameter:checks=[],onlyForRti,typeArgument*/
+/*class: UsedAsTypeParameter:typeArgument*/
 class UsedAsTypeParameter {} // only used as a type parameter
 
-/*class: UsedAsTestedTypeParameter:checks=[],onlyForRti,typeArgument*/
+/*class: UsedAsTestedTypeParameter:typeArgument*/
 class UsedAsTestedTypeParameter {} // only used as a type parameter
 
 /*class: Check:checks=[],instance*/
diff --git a/pkg/compiler/test/rti/emission/replaced_type_variable.dart b/pkg/compiler/test/rti/emission/replaced_type_variable.dart
index 78ae756..92ccac4 100644
--- a/pkg/compiler/test/rti/emission/replaced_type_variable.dart
+++ b/pkg/compiler/test/rti/emission/replaced_type_variable.dart
@@ -14,7 +14,7 @@
   Type get type => T;
 }
 
-/*class: A:checks=[],onlyForRti,typeArgument*/
+/*class: A:typeArgument*/
 class A {}
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/emission/runtime_type.dart b/pkg/compiler/test/rti/emission/runtime_type.dart
index ea9d7cc..d047f5f 100644
--- a/pkg/compiler/test/rti/emission/runtime_type.dart
+++ b/pkg/compiler/test/rti/emission/runtime_type.dart
@@ -7,7 +7,7 @@
 /*class: A:checks=[],instance*/
 class A<T> {}
 
-/*class: B:checks=[],onlyForRti,typeArgument*/
+/*class: B:typeArgument*/
 class B<T> {}
 
 main() {
diff --git a/pkg/compiler/test/rti/emission/subtype_named_args.dart b/pkg/compiler/test/rti/emission/subtype_named_args.dart
index d94bedf..ecc3fed 100644
--- a/pkg/compiler/test/rti/emission/subtype_named_args.dart
+++ b/pkg/compiler/test/rti/emission/subtype_named_args.dart
@@ -8,32 +8,32 @@
 
 import 'package:expect/expect.dart';
 
-/*spec.class: A:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: A:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: A:checkedTypeArgument,typeArgument*/
 class A {}
 
-/*spec.class: A1:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: A1:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: A1:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: A1:checkedTypeArgument,typeArgument*/
 class A1 {}
 
-/*spec.class: A2:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: A2:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: A2:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: A2:checkedTypeArgument,typeArgument*/
 class A2 {}
 
-/*spec.class: B:checkedInstance,checkedTypeArgument,checks=[$isA,$isA1,$isA2],onlyForRti,typeArgument*/
-/*prod.class: B:checkedTypeArgument,checks=[$isA,$isA1,$isA2],onlyForRti,typeArgument*/
+/*spec.class: B:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: B:checkedTypeArgument,typeArgument*/
 class B implements A, A1, A2 {}
 
-/*spec.class: C:checkedInstance,checkedTypeArgument,checks=[$isA,$isA1,$isA2,$isB],onlyForRti,typeArgument*/
-/*prod.class: C:checkedTypeArgument,checks=[$isA,$isA1,$isA2,$isB],onlyForRti,typeArgument*/
+/*spec.class: C:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: C:checkedTypeArgument,typeArgument*/
 class C implements B {}
 
-/*spec.class: D:checkedInstance,checkedTypeArgument,checks=[$isA,$isA1,$isA2,$isB,$isC],onlyForRti,typeArgument*/
-/*prod.class: D:checkedTypeArgument,checks=[$isA,$isA1,$isA2,$isB,$isC],onlyForRti,typeArgument*/
+/*spec.class: D:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: D:checkedTypeArgument,typeArgument*/
 class D implements C {}
 
-/*spec.class: G:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: G:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: G:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: G:checkedTypeArgument,typeArgument*/
 class G<T, S, U, W> {}
 
 typedef classesFunc({A a, B b, C c, D d});
diff --git a/pkg/compiler/test/rti/emission/superclass_complex.dart b/pkg/compiler/test/rti/emission/superclass_complex.dart
index adc95a3..d4b5c59 100644
--- a/pkg/compiler/test/rti/emission/superclass_complex.dart
+++ b/pkg/compiler/test/rti/emission/superclass_complex.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: A:checkedTypeArgument,typeArgument*/
 class A<T> {}
 
 /*class: B:checkedInstance,checks=[],indirectInstance*/
diff --git a/pkg/compiler/test/rti/emission/superclass_supertype_complex.dart b/pkg/compiler/test/rti/emission/superclass_supertype_complex.dart
index 0601bc9..bf500c1 100644
--- a/pkg/compiler/test/rti/emission/superclass_supertype_complex.dart
+++ b/pkg/compiler/test/rti/emission/superclass_supertype_complex.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: A:checkedTypeArgument,typeArgument*/
 class A<T> {}
 
 /*class: B:checkedInstance*/
diff --git a/pkg/compiler/test/rti/emission/supertype_complex.dart b/pkg/compiler/test/rti/emission/supertype_complex.dart
index c8e26ec..ec356b5 100644
--- a/pkg/compiler/test/rti/emission/supertype_complex.dart
+++ b/pkg/compiler/test/rti/emission/supertype_complex.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: A:checkedTypeArgument,typeArgument*/
 class A<T> {}
 
 /*class: B:checkedInstance*/
diff --git a/pkg/compiler/test/rti/emission/tear_off_types.dart b/pkg/compiler/test/rti/emission/tear_off_types.dart
index 14ac56a..ef8fb52 100644
--- a/pkg/compiler/test/rti/emission/tear_off_types.dart
+++ b/pkg/compiler/test/rti/emission/tear_off_types.dart
@@ -16,10 +16,10 @@
   test7();
 }
 
-/*class: A1:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: A1:checkedTypeArgument,typeArgument*/
 class A1<T> {}
 
-/*class: B1:checks=[],onlyForRti,typeArgument*/
+/*class: B1:typeArgument*/
 class B1 extends A1<int> {}
 
 @pragma('dart2js:noInline')
@@ -36,12 +36,12 @@
 @pragma('dart2js:noInline')
 bool _test1(f) => f is A1<int> Function();
 
-/*spec.class: A2:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: A2:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: A2:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: A2:checkedTypeArgument,typeArgument*/
 class A2<T> {}
 
-/*spec.class: B2:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: B2:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: B2:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: B2:checkedTypeArgument,typeArgument*/
 class B2 extends A2<int> {}
 
 @pragma('dart2js:noInline')
@@ -58,12 +58,12 @@
 @pragma('dart2js:noInline')
 bool _test2(f) => f is void Function(A2<int>);
 
-/*spec.class: A3:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: A3:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: A3:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: A3:checkedTypeArgument,typeArgument*/
 class A3<T> {}
 
-/*spec.class: B3:checkedInstance,checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
-/*prod.class: B3:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*spec.class: B3:checkedInstance,checkedTypeArgument,typeArgument*/
+/*prod.class: B3:checkedTypeArgument,typeArgument*/
 class B3 extends A3<int> {}
 
 @pragma('dart3js:noInline')
@@ -80,10 +80,10 @@
 @pragma('dart3js:noInline')
 _test3(f) => f is void Function(B3);
 
-/*class: A4:checks=[],onlyForRti,typeArgument*/
+/*class: A4:typeArgument*/
 class A4<T> {}
 
-/*class: B4:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: B4:checkedTypeArgument,typeArgument*/
 class B4 extends A4<int> {}
 
 @pragma('dart4js:noInline')
@@ -100,10 +100,10 @@
 @pragma('dart4js:noInline')
 _test4(f) => f is B4 Function();
 
-/*class: A5:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: A5:checkedTypeArgument,typeArgument*/
 class A5<T> {}
 
-/*class: B5:checks=[],onlyForRti,typeArgument*/
+/*class: B5:typeArgument*/
 class B5 extends A5<int> {}
 
 @pragma('dart2js:noInline')
@@ -120,10 +120,10 @@
 @pragma('dart2js:noInline')
 bool _test5(f) => f is void Function(void Function(A5<int>));
 
-/*class: A6:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: A6:checkedTypeArgument,typeArgument*/
 class A6<T> {}
 
-/*class: B6:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: B6:checkedTypeArgument,typeArgument*/
 class B6 extends A6<int> {}
 
 @pragma('dart6js:noInline')
@@ -140,10 +140,10 @@
 @pragma('dart6js:noInline')
 _test6(f) => f is void Function(B6) Function();
 
-/*class: A7:checks=[],onlyForRti,typeArgument*/
+/*class: A7:typeArgument*/
 class A7<T> {}
 
-/*class: B7:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: B7:checkedTypeArgument,typeArgument*/
 class B7 extends A7<int> {}
 
 @pragma('dart7js:noInline')
diff --git a/pkg/compiler/test/rti/emission/type_argument_dynamic.dart b/pkg/compiler/test/rti/emission/type_argument_dynamic.dart
index 0fb3030..745eb80 100644
--- a/pkg/compiler/test/rti/emission/type_argument_dynamic.dart
+++ b/pkg/compiler/test/rti/emission/type_argument_dynamic.dart
@@ -6,16 +6,16 @@
 
 import 'package:expect/expect.dart';
 
-/*class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: A:checkedTypeArgument,typeArgument*/
 class A {}
 
-/*class: B:checks=[$isA],onlyForRti,typeArgument*/
+/*class: B:typeArgument*/
 class B implements A {}
 
 /*class: C:checkedInstance,checks=[],instance*/
 class C<T> {}
 
-/*class: D:checks=[],onlyForRti,typeArgument*/
+/*class: D:typeArgument*/
 class D {}
 
 /*class: E:checks=[],instance*/
diff --git a/pkg/compiler/test/rti/emission/type_argument_static.dart b/pkg/compiler/test/rti/emission/type_argument_static.dart
index cf1ea59..79dd1d5 100644
--- a/pkg/compiler/test/rti/emission/type_argument_static.dart
+++ b/pkg/compiler/test/rti/emission/type_argument_static.dart
@@ -6,16 +6,16 @@
 
 import 'package:expect/expect.dart';
 
-/*class: A:checkedTypeArgument,checks=[],onlyForRti,typeArgument*/
+/*class: A:checkedTypeArgument,typeArgument*/
 class A {}
 
-/*class: B:checks=[$isA],onlyForRti,typeArgument*/
+/*class: B:typeArgument*/
 class B implements A {}
 
 /*class: C:checkedInstance,checks=[],instance*/
 class C<T> {}
 
-/*class: D:checks=[],onlyForRti,typeArgument*/
+/*class: D:typeArgument*/
 class D {}
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/emission/type_literal.dart b/pkg/compiler/test/rti/emission/type_literal.dart
index b49f32f..c075324 100644
--- a/pkg/compiler/test/rti/emission/type_literal.dart
+++ b/pkg/compiler/test/rti/emission/type_literal.dart
@@ -6,10 +6,10 @@
 
 import 'package:expect/expect.dart';
 
-/*class: Class1:checks=[],onlyForRti,typeLiteral*/
+/*class: Class1:typeLiteral*/
 class Class1 {}
 
-/*class: Class2:checks=[],onlyForRti,typeLiteral*/
+/*class: Class2:typeLiteral*/
 class Class2<X> {}
 
 void main() {
diff --git a/pkg/dartdev/lib/src/analytics.dart b/pkg/dartdev/lib/src/analytics.dart
index 18369cf..fd12e56 100644
--- a/pkg/dartdev/lib/src/analytics.dart
+++ b/pkg/dartdev/lib/src/analytics.dart
@@ -31,6 +31,11 @@
 const String _dartDirectoryName = '.dart';
 const String _settingsFileName = 'dartdev.json';
 const String _trackingId = 'UA-26406144-37';
+const String _readmeFileName = 'README.txt';
+const String _readmeFileContents = '''
+The present directory contains user-level settings for the
+Dart programming language (https://dart.dev).
+''';
 
 const String eventCategory = 'dartdev';
 const String exitCodeParam = 'exitCode';
@@ -73,6 +78,13 @@
     }
   }
 
+  var readmeFile =
+      File('${settingsDir.absolute.path}${path.separator}$_readmeFileName');
+  if (!readmeFile.existsSync()) {
+    readmeFile.createSync();
+    readmeFile.writeAsStringSync(_readmeFileContents);
+  }
+
   var settingsFile = File(path.join(settingsDir.path, _settingsFileName));
   instance = DartdevAnalytics(_trackingId, settingsFile, _appName);
   return instance;
diff --git a/runtime/observatory/tests/service/verify_http_timeline_test.dart b/runtime/observatory/tests/service/verify_http_timeline_test.dart
index 22fae9b..f7959e4 100644
--- a/runtime/observatory/tests/service/verify_http_timeline_test.dart
+++ b/runtime/observatory/tests/service/verify_http_timeline_test.dart
@@ -4,8 +4,10 @@
 // VMOptions=--timeline_streams=Dart
 
 import 'dart:async';
+import 'dart:convert';
 import 'dart:io';
 import 'dart:math';
+import 'dart:typed_data';
 import 'package:expect/expect.dart';
 import 'package:observatory/service_io.dart';
 import 'package:test/test.dart';
@@ -65,6 +67,7 @@
   final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
   server.listen((request) async {
     final response = request.response;
+    response.write(request.method);
     randomlyAddCookie(response);
     if (await randomlyRedirect(server, response)) {
       // Redirect calls close() on the response.
@@ -94,7 +97,11 @@
   for (int i = 0; i < 10; ++i) {
     final future = executeWithRandomDelay(() async {
       final r = await client.deleteUrl(randomlyAddRequestParams(address));
-      await r.close();
+      final string = 'DELETE $address';
+      r.headers.add(HttpHeaders.contentLengthHeader, string.length);
+      r.write(string);
+      final response = await r.close();
+      response.listen((_) {});
     });
     requests.add(future);
   }
@@ -103,11 +110,11 @@
   for (int i = 0; i < 10; ++i) {
     final future = executeWithRandomDelay(() async {
       final r = await client.getUrl(randomlyAddRequestParams(address));
-      await r.close();
+      final response = await r.close();
+      await response.drain();
     });
     requests.add(future);
   }
-
   // HTTP HEAD
   for (int i = 0; i < 10; ++i) {
     final future = executeWithRandomDelay(() async {
@@ -131,7 +138,8 @@
   for (int i = 0; i < 10; ++i) {
     final future = executeWithRandomDelay(() async {
       final r = await client.patchUrl(randomlyAddRequestParams(address));
-      await r.close();
+      final response = await r.close();
+      response.listen(null);
     });
     requests.add(future);
   }
@@ -140,6 +148,7 @@
   for (int i = 0; i < 10; ++i) {
     final future = executeWithRandomDelay(() async {
       final r = await client.postUrl(randomlyAddRequestParams(address));
+      r.add(Uint8List.fromList([0, 1, 2]));
       await r.close();
     });
     requests.add(future);
@@ -170,12 +179,11 @@
 bool hasCompletedEvents(List traceEvents) {
   final events = <String, int>{};
   for (final event in traceEvents) {
+    final id = event['id'];
+    events.putIfAbsent(id, () => 0);
     if (isStartEvent(event)) {
-      final id = event['id'];
-      events.putIfAbsent(id, () => 0);
       events[id]++;
     } else if (isFinishEvent(event)) {
-      final id = event['id'];
       events[id]--;
     }
   }
@@ -191,6 +199,11 @@
 List filterEventsByName(List traceEvents, String name) =>
     traceEvents.where((e) => e['name'].contains(name)).toList();
 
+List filterEventsByIdAndName(List traceEvents, String id, String name) =>
+    traceEvents
+        .where((e) => e['id'] == id && e['name'].contains(name))
+        .toList();
+
 void hasValidHttpConnections(List traceEvents) {
   final events = filterEventsByName(traceEvents, 'HTTP Connection');
   expect(hasCompletedEvents(events), isTrue);
@@ -202,6 +215,13 @@
   expect(args.containsKey('method'), isTrue);
   expect(args['method'], method);
   expect(args['filterKey'], 'HTTP/client');
+  expect(args.containsKey('uri'), isTrue);
+}
+
+void validateHttpFinishEvent(Map event) {
+  expect(event.containsKey('args'), isTrue);
+  final args = event['args'];
+  expect(args['filterKey'], 'HTTP/client');
   if (!args.containsKey('error')) {
     expect(args.containsKey('requestHeaders'), isTrue);
     expect(args['requestHeaders'] != null, isTrue);
@@ -224,34 +244,54 @@
   }
 }
 
-void validateHttpFinishEvent(Map event) {
-  expect(event.containsKey('args'), isTrue);
-  final args = event['args'];
-  expect(args['filterKey'], 'HTTP/client');
-  expect(args.containsKey('compressionState'), isTrue);
-  expect(args.containsKey('connectionInfo'), isTrue);
-  expect(args.containsKey('contentLength'), isTrue);
-  expect(args.containsKey('cookies'), isTrue);
-  expect(args.containsKey('responseHeaders'), isTrue);
-  expect(args.containsKey('isRedirect'), isTrue);
-  expect(args.containsKey('persistentConnection'), isTrue);
-  expect(args.containsKey('reasonPhrase'), isTrue);
-  expect(args.containsKey('redirects'), isTrue);
-  expect(args.containsKey('statusCode'), isTrue);
-}
-
 void hasValidHttpRequests(List traceEvents, String method) {
-  final events = filterEventsByName(traceEvents, 'HTTP Client $method');
-  expect(hasCompletedEvents(events), isTrue);
+  var events = filterEventsByName(traceEvents, 'HTTP CLIENT $method');
   for (final event in events) {
     if (isStartEvent(event)) {
       validateHttpStartEvent(event, method);
+      // Check body of request has been sent and recorded correctly.
+      if (method == 'DELETE' || method == 'POST') {
+        final id = event['id'];
+        final bodyEvent =
+            filterEventsByIdAndName(traceEvents, id, 'Request body');
+        // Due to randomness, it doesn't guarantee to have the timeline events.
+        if (bodyEvent.length == 1) {
+          if (method == 'POST') {
+            // add() was used
+            Expect.listEquals(
+                <int>[0, 1, 2], bodyEvent[0]['args']['encodedData']);
+          } else {
+            // write() was used.
+            Expect.isTrue(
+                bodyEvent[0]['args']['data'].startsWith('$method http'));
+          }
+        }
+      }
     } else if (isFinishEvent(event)) {
       validateHttpFinishEvent(event);
     } else {
       fail('unexpected event type: ${event["ph"]}');
     }
   }
+
+  // Check response body matches string stored in the map.
+  events = filterEventsByName(traceEvents, 'HTTP CLIENT response of $method');
+  if (method == 'DELETE') {
+    // It called listen().
+    expect(hasCompletedEvents(events), isTrue);
+  }
+  for (final event in events) {
+    // Each response will be associated with a request.
+    if (isFinishEvent(event)) {
+      continue;
+    }
+    final id = event['id'];
+    final data = filterEventsByIdAndName(traceEvents, id, 'Response body');
+    if (data.length != 0) {
+      Expect.equals(1, data.length);
+      Expect.listEquals(utf8.encode(method), data[0]['args']['data']);
+    }
+  }
 }
 
 void hasValidHttpCONNECTs(List traceEvents) =>
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 7e81415..170f52c 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -65,8 +65,6 @@
       barrier_(),
       barrier_done_(),
       read_only_(false),
-      gc_new_space_in_progress_(false),
-      gc_old_space_in_progress_(false),
       last_gc_was_old_space_(false),
       assume_scavenge_will_fail_(false),
       gc_on_nth_allocation_(kNoForcedGarbageCollection) {
@@ -237,6 +235,8 @@
       heap_(isolate()->heap()),
       old_space_(heap_->old_space()),
       writable_(writable) {
+  isolate()->safepoint_handler()->SafepointThreads(thread);
+
   {
     // It's not safe to iterate over old space when concurrent marking or
     // sweeping is in progress, or another thread is iterating the heap, so wait
@@ -255,7 +255,7 @@
         ml.Enter();
       }
       while (old_space_->tasks() > 0) {
-        ml.WaitWithSafepointCheck(thread);
+        ml.Wait();
       }
     }
 #if defined(DEBUG)
@@ -265,8 +265,6 @@
     old_space_->set_tasks(1);
   }
 
-  isolate()->safepoint_handler()->SafepointThreads(thread);
-
   if (writable_) {
     heap_->WriteProtectCode(false);
   }
@@ -277,16 +275,18 @@
     heap_->WriteProtectCode(true);
   }
 
-  isolate()->safepoint_handler()->ResumeThreads(thread());
-
-  MonitorLocker ml(old_space_->tasks_lock());
+  {
+    MonitorLocker ml(old_space_->tasks_lock());
 #if defined(DEBUG)
-  ASSERT(old_space_->iterating_thread_ == thread());
-  old_space_->iterating_thread_ = NULL;
+    ASSERT(old_space_->iterating_thread_ == thread());
+    old_space_->iterating_thread_ = NULL;
 #endif
-  ASSERT(old_space_->tasks() == 1);
-  old_space_->set_tasks(0);
-  ml.NotifyAll();
+    ASSERT(old_space_->tasks() == 1);
+    old_space_->set_tasks(0);
+    ml.NotifyAll();
+  }
+
+  isolate()->safepoint_handler()->ResumeThreads(thread());
 }
 
 void HeapIterationScope::IterateObjects(ObjectVisitor* visitor) const {
@@ -360,57 +360,14 @@
   return raw_obj;
 }
 
-bool Heap::BeginNewSpaceGC(Thread* thread) {
-  MonitorLocker ml(&gc_in_progress_monitor_);
-  bool start_gc_on_thread = true;
-  while (gc_new_space_in_progress_ || gc_old_space_in_progress_) {
-    start_gc_on_thread = !gc_new_space_in_progress_;
-    ml.WaitWithSafepointCheck(thread);
-  }
-  if (start_gc_on_thread) {
-    gc_new_space_in_progress_ = true;
-    return true;
-  }
-  return false;
-}
-
-void Heap::EndNewSpaceGC() {
-  MonitorLocker ml(&gc_in_progress_monitor_);
-  ASSERT(gc_new_space_in_progress_);
-  gc_new_space_in_progress_ = false;
-  last_gc_was_old_space_ = false;
-  ml.NotifyAll();
-}
-
-bool Heap::BeginOldSpaceGC(Thread* thread) {
-  MonitorLocker ml(&gc_in_progress_monitor_);
-  bool start_gc_on_thread = true;
-  while (gc_new_space_in_progress_ || gc_old_space_in_progress_) {
-    start_gc_on_thread = !gc_old_space_in_progress_;
-    ml.WaitWithSafepointCheck(thread);
-  }
-  if (start_gc_on_thread) {
-    gc_old_space_in_progress_ = true;
-    return true;
-  }
-  return false;
-}
-
-void Heap::EndOldSpaceGC() {
-  MonitorLocker ml(&gc_in_progress_monitor_);
-  ASSERT(gc_old_space_in_progress_);
-  gc_old_space_in_progress_ = false;
-  last_gc_was_old_space_ = true;
-  assume_scavenge_will_fail_ = false;
-  ml.NotifyAll();
-}
-
 void Heap::HintFreed(intptr_t size) {
   old_space_.HintFreed(size);
 }
 
 void Heap::NotifyIdle(int64_t deadline) {
   Thread* thread = Thread::Current();
+  SafepointOperationScope safepoint_operation(thread);
+
   // Check if we want to collect new-space first, because if we want to collect
   // both new-space and old-space, the new-space collection should run first
   // to shrink the root set (make old-space GC faster) and avoid
@@ -475,7 +432,8 @@
     // visiting pointers.
     return;
   }
-  if (BeginNewSpaceGC(thread)) {
+  {
+    SafepointOperationScope safepoint_operation(thread);
     RecordBeforeGC(kScavenge, reason);
     VMTagScope tagScope(thread, reason == kIdle ? VMTag::kGCIdleTagId
                                                 : VMTag::kGCNewSpaceTagId);
@@ -484,7 +442,7 @@
     RecordAfterGC(kScavenge);
     PrintStats();
     NOT_IN_PRODUCT(PrintStatsToTimeline(&tbes, reason));
-    EndNewSpaceGC();
+    last_gc_was_old_space_ = false;
   }
 }
 
@@ -498,7 +456,8 @@
     // visiting pointers.
     return;
   }
-  if (BeginNewSpaceGC(thread)) {
+  {
+    SafepointOperationScope safepoint_operation(thread);
     RecordBeforeGC(kScavenge, reason);
     {
       VMTagScope tagScope(thread, reason == kIdle ? VMTag::kGCIdleTagId
@@ -508,7 +467,7 @@
       RecordAfterGC(kScavenge);
       PrintStats();
       NOT_IN_PRODUCT(PrintStatsToTimeline(&tbes, reason));
-      EndNewSpaceGC();
+      last_gc_was_old_space_ = false;
     }
     if (reason == kNewSpace) {
       if (old_space_.ReachedHardThreshold()) {
@@ -537,11 +496,14 @@
     // visiting pointers.
     return;
   }
-  if (BeginOldSpaceGC(thread)) {
-    thread->isolate_group()->ForEachIsolate([&](Isolate* isolate) {
-      // Discard regexp backtracking stacks to further reduce memory usage.
-      isolate->CacheRegexpBacktrackStack(nullptr);
-    });
+  {
+    SafepointOperationScope safepoint_operation(thread);
+    thread->isolate_group()->ForEachIsolate(
+        [&](Isolate* isolate) {
+          // Discard regexp backtracking stacks to further reduce memory usage.
+          isolate->CacheRegexpBacktrackStack(nullptr);
+        },
+        /*at_safepoint=*/true);
 
     RecordBeforeGC(type, reason);
     VMTagScope tagScope(thread, reason == kIdle ? VMTag::kGCIdleTagId
@@ -553,11 +515,14 @@
     NOT_IN_PRODUCT(PrintStatsToTimeline(&tbes, reason));
 
     // Some Code objects may have been collected so invalidate handler cache.
-    thread->isolate_group()->ForEachIsolate([&](Isolate* isolate) {
-      isolate->handler_info_cache()->Clear();
-      isolate->catch_entry_moves_cache()->Clear();
-    });
-    EndOldSpaceGC();
+    thread->isolate_group()->ForEachIsolate(
+        [&](Isolate* isolate) {
+          isolate->handler_info_cache()->Clear();
+          isolate->catch_entry_moves_cache()->Clear();
+        },
+        /*at_safepoint=*/true);
+    last_gc_was_old_space_ = true;
+    assume_scavenge_will_fail_ = false;
   }
 }
 
@@ -637,11 +602,8 @@
 }
 
 void Heap::StartConcurrentMarking(Thread* thread) {
-  if (BeginOldSpaceGC(thread)) {
-    TIMELINE_FUNCTION_GC_DURATION_BASIC(thread, "StartConcurrentMarking");
-    old_space_.CollectGarbage(/*compact=*/false, /*finalize=*/false);
-    EndOldSpaceGC();
-  }
+  TIMELINE_FUNCTION_GC_DURATION_BASIC(thread, "StartConcurrentMarking");
+  old_space_.CollectGarbage(/*compact=*/false, /*finalize=*/false);
 }
 
 void Heap::CheckFinishConcurrentMarking(Thread* thread) {
@@ -751,8 +713,6 @@
 }
 
 void Heap::MergeFrom(Heap* donor) {
-  ASSERT(!donor->gc_new_space_in_progress_);
-  ASSERT(!donor->gc_old_space_in_progress_);
   ASSERT(!donor->read_only_);
   ASSERT(donor->old_space()->tasks() == 0);
 
@@ -1021,9 +981,6 @@
 #endif  // PRODUCT
 
 void Heap::RecordBeforeGC(GCType type, GCReason reason) {
-  ASSERT((type == kScavenge && gc_new_space_in_progress_) ||
-         (type == kMarkSweep && gc_old_space_in_progress_) ||
-         (type == kMarkCompact && gc_old_space_in_progress_));
   stats_.num_++;
   stats_.type_ = type;
   stats_.reason_ = reason;
@@ -1048,9 +1005,6 @@
   }
   stats_.after_.new_ = new_space_.GetCurrentUsage();
   stats_.after_.old_ = old_space_.GetCurrentUsage();
-  ASSERT((type == kScavenge && gc_new_space_in_progress_) ||
-         (type == kMarkSweep && gc_old_space_in_progress_) ||
-         (type == kMarkCompact && gc_old_space_in_progress_));
 #ifndef PRODUCT
   // For now we'll emit the same GC events on all isolates.
   if (Service::gc_stream.enabled()) {
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index fa9d733..8982ba3 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -383,12 +383,6 @@
   void PrintStats();
   void PrintStatsToTimeline(TimelineEventScope* event, GCReason reason);
 
-  // Updates gc in progress flags.
-  bool BeginNewSpaceGC(Thread* thread);
-  void EndNewSpaceGC();
-  bool BeginOldSpaceGC(Thread* thread);
-  void EndOldSpaceGC();
-
   void AddRegionsToObjectSet(ObjectSet* set) const;
 
   // Trigger major GC if 'gc_on_nth_allocation_' is set.
@@ -412,10 +406,6 @@
   // This heap is in read-only mode: No allocation is allowed.
   bool read_only_;
 
-  // GC on the heap is in progress.
-  Monitor gc_in_progress_monitor_;
-  bool gc_new_space_in_progress_;
-  bool gc_old_space_in_progress_;
   bool last_gc_was_old_space_;
   bool assume_scavenge_will_fail_;
 
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index c0a2597..e0f10cb 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -1030,9 +1030,10 @@
   }
 
   Thread* thread = Thread::Current();
+  const int64_t pre_safe_point = OS::GetCurrentMonotonicMicros();
+  SafepointOperationScope safepoint_scope(thread);
 
   const int64_t pre_wait_for_sweepers = OS::GetCurrentMonotonicMicros();
-
   // Wait for pending tasks to complete and then account for the driver task.
   Phase waited_for;
   {
@@ -1045,15 +1046,15 @@
     }
 
     while (tasks() > 0) {
-      locker.WaitWithSafepointCheck(thread);
+      locker.Wait();
     }
     ASSERT(phase() == kAwaitingFinalization || phase() == kDone);
     set_tasks(1);
   }
 
-  const int64_t pre_safe_point = OS::GetCurrentMonotonicMicros();
   if (FLAG_verbose_gc) {
-    const int64_t wait = pre_safe_point - pre_wait_for_sweepers;
+    const int64_t wait =
+        OS::GetCurrentMonotonicMicros() - pre_wait_for_sweepers;
     if (waited_for == kMarking) {
       THR_Print("Waited %" Pd64 " us for concurrent marking to finish.\n",
                 wait);
@@ -1068,9 +1069,8 @@
   // to ensure that if two threads are racing to collect at the same time the
   // loser skips collection and goes straight to allocation.
   {
-    SafepointOperationScope safepoint_scope(thread);
-    CollectGarbageAtSafepoint(compact, finalize, pre_wait_for_sweepers,
-                              pre_safe_point);
+    CollectGarbageHelper(compact, finalize, pre_wait_for_sweepers,
+                         pre_safe_point);
   }
 
   // Done, reset the task count.
@@ -1081,10 +1081,10 @@
   }
 }
 
-void PageSpace::CollectGarbageAtSafepoint(bool compact,
-                                          bool finalize,
-                                          int64_t pre_wait_for_sweepers,
-                                          int64_t pre_safe_point) {
+void PageSpace::CollectGarbageHelper(bool compact,
+                                     bool finalize,
+                                     int64_t pre_wait_for_sweepers,
+                                     int64_t pre_safe_point) {
   Thread* thread = Thread::Current();
   ASSERT(thread->IsAtSafepoint());
   auto isolate_group = heap_->isolate_group();
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index ef5badf..83c5488 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -538,10 +538,10 @@
   void FreeLargePage(OldPage* page, OldPage* previous_page);
   void FreePages(OldPage* pages);
 
-  void CollectGarbageAtSafepoint(bool compact,
-                                 bool finalize,
-                                 int64_t pre_wait_for_sweepers,
-                                 int64_t pre_safe_point);
+  void CollectGarbageHelper(bool compact,
+                            bool finalize,
+                            int64_t pre_wait_for_sweepers,
+                            int64_t pre_safe_point);
   void SweepLarge();
   void Sweep();
   void ConcurrentSweep(IsolateGroup* isolate_group);
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index 97087ed..f01e495 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -301,8 +301,10 @@
   // The compression state of this response.
   final HttpClientResponseCompressionState compressionState;
 
-  _HttpClientResponse(
-      _HttpIncoming _incoming, this._httpRequest, this._httpClient)
+  final TimelineTask? _timeline;
+
+  _HttpClientResponse(_HttpIncoming _incoming, this._httpRequest,
+      this._httpClient, this._timeline)
       : compressionState = _getCompressionState(_httpClient, _incoming.headers),
         super(_incoming) {
     // Set uri for potential exceptions.
@@ -390,9 +392,16 @@
     });
   }
 
+  void _timelineFinishWithError(String error) {
+    _timeline?.finish(arguments: {
+      'error': error,
+    });
+  }
+
   StreamSubscription<Uint8List> listen(void onData(Uint8List event)?,
       {Function? onError, void onDone()?, bool? cancelOnError}) {
     if (_incoming.upgraded) {
+      _timelineFinishWithError('Connection was upgraded');
       // If upgraded, the connection is already 'removed' form the client.
       // Since listening to upgraded data is 'bogus', simply close and
       // return empty stream subscription.
@@ -406,11 +415,38 @@
           .transform(gzip.decoder)
           .transform(const _ToUint8List());
     }
-    return stream.listen(onData,
-        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
+    if (_timeline != null) {
+      // If _timeline is not set up, don't add unnecessary map() to the stream.
+      stream = stream.map((data) {
+        _timeline?.instant('Response body', arguments: {
+          'data': data,
+        });
+        return data;
+      });
+    }
+    return stream.listen(onData, onError: (e, st) {
+      _timeline?.instant('Error response', arguments: {
+        'error': e.toString(),
+      });
+      if (onError == null) {
+        return;
+      }
+      if (onError is void Function(Object)) {
+        onError(e);
+      } else {
+        assert(onError is void Function(Object, StackTrace));
+        onError(e, st);
+      }
+    }, onDone: () {
+      _timeline?.finish();
+      if (onDone != null) {
+        onDone();
+      }
+    }, cancelOnError: cancelOnError);
   }
 
   Future<Socket> detachSocket() {
+    _timelineFinishWithError('Socket has been detached');
     _httpClient._connectionClosed(_httpRequest._httpClientConnection);
     return _httpRequest._httpClientConnection.detachSocket();
   }
@@ -714,7 +750,9 @@
   Encoding _encoding;
   bool _encodingMutable = true;
 
-  _IOSinkImpl(StreamConsumer<List<int>> target, this._encoding) : super(target);
+  final TimelineTask? _timeline;
+  _IOSinkImpl(StreamConsumer<List<int>> target, this._encoding, this._timeline)
+      : super(target);
 
   Encoding get encoding => _encoding;
 
@@ -728,7 +766,10 @@
   void write(Object? obj) {
     String string = '$obj';
     if (string.isEmpty) return;
-    add(_encoding.encode(string));
+    _timeline?.instant('Request body', arguments: {
+      'data': string,
+    });
+    super.add(_encoding.encode(string));
   }
 
   void writeAll(Iterable objects, [String separator = ""]) {
@@ -770,6 +811,7 @@
   final _HttpHeaders headers;
 
   _HttpOutboundMessage(Uri uri, String protocolVersion, _HttpOutgoing outgoing,
+      TimelineTask? timeline,
       {_HttpHeaders? initialHeaders})
       : _uri = uri,
         headers = new _HttpHeaders(protocolVersion,
@@ -778,7 +820,7 @@
                 : HttpClient.defaultHttpPort,
             initialHeaders: initialHeaders),
         _outgoing = outgoing,
-        super(outgoing, latin1) {
+        super(outgoing, latin1, timeline) {
     _outgoing.outbound = this;
     _encodingMutable = false;
   }
@@ -815,9 +857,24 @@
 
   void add(List<int> data) {
     if (data.length == 0) return;
+    _timeline?.instant('Request body', arguments: {
+      'encodedData': data,
+    });
     super.add(data);
   }
 
+  Future addStream(Stream<List<int>> s) {
+    if (_timeline == null) {
+      return super.addStream(s);
+    }
+    return super.addStream(s.map((data) {
+      _timeline?.instant('Request body', arguments: {
+        'encodedData': data,
+      });
+      return data;
+    }));
+  }
+
   void write(Object? obj) {
     if (!_encodingSet) {
       _encoding = encoding;
@@ -842,7 +899,7 @@
 
   _HttpResponse(Uri uri, String protocolVersion, _HttpOutgoing outgoing,
       HttpHeaders defaultHeaders, String? serverHeader)
-      : super(uri, protocolVersion, outgoing,
+      : super(uri, protocolVersion, outgoing, null,
             initialHeaders: defaultHeaders as _HttpHeaders) {
     if (serverHeader != null) {
       headers.set(HttpHeaders.serverHeader, serverHeader);
@@ -1083,7 +1140,7 @@
   _HttpClientRequest(_HttpOutgoing outgoing, Uri uri, this.method, this._proxy,
       this._httpClient, this._httpClientConnection, this._timeline)
       : uri = uri,
-        super(uri, "1.1", outgoing) {
+        super(uri, "1.1", outgoing, _timeline) {
     _timeline?.instant('Request initiated');
     // GET and HEAD have 'content-length: 0' by default.
     if (method == "GET" || method == "HEAD") {
@@ -1135,6 +1192,14 @@
         'redirects': formatRedirectInfo(),
         'statusCode': response.statusCode,
       });
+
+      // Start the timeline for response.
+      _timeline?.start('HTTP CLIENT response of ${method.toUpperCase()}',
+          arguments: {
+            'requestUri': uri.toString(),
+            'statusCode': response.statusCode,
+            'reasonPhrase': response.reasonPhrase,
+          });
     }, onError: (e) {});
   }
 
@@ -1169,7 +1234,8 @@
     if (_aborted) {
       return;
     }
-    var response = new _HttpClientResponse(incoming, this, _httpClient);
+    final response =
+        _HttpClientResponse(incoming, this, _httpClient, _timeline);
     Future<HttpClientResponse> future;
     if (followRedirects && response.isRedirect) {
       if (response.redirects.length < maxRedirects) {
diff --git a/tools/VERSION b/tools/VERSION
index afa83d0..d5b4582 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 38
+PRERELEASE 39
 PRERELEASE_PATCH 0
\ No newline at end of file