Version 2.11.0-161.0.dev

Merge commit '39719118a4b9f0b8c5affe36b7e63e5a086a65a9' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
index ac0d56c..78b882b 100644
--- a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
@@ -20,8 +20,11 @@
 import 'package:analysis_server/src/services/correction/dart/convert_to_generic_function_syntax.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_if_null.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_int_literal.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_list_literal.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_map_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_relative_import.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_set_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_where_type.dart';
 import 'package:analysis_server/src/services/correction/dart/create_method.dart';
 import 'package:analysis_server/src/services/correction/dart/make_final.dart';
@@ -63,70 +66,167 @@
 
 /// A fix producer that produces changes to fix multiple diagnostics.
 class BulkFixProcessor {
-  /// A map from the name of a lint rule to a generator used to create the
-  /// correction producer used to build a fix for that diagnostic. The
-  /// generators used for non-lint diagnostics are in the [nonLintProducerMap].
-  static const Map<String, ProducerGenerator> lintProducerMap = {
-    LintNames.annotate_overrides: AddOverride.newInstance,
-    LintNames.avoid_annotating_with_dynamic: RemoveTypeAnnotation.newInstance,
-    LintNames.avoid_empty_else: RemoveEmptyElse.newInstance,
-    LintNames.avoid_init_to_null: RemoveInitializer.newInstance,
-    LintNames.avoid_redundant_argument_values: RemoveArgument.newInstance,
-    LintNames.avoid_return_types_on_setters: RemoveTypeAnnotation.newInstance,
-    LintNames.avoid_single_cascade_in_expression_statements:
-        ReplaceCascadeWithDot.newInstance,
-    LintNames.avoid_types_on_closure_parameters:
-        RemoveTypeAnnotation.newInstance,
-    LintNames.await_only_futures: RemoveAwait.newInstance,
-    LintNames.curly_braces_in_flow_control_structures:
-        UseCurlyBraces.newInstance,
-    LintNames.diagnostic_describe_all_properties:
-        AddDiagnosticPropertyReference.newInstance,
-    LintNames.empty_catches: RemoveEmptyCatch.newInstance,
-    LintNames.empty_constructor_bodies: RemoveEmptyConstructorBody.newInstance,
-    LintNames.empty_statements: RemoveEmptyStatement.newInstance,
-    LintNames.hash_and_equals: CreateMethod.equalsOrHashCode,
-    LintNames.no_duplicate_case_values: RemoveDuplicateCase.newInstance,
-    LintNames.non_constant_identifier_names: RenameToCamelCase.newInstance,
-    LintNames.null_closures: ReplaceNullWithClosure.newInstance,
-    LintNames.omit_local_variable_types: ReplaceWithVar.newInstance,
-    LintNames.prefer_adjacent_string_concatenation: RemoveOperator.newInstance,
-    LintNames.prefer_conditional_assignment:
-        ReplaceWithConditionalAssignment.newInstance,
-    LintNames.prefer_const_constructors_in_immutables: AddConst.newInstance,
-    LintNames.prefer_const_declarations: ReplaceFinalWithConst.newInstance,
-    LintNames.prefer_contains: ConvertToContains.newInstance,
-    LintNames.prefer_equal_for_default_values:
-        ReplaceColonWithEquals.newInstance,
-    LintNames.prefer_final_fields: MakeFinal.newInstance,
-    LintNames.prefer_final_locals: MakeFinal.newInstance,
-    LintNames.prefer_for_elements_to_map_fromIterable:
-        ConvertMapFromIterableToForLiteral.newInstance,
-    LintNames.prefer_generic_function_type_aliases:
-        ConvertToGenericFunctionSyntax.newInstance,
-    LintNames.prefer_if_elements_to_conditional_expressions:
-        ConvertConditionalExpressionToIfElement.newInstance,
-    LintNames.prefer_if_null_operators: ConvertToIfNull.newInstance,
-    LintNames.prefer_int_literals: ConvertToIntLiteral.newInstance,
-    LintNames.prefer_is_empty: ReplaceWithIsEmpty.newInstance,
-    LintNames.prefer_is_not_empty: UesIsNotEmpty.newInstance,
-    LintNames.prefer_iterable_whereType: ConvertToWhereType.newInstance,
-    LintNames.prefer_null_aware_operators: ConvertToNullAware.newInstance,
-    LintNames.prefer_relative_imports: ConvertToRelativeImport.newInstance,
-    LintNames.prefer_single_quotes: ConvertToSingleQuotes.newInstance,
-    LintNames.prefer_spread_collections: ConvertAddAllToSpread.newInstance,
-    LintNames.slash_for_doc_comments: ConvertDocumentationIntoLine.newInstance,
-    LintNames.sort_child_properties_last: SortChildPropertyLast.newInstance,
-    LintNames.type_init_formals: RemoveTypeAnnotation.newInstance,
-    LintNames.unawaited_futures: AddAwait.newInstance,
-    LintNames.unnecessary_brace_in_string_interps:
-        RemoveInterpolationBraces.newInstance,
-    LintNames.unnecessary_const: RemoveUnnecessaryConst.newInstance,
-    LintNames.unnecessary_lambdas: ReplaceWithTearOff.newInstance,
-    LintNames.unnecessary_new: RemoveUnnecessaryNew.newInstance,
-    LintNames.unnecessary_overrides: RemoveMethodDeclaration.newInstance,
-    LintNames.unnecessary_this: RemoveThisExpression.newInstance,
-    LintNames.use_rethrow_when_possible: UseRethrow.newInstance,
+  /// A map from the name of a lint rule to a list of generators used to create
+  /// the correction producer used to build a fix for that diagnostic. Most
+  /// entries will have only one generator.  In cases where there is more than
+  /// one, they will be applied in series and the expectation is that only one
+  /// will produce a change for a given fix. If more than one change is produced
+  /// the result will almost certainly be invalid code. The generators used for
+  /// non-lint diagnostics are in the [nonLintProducerMap].
+  static const Map<String, List<ProducerGenerator>> lintProducerMap = {
+    LintNames.annotate_overrides: [
+      AddOverride.newInstance,
+    ],
+    LintNames.avoid_annotating_with_dynamic: [
+      RemoveTypeAnnotation.newInstance,
+    ],
+    LintNames.avoid_empty_else: [
+      RemoveEmptyElse.newInstance,
+    ],
+    LintNames.avoid_init_to_null: [
+      RemoveInitializer.newInstance,
+    ],
+    LintNames.avoid_redundant_argument_values: [
+      RemoveArgument.newInstance,
+    ],
+    LintNames.avoid_return_types_on_setters: [
+      RemoveTypeAnnotation.newInstance,
+    ],
+    LintNames.avoid_single_cascade_in_expression_statements: [
+      ReplaceCascadeWithDot.newInstance,
+    ],
+    LintNames.avoid_types_on_closure_parameters: [
+      RemoveTypeAnnotation.newInstance,
+    ],
+    LintNames.await_only_futures: [
+      RemoveAwait.newInstance,
+    ],
+    LintNames.curly_braces_in_flow_control_structures: [
+      UseCurlyBraces.newInstance,
+    ],
+    LintNames.diagnostic_describe_all_properties: [
+      AddDiagnosticPropertyReference.newInstance,
+    ],
+    LintNames.empty_catches: [
+      RemoveEmptyCatch.newInstance,
+    ],
+    LintNames.empty_constructor_bodies: [
+      RemoveEmptyConstructorBody.newInstance,
+    ],
+    LintNames.empty_statements: [
+      RemoveEmptyStatement.newInstance,
+    ],
+    LintNames.hash_and_equals: [CreateMethod.equalsOrHashCode],
+    LintNames.no_duplicate_case_values: [
+      RemoveDuplicateCase.newInstance,
+    ],
+    LintNames.non_constant_identifier_names: [
+      RenameToCamelCase.newInstance,
+    ],
+    LintNames.null_closures: [
+      ReplaceNullWithClosure.newInstance,
+    ],
+    LintNames.omit_local_variable_types: [
+      ReplaceWithVar.newInstance,
+    ],
+    LintNames.prefer_adjacent_string_concatenation: [
+      RemoveOperator.newInstance,
+    ],
+    LintNames.prefer_collection_literals: [
+      ConvertToListLiteral.newInstance,
+      ConvertToMapLiteral.newInstance,
+      ConvertToSetLiteral.newInstance,
+    ],
+    LintNames.prefer_conditional_assignment: [
+      ReplaceWithConditionalAssignment.newInstance,
+    ],
+    LintNames.prefer_const_constructors_in_immutables: [
+      AddConst.newInstance,
+    ],
+    LintNames.prefer_const_declarations: [
+      ReplaceFinalWithConst.newInstance,
+    ],
+    LintNames.prefer_contains: [
+      ConvertToContains.newInstance,
+    ],
+    LintNames.prefer_equal_for_default_values: [
+      ReplaceColonWithEquals.newInstance,
+    ],
+    LintNames.prefer_final_fields: [
+      MakeFinal.newInstance,
+    ],
+    LintNames.prefer_final_locals: [
+      MakeFinal.newInstance,
+    ],
+    LintNames.prefer_for_elements_to_map_fromIterable: [
+      ConvertMapFromIterableToForLiteral.newInstance,
+    ],
+    LintNames.prefer_generic_function_type_aliases: [
+      ConvertToGenericFunctionSyntax.newInstance,
+    ],
+    LintNames.prefer_if_elements_to_conditional_expressions: [
+      ConvertConditionalExpressionToIfElement.newInstance,
+    ],
+    LintNames.prefer_if_null_operators: [
+      ConvertToIfNull.newInstance,
+    ],
+    LintNames.prefer_int_literals: [
+      ConvertToIntLiteral.newInstance,
+    ],
+    LintNames.prefer_is_empty: [
+      ReplaceWithIsEmpty.newInstance,
+    ],
+    LintNames.prefer_is_not_empty: [
+      UesIsNotEmpty.newInstance,
+    ],
+    LintNames.prefer_iterable_whereType: [
+      ConvertToWhereType.newInstance,
+    ],
+    LintNames.prefer_null_aware_operators: [
+      ConvertToNullAware.newInstance,
+    ],
+    LintNames.prefer_relative_imports: [
+      ConvertToRelativeImport.newInstance,
+    ],
+    LintNames.prefer_single_quotes: [
+      ConvertToSingleQuotes.newInstance,
+    ],
+    LintNames.prefer_spread_collections: [
+      ConvertAddAllToSpread.newInstance,
+    ],
+    LintNames.slash_for_doc_comments: [
+      ConvertDocumentationIntoLine.newInstance,
+    ],
+    LintNames.sort_child_properties_last: [
+      SortChildPropertyLast.newInstance,
+    ],
+    LintNames.type_init_formals: [
+      RemoveTypeAnnotation.newInstance,
+    ],
+    LintNames.unawaited_futures: [
+      AddAwait.newInstance,
+    ],
+    LintNames.unnecessary_brace_in_string_interps: [
+      RemoveInterpolationBraces.newInstance,
+    ],
+    LintNames.unnecessary_const: [
+      RemoveUnnecessaryConst.newInstance,
+    ],
+    LintNames.unnecessary_lambdas: [
+      ReplaceWithTearOff.newInstance,
+    ],
+    LintNames.unnecessary_new: [
+      RemoveUnnecessaryNew.newInstance,
+    ],
+    LintNames.unnecessary_overrides: [
+      RemoveMethodDeclaration.newInstance,
+    ],
+    LintNames.unnecessary_this: [
+      RemoveThisExpression.newInstance,
+    ],
+    LintNames.use_rethrow_when_possible: [
+      UseRethrow.newInstance,
+    ],
   };
 
   /// A map from an error code to a generator used to create the correction
@@ -190,9 +290,11 @@
 
     var errorCode = error.errorCode;
     if (errorCode is LintCode) {
-      var generator = lintProducerMap[errorCode.name];
-      if (generator != null) {
-        await compute(generator());
+      var generators = lintProducerMap[errorCode.name];
+      if (generators != null) {
+        for (var generator in generators) {
+          await compute(generator());
+        }
       }
     } else {
       var generator = nonLintProducerMap[errorCode];
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_list_literal_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_list_literal_test.dart
new file mode 100644
index 0000000..8810f14
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_list_literal_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToListLiteralTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToListLiteralTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.prefer_collection_literals;
+
+  Future<void> test_singleFile() async {
+    await resolveTestUnit('''
+List l = List();
+var l2 = List<int>();
+''');
+    await assertHasFix('''
+List l = [];
+var l2 = <int>[];
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_map_literal_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_map_literal_test.dart
new file mode 100644
index 0000000..066755e
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_map_literal_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToMapLiteralTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToMapLiteralTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.prefer_collection_literals;
+
+  Future<void> test_singleFile() async {
+    await resolveTestUnit('''
+Map m = Map();
+var m2 = Map<String, int>();
+''');
+    await assertHasFix('''
+Map m = {};
+var m2 = <String, int>{};
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_set_literal_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_set_literal_test.dart
new file mode 100644
index 0000000..526e697
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_set_literal_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToSetLiteralTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToSetLiteralTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.prefer_collection_literals;
+
+  Future<void> test_singleFile() async {
+    await resolveTestUnit('''
+Set s = Set();
+var s1 = Set<int>();
+''');
+    await assertHasFix('''
+Set s = {};
+var s1 = <int>{};
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
index 4d7e35b..fd34894 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
@@ -19,8 +19,11 @@
 import 'convert_to_if_element_test.dart' as convert_to_if_element;
 import 'convert_to_if_null_test.dart' as convert_to_if_null;
 import 'convert_to_int_literal_test.dart' as convert_to_int_literal;
+import 'convert_to_list_literal_test.dart' as convert_to_list_literal;
+import 'convert_to_map_literal_test.dart' as convert_to_map_literal;
 import 'convert_to_null_aware_test.dart' as convert_to_null_aware;
 import 'convert_to_relative_import_test.dart' as convert_to_relative_import;
+import 'convert_to_set_literal_test.dart' as convert_to_set_literal;
 import 'convert_to_single_quoted_strings_test.dart'
     as convert_to_single_quoted_strings;
 import 'convert_to_spread_test.dart' as convert_to_spread;
@@ -70,8 +73,11 @@
     convert_to_if_element.main();
     convert_to_if_null.main();
     convert_to_int_literal.main();
+    convert_to_list_literal.main();
+    convert_to_map_literal.main();
     convert_to_null_aware.main();
     convert_to_relative_import.main();
+    convert_to_set_literal.main();
     convert_to_single_quoted_strings.main();
     convert_to_spread.main();
     convert_to_where_type.main();
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 31236b3..a2e9ade 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -67,6 +67,7 @@
     ElementKind kind = element.kind;
     if (kind == ElementKind.CLASS ||
         kind == ElementKind.CONSTRUCTOR ||
+        kind == ElementKind.ENUM ||
         kind == ElementKind.EXTENSION ||
         kind == ElementKind.FUNCTION_TYPE_ALIAS ||
         kind == ElementKind.SETTER) {
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 07891bc..4a49b97 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -5396,6 +5396,14 @@
   final List<String> superCalls = <String>[];
 
   @override
+  void visitBinaryExpression(BinaryExpression node) {
+    if (node.leftOperand is SuperExpression) {
+      superCalls.add(node.operator.lexeme);
+    }
+    super.visitBinaryExpression(node);
+  }
+
+  @override
   void visitMethodInvocation(MethodInvocation node) {
     if (node.target is SuperExpression) {
       superCalls.add(node.methodName.name);
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index d7c8abd..70061ed 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -510,6 +510,22 @@
       ..isReferencedAt('A.field); // 3', false);
   }
 
+  test_isReferencedBy_ClassElement_enum() async {
+    await _indexTestUnit('''
+enum MyEnum {a}
+
+main(MyEnum p) {
+  MyEnum v;
+  MyEnum.a;
+}
+''');
+    ClassElement element = findElement('MyEnum');
+    assertThat(element)
+      ..isReferencedAt('MyEnum p) {', false)
+      ..isReferencedAt('MyEnum v;', false)
+      ..isReferencedAt('MyEnum.a;', false);
+  }
+
   test_isReferencedBy_ClassElement_fromExtension() async {
     await _indexTestUnit('''
 class A<T> {}
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index c3174e4..e5fefd3 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -280,6 +280,29 @@
     await _verifyReferences(element, expected);
   }
 
+  test_searchReferences_ClassElement_enum() async {
+    await _resolveTestUnit('''
+enum MyEnum {a}
+
+main(MyEnum p) {
+  MyEnum v;
+  MyEnum.a;
+}
+''');
+    var element = findElement.enum_('MyEnum');
+    var main = findElement.function('main');
+    var expected = [
+      _expectId(
+        findElement.parameter('p'),
+        SearchResultKind.REFERENCE,
+        'MyEnum p',
+      ),
+      _expectId(main, SearchResultKind.REFERENCE, 'MyEnum v'),
+      _expectId(main, SearchResultKind.REFERENCE, 'MyEnum.a'),
+    ];
+    await _verifyReferences(element, expected);
+  }
+
   test_searchReferences_ClassElement_mixin() async {
     await _resolveTestUnit('''
 mixin A {}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_use_of_internal_member_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_use_of_internal_member_test.dart
index c2757f1..ac816b9 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_use_of_internal_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_use_of_internal_member_test.dart
@@ -211,6 +211,20 @@
     ]);
   }
 
+  test_outsidePackage_functionLiteralForInternalTypedef() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+@internal
+typedef IntFunc = int Function(int);
+int foo(IntFunc f, int x) => f(x);
+''');
+
+    await assertNoErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int g() => foo((x) => 2*x, 7);
+''');
+  }
+
   test_outsidePackage_inCommentReference() async {
     newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
 import 'package:meta/meta.dart';
@@ -425,6 +439,70 @@
     ]);
   }
 
+  test_outsidePackage_setter() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal
+  set s(int value) {}
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+f() {
+  C().s = 7;
+}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 46, 1),
+    ]);
+  }
+
+  test_outsidePackage_setter_compound() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  int get s() => 1;
+
+  @internal
+  set s(int value) {}
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+f() {
+  C().s += 7;
+}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 46, 1),
+    ]);
+  }
+
+  test_outsidePackage_setter_questionQuestion() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  int get s() => 1;
+
+  @internal
+  set s(int value) {}
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+f() {
+  C().s ??= 7;
+}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 46, 1),
+    ]);
+  }
+
   test_outsidePackage_superConstructor() async {
     newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
 import 'package:meta/meta.dart';
@@ -526,4 +604,20 @@
       error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 42, 1),
     ]);
   }
+
+  test_outsidePackage_variable_prefixed() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+int a = 1;
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart' as foo;
+
+int b = foo.a + 1;
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 53, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
index eda7bec..f871116 100644
--- a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
@@ -82,6 +82,36 @@
 ''');
   }
 
+  test_fromExtendingClass_operator() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  operator ==(Object o) => o is A;
+}
+class B extends A {
+  @override
+  operator ==(Object o) => o is B;
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 140, 2),
+    ]);
+  }
+
+  test_fromExtendingClass_operator_containsSuperCall() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  operator ==(Object o) => o is A;
+}
+class B extends A {
+  @override
+  operator ==(Object o) => o is B && super == o;
+}
+''');
+  }
+
   test_fromInterface() async {
     await assertNoErrorsInCode(r'''
 import 'package:meta/meta.dart';
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 2b45419..7cb8bc2 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -1734,7 +1734,6 @@
   /// The types defined in 'dart:core'.
   CommonElements get commonElements;
 
-  bool get useNullSafety;
   bool get useLegacySubtyping;
 
   DartType bottomType() =>
@@ -1844,7 +1843,7 @@
     } else if (typeArgument.isNull) {
       DartType futureOfNull =
           commonElements.futureType(commonElements.nullType);
-      result = useNullSafety ? nullableType(futureOfNull) : futureOfNull;
+      result = nullableType(futureOfNull);
     } else {
       result = FutureOrType._(typeArgument);
     }
@@ -2281,14 +2280,10 @@
     if (isCovariant) {
       // A covariant parameter has type `Object` in the method signature.
       var objectType = commonElements.objectType;
-      if (useNullSafety) {
-        if (isNonNullableByDefaultLibrary) {
-          return nullableType(objectType);
-        } else {
-          return legacyType(objectType);
-        }
+      if (isNonNullableByDefaultLibrary) {
+        return nullableType(objectType);
       } else {
-        return objectType;
+        return legacyType(objectType);
       }
     }
     return type;
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
index bedbb6c..946412a 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
@@ -449,12 +449,10 @@
     }
 
     if (type is NullableType) {
-      assert(dartTypes.useNullSafety);
       return _createFromStaticType(type.baseType, classRelation, true);
     }
 
     if (type is LegacyType) {
-      assert(dartTypes.useNullSafety);
       DartType baseType = type.baseType;
       if (baseType is NeverType) {
         // Never* is same as Null, for both 'is' and 'as'.
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index baa8308..b8840fb 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -278,12 +278,10 @@
     }
 
     if (type is NullableType) {
-      assert(dartTypes.useNullSafety);
       return _createFromStaticType(type.baseType, classRelation, true);
     }
 
     if (type is LegacyType) {
-      assert(dartTypes.useNullSafety);
       DartType baseType = type.baseType;
       if (baseType is NeverType) {
         // Never* is same as Null, for both 'is' and 'as'.
diff --git a/pkg/compiler/lib/src/ir/types.dart b/pkg/compiler/lib/src/ir/types.dart
index a43e4fe..2d2d603 100644
--- a/pkg/compiler/lib/src/ir/types.dart
+++ b/pkg/compiler/lib/src/ir/types.dart
@@ -17,8 +17,6 @@
   KernelDartTypes(this.elementMap, this._options);
 
   @override
-  bool get useNullSafety => _options.useNullSafety;
-  @override
   bool get useLegacySubtyping => _options.useLegacySubtyping;
 
   @override
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index bd1929e..e4a2425 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -13,7 +13,6 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../ir/element_map.dart';
-import '../options.dart';
 
 /// Visitor that converts string literals and concatenations of string literals
 /// into the string value.
@@ -44,18 +43,16 @@
 
 /// Visitor that converts kernel dart types into [DartType].
 class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
-  final CompilerOptions _options;
   final IrToElementMap elementMap;
   final Map<ir.TypeParameter, DartType> currentFunctionTypeParameters =
       <ir.TypeParameter, DartType>{};
   bool topLevel = true;
 
-  DartTypeConverter(this._options, this.elementMap);
+  DartTypeConverter(this.elementMap);
 
   DartTypes get _dartTypes => elementMap.commonElements.dartTypes;
 
   DartType _convertNullability(DartType baseType, ir.Nullability nullability) {
-    if (!_options.useNullSafety) return baseType;
     switch (nullability) {
       case ir.Nullability.nullable:
         return _dartTypes.nullableType(baseType);
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 383ed44..5f63cfb 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -768,11 +768,9 @@
         _commonElements.installSpecializedIsTest,
         _commonElements.generalIsTestImplementation,
         _commonElements.generalAsCheckImplementation,
-        if (_options.useNullSafety) ...[
-          _commonElements.installSpecializedAsCheck,
-          _commonElements.generalNullableIsTestImplementation,
-          _commonElements.generalNullableAsCheckImplementation,
-        ],
+        _commonElements.installSpecializedAsCheck,
+        _commonElements.generalNullableIsTestImplementation,
+        _commonElements.generalNullableAsCheckImplementation,
         // Specialized checks.
         _commonElements.specializedIsBool,
         _commonElements.specializedAsBool,
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 5a3de9a..b3f9cb7 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -136,7 +136,7 @@
       AnnotationsData annotations)
       : this.options = _elementMap.options {
     _elementEnvironment = new JsElementEnvironment(this);
-    _typeConverter = new DartTypeConverter(options, this);
+    _typeConverter = new DartTypeConverter(this);
     _types = new KernelDartTypes(this, options);
     _commonElements = new CommonElementsImpl(_types, _elementEnvironment);
     _constantValuefier = new ConstantValuefier(this);
@@ -296,7 +296,7 @@
   JsKernelToElementMap.readFromDataSource(this.options, this.reporter,
       this._environment, ir.Component component, DataSource source) {
     _elementEnvironment = new JsElementEnvironment(this);
-    _typeConverter = new DartTypeConverter(options, this);
+    _typeConverter = new DartTypeConverter(this);
     _types = new KernelDartTypes(this, options);
     _commonElements = new CommonElementsImpl(_types, _elementEnvironment);
     _constantValuefier = new ConstantValuefier(this);
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 46d5a3a..a574666 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -117,7 +117,7 @@
   KernelToElementMapImpl(
       this.reporter, this._environment, this._frontendStrategy, this.options) {
     _elementEnvironment = new KernelElementEnvironment(this);
-    _typeConverter = new DartTypeConverter(options, this);
+    _typeConverter = new DartTypeConverter(this);
     _types = new KernelDartTypes(this, options);
     _commonElements = new CommonElementsImpl(_types, _elementEnvironment);
     _constantValuefier = new ConstantValuefier(this);
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index fee3632..67a549e 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -74,17 +74,7 @@
       ir.Component component;
       var isDill = resolvedUri.path.endsWith('.dill');
 
-      // TODO(sigmund): remove after we unfork the sdk, and force null-safety to
-      // always be considered to be true.
-      void inferNullSafety() {
-        if (component.libraries.any((lib) =>
-            lib.isNonNullableByDefault && lib.importUri.scheme == 'dart')) {
-          _options.useNullSafety = true;
-        }
-      }
-
       void inferNullSafetyMode(bool isSound) {
-        if (isSound) assert(_options.useNullSafety == true);
         if (_options.nullSafetyMode == NullSafetyMode.unspecified) {
           _options.nullSafetyMode =
               isSound ? NullSafetyMode.sound : NullSafetyMode.unsound;
@@ -93,9 +83,6 @@
 
       void validateNullSafety() {
         assert(_options.nullSafetyMode != NullSafetyMode.unspecified);
-        if (_options.nullSafetyMode == NullSafetyMode.sound) {
-          assert(_options.useNullSafety);
-        }
       }
 
       if (isDill) {
@@ -119,7 +106,6 @@
           throw ArgumentError("$resolvedUri was compiled with $dillMode null "
               "safety and is incompatible with the '$option' option");
         }
-        inferNullSafety();
         inferNullSafetyMode(isStrongDill);
         validateNullSafety();
 
@@ -160,7 +146,7 @@
           ..onDiagnostic = onDiagnostic;
         bool isLegacy =
             await fe.uriUsesLegacyLanguageVersion(resolvedUri, options);
-        inferNullSafetyMode(_options.useNullSafety && !isLegacy);
+        inferNullSafetyMode(!isLegacy);
 
         List<Uri> dependencies = [];
         if (_options.platformBinaries != null) {
@@ -170,6 +156,14 @@
         if (_options.dillDependencies != null) {
           dependencies.addAll(_options.dillDependencies);
         }
+
+        fe.NnbdMode nnbdMode;
+        if (_options.enableNonNullable) {
+          nnbdMode = _options.useLegacySubtyping
+              ? fe.NnbdMode.Weak
+              : fe.NnbdMode.Strong;
+        }
+
         initializedCompilerState = fe.initializeCompiler(
             initializedCompilerState,
             target,
@@ -177,13 +171,10 @@
             dependencies,
             _options.packageConfig,
             experimentalFlags: _options.languageExperiments,
-            nnbdMode: _options.useLegacySubtyping
-                ? fe.NnbdMode.Weak
-                : fe.NnbdMode.Strong);
+            nnbdMode: nnbdMode);
         component = await fe.compile(initializedCompilerState, verbose,
             fileSystem, onDiagnostic, resolvedUri);
         if (component == null) return null;
-        inferNullSafety();
         validateNullSafety();
       }
 
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 049814a..a01fac5 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -855,8 +855,7 @@
     // compatibility or conditional support by context.
     if (type is NullableType ||
         type is LegacyType ||
-        ((!options.useNullSafety || options.useLegacySubtyping) &&
-            type is! VoidType)) {
+        (options.useLegacySubtyping && type is! VoidType)) {
       _behavior.typesReturned.add(commonElements.nullType);
     }
   }
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 368ee30..f9d0f30 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -110,6 +110,10 @@
   /// `true` if variance is enabled.
   bool get enableVariance => languageExperiments[fe.ExperimentalFlag.variance];
 
+  /// Whether `--enable-experiment=non-nullable` is provided.
+  bool get enableNonNullable =>
+      languageExperiments[fe.ExperimentalFlag.nonNullable];
+
   /// A possibly null state object for kernel compilation.
   fe.InitializedCompilerState kernelInitializedCompilerState;
 
@@ -375,13 +379,6 @@
   /// called.
   bool experimentCallInstrumentation = false;
 
-  /// Whether null-safety (non-nullable types) are enabled in the sdk.
-  ///
-  /// This may be true either when `--enable-experiment=non-nullable` is
-  /// provided on the command-line, or when the provided .dill file for the sdk
-  /// was built with null-safety enabled.
-  bool useNullSafety = false;
-
   /// When null-safety is enabled, whether the compiler should emit code with
   /// unsound or sound semantics.
   ///
@@ -400,7 +397,7 @@
   bool get useLegacySubtyping {
     assert(nullSafetyMode != NullSafetyMode.unspecified,
         "Null safety mode unspecified");
-    return !useNullSafety || (nullSafetyMode == NullSafetyMode.unsound);
+    return nullSafetyMode == NullSafetyMode.unsound;
   }
 
   /// The path to the file that contains the profiled allocations.
@@ -559,7 +556,7 @@
       throw ArgumentError("'${Flags.soundNullSafety}' incompatible with "
           "'${Flags.noSoundNullSafety}'");
     }
-    if (!useNullSafety && _soundNullSafety) {
+    if (!enableNonNullable && _soundNullSafety) {
       throw ArgumentError("'${Flags.soundNullSafety}' requires the "
           "'non-nullable' experiment to be enabled");
     }
@@ -587,10 +584,6 @@
     if (_noLegacyJavaScript) legacyJavaScript = false;
     if (_legacyJavaScript) legacyJavaScript = true;
 
-    if (languageExperiments[fe.ExperimentalFlag.nonNullable]) {
-      useNullSafety = true;
-    }
-
     if (_soundNullSafety) nullSafetyMode = NullSafetyMode.sound;
     if (_noSoundNullSafety) nullSafetyMode = NullSafetyMode.unsound;
 
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 06de6f8..f329a54 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -112,14 +112,8 @@
           "null safety and is incompatible with the '$option' option");
     }
 
-    if (component.libraries.any((lib) =>
-        lib.isNonNullableByDefault && lib.importUri.scheme == 'dart')) {
-      _options.useNullSafety = true;
-    }
-
     if (component.mode == ir.NonNullableByDefaultCompiledMode.Strong) {
       _options.nullSafetyMode = NullSafetyMode.sound;
-      assert(_options.useNullSafety);
     } else {
       _options.nullSafetyMode = NullSafetyMode.unsound;
     }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index a43c369..e093833 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -364,8 +364,6 @@
         return options.useContentSecurityPolicy;
       case 'VARIANCE':
         return options.enableVariance;
-      case 'NNBD':
-        return options.useNullSafety;
       case 'LEGACY':
         return options.useLegacySubtyping;
       case 'LEGACY_JAVASCRIPT':
@@ -4655,11 +4653,7 @@
 
   bool _equivalentToMissingRti(InterfaceType type) {
     assert(type.element == _commonElements.jsArrayClass);
-    if (dartTypes.useNullSafety) {
-      return dartTypes.isStrongTopType(type.typeArguments.single);
-    } else {
-      return dartTypes.treatAsRawType(type);
-    }
+    return dartTypes.isStrongTopType(type.typeArguments.single);
   }
 
   void _handleForeignJs(ir.StaticInvocation invocation) {
@@ -6360,13 +6354,11 @@
 
     AbstractValue unwrappedType = kernelBuilder._typeInferenceMap
         .getReturnTypeOf(kernelBuilder._commonElements.exceptionUnwrapper);
-    if (kernelBuilder.options.useNullSafety) {
-      // Global type analysis does not currently understand that strong mode
-      // `Object` is not nullable, so is imprecise in the return type of the
-      // unwrapper, which leads to unnecessary checks for 'on Object'.
-      unwrappedType =
-          kernelBuilder._abstractValueDomain.excludeNull(unwrappedType);
-    }
+    // Global type analysis does not currently understand that strong mode
+    // `Object` is not nullable, so is imprecise in the return type of the
+    // unwrapper, which leads to unnecessary checks for 'on Object'.
+    unwrappedType =
+        kernelBuilder._abstractValueDomain.excludeNull(unwrappedType);
     kernelBuilder._pushStaticInvocation(
         kernelBuilder._commonElements.exceptionUnwrapper,
         [exception],
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 811409f..6a551f89 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -4143,26 +4143,20 @@
   AbstractValue supersetType = checkedAbstractValue.abstractValue;
   AbstractBool expressionIsNull = expression.isNull(abstractValueDomain);
 
-  if (!isCast && options.useNullSafety) {
+  bool _nullIs(DartType type) =>
+      dartTypes.isStrongTopType(type) ||
+      type is LegacyType &&
+          (type.baseType.isObject || type.baseType is NeverType) ||
+      type is NullableType ||
+      type is FutureOrType && _nullIs(type.typeArgument) ||
+      type.isNull;
+
+  if (!isCast) {
     if (expressionIsNull.isDefinitelyTrue) {
-      if (dartType.isObject) return AbstractBool.False;
-      if (dartTypes.isTopType(dartType) ||
-          dartType is NullableType ||
-          dartType.isNull) {
-        return AbstractBool.True;
-      }
-      if (dartType is TypeVariableType || dartType is FunctionTypeVariable) {
-        return AbstractBool.Maybe;
-      }
-      if (dartType is LegacyType) {
-        DartType baseType = dartType.baseType;
-        if (baseType is NeverType) return AbstractBool.True;
-        if (baseType is TypeVariableType || baseType is FunctionTypeVariable) {
-          return AbstractBool.Maybe;
-        }
-      }
-      return AbstractBool.False;
-    } else if (expressionIsNull.isPotentiallyTrue) {
+      if (dartType.containsFreeTypeVariables) return AbstractBool.Maybe;
+      return AbstractBool.trueOrFalse(_nullIs(dartType));
+    }
+    if (expressionIsNull.isPotentiallyTrue) {
       if (dartType.isObject) return AbstractBool.Maybe;
     }
   }
@@ -4231,8 +4225,7 @@
   AbstractBool isNullAsCheck = !options.useLegacySubtyping && isCast
       ? expressionIsNull
       : AbstractBool.False;
-  AbstractBool isNullIsTest =
-      options.useNullSafety && !isCast ? expressionIsNull : AbstractBool.False;
+  AbstractBool isNullIsTest = !isCast ? expressionIsNull : AbstractBool.False;
 
   AbstractBool unwrapAndCheck(DartType type) {
     if (dartTypes.isTopType(dartType)) return AbstractBool.True;
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index e12559c..39140be 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -111,7 +111,7 @@
     /// however dart2js moves the null check to the callee for performance
     /// reasons. As a result the body cannot trust or check that the type is not
     /// nullable.
-    if (builder.options.useNullSafety && memberContext.name == '==') {
+    if (memberContext.name == '==') {
       type = _closedWorld.dartTypes.nullableType(type);
     }
     HInstruction trusted = _trustType(original, type);
diff --git a/pkg/compiler/test/helpers/compiler_helper.dart b/pkg/compiler/test/helpers/compiler_helper.dart
index 3dd4594..562741f 100644
--- a/pkg/compiler/test/helpers/compiler_helper.dart
+++ b/pkg/compiler/test/helpers/compiler_helper.dart
@@ -42,7 +42,8 @@
     bool omitImplicitChecks: true,
     bool enableVariance: false,
     void check(String generatedEntry),
-    bool returnAll: false}) async {
+    bool returnAll: false,
+    bool soundNullSafety: false}) async {
   OutputCollector outputCollector = returnAll ? new OutputCollector() : null;
   List<String> options = <String>[];
   if (disableTypeInference) {
@@ -66,6 +67,11 @@
   if (enableVariance) {
     options.add('${Flags.enableLanguageExperiments}=variance');
   }
+  if (soundNullSafety) {
+    options.add(Flags.soundNullSafety);
+  } else {
+    options.add(Flags.noSoundNullSafety);
+  }
 
   // Pretend this is a dart2js_native test to allow use of 'native' keyword
   // and import of private libraries.
@@ -103,6 +109,7 @@
 Future<String> compileAll(String code,
     {bool disableInlining: true,
     bool minify: false,
+    bool soundNullSafety: false,
     int expectedErrors,
     int expectedWarnings}) async {
   OutputCollector outputCollector = new OutputCollector();
@@ -114,6 +121,11 @@
   if (minify) {
     options.add(Flags.minify);
   }
+  if (soundNullSafety) {
+    options.add(Flags.soundNullSafety);
+  } else {
+    options.add(Flags.noSoundNullSafety);
+  }
 
   // Pretend this is a dart2js_native test to allow use of 'native' keyword
   // and import of private libraries.
diff --git a/pkg/dartdev/analysis_options.yaml b/pkg/dartdev/analysis_options.yaml
index 4416a89..5168988 100644
--- a/pkg/dartdev/analysis_options.yaml
+++ b/pkg/dartdev/analysis_options.yaml
@@ -12,53 +12,11 @@
 
 linter:
   rules:
-    - avoid_function_literals_in_foreach_calls
-    - avoid_private_typedef_functions
-    - avoid_redundant_argument_values
-    - avoid_renaming_method_parameters
-    - avoid_returning_null_for_void
-    - avoid_void_async
-    - await_only_futures
-    - camel_case_types
-    - constant_identifier_names
+    - always_declare_return_types
     - directives_ordering
-    - empty_statements
-    - file_names
-    - iterable_contains_unrelated_type
-    - lines_longer_than_80_chars
-    - list_remove_unrelated_type
-    - missing_whitespace_between_adjacent_strings
-    - no_runtimeType_toString
-    - non_constant_identifier_names
-    - only_throw_errors
     - overridden_fields
-    - package_names
-    - package_prefixed_library_names
-    - prefer_asserts_in_initializer_lists
-    - prefer_const_constructors
-    - prefer_const_declarations
-    - prefer_function_declarations_over_variables
-    - prefer_initializing_formals
-    - prefer_inlined_adds
-    - prefer_interpolation_to_compose_strings
-    - prefer_is_not_operator
-    - prefer_final_fields
-    - prefer_null_aware_operators
-    - prefer_relative_imports
-    - prefer_typing_uninitialized_variables
-    - prefer_void_to_null
-    - provide_deprecation_message
+    - prefer_single_quotes
     - sort_pub_dependencies
-    - test_types_in_equals
-    - throw_in_finally
-    - type_annotate_public_apis
     - unnecessary_brace_in_string_interps
-    - unnecessary_lambdas
-    - unnecessary_null_aware_assignments
     - unnecessary_overrides
     - unnecessary_parenthesis
-    - unnecessary_statements
-    - unnecessary_string_interpolations
-    - use_is_even_rather_than_modulo
-    - use_string_buffers
-    - void_checks
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index 777dd30..a6ec4bf 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -36,15 +36,15 @@
   final stopwatch = Stopwatch();
   int result;
 
-  // The exit code for the dartdev process, null indicates that it has not yet
-  // been set yet. The value is set in the catch and finally blocks below.
+  // The exit code for the dartdev process; null indicates that it has not been
+  // set yet. The value is set in the catch and finally blocks below.
   int exitCode;
 
-  // Any caught non-UsageExceptions when running the sub command
+  // Any caught non-UsageExceptions when running the sub command.
   Object exception;
   StackTrace stackTrace;
 
-  // The Analytics instance used to report information back to Google Analytics,
+  // The Analytics instance used to report information back to Google Analytics;
   // see lib/src/analytics.dart.
   Analytics analytics =
       createAnalyticsInstance(args.contains('--disable-dartdev-analytics'));
@@ -67,13 +67,13 @@
     // enableAnalytics), in which we favor the disabling of analytics.
     analytics.enabled = false;
 
-    // Alert the user that analytics have been disabled:
+    // Alert the user that analytics has been disabled.
     print(analyticsDisabledNoticeMessage);
     io.exit(0);
   } else if (args.contains('--enable-analytics')) {
     analytics.enabled = true;
 
-    // Alert the user again that anonymous data will be collected:
+    // Alert the user again that anonymous data will be collected.
     print(analyticsNoticeOnFirstRunMessage);
     io.exit(0);
   }
@@ -84,15 +84,14 @@
     stopwatch.start();
     final runner = DartdevRunner(args);
 
-    // Run can't be called with the '--disable-dartdev-analytics' flag, remove
+    // Run can't be called with the '--disable-dartdev-analytics' flag; remove
     // it if it is contained in args.
     if (args.contains('--disable-dartdev-analytics')) {
       args = List.from(args)..remove('--disable-dartdev-analytics');
     }
 
-    // These flags have a format that can't be handled by package:args, so
-    // while they are valid flags we'll assume the VM has verified them by this
-    // point.
+    // These flags have a format that can't be handled by package:args, so while
+    // they are valid flags we'll assume the VM has verified them by this point.
     args = args
         .where(
           (element) => !(element.contains('--observe') ||
@@ -101,17 +100,16 @@
         .toList();
 
     // If ... help pub ... is in the args list, remove 'help', and add '--help'
-    // to the end of the list.  This will make it possible to use the help
-    // command to access subcommands of pub such as `dart help pub publish`, see
-    // https://github.com/dart-lang/sdk/issues/42965
+    // to the end of the list. This will make it possible to use the help
+    // command to access subcommands of pub such as `dart help pub publish`; see
+    // https://github.com/dart-lang/sdk/issues/42965.
     if (PubUtils.shouldModifyArgs(args, runner.commands.keys.toList())) {
       args = PubUtils.modifyArgs(args);
     }
 
     // For the commands format and migrate, dartdev itself sends the
-    // sendScreenView notification to analytics, for all other
-    // dartdev commands (instances of DartdevCommand) the commands send this
-    // to analytics.
+    // sendScreenView notification to analytics; for all other dartdev commands
+    // (instances of DartdevCommand) the commands send it to analytics.
     commandName = ArgParserUtils.getCommandStr(args);
     if (analytics.enabled &&
         (commandName == formatCmdName || commandName == migrateCmdName)) {
@@ -119,7 +117,7 @@
       analytics.sendScreenView(commandName);
     }
 
-    // Finally, call the runner to execute the command, see DartdevRunner.
+    // Finally, call the runner to execute the command; see DartdevRunner.
     result = await runner.run(args);
   } catch (e, st) {
     if (e is UsageException) {
@@ -174,8 +172,8 @@
     }
 
     // Set the enabled flag in the analytics object to true. Note: this will not
-    // enable the analytics unless the disclosure was shown (terminal
-    // detected), and the machine is not detected to be a bot.
+    // enable the analytics unless the disclosure was shown (terminal detected),
+    // and the machine is not detected to be a bot.
     if (analytics.firstRun) {
       analytics.enabled = true;
     }
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index 597fe79..38f06ea 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -240,6 +240,7 @@
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...args
     ];
   }
@@ -264,6 +265,7 @@
       else if (_configuration.hotReloadRollback)
         '--hot-reload-rollback-test-mode',
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...testFile.sharedOptions,
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
@@ -882,6 +884,7 @@
     return [
       if (_enableAsserts) '--enable_asserts',
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...testFile.sharedOptions,
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
@@ -929,6 +932,7 @@
     return [
       if (_enableAsserts) '--enable_asserts',
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...testFile.sharedOptions,
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
@@ -946,6 +950,7 @@
     return [
       if (_enableAsserts) '--enable_asserts',
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...testFile.sharedOptions,
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index d6436b7..8447788 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -144,6 +144,40 @@
   size_ += (stop - start);
 }
 
+static UnboxedFieldBitmap CalculateTargetUnboxedFieldsBitmap(
+    Serializer* s,
+    intptr_t class_id) {
+  const auto unboxed_fields_bitmap_host =
+      s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
+          class_id);
+
+  UnboxedFieldBitmap unboxed_fields_bitmap;
+  if (unboxed_fields_bitmap_host.IsEmpty() ||
+      kWordSize == compiler::target::kWordSize) {
+    unboxed_fields_bitmap = unboxed_fields_bitmap_host;
+  } else {
+    ASSERT(kWordSize == 8 && compiler::target::kWordSize == 4);
+    // A new bitmap is built if the word sizes in the target and
+    // host are different
+    unboxed_fields_bitmap.Reset();
+    intptr_t target_i = 0, host_i = 0;
+
+    while (host_i < UnboxedFieldBitmap::Length()) {
+      // Each unboxed field has constant length, therefore the number of
+      // words used by it should double when compiling from 64-bit to 32-bit.
+      if (unboxed_fields_bitmap_host.Get(host_i++)) {
+        unboxed_fields_bitmap.Set(target_i++);
+        unboxed_fields_bitmap.Set(target_i++);
+      } else {
+        // For object pointers, the field is always one word length
+        target_i++;
+      }
+    }
+  }
+
+  return unboxed_fields_bitmap;
+}
+
 class ClassSerializationCluster : public SerializationCluster {
  public:
   explicit ClassSerializationCluster(intptr_t num_cids)
@@ -236,39 +270,6 @@
   GrowableArray<ClassPtr> predefined_;
   GrowableArray<ClassPtr> objects_;
 
-  UnboxedFieldBitmap CalculateTargetUnboxedFieldsBitmap(Serializer* s,
-                                                        intptr_t class_id) {
-    const auto unboxed_fields_bitmap_host =
-        s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            class_id);
-
-    UnboxedFieldBitmap unboxed_fields_bitmap;
-    if (unboxed_fields_bitmap_host.IsEmpty() ||
-        kWordSize == compiler::target::kWordSize) {
-      unboxed_fields_bitmap = unboxed_fields_bitmap_host;
-    } else {
-      ASSERT(kWordSize == 8 && compiler::target::kWordSize == 4);
-      // A new bitmap is built if the word sizes in the target and
-      // host are different
-      unboxed_fields_bitmap.Reset();
-      intptr_t target_i = 0, host_i = 0;
-
-      while (host_i < UnboxedFieldBitmap::Length()) {
-        // Each unboxed field has constant length, therefore the number of
-        // words used by it should double when compiling from 64-bit to 32-bit.
-        if (unboxed_fields_bitmap_host.Get(host_i++)) {
-          unboxed_fields_bitmap.Set(target_i++);
-          unboxed_fields_bitmap.Set(target_i++);
-        } else {
-          // For object pointers, the field is always one word length
-          target_i++;
-        }
-      }
-    }
-
-    return unboxed_fields_bitmap;
-  }
-
   bool RequireLegacyErasureOfConstants(ClassPtr cls) {
     // Do not generate a core snapshot containing constants that would require
     // a legacy erasure of their types if loaded in an isolate running in weak
@@ -290,7 +291,7 @@
   ClassDeserializationCluster() {}
   ~ClassDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     predefined_start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     intptr_t count = d->ReadUnsigned();
@@ -312,7 +313,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     ClassTable* table = d->isolate()->class_table();
 
     for (intptr_t id = predefined_start_index_; id < predefined_stop_index_;
@@ -443,7 +444,6 @@
       AutoTraceObject(type_args);
       const intptr_t length = Smi::Value(type_args->ptr()->length_);
       s->WriteUnsigned(length);
-      s->Write<bool>(type_args->ptr()->IsCanonical());
       intptr_t hash = Smi::Value(type_args->ptr()->hash_);
       s->Write<int32_t>(hash);
       const intptr_t nullability = Smi::Value(type_args->ptr()->nullability_);
@@ -465,7 +465,7 @@
   TypeArgumentsDeserializationCluster() {}
   ~TypeArgumentsDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -477,11 +477,10 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypeArgumentsPtr type_args = static_cast<TypeArgumentsPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(type_args, kTypeArgumentsCid,
                                      TypeArguments::InstanceSize(length),
                                      is_canonical);
@@ -496,23 +495,22 @@
     }
   }
 
-  void PostLoadEarly(Deserializer* d, const Array& refs) {
-    if (d->isolate() == Dart::vm_isolate()) {
-      return;
-    }
-    CanonicalTypeArgumentsSet table(
-        d->zone(), d->isolate()->object_store()->canonical_type_arguments());
-    TypeArguments& type_arg = TypeArguments::Handle(d->zone());
-    for (intptr_t i = start_index_; i < stop_index_; i++) {
-      type_arg ^= refs.At(i);
-      if (type_arg.IsCanonical()) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      CanonicalTypeArgumentsSet table(
+          d->zone(), d->isolate()->object_store()->canonical_type_arguments());
+      TypeArguments& type_arg = TypeArguments::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        type_arg ^= refs.At(i);
+        ASSERT(type_arg.IsCanonical());
         bool present = table.Insert(type_arg);
         // Two recursive types with different topology (and hashes) may be
         // equal.
         ASSERT(!present || type_arg.IsRecursive());
       }
+      d->isolate()->object_store()->set_canonical_type_arguments(
+          table.Release());
     }
-    d->isolate()->object_store()->set_canonical_type_arguments(table.Release());
   }
 };
 
@@ -560,7 +558,7 @@
   PatchClassDeserializationCluster() {}
   ~PatchClassDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -571,7 +569,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       PatchClassPtr cls = static_cast<PatchClassPtr>(d->Ref(id));
       Deserializer::InitializeHeader(cls, kPatchClassCid,
@@ -675,7 +673,7 @@
   FunctionDeserializationCluster() {}
   ~FunctionDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -685,7 +683,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     Snapshot::Kind kind = d->kind();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -738,7 +736,7 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     if (d->kind() == Snapshot::kFullAOT) {
       Function& func = Function::Handle(d->zone());
       for (intptr_t i = start_index_; i < stop_index_; i++) {
@@ -827,7 +825,7 @@
   ClosureDataDeserializationCluster() {}
   ~ClosureDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -838,7 +836,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ClosureDataPtr data = static_cast<ClosureDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(data, kClosureDataCid,
@@ -897,7 +895,7 @@
   SignatureDataDeserializationCluster() {}
   ~SignatureDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -908,7 +906,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       SignatureDataPtr data = static_cast<SignatureDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(data, kSignatureDataCid,
@@ -966,7 +964,7 @@
   FfiTrampolineDataDeserializationCluster() {}
   ~FfiTrampolineDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -977,7 +975,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       FfiTrampolineDataPtr data = static_cast<FfiTrampolineDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(data, kFfiTrampolineDataCid,
@@ -1031,7 +1029,7 @@
   RedirectionDataDeserializationCluster() {}
   ~RedirectionDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1042,7 +1040,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RedirectionDataPtr data = static_cast<RedirectionDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(data, kRedirectionDataCid,
@@ -1168,7 +1166,7 @@
   FieldDeserializationCluster() {}
   ~FieldDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1178,7 +1176,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     Snapshot::Kind kind = d->kind();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -1223,7 +1221,7 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     Field& field = Field::Handle(d->zone());
     if (!Isolate::Current()->use_field_guards()) {
       for (intptr_t i = start_index_; i < stop_index_; i++) {
@@ -1290,7 +1288,7 @@
   ScriptDeserializationCluster() {}
   ~ScriptDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1300,7 +1298,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ScriptPtr script = static_cast<ScriptPtr>(d->Ref(id));
       Deserializer::InitializeHeader(script, kScriptCid,
@@ -1363,7 +1361,7 @@
   LibraryDeserializationCluster() {}
   ~LibraryDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1373,7 +1371,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LibraryPtr lib = static_cast<LibraryPtr>(d->Ref(id));
       Deserializer::InitializeHeader(lib, kLibraryCid, Library::InstanceSize());
@@ -1435,7 +1433,7 @@
   NamespaceDeserializationCluster() {}
   ~NamespaceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1445,7 +1443,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       NamespacePtr ns = static_cast<NamespacePtr>(d->Ref(id));
       Deserializer::InitializeHeader(ns, kNamespaceCid,
@@ -1500,7 +1498,7 @@
   KernelProgramInfoDeserializationCluster() {}
   ~KernelProgramInfoDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1511,7 +1509,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       KernelProgramInfoPtr info = static_cast<KernelProgramInfoPtr>(d->Ref(id));
       Deserializer::InitializeHeader(info, kKernelProgramInfoCid,
@@ -1521,7 +1519,7 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     Array& array = Array::Handle(d->zone());
     KernelProgramInfo& info = KernelProgramInfo::Handle(d->zone());
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -1861,7 +1859,7 @@
   CodeDeserializationCluster() {}
   ~CodeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     PageSpace* old_space = d->heap()->old_space();
     start_index_ = d->next_index();
     const intptr_t count = d->ReadUnsigned();
@@ -1879,7 +1877,7 @@
     deferred_stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ReadFill(d, id, false);
     }
@@ -1931,7 +1929,7 @@
     code->ptr()->state_bits_ = d->Read<int32_t>();
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     d->EndInstructions(refs, start_index_, stop_index_);
 
 #if !defined(PRODUCT)
@@ -2013,7 +2011,7 @@
   BytecodeDeserializationCluster() {}
   virtual ~BytecodeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2023,7 +2021,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     ASSERT(d->kind() != Snapshot::kFullAOT);
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -2039,7 +2037,7 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     Bytecode& bytecode = Bytecode::Handle(d->zone());
     ExternalTypedData& binary = ExternalTypedData::Handle(d->zone());
 
@@ -2151,7 +2149,7 @@
   ObjectPoolDeserializationCluster() {}
   ~ObjectPoolDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2163,7 +2161,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id += 1) {
       const intptr_t length = d->ReadUnsigned();
       ObjectPoolPtr pool = static_cast<ObjectPoolPtr>(d->Ref(id + 0));
@@ -2315,7 +2313,7 @@
   WeakSerializationReferenceDeserializationCluster() {}
   ~WeakSerializationReferenceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2329,7 +2327,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       auto const ref = static_cast<WeakSerializationReferencePtr>(d->Ref(id));
       Deserializer::InitializeHeader(
@@ -2387,7 +2385,7 @@
   PcDescriptorsDeserializationCluster() {}
   ~PcDescriptorsDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2399,7 +2397,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id += 1) {
       const intptr_t length = d->ReadUnsigned();
       PcDescriptorsPtr desc = static_cast<PcDescriptorsPtr>(d->Ref(id));
@@ -2480,7 +2478,7 @@
   RODataDeserializationCluster() {}
   ~RODataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     intptr_t count = d->ReadUnsigned();
     uint32_t running_offset = 0;
     for (intptr_t i = 0; i < count; i++) {
@@ -2489,7 +2487,7 @@
     }
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     // No-op.
   }
 };
@@ -2550,7 +2548,7 @@
   ExceptionHandlersDeserializationCluster() {}
   ~ExceptionHandlersDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2562,7 +2560,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ExceptionHandlersPtr handlers =
           static_cast<ExceptionHandlersPtr>(d->Ref(id));
@@ -2638,7 +2636,7 @@
   ContextDeserializationCluster() {}
   ~ContextDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2650,7 +2648,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ContextPtr context = static_cast<ContextPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
@@ -2714,7 +2712,7 @@
   ContextScopeDeserializationCluster() {}
   ~ContextScopeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2726,7 +2724,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ContextScopePtr scope = static_cast<ContextScopePtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
@@ -2781,7 +2779,7 @@
   ParameterTypeCheckDeserializationCluster() {}
   ~ParameterTypeCheckDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2792,7 +2790,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ParameterTypeCheckPtr check =
           static_cast<ParameterTypeCheckPtr>(d->Ref(id));
@@ -2846,7 +2844,7 @@
   UnlinkedCallDeserializationCluster() {}
   ~UnlinkedCallDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2857,7 +2855,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       UnlinkedCallPtr unlinked = static_cast<UnlinkedCallPtr>(d->Ref(id));
       Deserializer::InitializeHeader(unlinked, kUnlinkedCallCid,
@@ -2914,7 +2912,7 @@
   ICDataDeserializationCluster() {}
   ~ICDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2924,7 +2922,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ICDataPtr ic = static_cast<ICDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(ic, kICDataCid, ICData::InstanceSize());
@@ -2978,7 +2976,7 @@
   MegamorphicCacheDeserializationCluster() {}
   ~MegamorphicCacheDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2989,7 +2987,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       MegamorphicCachePtr cache = static_cast<MegamorphicCachePtr>(d->Ref(id));
       Deserializer::InitializeHeader(cache, kMegamorphicCacheCid,
@@ -3000,7 +2998,7 @@
   }
 
 #if defined(DART_PRECOMPILED_RUNTIME)
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     if (FLAG_use_bare_instructions) {
       // By default, every megamorphic call site will load the target
       // [Function] from the hash table and call indirectly via loading the
@@ -3068,7 +3066,7 @@
   SubtypeTestCacheDeserializationCluster() {}
   ~SubtypeTestCacheDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3079,7 +3077,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       SubtypeTestCachePtr cache = static_cast<SubtypeTestCachePtr>(d->Ref(id));
       Deserializer::InitializeHeader(cache, kSubtypeTestCacheCid,
@@ -3131,7 +3129,7 @@
   LoadingUnitDeserializationCluster() {}
   ~LoadingUnitDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3142,7 +3140,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LoadingUnitPtr unit = static_cast<LoadingUnitPtr>(d->Ref(id));
       Deserializer::InitializeHeader(unit, kLoadingUnitCid,
@@ -3200,7 +3198,7 @@
   LanguageErrorDeserializationCluster() {}
   ~LanguageErrorDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3211,7 +3209,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LanguageErrorPtr error = static_cast<LanguageErrorPtr>(d->Ref(id));
       Deserializer::InitializeHeader(error, kLanguageErrorCid,
@@ -3266,7 +3264,7 @@
   UnhandledExceptionDeserializationCluster() {}
   ~UnhandledExceptionDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3277,7 +3275,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       UnhandledExceptionPtr exception =
           static_cast<UnhandledExceptionPtr>(d->Ref(id));
@@ -3349,13 +3347,14 @@
     intptr_t next_field_offset = host_next_field_offset_in_words_
                                  << kWordSizeLog2;
     const intptr_t count = objects_.length();
+    s->WriteUnsigned64(CalculateTargetUnboxedFieldsBitmap(s, cid_).Value());
     const auto unboxed_fields_bitmap =
         s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
             cid_);
+
     for (intptr_t i = 0; i < count; i++) {
       InstancePtr instance = objects_[i];
       AutoTraceObject(instance);
-      s->Write<bool>(instance->ptr()->IsCanonical());
       intptr_t offset = Instance::NextFieldOffset();
       while (offset < next_field_offset) {
         if (unboxed_fields_bitmap.Get(offset / kWordSize)) {
@@ -3389,7 +3388,7 @@
   explicit InstanceDeserializationCluster(intptr_t cid) : cid_(cid) {}
   ~InstanceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3403,17 +3402,14 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2;
     intptr_t instance_size =
         Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize);
+    const UnboxedFieldBitmap unboxed_fields_bitmap(d->ReadUnsigned64());
 
-    const auto unboxed_fields_bitmap =
-        d->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            cid_);
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       InstancePtr instance = static_cast<InstancePtr>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(instance, cid_, instance_size,
                                      is_canonical);
       intptr_t offset = Instance::NextFieldOffset();
@@ -3489,7 +3485,7 @@
   LibraryPrefixDeserializationCluster() {}
   ~LibraryPrefixDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3500,7 +3496,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LibraryPrefixPtr prefix = static_cast<LibraryPrefixPtr>(d->Ref(id));
       Deserializer::InitializeHeader(prefix, kLibraryPrefixCid,
@@ -3525,11 +3521,7 @@
 
   void Trace(Serializer* s, ObjectPtr object) {
     TypePtr type = Type::RawCast(object);
-    if (type->ptr()->IsCanonical()) {
-      canonical_objects_.Add(type);
-    } else {
-      objects_.Add(type);
-    }
+    objects_.Add(type);
 
     PushFromTo(type);
 
@@ -3546,13 +3538,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeCid);
-    intptr_t count = canonical_objects_.length();
-    s->WriteUnsigned(count);
-    for (intptr_t i = 0; i < count; i++) {
-      TypePtr type = canonical_objects_[i];
-      s->AssignRef(type);
-    }
-    count = objects_.length();
+    intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       TypePtr type = objects_[i];
@@ -3561,11 +3547,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = canonical_objects_.length();
-    for (intptr_t i = 0; i < count; i++) {
-      WriteType(s, canonical_objects_[i]);
-    }
-    count = objects_.length();
+    intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       WriteType(s, objects_[i]);
     }
@@ -3588,7 +3570,6 @@
     s->Write<uint8_t>(combined);
   }
 
-  GrowableArray<TypePtr> canonical_objects_;
   GrowableArray<TypePtr> objects_;
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
@@ -3598,78 +3579,55 @@
   TypeDeserializationCluster() {}
   ~TypeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
-    canonical_start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Type::InstanceSize()));
-    }
-    canonical_stop_index_ = d->next_index();
-
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
-    count = d->ReadUnsigned();
+    PageSpace* old_space = d->heap()->old_space();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Type::InstanceSize()));
     }
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
-    for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-         id++) {
-      TypePtr type = static_cast<TypePtr>(d->Ref(id));
-      ReadType(d, type, /*is_canonical=*/true);
-    }
-
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypePtr type = static_cast<TypePtr>(d->Ref(id));
-      ReadType(d, type, /*is_canonical=*/false);
+      Deserializer::InitializeHeader(type, kTypeCid, Type::InstanceSize(),
+                                     is_canonical);
+      ReadFromTo(type);
+      type->ptr()->token_pos_ = d->ReadTokenPosition();
+      const uint8_t combined = d->Read<uint8_t>();
+      type->ptr()->type_state_ = combined >> kNullabilityBitSize;
+      type->ptr()->nullability_ = combined & kNullabilityBitMask;
     }
   }
 
-  void PostLoadEarly(Deserializer* d, const Array& refs) {
-    if (d->isolate() == Dart::vm_isolate()) {
-      return;
-    }
-    CanonicalTypeSet table(d->zone(),
-                           d->isolate()->object_store()->canonical_types());
-    Type& type = Type::Handle(d->zone());
-    for (intptr_t i = canonical_start_index_; i < canonical_stop_index_; i++) {
-      type ^= refs.At(i);
-      if (type.IsCanonical()) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      CanonicalTypeSet table(d->zone(),
+                             d->isolate()->object_store()->canonical_types());
+      Type& type = Type::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        type ^= refs.At(i);
+        ASSERT(type.IsCanonical());
         bool present = table.Insert(type);
         // Two recursive types with different topology (and hashes) may be
         // equal.
         ASSERT(!present || type.IsRecursive());
       }
+      d->isolate()->object_store()->set_canonical_types(table.Release());
     }
-    d->isolate()->object_store()->set_canonical_types(table.Release());
-  }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
     Type& type = Type::Handle(d->zone());
     Code& stub = Code::Handle(d->zone());
 
     if (Snapshot::IncludesCode(d->kind())) {
-      for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-           id++) {
-        type ^= refs.At(id);
-        stub = type.type_test_stub();
-        type.SetTypeTestingStub(stub);  // Update type_test_stub_entry_point_
-      }
       for (intptr_t id = start_index_; id < stop_index_; id++) {
         type ^= refs.At(id);
         stub = type.type_test_stub();
         type.SetTypeTestingStub(stub);  // Update type_test_stub_entry_point_
       }
     } else {
-      for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-           id++) {
-        type ^= refs.At(id);
-        stub = TypeTestingStubGenerator::DefaultCodeForType(type);
-        type.SetTypeTestingStub(stub);
-      }
       for (intptr_t id = start_index_; id < stop_index_; id++) {
         type ^= refs.At(id);
         stub = TypeTestingStubGenerator::DefaultCodeForType(type);
@@ -3677,20 +3635,6 @@
       }
     }
   }
-
- private:
-  void ReadType(Deserializer* d, TypePtr type, bool is_canonical) {
-    Deserializer::InitializeHeader(type, kTypeCid, Type::InstanceSize(),
-                                   is_canonical);
-    ReadFromTo(type);
-    type->ptr()->token_pos_ = d->ReadTokenPosition();
-    const uint8_t combined = d->Read<uint8_t>();
-    type->ptr()->type_state_ = combined >> kNullabilityBitSize;
-    type->ptr()->nullability_ = combined & kNullabilityBitMask;
-  }
-
-  intptr_t canonical_start_index_;
-  intptr_t canonical_stop_index_;
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -3734,7 +3678,7 @@
   TypeRefDeserializationCluster() {}
   ~TypeRefDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3744,7 +3688,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypeRefPtr type = static_cast<TypeRefPtr>(d->Ref(id));
       Deserializer::InitializeHeader(type, kTypeRefCid,
@@ -3753,7 +3697,7 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     TypeRef& type_ref = TypeRef::Handle(d->zone());
     Code& stub = Code::Handle(d->zone());
 
@@ -3782,24 +3726,14 @@
 
   void Trace(Serializer* s, ObjectPtr object) {
     TypeParameterPtr type = TypeParameter::RawCast(object);
-    if (type->ptr()->IsCanonical()) {
-      canonical_objects_.Add(type);
-    } else {
-      objects_.Add(type);
-    }
+    objects_.Add(type);
 
     PushFromTo(type);
   }
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeParameterCid);
-    intptr_t count = canonical_objects_.length();
-    s->WriteUnsigned(count);
-    for (intptr_t i = 0; i < count; i++) {
-      TypeParameterPtr type = canonical_objects_[i];
-      s->AssignRef(type);
-    }
-    count = objects_.length();
+    intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       TypeParameterPtr type = objects_[i];
@@ -3808,11 +3742,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = canonical_objects_.length();
-    for (intptr_t i = 0; i < count; i++) {
-      WriteTypeParameter(s, canonical_objects_[i]);
-    }
-    count = objects_.length();
+    intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       WriteTypeParameter(s, objects_[i]);
     }
@@ -3837,7 +3767,6 @@
     s->Write<uint8_t>(combined);
   }
 
-  GrowableArray<TypeParameterPtr> canonical_objects_;
   GrowableArray<TypeParameterPtr> objects_;
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
@@ -3847,18 +3776,10 @@
   TypeParameterDeserializationCluster() {}
   ~TypeParameterDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
-    canonical_start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, TypeParameter::InstanceSize()));
-    }
-    canonical_stop_index_ = d->next_index();
-
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
-    count = d->ReadUnsigned();
+    PageSpace* old_space = d->heap()->old_space();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, TypeParameter::InstanceSize()));
@@ -3866,49 +3787,42 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
-    for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-         id++) {
-      TypeParameterPtr type = static_cast<TypeParameterPtr>(d->Ref(id));
-      ReadTypeParameter(d, type, /* is_canonical = */ true);
-    }
-
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypeParameterPtr type = static_cast<TypeParameterPtr>(d->Ref(id));
-      ReadTypeParameter(d, type, /* is_canonical = */ false);
+      Deserializer::InitializeHeader(
+          type, kTypeParameterCid, TypeParameter::InstanceSize(), is_canonical);
+      ReadFromTo(type);
+      type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
+      type->ptr()->token_pos_ = d->ReadTokenPosition();
+      type->ptr()->index_ = d->Read<int16_t>();
+      const uint8_t combined = d->Read<uint8_t>();
+      type->ptr()->flags_ = combined >> kNullabilityBitSize;
+      type->ptr()->nullability_ = combined & kNullabilityBitMask;
     }
   }
 
-  void PostLoadEarly(Deserializer* d, const Array& refs) {
-    if (d->isolate() == Dart::vm_isolate()) {
-      return;
-    }
-    CanonicalTypeParameterSet table(
-        d->zone(), d->isolate()->object_store()->canonical_type_parameters());
-    TypeParameter& type_param = TypeParameter::Handle(d->zone());
-    for (intptr_t i = canonical_start_index_; i < canonical_stop_index_; i++) {
-      type_param ^= refs.At(i);
-      if (type_param.IsCanonical() && !type_param.IsDeclaration()) {
-        bool present = table.Insert(type_param);
-        ASSERT(!present);
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      CanonicalTypeParameterSet table(
+          d->zone(), d->isolate()->object_store()->canonical_type_parameters());
+      TypeParameter& type_param = TypeParameter::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        type_param ^= refs.At(i);
+        ASSERT(type_param.IsCanonical());
+        if (!type_param.IsDeclaration()) {
+          bool present = table.Insert(type_param);
+          ASSERT(!present);
+        }
       }
+      d->isolate()->object_store()->set_canonical_type_parameters(
+          table.Release());
     }
-    d->isolate()->object_store()->set_canonical_type_parameters(
-        table.Release());
-  }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
     TypeParameter& type_param = TypeParameter::Handle(d->zone());
     Code& stub = Code::Handle(d->zone());
 
     if (Snapshot::IncludesCode(d->kind())) {
-      for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-           id++) {
-        type_param ^= refs.At(id);
-        stub = type_param.type_test_stub();
-        type_param.SetTypeTestingStub(
-            stub);  // Update type_test_stub_entry_point_
-      }
       for (intptr_t id = start_index_; id < stop_index_; id++) {
         type_param ^= refs.At(id);
         stub = type_param.type_test_stub();
@@ -3916,12 +3830,6 @@
             stub);  // Update type_test_stub_entry_point_
       }
     } else {
-      for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-           id++) {
-        type_param ^= refs.At(id);
-        stub = TypeTestingStubGenerator::DefaultCodeForType(type_param);
-        type_param.SetTypeTestingStub(stub);
-      }
       for (intptr_t id = start_index_; id < stop_index_; id++) {
         type_param ^= refs.At(id);
         stub = TypeTestingStubGenerator::DefaultCodeForType(type_param);
@@ -3929,24 +3837,6 @@
       }
     }
   }
-
- private:
-  void ReadTypeParameter(Deserializer* d,
-                         TypeParameterPtr type,
-                         bool is_canonical) {
-    Deserializer::InitializeHeader(type, kTypeParameterCid,
-                                   TypeParameter::InstanceSize(), is_canonical);
-    ReadFromTo(type);
-    type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
-    type->ptr()->token_pos_ = d->ReadTokenPosition();
-    type->ptr()->index_ = d->Read<int16_t>();
-    const uint8_t combined = d->Read<uint8_t>();
-    type->ptr()->flags_ = combined >> kNullabilityBitSize;
-    type->ptr()->nullability_ = combined & kNullabilityBitMask;
-  }
-
-  intptr_t canonical_start_index_;
-  intptr_t canonical_stop_index_;
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -3976,7 +3866,6 @@
     for (intptr_t i = 0; i < count; i++) {
       ClosurePtr closure = objects_[i];
       AutoTraceObject(closure);
-      s->Write<bool>(closure->ptr()->IsCanonical());
       WriteFromTo(closure);
     }
   }
@@ -3991,7 +3880,7 @@
   ClosureDeserializationCluster() {}
   ~ClosureDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4001,10 +3890,9 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ClosurePtr closure = static_cast<ClosurePtr>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(closure, kClosureCid,
                                      Closure::InstanceSize(), is_canonical);
       ReadFromTo(closure);
@@ -4036,14 +3924,12 @@
       SmiPtr smi = smis_[i];
       s->AssignRef(smi);
       AutoTraceObject(smi);
-      s->Write<bool>(true);
       s->Write<int64_t>(Smi::Value(smi));
     }
     for (intptr_t i = 0; i < mints_.length(); i++) {
       MintPtr mint = mints_[i];
       s->AssignRef(mint);
       AutoTraceObject(mint);
-      s->Write<bool>(mint->ptr()->IsCanonical());
       s->Write<int64_t>(mint->ptr()->value_);
     }
   }
@@ -4061,13 +3947,12 @@
   MintDeserializationCluster() {}
   ~MintDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     PageSpace* old_space = d->heap()->old_space();
 
     start_index_ = d->next_index();
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      bool is_canonical = d->Read<bool>();
       int64_t value = d->Read<int64_t>();
       if (Smi::IsValid(value)) {
         d->AssignRef(Smi::New(value));
@@ -4083,17 +3968,20 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {}
+  void ReadFill(Deserializer* d, bool is_canonical) {}
 
-  void PostLoad(Deserializer* d, const Array& refs) {
-    const Class& mint_cls = Class::Handle(
-        d->zone(), Isolate::Current()->object_store()->mint_class());
-    mint_cls.set_constants(Object::empty_array());
-    Object& number = Object::Handle(d->zone());
-    for (intptr_t i = start_index_; i < stop_index_; i++) {
-      number = refs.At(i);
-      if (number.IsMint() && number.IsCanonical()) {
-        mint_cls.InsertCanonicalMint(d->zone(), Mint::Cast(number));
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      const Class& mint_cls = Class::Handle(
+          d->zone(), Isolate::Current()->object_store()->mint_class());
+      mint_cls.set_constants(Object::empty_array());
+      Object& number = Object::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        number = refs.At(i);
+        if (number.IsMint()) {
+          ASSERT(number.IsCanonical());
+          mint_cls.InsertCanonicalMint(d->zone(), Mint::Cast(number));
+        }
       }
     }
   }
@@ -4125,7 +4013,6 @@
     for (intptr_t i = 0; i < count; i++) {
       DoublePtr dbl = objects_[i];
       AutoTraceObject(dbl);
-      s->Write<bool>(dbl->ptr()->IsCanonical());
       s->Write<double>(dbl->ptr()->value_);
     }
   }
@@ -4140,7 +4027,7 @@
   DoubleDeserializationCluster() {}
   ~DoubleDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4150,10 +4037,9 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       DoublePtr dbl = static_cast<DoublePtr>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(dbl, kDoubleCid, Double::InstanceSize(),
                                      is_canonical);
       dbl->ptr()->value_ = d->Read<double>();
@@ -4189,7 +4075,6 @@
     for (intptr_t i = 0; i < count; i++) {
       GrowableObjectArrayPtr array = objects_[i];
       AutoTraceObject(array);
-      s->Write<bool>(array->ptr()->IsCanonical());
       WriteFromTo(array);
     }
   }
@@ -4205,7 +4090,7 @@
   GrowableObjectArrayDeserializationCluster() {}
   ~GrowableObjectArrayDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4216,11 +4101,10 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       GrowableObjectArrayPtr list =
           static_cast<GrowableObjectArrayPtr>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(list, kGrowableObjectArrayCid,
                                      GrowableObjectArray::InstanceSize(),
                                      is_canonical);
@@ -4262,7 +4146,6 @@
       AutoTraceObject(data);
       const intptr_t length = Smi::Value(data->ptr()->length_);
       s->WriteUnsigned(length);
-      s->Write<bool>(data->ptr()->IsCanonical());
       uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
       s->WriteBytes(cdata, length * element_size);
     }
@@ -4279,7 +4162,7 @@
   explicit TypedDataDeserializationCluster(intptr_t cid) : cid_(cid) {}
   ~TypedDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4292,13 +4175,12 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypedDataPtr data = static_cast<TypedDataPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
-      bool is_canonical = d->Read<bool>();
       const intptr_t length_in_bytes = length * element_size;
       Deserializer::InitializeHeader(
           data, cid_, TypedData::InstanceSize(length_in_bytes), is_canonical);
@@ -4342,7 +4224,6 @@
     for (intptr_t i = 0; i < count; i++) {
       TypedDataViewPtr view = objects_[i];
       AutoTraceObject(view);
-      s->Write<bool>(view->ptr()->IsCanonical());
       WriteFromTo(view);
     }
   }
@@ -4358,7 +4239,7 @@
   explicit TypedDataViewDeserializationCluster(intptr_t cid) : cid_(cid) {}
   ~TypedDataViewDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4369,17 +4250,16 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id));
-      const bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(view, cid_, TypedDataView::InstanceSize(),
                                      is_canonical);
       ReadFromTo(view);
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     auto& view = TypedDataView::Handle(d->zone());
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       view ^= refs.At(id);
@@ -4401,7 +4281,6 @@
   void Trace(Serializer* s, ObjectPtr object) {
     ExternalTypedDataPtr data = ExternalTypedData::RawCast(object);
     objects_.Add(data);
-    ASSERT(!data->ptr()->IsCanonical());
   }
 
   void WriteAlloc(Serializer* s) {
@@ -4439,7 +4318,7 @@
   explicit ExternalTypedDataDeserializationCluster(intptr_t cid) : cid_(cid) {}
   ~ExternalTypedDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4450,7 +4329,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -4511,7 +4390,7 @@
   StackTraceDeserializationCluster() {}
   ~StackTraceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4522,7 +4401,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       StackTracePtr trace = static_cast<StackTracePtr>(d->Ref(id));
       Deserializer::InitializeHeader(trace, kStackTraceCid,
@@ -4576,7 +4455,7 @@
   RegExpDeserializationCluster() {}
   ~RegExpDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4586,7 +4465,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RegExpPtr regexp = static_cast<RegExpPtr>(d->Ref(id));
       Deserializer::InitializeHeader(regexp, kRegExpCid,
@@ -4640,7 +4519,7 @@
   WeakPropertyDeserializationCluster() {}
   ~WeakPropertyDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4651,7 +4530,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       WeakPropertyPtr property = static_cast<WeakPropertyPtr>(d->Ref(id));
       Deserializer::InitializeHeader(property, kWeakPropertyCid,
@@ -4701,7 +4580,6 @@
     for (intptr_t i = 0; i < count; i++) {
       LinkedHashMapPtr map = objects_[i];
       AutoTraceObject(map);
-      s->Write<bool>(map->ptr()->IsCanonical());
 
       WriteField(map, type_arguments_);
 
@@ -4735,7 +4613,7 @@
   LinkedHashMapDeserializationCluster() {}
   ~LinkedHashMapDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4746,12 +4624,11 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     PageSpace* old_space = d->heap()->old_space();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LinkedHashMapPtr map = static_cast<LinkedHashMapPtr>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(
           map, kLinkedHashMapCid, LinkedHashMap::InstanceSize(), is_canonical);
 
@@ -4823,7 +4700,6 @@
       AutoTraceObject(array);
       const intptr_t length = Smi::Value(array->ptr()->length_);
       s->WriteUnsigned(length);
-      s->Write<bool>(array->ptr()->IsCanonical());
       WriteField(array, type_arguments_);
       for (intptr_t j = 0; j < length; j++) {
         s->WriteElementRef(array->ptr()->data()[j], j);
@@ -4842,7 +4718,7 @@
   explicit ArrayDeserializationCluster(intptr_t cid) : cid_(cid) {}
   ~ArrayDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4854,11 +4730,10 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ArrayPtr array = static_cast<ArrayPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(array, cid_, Array::InstanceSize(length),
                                      is_canonical);
       array->ptr()->type_arguments_ =
@@ -4905,7 +4780,7 @@
       AutoTraceObject(str);
       const intptr_t length = Smi::Value(str->ptr()->length_);
       ASSERT(length <= compiler::target::kSmiMax);
-      s->WriteUnsigned((length << 1) | (str->ptr()->IsCanonical() ? 1 : 0));
+      s->WriteUnsigned(length);
       s->WriteBytes(str->ptr()->data(), length);
     }
   }
@@ -4920,7 +4795,7 @@
   OneByteStringDeserializationCluster() {}
   ~OneByteStringDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4932,12 +4807,10 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       OneByteStringPtr str = static_cast<OneByteStringPtr>(d->Ref(id));
-      const intptr_t combined = d->ReadUnsigned();
-      const intptr_t length = combined >> 1;
-      const bool is_canonical = (combined & 1) != 0;
+      const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(str, kOneByteStringCid,
                                      OneByteString::InstanceSize(length),
                                      is_canonical);
@@ -4952,21 +4825,19 @@
     }
   }
 
-  void PostLoadEarly(Deserializer* d, const Array& refs) {
-    if (d->isolate() == Dart::vm_isolate()) {
-      return;
-    }
-    CanonicalStringSet table(d->zone(),
-                             d->isolate()->object_store()->symbol_table());
-    String& str = String::Handle(d->zone());
-    for (intptr_t i = start_index_; i < stop_index_; i++) {
-      str ^= refs.At(i);
-      if (str.IsCanonical()) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      CanonicalStringSet table(d->zone(),
+                               d->isolate()->object_store()->symbol_table());
+      String& str = String::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        str ^= refs.At(i);
+        ASSERT(str.IsCanonical());
         bool present = table.Insert(str);
         ASSERT(!present);
       }
+      d->isolate()->object_store()->set_symbol_table(table.Release());
     }
-    d->isolate()->object_store()->set_symbol_table(table.Release());
   }
 };
 
@@ -5001,7 +4872,7 @@
       AutoTraceObject(str);
       const intptr_t length = Smi::Value(str->ptr()->length_);
       ASSERT(length <= (compiler::target::kSmiMax / 2));
-      s->WriteUnsigned((length << 1) | (str->ptr()->IsCanonical() ? 1 : 0));
+      s->WriteUnsigned(length);
       s->WriteBytes(reinterpret_cast<uint8_t*>(str->ptr()->data()), length * 2);
     }
   }
@@ -5016,7 +4887,7 @@
   TwoByteStringDeserializationCluster() {}
   ~TwoByteStringDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -5028,12 +4899,10 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TwoByteStringPtr str = static_cast<TwoByteStringPtr>(d->Ref(id));
-      const intptr_t combined = d->ReadUnsigned();
-      const intptr_t length = combined >> 1;
-      const bool is_canonical = (combined & 1) != 0;
+      const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(str, kTwoByteStringCid,
                                      TwoByteString::InstanceSize(length),
                                      is_canonical);
@@ -5049,21 +4918,19 @@
     }
   }
 
-  void PostLoadEarly(Deserializer* d, const Array& refs) {
-    if (d->isolate() == Dart::vm_isolate()) {
-      return;
-    }
-    CanonicalStringSet table(d->zone(),
-                             d->isolate()->object_store()->symbol_table());
-    String& str = String::Handle(d->zone());
-    for (intptr_t i = start_index_; i < stop_index_; i++) {
-      str ^= refs.At(i);
-      if (str.IsCanonical()) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      CanonicalStringSet table(d->zone(),
+                               d->isolate()->object_store()->symbol_table());
+      String& str = String::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        str ^= refs.At(i);
+        ASSERT(str.IsCanonical());
         bool present = table.Insert(str);
         ASSERT(!present);
       }
+      d->isolate()->object_store()->set_symbol_table(table.Release());
     }
-    d->isolate()->object_store()->set_symbol_table(table.Release());
   }
 };
 
@@ -5560,7 +5427,8 @@
       kind_(kind),
       stream_(stream),
       image_writer_(image_writer),
-      clusters_by_cid_(NULL),
+      canonical_clusters_by_cid_(nullptr),
+      clusters_by_cid_(nullptr),
       stack_(),
       num_cids_(0),
       num_tlc_cids_(0),
@@ -5583,9 +5451,13 @@
 {
   num_cids_ = thread->isolate()->class_table()->NumCids();
   num_tlc_cids_ = thread->isolate()->class_table()->NumTopLevelCids();
+  canonical_clusters_by_cid_ = new SerializationCluster*[num_cids_];
+  for (intptr_t i = 0; i < num_cids_; i++) {
+    canonical_clusters_by_cid_[i] = nullptr;
+  }
   clusters_by_cid_ = new SerializationCluster*[num_cids_];
   for (intptr_t i = 0; i < num_cids_; i++) {
-    clusters_by_cid_[i] = NULL;
+    clusters_by_cid_[i] = nullptr;
   }
   if (profile_writer_ != nullptr) {
     offsets_table_ = new (zone_) OffsetsTable(zone_);
@@ -5593,6 +5465,7 @@
 }
 
 Serializer::~Serializer() {
+  delete[] canonical_clusters_by_cid_;
   delete[] clusters_by_cid_;
 }
 
@@ -6032,23 +5905,31 @@
 
 void Serializer::Trace(ObjectPtr object) {
   intptr_t cid;
+  bool is_canonical;
   if (!object->IsHeapObject()) {
     // Smis are merged into the Mint cluster because Smis for the writer might
     // become Mints for the reader and vice versa.
     cid = kMintCid;
+    is_canonical = true;
   } else {
     cid = object->GetClassId();
+    is_canonical = object->ptr()->IsCanonical();
   }
 
-  SerializationCluster* cluster = clusters_by_cid_[cid];
-  if (cluster == NULL) {
+  SerializationCluster* cluster =
+      is_canonical ? canonical_clusters_by_cid_[cid] : clusters_by_cid_[cid];
+  if (cluster == nullptr) {
     cluster = NewClusterForClass(cid);
-    if (cluster == NULL) {
+    if (cluster == nullptr) {
       UnexpectedObject(object, "No serialization cluster defined");
     }
-    clusters_by_cid_[cid] = cluster;
+    if (is_canonical) {
+      canonical_clusters_by_cid_[cid] = cluster;
+    } else {
+      clusters_by_cid_[cid] = cluster;
+    }
   }
-  ASSERT(cluster != NULL);
+  ASSERT(cluster != nullptr);
 
 #if defined(SNAPSHOT_BACKTRACE)
   current_parent_ = object;
@@ -6129,11 +6010,16 @@
     Trace(stack_.RemoveLast());
   }
 
-  intptr_t num_clusters = 0;
-  for (intptr_t cid = 1; cid < num_cids_; cid++) {
-    SerializationCluster* cluster = clusters_by_cid_[cid];
-    if (cluster != NULL) {
-      num_clusters++;
+  GrowableArray<SerializationCluster*> canonical_clusters;
+  for (intptr_t cid = 0; cid < num_cids_; cid++) {
+    if (canonical_clusters_by_cid_[cid] != nullptr) {
+      canonical_clusters.Add(canonical_clusters_by_cid_[cid]);
+    }
+  }
+  GrowableArray<SerializationCluster*> clusters;
+  for (intptr_t cid = 0; cid < num_cids_; cid++) {
+    if (clusters_by_cid_[cid] != nullptr) {
+      clusters.Add(clusters_by_cid_[cid]);
     }
   }
 
@@ -6160,17 +6046,21 @@
 
   WriteUnsigned(num_base_objects_);
   WriteUnsigned(num_objects);
-  WriteUnsigned(num_clusters);
+  WriteUnsigned(canonical_clusters.length());
+  WriteUnsigned(clusters.length());
   WriteUnsigned(field_table_->NumFieldIds());
 
-  for (intptr_t cid = 1; cid < num_cids_; cid++) {
-    SerializationCluster* cluster = clusters_by_cid_[cid];
-    if (cluster != NULL) {
-      cluster->WriteAndMeasureAlloc(this);
+  for (SerializationCluster* cluster : canonical_clusters) {
+    cluster->WriteAndMeasureAlloc(this);
 #if defined(DEBUG)
-      Write<int32_t>(next_ref_index_);
+    Write<int32_t>(next_ref_index_);
 #endif
-    }
+  }
+  for (SerializationCluster* cluster : clusters) {
+    cluster->WriteAndMeasureAlloc(this);
+#if defined(DEBUG)
+    Write<int32_t>(next_ref_index_);
+#endif
   }
 
   // We should have assigned a ref to every object we pushed.
@@ -6192,14 +6082,17 @@
   }
 #endif
 
-  for (intptr_t cid = 1; cid < num_cids_; cid++) {
-    SerializationCluster* cluster = clusters_by_cid_[cid];
-    if (cluster != NULL) {
-      cluster->WriteAndMeasureFill(this);
+  for (SerializationCluster* cluster : canonical_clusters) {
+    cluster->WriteAndMeasureFill(this);
 #if defined(DEBUG)
-      Write<int32_t>(kSectionMarker);
+    Write<int32_t>(kSectionMarker);
 #endif
-    }
+  }
+  for (SerializationCluster* cluster : clusters) {
+    cluster->WriteAndMeasureFill(this);
+#if defined(DEBUG)
+    Write<int32_t>(kSectionMarker);
+#endif
   }
 
   roots->WriteRoots(this);
@@ -6437,21 +6330,23 @@
       zone_(thread->zone()),
       kind_(kind),
       stream_(buffer, size),
-      image_reader_(NULL),
+      image_reader_(nullptr),
       refs_(nullptr),
       next_ref_index_(kFirstReference),
       previous_text_offset_(0),
-      clusters_(NULL),
+      canonical_clusters_(nullptr),
+      clusters_(nullptr),
       field_table_(thread->isolate()->field_table()) {
   if (Snapshot::IncludesCode(kind)) {
-    ASSERT(instructions_buffer != NULL);
-    ASSERT(data_buffer != NULL);
+    ASSERT(instructions_buffer != nullptr);
+    ASSERT(data_buffer != nullptr);
     image_reader_ = new (zone_) ImageReader(data_buffer, instructions_buffer);
   }
   stream_.SetPosition(offset);
 }
 
 Deserializer::~Deserializer() {
+  delete[] canonical_clusters_;
   delete[] clusters_;
 }
 
@@ -6888,9 +6783,11 @@
   Array& refs = Array::Handle(zone_);
   num_base_objects_ = ReadUnsigned();
   num_objects_ = ReadUnsigned();
+  num_canonical_clusters_ = ReadUnsigned();
   num_clusters_ = ReadUnsigned();
   const intptr_t field_table_len = ReadUnsigned();
 
+  canonical_clusters_ = new DeserializationCluster*[num_canonical_clusters_];
   clusters_ = new DeserializationCluster*[num_clusters_];
   refs_ = Array::New(num_objects_ + kFirstReference, Heap::kOld);
   if (field_table_len > 0) {
@@ -6910,9 +6807,17 @@
              num_base_objects_, next_ref_index_ - kFirstReference);
     }
 
+    for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
+      canonical_clusters_[i] = ReadCluster();
+      canonical_clusters_[i]->ReadAlloc(this, /*is_canonical*/ true);
+#if defined(DEBUG)
+      intptr_t serializers_next_ref_index_ = Read<int32_t>();
+      ASSERT_EQUAL(serializers_next_ref_index_, next_ref_index_);
+#endif
+    }
     for (intptr_t i = 0; i < num_clusters_; i++) {
       clusters_[i] = ReadCluster();
-      clusters_[i]->ReadAlloc(this);
+      clusters_[i]->ReadAlloc(this, /*is_canonical*/ false);
 #if defined(DEBUG)
       intptr_t serializers_next_ref_index_ = Read<int32_t>();
       ASSERT_EQUAL(serializers_next_ref_index_, next_ref_index_);
@@ -6922,8 +6827,15 @@
     // We should have completely filled the ref array.
     ASSERT_EQUAL(next_ref_index_ - kFirstReference, num_objects_);
 
+    for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
+      canonical_clusters_[i]->ReadFill(this, /*is_canonical*/ true);
+#if defined(DEBUG)
+      int32_t section_marker = Read<int32_t>();
+      ASSERT(section_marker == kSectionMarker);
+#endif
+    }
     for (intptr_t i = 0; i < num_clusters_; i++) {
-      clusters_[i]->ReadFill(this);
+      clusters_[i]->ReadFill(this, /*is_canonical*/ false);
 #if defined(DEBUG)
       int32_t section_marker = Read<int32_t>();
       ASSERT(section_marker == kSectionMarker);
@@ -6955,12 +6867,12 @@
   // canonicalization first, canonicalize and update the ref array, the load
   // the remaining clusters to avoid a full heap walk to update references to
   // the losers of any canonicalization races.
-  for (intptr_t i = 0; i < num_clusters_; i++) {
-    clusters_[i]->PostLoadEarly(this, refs);
+  for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
+    canonical_clusters_[i]->PostLoad(this, refs, /*is_canonical*/ true);
   }
 
   for (intptr_t i = 0; i < num_clusters_; i++) {
-    clusters_[i]->PostLoad(this, refs);
+    clusters_[i]->PostLoad(this, refs, /*is_canonical*/ false);
   }
 }
 
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index 4188c75..ab079c8 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -109,15 +109,16 @@
 
   // Allocate memory for all objects in the cluster and write their addresses
   // into the ref array. Do not touch this memory.
-  virtual void ReadAlloc(Deserializer* deserializer) = 0;
+  virtual void ReadAlloc(Deserializer* deserializer, bool is_canonical) = 0;
 
   // Initialize the cluster's objects. Do not touch the memory of other objects.
-  virtual void ReadFill(Deserializer* deserializer) = 0;
+  virtual void ReadFill(Deserializer* deserializer, bool is_canonical) = 0;
 
   // Complete any action that requires the full graph to be deserialized, such
   // as rehashing.
-  virtual void PostLoadEarly(Deserializer* deserializer, const Array& refs) {}
-  virtual void PostLoad(Deserializer* deserializer, const Array& refs) {}
+  virtual void PostLoad(Deserializer* deserializer,
+                        const Array& refs,
+                        bool is_canonical) {}
 
  protected:
   // The range of the ref array that belongs to this cluster.
@@ -499,6 +500,7 @@
   Snapshot::Kind kind_;
   NonStreamingWriteStream* stream_;
   ImageWriter* image_writer_;
+  SerializationCluster** canonical_clusters_by_cid_;
   SerializationCluster** clusters_by_cid_;
   GrowableArray<ObjectPtr> stack_;
   intptr_t num_cids_;
@@ -724,10 +726,12 @@
   ImageReader* image_reader_;
   intptr_t num_base_objects_;
   intptr_t num_objects_;
+  intptr_t num_canonical_clusters_;
   intptr_t num_clusters_;
   ArrayPtr refs_;
   intptr_t next_ref_index_;
   intptr_t previous_text_offset_;
+  DeserializationCluster** canonical_clusters_;
   DeserializationCluster** clusters_;
   FieldTable* field_table_;
 };
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index 2f59b9d..376e39a 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -935,9 +935,11 @@
 
 bool _nullIs(Rti testRti) {
   int kind = Rti._getKind(testRti);
-  return isTopType(testRti) ||
+  return isStrongTopType(testRti) ||
+      isLegacyObjectType(testRti) ||
       _Utils.isIdentical(testRti, LEGACY_TYPE_REF<Never>()) ||
       kind == Rti.kindQuestion ||
+      kind == Rti.kindFutureOr && _nullIs(Rti._getFutureOrArgument(testRti)) ||
       isNullType(testRti);
 }
 
@@ -1068,7 +1070,7 @@
 /// Specialization for 'is Object'.
 /// Called from generated code via Rti `_is` method.
 bool _isObject(Object? object) {
-  return !JS_GET_FLAG('NNBD') || object != null;
+  return object != null;
 }
 
 /// Specialization for 'as Object'.
@@ -1890,9 +1892,7 @@
       } else if (baseKind == Rti.kindNever) {
         return _lookupFutureRti(universe, baseType);
       } else if (isNullType(baseType)) {
-        return JS_GET_FLAG('NNBD')
-            ? TYPE_REF<Future<Null>?>()
-            : TYPE_REF<Future<Null>>();
+        return TYPE_REF<Future<Null>?>();
       }
     }
     Rti rti = Rti.allocate();
diff --git a/tools/VERSION b/tools/VERSION
index 77e4c0e..e19e106 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 11
 PATCH 0
-PRERELEASE 160
+PRERELEASE 161
 PRERELEASE_PATCH 0
\ No newline at end of file