Version 2.14.0-367.0.dev

Merge commit 'f5a98e7676030e96f55263ff987c0acb39f5256f' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index aee53d3..b1dcdb8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -264,6 +264,16 @@
 [#46545]: https://github.com/dart-lang/sdk/issues/46545
 [1]: https://dart.dev/faq#q-what-browsers-do-you-support-as-javascript-compilation-targets
 
+#### Dart Dev Compiler (DDC)
+
+- **Breaking Change** [#44154][]: Subtyping relations of `package:js` classes
+  have been changed to be more correct and consistent with Dart2JS.
+  Like `anonymous` classes, non-`anonymous` classes will no longer check the
+  underlying type in DDC. The internal type representation of these objects have
+  changed as well, which will affect the `toString` value of these types.
+
+[#44154]: https://github.com/dart-lang/sdk/issues/44154
+
 ## 2.13.4 - 2021-06-28
 
 This is a patch release that fixes:
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 9d3ca36..126df97 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -91,10 +91,6 @@
   ImpactCacheDeleter get impactCacheDeleter => _impactCacheDeleter;
 
   final Environment environment;
-  // TODO(sigmund): delete once we migrate the rest of the compiler to use
-  // `environment` directly.
-  @deprecated
-  fromEnvironment(String name) => environment.valueOf(name);
 
   Entity get currentElement => _reporter.currentElement;
 
diff --git a/pkg/compiler/test/codegen/data_2/unused_empty_map.dart b/pkg/compiler/test/codegen/data_2/unused_empty_map.dart
index d9e0363..0ac9666 100644
--- a/pkg/compiler/test/codegen/data_2/unused_empty_map.dart
+++ b/pkg/compiler/test/codegen/data_2/unused_empty_map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// ignore_for_file: unused_local_variable
+
 @pragma('dart2js:noInline')
 // No code to construct unused map.
 /*member: foo1:function() {
diff --git a/pkg/compiler/test/deferred/load_graph_segmentation_test.dart b/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
index 823899f..161a92b 100644
--- a/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
+++ b/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
@@ -42,6 +42,7 @@
 
     var mainOutputUnit = closedWorld.outputUnitData.mainOutputUnit;
     var backendStrategy = compiler.backendStrategy;
+    // ignore: deprecated_member_use_from_same_package
     var classes = backendStrategy.emitterTask.neededClasses;
     var inputElement = classes.where((e) => e.name == 'InputElement').single;
     dynamic lib1 = lookupLibrary("memory:lib1.dart");
diff --git a/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart b/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
index 0058660..ba061e2 100644
--- a/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
+++ b/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
@@ -56,6 +56,7 @@
   @override
   void reportInfoMessage(Spannable node, MessageKind errorCode,
       [Map<String, String> arguments = const {}]) {
+    // ignore: deprecated_member_use_from_same_package
     reporter.reportInfoMessage(node, errorCode, arguments);
   }
 
diff --git a/pkg/compiler/test/end_to_end/library_env_test.dart b/pkg/compiler/test/end_to_end/library_env_test.dart
index ac96c89..f194f37 100644
--- a/pkg/compiler/test/end_to_end/library_env_test.dart
+++ b/pkg/compiler/test/end_to_end/library_env_test.dart
@@ -85,48 +85,57 @@
 }
 
 runTest() async {
-  var compiler = new CustomCompiler([], {});
+  {
+    final compiler = new CustomCompiler([], {});
 
-  await compiler.setupSdk();
+    await compiler.setupSdk();
+    final lookup = compiler.environment.valueOf;
 
-  // Core libraries are always present.
-  Expect.equals("true", compiler.fromEnvironment("dart.library.collection"));
-  // Non-existing entries in the environment return 'null'.
-  Expect.isNull(compiler.fromEnvironment("not in env"));
-  // Check for client libraries (default if there are no flags to the compiler).
-  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.client"));
-  Expect.equals("true", compiler.fromEnvironment("dart.library.html"));
-  // Check for shared libraries..
-  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.shared"));
-  // Check server libraries are not present.
-  Expect.equals(null, compiler.fromEnvironment("dart.library.mock.server"));
-  Expect.equals(null, compiler.fromEnvironment("dart.library.io"));
+    // Core libraries are always present.
+    Expect.equals("true", lookup("dart.library.collection"));
+    // Non-existing entries in the environment return 'null'.
+    Expect.isNull(lookup("not in env"));
+    // Check for client libraries (default if there are no flags to the compiler).
+    Expect.equals("true", lookup("dart.library.mock.client"));
+    Expect.equals("true", lookup("dart.library.html"));
+    // Check for shared libraries..
+    Expect.equals("true", lookup("dart.library.mock.shared"));
+    // Check server libraries are not present.
+    Expect.equals(null, lookup("dart.library.mock.server"));
+    Expect.equals(null, lookup("dart.library.io"));
+  }
+  {
+    final compiler = new CustomCompiler([Flags.serverMode], {});
 
-  compiler = new CustomCompiler([Flags.serverMode], {});
+    await compiler.setupSdk();
+    final lookup = compiler.environment.valueOf;
 
-  await compiler.setupSdk();
+    // Core libraries are always present.
+    Expect.equals("true", lookup("dart.library.collection"));
+    // Non-existing entries in the environment return 'null'.
+    Expect.isNull(lookup("not in env"));
+    // Check client libraries are not present.
+    Expect.equals(null, lookup("dart.library.mock.client"));
+    Expect.equals(null, lookup("dart.library.html"));
+    // Check for shared libraries..
+    Expect.equals("true", lookup("dart.library.mock.shared"));
+    // Check for server libraries.
+    Expect.equals("true", lookup("dart.library.mock.server"));
+    Expect.equals("true", lookup("dart.library.io"));
+  }
+  {
+    // Check that user-defined env-variables win.
+    final compiler = new CustomCompiler([], {
+      'dart.library.collection': "false",
+      'dart.library.mock.client': "foo"
+    });
 
-  // Core libraries are always present.
-  Expect.equals("true", compiler.fromEnvironment("dart.library.collection"));
-  // Non-existing entries in the environment return 'null'.
-  Expect.isNull(compiler.fromEnvironment("not in env"));
-  // Check client libraries are not present.
-  Expect.equals(null, compiler.fromEnvironment("dart.library.mock.client"));
-  Expect.equals(null, compiler.fromEnvironment("dart.library.html"));
-  // Check for shared libraries..
-  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.shared"));
-  // Check for server libraries.
-  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.server"));
-  Expect.equals("true", compiler.fromEnvironment("dart.library.io"));
+    await compiler.setupSdk();
+    final lookup = compiler.environment.valueOf;
 
-  // Check that user-defined env-variables win.
-  compiler = new CustomCompiler([],
-      {'dart.library.collection': "false", 'dart.library.mock.client': "foo"});
-
-  await compiler.setupSdk();
-
-  Expect.equals("false", compiler.fromEnvironment("dart.library.collection"));
-  Expect.equals("foo", compiler.fromEnvironment("dart.library.mock.client"));
+    Expect.equals("false", lookup("dart.library.collection"));
+    Expect.equals("foo", lookup("dart.library.mock.client"));
+  }
 }
 
 main() {
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index d6d428c..2de20df3 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -748,13 +748,17 @@
     for (var e in compiler.classIdentifiers.entries)
       e.key: identifierNames[e.value],
   };
+  var procedureJsNames = <Procedure, String>{
+    for (var e in compiler.procedureIdentifiers.entries)
+      e.key: identifierNames[e.value],
+  };
   var variableJsNames = <VariableDeclaration, String>{
     for (var e in compiler.variableIdentifiers.entries)
       e.key: identifierNames[e.value],
   };
 
-  return ModuleSymbolsCollector(
-          moduleName, classJsNames, compiler.memberNames, variableJsNames)
+  return ModuleSymbolsCollector(moduleName, classJsNames, compiler.memberNames,
+          procedureJsNames, variableJsNames)
       .collectSymbolInfo(component);
 }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index e1d06c4..e777ddf 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -61,6 +61,13 @@
   /// module.
   final memberNames = <Member, String>{};
 
+  /// Maps each `Procedure` node compiled in the module to the `Identifier`s
+  /// used to name the class in JavaScript.
+  ///
+  /// This mapping is used when generating the symbol information for the
+  /// module.
+  final procedureIdentifiers = <Procedure, js_ast.Identifier>{};
+
   /// Maps each `VariableDeclaration` node compiled in the module to the name
   /// used for the variable in JavaScript.
   ///
@@ -1670,7 +1677,7 @@
       ctorFields = ctor.initializers
           .map((c) => c is FieldInitializer ? c.field : null)
           .toSet()
-            ..remove(null);
+        ..remove(null);
     }
 
     var body = <js_ast.Statement>[];
@@ -2368,8 +2375,9 @@
       Class memberClass}) {
     // Static members skip the rename steps and may require JS interop renames.
     if (isStatic) {
-      // TODO(nshahan) Record the name for this member in memberNames.
-      return _emitStaticMemberName(name, member);
+      var memberName = _emitStaticMemberName(name, member);
+      memberNames[member] = memberName.valueWithoutQuotes;
+      return memberName;
     }
 
     // We allow some (illegal in Dart) member names to be used in our private
@@ -2379,6 +2387,7 @@
       var runtimeName = _jsExportName(member);
       if (runtimeName != null) {
         var parts = runtimeName.split('.');
+        // TODO(nshahan) Record the name for this member in memberNames.
         if (parts.length < 2) return propertyName(runtimeName);
 
         js_ast.Expression result = _emitIdentifier(parts[0]);
@@ -2652,8 +2661,9 @@
     _currentUri = node.fileUri;
 
     var name = node.name.text;
+    memberNames[node] = name;
     var result = js_ast.Method(
-        propertyName(name), _emitFunction(node.function, node.name.text),
+        propertyName(name), _emitFunction(node.function, name),
         isGetter: node.isGetter, isSetter: node.isSetter)
       ..sourceInformation = _nodeEnd(node.fileEndOffset);
 
@@ -2678,8 +2688,10 @@
 
     var nameExpr = _emitTopLevelName(p);
     var jsName = _safeFunctionNameForSafari(p.name.text, fn);
-    body.add(js.statement('# = #',
-        [nameExpr, js_ast.NamedFunction(_emitTemporaryId(jsName), fn)]));
+    var functionName = _emitTemporaryId(jsName);
+    procedureIdentifiers[p] = functionName;
+    body.add(js.statement(
+        '# = #', [nameExpr, js_ast.NamedFunction(functionName, fn)]));
 
     _currentUri = savedUri;
     _staticTypeContext.leaveMember(p);
@@ -2872,27 +2884,15 @@
     js_ast.Expression typeRep;
 
     // Type parameters don't matter as JS interop types cannot be reified.
-    // We have to use lazy JS types because until we have proper module
-    // loading for JS libraries bundled with Dart libraries, we will sometimes
-    // need to load Dart libraries before the corresponding JS libraries are
-    // actually loaded.
-    // Given a JS type such as:
-    //     @JS('google.maps.Location')
-    //     class Location { ... }
-    // We can't emit a reference to MyType because the JS library that defines
-    // it may be loaded after our code. So for now, we use a special lazy type
-    // object to represent MyType.
-    // Anonymous JS types do not have a corresponding concrete JS type so we
-    // have to use a helper to define them.
-    if (isJSAnonymousType(c)) {
-      typeRep = runtimeCall(
-          'anonymousJSType(#)', [js.escapedString(getLocalClassName(c))]);
-    } else {
-      var jsName = _emitJsNameWithoutGlobal(c);
-      if (jsName != null) {
-        typeRep = runtimeCall('lazyJSType(() => #, #)',
-            [_emitJSInteropForGlobal(jsName), js.escapedString(jsName)]);
-      }
+    // package:js types fall under either named or anonymous types. Named types
+    // are used to correspond to JS types that exist, but we do not use the
+    // underlying type for type checks, so they operate virtually the same as
+    // anonymous types. We represent package:js types with a corresponding type
+    // object.
+    var jsName = isJSAnonymousType(c) ?
+        getLocalClassName(c) : _emitJsNameWithoutGlobal(c);
+    if (jsName != null) {
+      typeRep = runtimeCall('packageJSType(#)', [js.escapedString(jsName)]);
     }
 
     if (typeRep != null) {
@@ -3605,7 +3605,7 @@
     }
 
     for (var p in f.positionalParameters) {
-      var jsParam = _emitVariableDef(p);
+      var jsParam = _emitVariableRef(p);
       if (_checkParameters) {
         initParameter(p, jsParam);
       }
@@ -4510,13 +4510,9 @@
     var name = v.name;
     if (name == null || name.startsWith('#')) {
       name = name == null ? 't${_tempVariables.length}' : name.substring(1);
-      // TODO(nshahan) Record the Identifier for this variable in
-      // variableIdentifiers.
       return _tempVariables.putIfAbsent(v, () => _emitTemporaryId(name));
     }
-    var identifier = _emitIdentifier(name);
-    variableIdentifiers[v] = identifier;
-    return identifier;
+    return _emitIdentifier(name);
   }
 
   /// Emits the declaration of a variable.
@@ -4524,7 +4520,9 @@
   /// This is similar to [_emitVariableRef] but it also attaches source
   /// location information, so hover will work as expected.
   js_ast.Identifier _emitVariableDef(VariableDeclaration v) {
-    return _emitVariableRef(v)..sourceInformation = _nodeStart(v);
+    var identifier = _emitVariableRef(v)..sourceInformation = _nodeStart(v);
+    variableIdentifiers[v] = identifier;
+    return identifier;
   }
 
   js_ast.Statement _initLetVariables() {
@@ -6403,8 +6401,9 @@
       Library library, String className, Member member,
       [js_ast.TemporaryId id]) {
     var name = '$className.${member.name.text}';
-    // Names used in the symbols for the public fields
-    // memberNames[member] = 'Symbol($name)';
+    // Wrap the name as a symbol here so it matches what you would find at
+    // runtime when you get all properties and symbols from an instance.
+    memberNames[member] = 'Symbol($name)';
     return emitPrivateNameSymbol(library, name, id);
   }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
index 2f16592..acb2bcd 100644
--- a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
+++ b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
@@ -14,13 +14,15 @@
   /// The first scope added to the stack should always be the library scope. The
   /// last element in the list represents the current scope.
   final _scopes = <ScopeSymbol>[];
+
   final ModuleSymbols _moduleSymbols;
   final Map<Class, String> _classJsNames;
   final Map<Member, String> _memberJsNames;
+  final Map<Procedure, String> _procedureJsNames;
   final Map<VariableDeclaration, String> _variableJsNames;
 
   ModuleSymbolsCollector(String moduleName, this._classJsNames,
-      this._memberJsNames, this._variableJsNames)
+      this._memberJsNames, this._procedureJsNames, this._variableJsNames)
       : _moduleSymbols = ModuleSymbols(
             version: ModuleSymbols.current.version,
             moduleName: moduleName,
@@ -28,7 +30,7 @@
             scripts: <Script>[],
             classes: <ClassSymbol>[],
             // TODO(nshahan) functionTypes
-            // TODO(nshahan) functions
+            functions: <FunctionSymbol>[],
             // TODO(nshahan) scopes
             variables: <VariableSymbol>[]);
 
@@ -142,8 +144,27 @@
     // Legacy libraries contain procedures with no bodies for all Object methods
     // in every class. We can ignore these unless they actually contain a body.
     if (node.function.body == null) return;
-    // TODO(nshahan) implement visitProcedure
-    super.visitProcedure(node);
+    var functionSymbol = FunctionSymbol(
+        name: node.name.text,
+        // TODO(nshahan) typeId - probably should canonicalize but keep original
+        // type argument names.
+        isStatic: node.isStatic,
+        isConst: node.isConst,
+        localId: _memberJsNames[node] ?? _procedureJsNames[node],
+        scopeId: _scopes.last.id,
+        variableIds: <String>[],
+        scopeIds: <String>[],
+        location: SourceLocation(
+            scriptId: _scriptId(node.location.file),
+            tokenPos: node.fileOffset,
+            endTokenPos: node.fileEndOffset));
+
+    _scopes.add(functionSymbol);
+    node.visitChildren(this);
+    _scopes
+      ..removeLast()
+      ..last.scopeIds.add(functionSymbol.id);
+    _moduleSymbols.functions.add(functionSymbol);
   }
 
   @override
diff --git a/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart b/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart
index ee907ce..c08995f 100644
--- a/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart
+++ b/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart
@@ -293,6 +293,394 @@
           expect(fieldSymbol.isStatic, isFalse);
         });
       });
+      group('class public instance method debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            String publicInstanceMethod() => 'Cello';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicInstanceMethod'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class private instance method debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            String _privateInstanceMethod() => 'Cello';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|Symbol(_privateInstanceMethod)'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class public static method debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            static String publicStaticMethod() => 'Cello';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicStaticMethod'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
+      group('class private static method debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            static String _privateStaticMethod() => 'Fosse';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|_privateStaticMethod'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
+      group('class public instance getter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            String get publicGetter() => 'Fosse';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicGetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class private instance getter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            String get _privateGetter() => 'Fosse';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|Symbol(_privateGetter)'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class public instance setter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            var _value
+            set publicSetter(String v) => _value = v;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicSetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class private instance setter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            var _value
+            set _privateSetter(String v) => _value = v;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|Symbol(_privateSetter)'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is not static', () async {
+          expect(methodSymbol.isStatic, isFalse);
+        });
+      });
+      group('class public static getter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            static String get publicGetter() => 'Fosse';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicGetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
+      group('class private static getter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            static String get _privateGetter() => 'Fosse';
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|_privateGetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
+      group('class public static setter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            var _value;
+            static set publicSetter(String v) => _value = v;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|publicSetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
+      group('class private static setter debug symbols', () {
+        TestDriver driver;
+        ClassSymbol classSymbol;
+        FunctionSymbol methodSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            var _value;
+            static set _privateSetter(String v) => _value = v;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          classSymbol = result.symbols.classes.single;
+          methodSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('functionId in classSymbol', () async {
+          expect(methodSymbol.id, endsWith('A|_privateSetter'));
+          expect(methodSymbol.id, classSymbol.functionIds.single);
+        });
+        test('has class scopeId', () async {
+          expect(methodSymbol.scopeId, endsWith('|A'));
+          expect(methodSymbol.scopeId, classSymbol.id);
+        });
+        test('is static', () async {
+          expect(methodSymbol.isStatic, isTrue);
+        });
+      });
     });
   }
 }
diff --git a/pkg/dev_compiler/test/module_symbols/function_symbols_test.dart b/pkg/dev_compiler/test/module_symbols/function_symbols_test.dart
new file mode 100644
index 0000000..f39f27b
--- /dev/null
+++ b/pkg/dev_compiler/test/module_symbols/function_symbols_test.dart
@@ -0,0 +1,326 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+import 'package:dev_compiler/src/kernel/module_symbols.dart';
+import 'package:test/test.dart';
+
+import '../shared_test_options.dart';
+import 'module_symbols_test_shared.dart';
+
+void main() async {
+  for (var mode in [
+    NullSafetyTestOption('Sound Mode:', true),
+    NullSafetyTestOption('Weak Mode:', false)
+  ]) {
+    group(mode.description, () {
+      var options = SetupCompilerOptions(soundNullSafety: mode.soundNullSafety);
+      group('top level function debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          void topLevelFunction() {
+            return;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          librarySymbol = result.symbols.libraries.single;
+          functionSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('has name', () async {
+          expect(functionSymbol.name, equals('topLevelFunction'));
+        });
+        // TODO(nshahan) Test for typeId.
+        test('is static', () async {
+          expect(functionSymbol.isStatic, isTrue);
+        });
+        test('is not const', () async {
+          expect(functionSymbol.isConst, isFalse);
+        });
+        test('has localId', () async {
+          expect(functionSymbol.localId, 'topLevelFunction');
+        });
+        test('has library scopeId', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+        test('no local variables', () async {
+          expect(functionSymbol.variableIds, isEmpty);
+        });
+        test('no scopes', () async {
+          expect(functionSymbol.scopeIds, isEmpty);
+        });
+        group('location', () {
+          test('has scriptId', () async {
+            expect(functionSymbol.location.scriptId, endsWith('/foo.dart'));
+          });
+          test('has start token', () async {
+            expect(functionSymbol.location.tokenPos,
+                27 + options.dartLangComment.length);
+          });
+          test('has end token', () async {
+            expect(functionSymbol.location.endTokenPos,
+                78 + options.dartLangComment.length);
+          });
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|topLevelFunction'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+      });
+      group('top level private function debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          void _topLevelFunction() {
+            return;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionSymbol = result.symbols.functions.single;
+          librarySymbol = result.symbols.libraries.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|_topLevelFunction'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+        test('scopeId is LibrarySymbol id', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+      });
+      group('top level public getter debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          String get topLevelGetter => 'Cello';
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionSymbol = result.symbols.functions.single;
+          librarySymbol = result.symbols.libraries.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|topLevelGetter'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+        test('scopeId is LibrarySymbol id', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+        test('is static', () async {
+          expect(functionSymbol.isStatic, isTrue);
+        });
+      });
+      group('top level private getter debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          String get _topLevelGetter => 'Cello';
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionSymbol = result.symbols.functions.single;
+          librarySymbol = result.symbols.libraries.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|_topLevelGetter'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+        test('scopeId is LibrarySymbol id', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+        test('is static', () async {
+          expect(functionSymbol.isStatic, isTrue);
+        });
+      });
+      group('top level public setter debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+          var _value;
+          set topLevelSetter(String v) => _value = v;
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionSymbol = result.symbols.functions.single;
+          librarySymbol = result.symbols.libraries.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|topLevelSetter'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+        test('scopeId is LibrarySymbol id', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+        test('is static', () async {
+          expect(functionSymbol.isStatic, isTrue);
+        });
+      });
+      group('top level private setter debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        LibrarySymbol librarySymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          var _value;
+          set _topLevelSetter(String v) => _value = v;
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionSymbol = result.symbols.functions.single;
+          librarySymbol = result.symbols.libraries.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('id in LibrarySymbol scopes', () async {
+          expect(functionSymbol.id, endsWith('foo.dart|_topLevelSetter'));
+          expect(functionSymbol.id, librarySymbol.scopeIds.single);
+        });
+        test('scopeId is LibrarySymbol id', () async {
+          expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+          expect(functionSymbol.scopeId, librarySymbol.id);
+        });
+        test('is static', () async {
+          expect(functionSymbol.isStatic, isTrue);
+        });
+      });
+      group('function arguments debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionWithPositionalArgSymbol;
+        FunctionSymbol functionWithOptionalArgSymbol;
+        FunctionSymbol functionWithNamedArgSymbol;
+        VariableSymbol xSymbol;
+        VariableSymbol ySymbol;
+        VariableSymbol zSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          class A {
+            const A();
+          }
+          const a = A();
+          void functionWithPositionalArg(A x) {}
+          void functionWithOptionalArg([A y = a]) {}
+          void functionWithNamedArg({A z = a}) {}
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          functionWithPositionalArgSymbol = result.symbols.functions
+              .singleWhere((f) => f.name == 'functionWithPositionalArg');
+          functionWithOptionalArgSymbol = result.symbols.functions
+              .singleWhere((f) => f.name == 'functionWithOptionalArg');
+          functionWithNamedArgSymbol = result.symbols.functions
+              .singleWhere((f) => f.name == 'functionWithNamedArg');
+          xSymbol = result.symbols.variables.singleWhere((v) => v.name == 'x');
+          ySymbol = result.symbols.variables.singleWhere((v) => v.name == 'y');
+          zSymbol = result.symbols.variables.singleWhere((v) => v.name == 'z');
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('function has a variable id for positional argument', () async {
+          var argumentId = functionWithPositionalArgSymbol.variableIds.single;
+          expect(argumentId, endsWith('|x'));
+          expect(argumentId, xSymbol.id);
+        });
+        test('positional argument symbol has a function scope', () async {
+          expect(xSymbol.scopeId, endsWith('|functionWithPositionalArg'));
+          expect(xSymbol.scopeId, functionWithPositionalArgSymbol.id);
+        });
+        test('function has a variable id for optional argument', () async {
+          var argumentId = functionWithOptionalArgSymbol.variableIds.single;
+          expect(argumentId, endsWith('|y'));
+          expect(argumentId, ySymbol.id);
+        });
+        test('optional argument symbol has a function scope', () async {
+          expect(ySymbol.scopeId, endsWith('|functionWithOptionalArg'));
+          expect(ySymbol.scopeId, functionWithOptionalArgSymbol.id);
+        });
+        test('function has a variable id for named argument', () async {
+          var argumentId = functionWithNamedArgSymbol.variableIds.single;
+          expect(argumentId, endsWith('|z'));
+          expect(argumentId, zSymbol.id);
+        });
+        test('named argument symbol has a function scope', () async {
+          expect(zSymbol.scopeId, endsWith('|functionWithNamedArg'));
+          expect(zSymbol.scopeId, functionWithNamedArgSymbol.id);
+        });
+      });
+      group('function local variable debug symbols', () {
+        TestDriver driver;
+        FunctionSymbol functionSymbol;
+        VariableSymbol variableSymbol;
+        final source = '''
+          ${options.dartLangComment}
+
+          int topLevelFunction() {
+            int i = 42;
+            return i;
+          }
+          ''';
+        setUpAll(() async {
+          driver = TestDriver(options, source);
+          var result = await driver.compile();
+          variableSymbol = result.symbols.variables.single;
+          functionSymbol = result.symbols.functions.single;
+        });
+        tearDownAll(() {
+          driver.cleanUp();
+        });
+        test('local variableId in FunctionSymbol', () async {
+          expect(variableSymbol.id, endsWith('|i'));
+          expect(variableSymbol.id, functionSymbol.variableIds.single);
+        });
+        test('scopeId is FunctionSymbol id', () async {
+          expect(variableSymbol.scopeId, endsWith('|topLevelFunction'));
+          expect(variableSymbol.scopeId, functionSymbol.id);
+        });
+      });
+    });
+  }
+}
diff --git a/pkg/vm/lib/metadata/call_site_attributes.dart b/pkg/vm/lib/metadata/call_site_attributes.dart
index 7ef8c93..23733d8 100644
--- a/pkg/vm/lib/metadata/call_site_attributes.dart
+++ b/pkg/vm/lib/metadata/call_site_attributes.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.metadata.call_site_attributes;
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/src/printer.dart';
 
diff --git a/pkg/vm/lib/transformations/call_site_annotator.dart b/pkg/vm/lib/transformations/call_site_annotator.dart
index 2416787..691ba84 100644
--- a/pkg/vm/lib/transformations/call_site_annotator.dart
+++ b/pkg/vm/lib/transformations/call_site_annotator.dart
@@ -2,14 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
 // This transformation annotates call sites with the receiver type.
 // This is done to avoid reimplementing [Expression.getStaticType] in
 // C++.
 // We don't annotate all call-sites, but only those where VM could benefit from
 // knowing static type of the receiver.
-library vm.transformations.call_site_annotator;
 
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index 93dc309..88edf51 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
 // This file contains logic which is shared between the ffi_definition and
 // ffi_use_site transformers.
 
diff --git a/pkg/vm/lib/transformations/ffi_native.dart b/pkg/vm/lib/transformations/ffi_native.dart
index 54bdcb6..e666652 100644
--- a/pkg/vm/lib/transformations/ffi_native.dart
+++ b/pkg/vm/lib/transformations/ffi_native.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/library_index.dart' show LibraryIndex;
 import 'package:kernel/reference_from_index.dart'
diff --git a/pkg/vm/lib/transformations/late_var_init_transformer.dart b/pkg/vm/lib/transformations/late_var_init_transformer.dart
index 7d245f1..48fd416 100644
--- a/pkg/vm/lib/transformations/late_var_init_transformer.dart
+++ b/pkg/vm/lib/transformations/late_var_init_transformer.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
 import 'package:kernel/ast.dart';
 
 /// Wraps the initializers of late local variables in closures.
diff --git a/pkg/vm/lib/transformations/mixin_deduplication.dart b/pkg/vm/lib/transformations/mixin_deduplication.dart
index ba65266..61f008b 100644
--- a/pkg/vm/lib/transformations/mixin_deduplication.dart
+++ b/pkg/vm/lib/transformations/mixin_deduplication.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.transformations.mixin_deduplication;
-
 import 'package:kernel/ast.dart';
 
 /// De-duplication of identical mixin applications.
diff --git a/pkg/vm/lib/transformations/specializer/factory_specializer.dart b/pkg/vm/lib/transformations/specializer/factory_specializer.dart
index 7475638..b86c3e6 100644
--- a/pkg/vm/lib/transformations/specializer/factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/factory_specializer.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.transformations.specializer.factory_specializer;
-
 import 'package:kernel/kernel.dart';
 import 'package:kernel/core_types.dart';
 import 'package:vm/transformations/specializer/list_factory_specializer.dart';
diff --git a/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart b/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
index 248c192..1a3f10f 100644
--- a/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.transformations.specializer.list_factory_specializer;
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:vm/transformations/specializer/factory_specializer.dart';
diff --git a/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart b/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart
index 8a01984..55f9d52 100644
--- a/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.transformations.specializer.map_factory_specializer;
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart';
 import 'dart:core';
diff --git a/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart b/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart
index a508435..2479e3d 100644
--- a/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
-library vm.transformations.specializer.set_factory_specializer;
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart' show CoreTypes;
 
diff --git a/pkg/vm/lib/transformations/unreachable_code_elimination.dart b/pkg/vm/lib/transformations/unreachable_code_elimination.dart
index 10bd958..d61b8f4 100644
--- a/pkg/vm/lib/transformations/unreachable_code_elimination.dart
+++ b/pkg/vm/lib/transformations/unreachable_code_elimination.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
 import 'package:kernel/ast.dart';
 
 /// Simple unreachable code elimination: removes asserts and if statements
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
index 507cb4b..0fee483 100644
--- a/pkg/vm/test/transformations/type_flow/transformer_test.dart
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -18,12 +18,11 @@
 
 final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
 
-runTestCase(
-    Uri source, List<String> experimentalFlags, bool enableNullSafety) async {
+runTestCase(Uri source, bool enableNullSafety) async {
   final target =
       new TestingVmTarget(new TargetFlags(enableNullSafety: enableNullSafety));
-  Component component = await compileTestCaseToKernelProgram(source,
-      target: target, experimentalFlags: experimentalFlags);
+  Component component =
+      await compileTestCaseToKernelProgram(source, target: target);
 
   final coreTypes = new CoreTypes(component);
 
@@ -74,12 +73,7 @@
           !path.endsWith('.pb.dart') &&
           (testNameFilter == null || path.contains(testNameFilter))) {
         final bool enableNullSafety = path.endsWith('_nnbd_strong.dart');
-        final bool enableNNBD = enableNullSafety || path.endsWith('_nnbd.dart');
-        final List<String> experimentalFlags = [
-          if (enableNNBD) 'non-nullable',
-        ];
-        test(path,
-            () => runTestCase(entry.uri, experimentalFlags, enableNullSafety));
+        test(path, () => runTestCase(entry.uri, enableNullSafety));
       }
     }
   }, timeout: Timeout.none);
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
index d4a77af..64dbb46 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
@@ -2,10 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 dynamic foo() => null;
-bool bar() => null;
+bool bar() => false;
 
 void bool_expressions() {
   if (foo()) {}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
index 5b8180a..85822829 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
@@ -3,26 +3,26 @@
 RESULT: _T {}?
 ------------ bar ------------
 
-RESULT: _T {}?
+RESULT: _T (dart.core::bool, false)
 ------------ bool_expressions ------------
 t0* = _Call direct [#lib::foo] ()
-t1 = _TypeCheck (t0 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
+t1 = _TypeCheck (t0 against dart.core::bool) (for #lib::foo() as dart.core::bool)
 t2* = _Call direct [#lib::bar] ()
 t3* = _Call [dart.core::num.+] (_T (dart.core::int)+, _T (dart.core::_Smi, 1))
-i_0 = _Join [dart.core::int*] (_T (dart.core::_Smi, 0), t3)
+i_0 = _Join [dart.core::int] (_T (dart.core::_Smi, 0), t3)
 t5* = _Call [dart.core::num.<] (i_0, _T (dart.core::_Smi, 10))
 t6* = _Call direct [#lib::bar] ()
-t7 = _TypeCheck (t6 against dart.core::bool*) (for x is dart.core::bool*)
+t7 = _TypeCheck (t6 against dart.core::bool) (for x is dart.core::bool)
 t8* = _Call direct [#lib::foo] ()
 t9 = _Join [dynamic] (_T (dart.core::bool, true), t8)
-t10 = _TypeCheck (t9 against dart.core::bool*) (for (x ?{dynamic} true : #lib::foo()) as dart.core::bool*)
+t10 = _TypeCheck (t9 against dart.core::bool) (for (x ?{dynamic} true : #lib::foo()) as dart.core::bool)
 t11* = _Call direct [#lib::bar] ()
 t12* = _Call direct [#lib::bar] ()
 t13* = _Call direct [#lib::foo] ()
-t14 = _TypeCheck (t13 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
+t14 = _TypeCheck (t13 against dart.core::bool) (for #lib::foo() as dart.core::bool)
 t15* = _Call direct [#lib::foo] ()
-t16 = _TypeCheck (t15 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
-y_0 = _Join [dart.core::bool*] (_T (dart.core::bool), _T (dart.core::bool, true))
+t16 = _TypeCheck (t15 against dart.core::bool) (for #lib::foo() as dart.core::bool)
+y_0 = _Join [dart.core::bool] (_T (dart.core::bool), _T (dart.core::bool, true))
 RESULT: _T {}?
 ------------ main ------------
 
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
index 1f4d7da..d507ee0 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 abstract class A {
   void foo1(Object x) {}
   dynamic get foo2;
@@ -13,19 +11,19 @@
 class B {
   void bar1(Object arg) {}
   dynamic get bar2 => null;
-  set bar3(int y) {}
-  int bar4;
+  set bar3(int? y) {}
+  int? bar4;
 }
 
 class C {
-  interfaceCalls(A aa, Object a2, Object a3, Object a4) {
+  interfaceCalls(A aa, Object a2, Object a3, Object? a4) {
     aa.foo1(new B());
     aa.foo3 = aa.foo2;
     a4 = aa.foo2(a2, a3, aa.foo1);
     return a4;
   }
 
-  dynamicCalls(dynamic aa, Object a2, Object a3, Object a4) {
+  dynamicCalls(dynamic aa, Object a2, Object a3, Object? a4) {
     aa.foo1(new B());
     aa.foo3 = aa.foo2;
     a4 = aa.foo2(a2, a3, aa.foo1);
@@ -34,7 +32,7 @@
 }
 
 class D extends B {
-  superCalls(Object a1, Object a2, Object a3, Object a4) {
+  superCalls(Object a1, Object a2, Object a3, Object? a4) {
     super.bar1(a1);
     super.bar3 = super.bar4;
     a4 = super.bar2(a2, a3, super.bar1);
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
index b9d7b32..2731094 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
@@ -38,7 +38,7 @@
 t6 = _Call [#lib::A.foo1] (%aa, t5)
 t7 = _Narrow (%aa to _T ANY)
 t8* = _Call get [#lib::A.foo2] (t7)
-t9 = _TypeCheck (t8 against dart.core::int*) (for aa.{#lib::A.foo2} as dart.core::int*)
+t9 = _TypeCheck (t8 against dart.core::int) (for aa.{#lib::A.foo2} as dart.core::int)
 t10 = _Call set [#lib::A.foo3] (t7, t9)
 t11* = _Call get [#lib::A.foo1] (t7)
 t12* = _Call get [#lib::A.foo2] (t7)
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart
index 1140e51..fe65bb4 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart
@@ -11,8 +11,6 @@
 // call, and we want to make sure there is only one call-site in this example
 // (call-site level info is not available yet).
 
-// @dart=2.9
-
 import 'dart:collection';
 
 class Element {}
@@ -32,10 +30,10 @@
 class InheritedElement extends Element {
   // The inferred type for '_dependents' needs to be concrete and have exact
   // type arguments.
-  final MockHashMap<Element, Object> _dependents =
-      MockHashMap<Element, Object>();
+  final MockHashMap<Element, Object?> _dependents =
+      MockHashMap<Element, Object?>();
 
-  void setDependencies(Element dependent, Object value) {
+  void setDependencies(Element dependent, Object? value) {
     _dependents.setEntry(dependent, value);
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
index ad64881..f833ff4 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
@@ -16,10 +16,10 @@
 %this = _Parameter #0 [_T (#lib::_NotRealHashMap)+]
 %key = _Parameter #1
 %value = _Parameter #2
-t3 = _Extract (%this[#lib::_NotRealHashMap/0]*)
-t4 = _TypeCheck (%key against t3) (for #lib::_NotRealHashMap.K* key;)
-t5 = _Extract (%this[#lib::_NotRealHashMap/1]*)
-t6 = _TypeCheck (%value against t5) (for #lib::_NotRealHashMap.V* value;)
+t3 = _Extract (%this[#lib::_NotRealHashMap/0])
+t4 = _TypeCheck (%key against t3) (for #lib::_NotRealHashMap.K% key;)
+t5 = _Extract (%this[#lib::_NotRealHashMap/1])
+t6 = _TypeCheck (%value against t5) (for #lib::_NotRealHashMap.V% value;)
 RESULT: _T {}?
 ------------ InheritedElement. ------------
 %this = _Parameter #0 [_T (#lib::InheritedElement)+]
@@ -34,7 +34,7 @@
 RESULT: _T {}?
 ------------ InheritedElement._dependents ------------
 %this = _Parameter #0 [_T (#lib::InheritedElement)+]
-t1* = _Call direct [#lib::MockHashMap.] (#lib::Element*, dart.core::Object*)
+t1* = _Call direct [#lib::MockHashMap.] (#lib::Element, dart.core::Object?)
 RESULT: t1
 ------------ main ------------
 t0* = _Call direct [#lib::InheritedElement.] (_T (#lib::InheritedElement))
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart
index 9526505..3757ca5 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart
@@ -2,14 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 class T {}
 
 empty1() {}
 void empty2() {}
 dynamic empty3() {} // ignore: missing_return
-Object empty4() {} // ignore: missing_return
+Object? empty4() {} // ignore: missing_return
 
 Object return1() {
   return new T();
@@ -186,7 +184,8 @@
   if (c) {
     return new T();
   }
-  try {} on ArgumentError {} finally {
+  try {} on ArgumentError {
+  } finally {
     throw 'Error!';
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
index b52da4f..4101ae0 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
@@ -2,15 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
-bool someStatic;
+late bool someStatic;
 
 class A {}
 
 class B {}
 
-Object foo(Object a1, [Object a2]) {
+Object? foo(Object a1, [Object? a2]) {
   if (someStatic) {
     a1 = new A();
   }
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
index b5c21e4..b559883 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
@@ -11,21 +11,21 @@
 %a2 = _Parameter #1 [_T (dart.core::Object)+?]
 t2* = _Call direct get [#lib::someStatic] ()
 t3* = _Call direct [#lib::A.] (_T (#lib::A))
-a1_0 = _Join [dart.core::Object*] (t3, %a1)
+a1_0 = _Join [dart.core::Object] (t3, %a1)
 t5 = _Call direct [#lib::bar] (a1_0, _T (dart.core::_Smi, 42))
 t6* = _Call direct [#lib::B.] (_T (#lib::B))
 t7* = _Call [dart.core::Object.==] (t6, %a2)
-t8 = _Join [dart.core::Object*] (t6, %a2)
+t8 = _Join [dart.core::Object?] (t6, %a2)
 t9 = _Narrow (t8 to _T (dart.core::Object)+?)
 RESULT: t9
 ------------ bar ------------
 %a1 = _Parameter #0 [_T (dart.core::Object)+?]
 %a2 = _Parameter #1 [_T (dart.core::int)+?]
-t2 = _TypeCheck (%a1 against dart.core::int*) (for v1 is dart.core::int*)
+t2 = _TypeCheck (%a1 against dart.core::int) (for v1 is dart.core::int)
 t3* = _Call [dart.core::num.+] (t2, %a2)
 t4* = _Call [dart.core::num.*] (t3, _T (dart.core::_Smi, 3))
 t5* = _Call [dart.core::int.unary-] (_T (dart.core::_Smi, 1))
-%result = _Join [dart.core::int*] (t4, t5)
+%result = _Join [dart.core::int] (t4, t5)
 RESULT: %result
 ------------ loop1 ------------
 %a1 = _Parameter #0 [_T (dart.core::Object)+?]
@@ -35,10 +35,10 @@
 ------------ loop2 ------------
 %x = _Parameter #0 [_T (dart.core::int)+?]
 t1* = _Call [dart.core::num.+] (_T (dart.core::int)+, _T (dart.core::_Smi, 1))
-i_0 = _Join [dart.core::int*] (_T (dart.core::_Smi, 0), t1)
+i_0 = _Join [dart.core::int] (_T (dart.core::_Smi, 0), t1)
 t3* = _Call [dart.core::num.<] (i_0, _T (dart.core::_Smi, 5))
 t4* = _Call [dart.core::num.+] (_T (dart.core::int)+?, _T (dart.core::_Smi, 10))
-x_0 = _Join [dart.core::int*] (%x, t4)
+x_0 = _Join [dart.core::int] (%x, t4)
 RESULT: x_0
 ------------ main ------------
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart
index cf61eb7..5fbfc30 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 class ClassAnnotation {
   const ClassAnnotation();
 }
@@ -47,7 +45,7 @@
 @TypedefAnnotation([1, 2, 3])
 typedef void SomeType<T>(List<T> arg);
 
-int foo(SomeType<int> a) {
+int foo(SomeType<int>? a) {
   @VarAnnotation()
   int x = 2;
   return x + 2;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
index 70239f8..a86774c 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
@@ -1,23 +1,23 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
-typedef SomeType<contravariant T extends core::Object* = dynamic> = (core::List<T*>*) →* void;
+typedef SomeType<contravariant T extends core::Object? = dynamic> = (core::List<T%>) → void;
 abstract class A extends core::Object {
   static method staticMethod() → void {}
 }
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method instanceMethod() → void {}
 }
-[@vm.unboxing-info.metadata=()->i]static method foo() → core::int* {
-  core::int* x = 2;
-  return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] x.{core::num::+}(2){(core::num*) →* core::int*};
+[@vm.unboxing-info.metadata=()->i]static method foo() → core::int {
+  core::int x = 2;
+  return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] x.{core::num::+}(2){(core::num) → core::int};
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   self::A::staticMethod();
-  [@vm.direct-call.metadata=#lib::B.instanceMethod] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::instanceMethod}(){() →* void};
+  [@vm.direct-call.metadata=#lib::B.instanceMethod] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::instanceMethod}(){() → void};
   self::foo();
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart
index 121201d..b331cb8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart
@@ -2,16 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 import 'dart:collection';
 
 class Element {}
 
 class InheritedElement extends Element {
-  final Map<Element, Object> _dependents = <Element, Object>{};
+  final Map<Element, Object?> _dependents = <Element, Object?>{};
 
-  void setDependencies(Element dependent, Object value) {
+  void setDependencies(Element dependent, Object? value) {
     _dependents[dependent] = value;
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect
index ca4d73c..4a919d4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect
@@ -1,25 +1,25 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 import "dart:collection";
 
 class Element extends core::Object {
-  synthetic constructor •() → self::Element*
+  synthetic constructor •() → self::Element
     : super core::Object::•()
     ;
 }
 class InheritedElement extends self::Element {
-[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element*, dart.core::Object*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::Map<self::Element*, core::Object*>* _dependents;
-  synthetic constructor •() → self::InheritedElement*
-    : self::InheritedElement::_dependents = <self::Element*, core::Object*>{}, super self::Element::•()
+[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element, dart.core::Object?>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::Map<self::Element, core::Object?> _dependents;
+  synthetic constructor •() → self::InheritedElement
+    : self::InheritedElement::_dependents = <self::Element, core::Object?>{}, super self::Element::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method setDependencies([@vm.inferred-type.metadata=!] self::Element* dependent, [@vm.inferred-type.metadata=dart.core::_Smi?] core::Object* value) → void {
-    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<#lib::Element*, dart.core::Object*>*] [@vm.direct-call.metadata=dart.collection::__InternalLinkedHashMap&_HashVMBase&MapMixin&_LinkedHashMapMixin.[]=] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::InheritedElement._dependents] [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element*, dart.core::Object*>] this.{self::InheritedElement::_dependents}{core::Map<self::Element*, core::Object*>*}.{core::Map::[]=}(dependent, value){(self::Element*, core::Object*) →* void};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method setDependencies([@vm.inferred-type.metadata=!] self::Element dependent, [@vm.inferred-type.metadata=dart.core::_Smi?] core::Object? value) → void {
+    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<#lib::Element, dart.core::Object?>] [@vm.direct-call.metadata=dart.collection::__InternalLinkedHashMap&_HashVMBase&MapMixin&_LinkedHashMapMixin.[]=] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::InheritedElement._dependents] [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element, dart.core::Object?>] this.{self::InheritedElement::_dependents}{core::Map<self::Element, core::Object?>}.{core::Map::[]=}(dependent, value){(self::Element, core::Object?) → void};
   }
 }
 static method main() → dynamic {
-  self::InheritedElement* ie = new self::InheritedElement::•();
-  [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(ie, 0){(self::Element*, core::Object*) →* void};
-  [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(new self::Element::•(), null){(self::Element*, core::Object*) →* void};
+  self::InheritedElement ie = new self::InheritedElement::•();
+  [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(ie, 0){(self::Element, core::Object?) → void};
+  [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(new self::Element::•(), null){(self::Element, core::Object?) → void};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
index 8356b38..4025830 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 abstract class A {
   int foo();
 }
@@ -30,7 +28,7 @@
   aa.foo();
 }
 
-void callerA3({A aa}) {
+void callerA3({required A aa}) {
   aa.foo();
 }
 
@@ -46,7 +44,7 @@
   x.toString();
 }
 
-A dd;
+late A dd;
 E ee = new E();
 
 main(List<String> args) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
index ebf2078..67ffa52 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
@@ -1,65 +1,65 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
     return 1;
 }
 class C extends core::Object implements self::A {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
     return 2;
 }
 class D extends self::C {
-  synthetic constructor •() → self::D*
+  synthetic constructor •() → self::D
     : super self::C::•()
     ;
 }
 class E extends core::Object {
-  synthetic constructor •() → self::E*
+  synthetic constructor •() → self::E
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method toString() → core::String*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method toString() → core::String
     return "D";
 }
-[@vm.inferred-type.metadata=#lib::D?]static field self::A* dd;
-[@vm.inferred-type.metadata=#lib::E?]static field self::E* ee = new self::E::•();
-static method callerA1([@vm.inferred-type.metadata=!] self::A* aa) → void {
-  [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+[@vm.inferred-type.metadata=#lib::D]late static field self::A dd;
+[@vm.inferred-type.metadata=#lib::E?]static field self::E ee = new self::E::•();
+static method callerA1([@vm.inferred-type.metadata=!] self::A aa) → void {
+  [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
 }
-static method callerA2([@vm.inferred-type.metadata=#lib::B] self::A* aa) → void {
-  [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+static method callerA2([@vm.inferred-type.metadata=#lib::B] self::A aa) → void {
+  [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
 }
-static method callerA3([@vm.inferred-type.metadata=#lib::C] self::A* aa) → void {
-  [@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+static method callerA3([@vm.inferred-type.metadata=#lib::C] self::A aa) → void {
+  [@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
 }
-static method callerA4([@vm.inferred-type.metadata=#lib::D?] self::A* aa) → void {
-  [@vm.direct-call.metadata=#lib::C.foo??] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+static method callerA4([@vm.inferred-type.metadata=#lib::D] self::A aa) → void {
+  [@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
 }
 static method callerE1() → void {
-  [@vm.direct-call.metadata=dart.core::_StringBase.toString] [@vm.inferred-type.metadata=!? (skip check) (receiver not int)](#C1).{core::Object::toString}(){() →* core::String*};
+  [@vm.direct-call.metadata=dart.core::_StringBase.toString] [@vm.inferred-type.metadata=!? (skip check) (receiver not int)](#C1).{core::Object::toString}(){() → core::String};
 }
 static method callerE2([@vm.inferred-type.metadata=#lib::E?] dynamic x) → void {
-  [@vm.inferred-type.metadata=!? (receiver not int)] x.{core::Object::toString}(){() →* core::String*};
+  [@vm.inferred-type.metadata=!? (receiver not int)] x.{core::Object::toString}(){() → core::String};
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   self::callerA1(new self::B::•());
   self::callerA1(new self::C::•());
   self::callerA2(new self::B::•());
-  let final self::C* #t1 = new self::C::•() in self::callerA3(#t1);
-  self::callerA4([@vm.inferred-type.metadata=#lib::D?] self::dd);
+  let final self::C #t1 = new self::C::•() in self::callerA3(#t1);
+  self::callerA4([@vm.inferred-type.metadata=#lib::D] self::dd);
   self::dd = new self::D::•();
   self::callerE1();
   self::callerE2([@vm.inferred-type.metadata=#lib::E?] self::ee);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart
index bd09bf6..5b75823 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart
@@ -1,6 +1,8 @@
-// @dart=2.9
+// 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.
 
 main() {
-  dynamic x = List<int>.filled(10, null);
+  dynamic x = List<int?>.filled(10, null);
   x[0] + 10;
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect
index 17a558f..5fa7916 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect
@@ -1,8 +1,8 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 static method main() → dynamic {
-  dynamic x = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] core::_List::•<core::int*>(10);
+  dynamic x = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(10);
   [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.direct-call.metadata=dart.core::_List.[]] [@vm.inferred-type.metadata=int? (receiver not int)] x{dynamic}.[](0){dynamic}.+(10);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart
index cfe006d..9cfd697 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart
@@ -2,71 +2,69 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 import 'dart:ffi';
 
 /// Retained because of being by-value return type in FFI call.
 class Struct1 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Retained because of being by-value return type in FFI call.
 class Struct2 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Retained because of being by-value argument type in FFI callback.
 class Struct3 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Class not retained, not referenced at all.
 class Struct4 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Constructor not retained, only referenced as argument type in FFI
 /// call but never instantiated in Dart code.
 class Struct5 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Constructor not retained, only referenced as argument type in FFI
 /// call but never instantiated in Dart code.
 class Struct6 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Constructor not retained, only referenced as return value type in FFI
 /// callback but never instantiated in Dart code.
 class Struct7 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Not retained because of FFI call not being reachable.
 class Struct8 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Not retained because of FFI call not being reachable.
 class Struct9 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Not tetained because of FFI callback not being reachable.
 class Struct10 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 /// Retained by CFE rewrite of load from pointer.
 class Struct11 extends Struct {
-  Struct12 nested;
+  external Struct12 nested;
 }
 
 /// Retained by rewrite of load from surrounding struct.
 class Struct12 extends Struct {
-  Pointer notEmpty;
+  external Pointer notEmpty;
 }
 
 void main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
index f360e5e..9086aa75 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:ffi" as ffi;
@@ -39,11 +39,11 @@
   constructor #fromTypedDataBase([@vm.inferred-type.metadata=dart.ffi::Pointer] core::Object #typedDataBase) → self::Struct11
     : super ffi::Struct::_fromTypedDataBase(#typedDataBase)
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get nested() → self::Struct12*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get nested() → self::Struct12
     return new self::Struct12::#fromTypedDataBase( block {
       core::Object #typedDataBase = [@vm.direct-call.metadata=dart.ffi::_Compound._typedDataBase] this.{ffi::_Compound::_typedDataBase}{core::Object};
       core::int #offset = (#C12).{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
-    } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_fromAddress<self::Struct12*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.direct-call.metadata=dart.ffi::Pointer.address] [@vm.inferred-type.metadata=int?] #typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in [@vm.direct-call.metadata=dart.typed_data::_ByteBuffer.asUint8List] [@vm.inferred-type.metadata=dart.typed_data::_Uint8ArrayView (skip check)] [@vm.inferred-type.metadata=dart.typed_data::_ByteBuffer] #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=dart.core::_Smi] #typedData.{typ::TypedData::offsetInBytes}{core::int}.{core::num::+}(#offset){(core::num) → core::num}, (#C15).{core::List::[]}(ffi::_abi()){(core::int) → core::int*}){([core::int, core::int?]) → typ::Uint8List});
+    } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_fromAddress<self::Struct12>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.direct-call.metadata=dart.ffi::Pointer.address] [@vm.inferred-type.metadata=int?] #typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in [@vm.direct-call.metadata=dart.typed_data::_ByteBuffer.asUint8List] [@vm.inferred-type.metadata=dart.typed_data::_Uint8ArrayView (skip check)] [@vm.inferred-type.metadata=dart.typed_data::_ByteBuffer] #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=dart.core::_Smi] #typedData.{typ::TypedData::offsetInBytes}{core::int}.{core::num::+}(#offset){(core::num) → core::num}, (#C15).{core::List::[]}(ffi::_abi()){(core::int) → core::int*}){([core::int, core::int?]) → typ::Uint8List});
 }
 @#C6
 class Struct12 extends ffi::Struct {
@@ -51,8 +51,8 @@
     : super ffi::Struct::_fromTypedDataBase(#typedDataBase)
     ;
 }
-[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<(self::Struct3*) →* ffi::Int32*>*>* _#ffiCallback0 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<(self::Struct3*) →* ffi::Int32*>*>(ffi::_nativeCallbackFunction<(self::Struct3*) →* ffi::Int32*>(#C16, 0));
-[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<() →* self::Struct7*>*>* _#ffiCallback1 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<() →* self::Struct7*>*>(ffi::_nativeCallbackFunction<() →* self::Struct7*>(#C17, null));
+[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<(self::Struct3) → ffi::Int32>*>* _#ffiCallback0 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<(self::Struct3) → ffi::Int32>*>(ffi::_nativeCallbackFunction<(self::Struct3) → ffi::Int32>(#C16, 0))/*isLegacy*/;
+[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<() → self::Struct7>*>* _#ffiCallback1 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<() → self::Struct7>*>(ffi::_nativeCallbackFunction<() → self::Struct7>(#C17, null))/*isLegacy*/;
 static method main() → void {
   self::testLookupFunctionReturn();
   self::testLookupFunctionArgument();
@@ -64,56 +64,56 @@
   self::testNestedLoad();
 }
 static method testLookupFunctionReturn() → void {
-  final ffi::DynamicLibrary* dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
-  final () →* self::Struct1* function1 = block {
+  final ffi::DynamicLibrary dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
+  final () → self::Struct1 function1 = block {
     _in::_nativeEffect(new self::Struct1::#fromTypedDataBase([@vm.inferred-type.metadata=dart.typed_data::_Uint8List] typ::Uint8List::•(#C18)));
-  } =>ffi::_asFunctionInternal<() →* self::Struct1*, () →* self::Struct1*>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<() →* self::Struct1*>*>("function1"){(core::String) → ffi::Pointer<ffi::NativeFunction<() →* self::Struct1*>*>}, false);
-  final self::Struct1* struct1 = function1(){() →* self::Struct1*};
+  } =>ffi::_asFunctionInternal<() → self::Struct1, () → self::Struct1>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<() → self::Struct1>*>("function1"){(core::String) → ffi::Pointer<ffi::NativeFunction<() → self::Struct1>*>}, false);
+  final self::Struct1 struct1 = function1(){() → self::Struct1};
   core::print(struct1);
 }
 static method testAsFunctionReturn() → void {
-  final ffi::Pointer<ffi::NativeFunction<() →* self::Struct2*>*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<() →* self::Struct2*>*>(3735928559);
-  final () →* self::Struct2* function2 = block {
+  final ffi::Pointer<ffi::NativeFunction<() → self::Struct2>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<() → self::Struct2>>(3735928559);
+  final () → self::Struct2 function2 = block {
     _in::_nativeEffect(new self::Struct2::#fromTypedDataBase([@vm.inferred-type.metadata=dart.typed_data::_Uint8List] typ::Uint8List::•(#C18)));
-  } =>ffi::_asFunctionInternal<() →* self::Struct2*, () →* self::Struct2*>(pointer, false);
-  final self::Struct2* struct2 = function2(){() →* self::Struct2*};
+  } =>ffi::_asFunctionInternal<() → self::Struct2, () → self::Struct2>(pointer, false);
+  final self::Struct2 struct2 = function2(){() → self::Struct2};
   core::print(struct2);
 }
-[@vm.unboxing-info.metadata=(b)->i]static method useStruct3(self::Struct3* struct3) → core::int* {
+[@vm.unboxing-info.metadata=(b)->i]static method useStruct3(self::Struct3 struct3) → core::int {
   return 42;
 }
 static method testFromFunctionArgument() → void {
-  final ffi::Pointer<ffi::NativeFunction<(self::Struct3*) →* ffi::Int32*>*>* pointer = block {
+  final ffi::Pointer<ffi::NativeFunction<(self::Struct3) → ffi::Int32>> pointer = block {
     _in::_nativeEffect(new self::Struct3::#fromTypedDataBase([@vm.inferred-type.metadata=dart.typed_data::_Uint8List] typ::Uint8List::•(#C18)));
   } =>[@vm.inferred-type.metadata=dart.ffi::Pointer?] self::_#ffiCallback0;
   core::print(pointer);
 }
 static method testLookupFunctionArgument() → void {
-  final ffi::DynamicLibrary* dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
-  final (self::Struct5*) →* void function5 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct5*) →* void, (self::Struct5*) →* ffi::Void*>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<(self::Struct5*) →* ffi::Void*>*>("function5"){(core::String) → ffi::Pointer<ffi::NativeFunction<(self::Struct5*) →* ffi::Void*>*>}, false);
+  final ffi::DynamicLibrary dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
+  final (self::Struct5) → void function5 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct5) → void, (self::Struct5) → ffi::Void>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<(self::Struct5) → ffi::Void>*>("function5"){(core::String) → ffi::Pointer<ffi::NativeFunction<(self::Struct5) → ffi::Void>*>}, false);
   core::print(function5);
 }
 static method testAsFunctionArgument() → void {
-  final ffi::Pointer<ffi::NativeFunction<(self::Struct6*) →* ffi::Void*>*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<(self::Struct6*) →* ffi::Void*>*>(3735928559);
-  final (self::Struct6*) →* void function6 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct6*) →* void, (self::Struct6*) →* ffi::Void*>(pointer, false);
+  final ffi::Pointer<ffi::NativeFunction<(self::Struct6) → ffi::Void>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<(self::Struct6) → ffi::Void>>(3735928559);
+  final (self::Struct6) → void function6 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct6) → void, (self::Struct6) → ffi::Void>(pointer, false);
   core::print(function6);
 }
-static method returnStruct7() → self::Struct7* {
+static method returnStruct7() → self::Struct7 {
   throw "I don't want to create a Struct7!";
 }
 static method testFromFunctionReturn() → void {
-  final ffi::Pointer<ffi::NativeFunction<() →* self::Struct7*>*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] self::_#ffiCallback1;
+  final ffi::Pointer<ffi::NativeFunction<() → self::Struct7>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] self::_#ffiCallback1;
   core::print(pointer);
 }
 static method testPointerLoad() → void {
-  final ffi::Pointer<self::Struct11*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11*>(3735928559);
-  final self::Struct11* struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
+  final ffi::Pointer<self::Struct11> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11>(3735928559);
+  final self::Struct11 struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
   core::print(struct11);
 }
 static method testNestedLoad() → void {
-  final ffi::Pointer<self::Struct11*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11*>(3735928559);
-  final self::Struct11* struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
-  final self::Struct12* struct12 = [@vm.direct-call.metadata=#lib::Struct11.nested] [@vm.inferred-type.metadata=#lib::Struct12] struct11.{self::Struct11::nested}{self::Struct12*};
+  final ffi::Pointer<self::Struct11> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11>(3735928559);
+  final self::Struct11 struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
+  final self::Struct12 struct12 = [@vm.direct-call.metadata=#lib::Struct11.nested] [@vm.inferred-type.metadata=#lib::Struct12] struct11.{self::Struct11::nested}{self::Struct12};
   core::print(struct12);
 }
 constants  {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
index 03e65ae..f2136d5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 import 'dart:async';
 
 dynamic usedObject;
@@ -55,14 +53,14 @@
   use(x);
 }
 
-void foo2(Future<A> a1, A a2, FutureOr<A> a3, FutureOr<A> a4) {
+void foo2(Future<A>? a1, A? a2, FutureOr<A>? a3, FutureOr<A>? a4) {
   foo2_a1(a1);
   foo2_a2(a2);
   foo2_a3(a3);
   foo2_a4(a4);
 }
 
-Function unknown;
+late Function unknown;
 getDynamic() => unknown.call();
 
 main(List<String> args) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
index 4c9cbc4..c9b4c9f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
@@ -6,33 +6,33 @@
 import "dart:async";
 
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
 }
 static field dynamic usedObject;
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
-static method foo1_a1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] dynamic x) → void {
+static method foo1_a1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] dynamic x) → void {
   self::use(x);
 }
 static method foo1_a2([@vm.inferred-type.metadata=#lib::B] dynamic x) → void {
   self::use(x);
 }
-static method foo1_a3([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] dynamic x) → void {
+static method foo1_a3([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] dynamic x) → void {
   self::use(x);
 }
 static method foo1_a4([@vm.inferred-type.metadata=#lib::B] dynamic x) → void {
   self::use(x);
 }
-static method foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] asy::Future<self::A*>* a1, [@vm.inferred-type.metadata=#lib::B] self::A* a2, [@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] FutureOr<self::A*>* a3, [@vm.inferred-type.metadata=#lib::B] FutureOr<self::A*>* a4) → void {
+static method foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future<self::A> a1, [@vm.inferred-type.metadata=#lib::B] self::A a2, [@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] FutureOr<self::A>a3, [@vm.inferred-type.metadata=#lib::B] FutureOr<self::A>a4) → void {
   self::foo1_a1(a1);
   self::foo1_a2(a2);
   self::foo1_a3(a3);
@@ -50,7 +50,7 @@
 static method foo2_a4(dynamic x) → void {
   self::use(x);
 }
-static method foo2([@vm.inferred-type.metadata=dart.async::_Future?] asy::Future<self::A*>* a1, [@vm.inferred-type.metadata=#lib::B?] self::A* a2, FutureOr<self::A*>* a3, FutureOr<self::A*>* a4) → void {
+static method foo2([@vm.inferred-type.metadata=dart.async::_Future?] asy::Future<self::A>? a1, [@vm.inferred-type.metadata=#lib::B?] self::A? a2, FutureOr<self::A>? a3, FutureOr<self::A>? a4) → void {
   self::foo2_a1(a1);
   self::foo2_a2(a2);
   self::foo2_a3(a3);
@@ -58,7 +58,7 @@
 }
 static method getDynamic() → dynamic
   return self::unknown();
-static method main(core::List<core::String*>* args) → dynamic {
-  self::foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] asy::Future::value<self::B*>(new self::B::•()), new self::B::•(), [@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] asy::Future::value<self::B*>(new self::B::•()), new self::B::•());
-  self::foo2(self::getDynamic() as{TypeError,ForDynamic} asy::Future<self::A*>*, self::getDynamic() as{TypeError,ForDynamic} self::A*, self::getDynamic() as{TypeError,ForDynamic} FutureOr<self::A*>*, self::getDynamic() as{TypeError,ForDynamic} FutureOr<self::A*>*);
+static method main(core::List<core::String> args) → dynamic {
+  self::foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future::value<self::B>(new self::B::•()), new self::B::•(), [@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future::value<self::B>(new self::B::•()), new self::B::•());
+  self::foo2(self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::A>?, self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A?, self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<self::A>?, self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<self::A>?);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart
index bb66a2b..67c62c8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart
@@ -4,8 +4,6 @@
 
 // Test for tree shaking of instance fields with initializers.
 
-// @dart = 2.12
-
 int sideEffect(int x) {
   print(x);
   return x;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart
index 7420b2c..fccae87 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart
@@ -11,8 +11,6 @@
 //   self-induced invalidations.
 //
 
-// @dart=2.9
-
 class StreamSubscription {}
 
 class _BufferingStreamSubscription extends StreamSubscription {}
@@ -20,11 +18,11 @@
 class _BroadcastSubscription extends StreamSubscription {}
 
 abstract class Stream {
-  StreamSubscription foobar(void onData(event), {Function onError});
+  StreamSubscription foobar(void onData(event)?, {Function? onError});
 }
 
 abstract class _StreamImpl extends Stream {
-  StreamSubscription foobar(void onData(data), {Function onError}) {
+  StreamSubscription foobar(void onData(data)?, {Function? onError}) {
     return _createSubscription();
   }
 
@@ -46,7 +44,7 @@
 
   StreamView(Stream stream) : _stream = stream;
 
-  StreamSubscription foobar(void onData(value), {Function onError}) {
+  StreamSubscription foobar(void onData(value)?, {Function? onError}) {
     return _stream.foobar(onData, onError: onError);
   }
 }
@@ -54,15 +52,15 @@
 class ByteStream extends StreamView {
   ByteStream(Stream stream) : super(stream);
 
-  super_foobar1(void onData(value)) {
+  super_foobar1(void onData(value)?) {
     super.foobar(onData);
   }
 
-  super_foobar2(void onData(value)) {
+  super_foobar2(void onData(value)?) {
     super.foobar(onData);
   }
 
-  super_foobar3({void onData(value), Function onError}) {
+  super_foobar3({void onData(value)?, Function? onError}) {
     super.foobar(onData, onError: onError);
   }
 
@@ -70,7 +68,7 @@
 }
 
 class _HandleErrorStream extends Stream {
-  StreamSubscription foobar(void onData(event), {Function onError}) {
+  StreamSubscription foobar(void onData(event)?, {Function? onError}) {
     return new _BufferingStreamSubscription();
   }
 }
@@ -79,26 +77,26 @@
   new ByteStream(new ByteStream(new _GeneratedStreamImpl()));
 }
 
-void round1({void onData(value)}) {
+void round1({void onData(value)?}) {
   var x = new ByteStream(new ByteStream(new _GeneratedStreamImpl()));
   x.super_foobar1(onData);
 }
 
-void round2({void onData(value), Function onError}) {
+void round2({void onData(value)?, Function? onError}) {
   new _ControllerStream();
   Stream x = new _GeneratedStreamImpl();
   x = new ByteStream(x);
   x.foobar(onData, onError: onError);
 }
 
-void round3({void onData(value), Function onError}) {
+void round3({void onData(value)?, Function? onError}) {
   Stream x = new _GeneratedStreamImpl();
   x = new ByteStream(x);
   x = new _ControllerStream();
   x.foobar(onData, onError: onError);
 }
 
-void round4({void onData(value)}) {
+void round4({void onData(value)?}) {
   var x = new ByteStream(new _ControllerStream());
   var y = x.super_stream;
   var z = x._stream;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
index 4b18c73..4771de1 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
@@ -1,80 +1,79 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class StreamSubscription extends core::Object {
-  synthetic constructor •() → self::StreamSubscription*
+  synthetic constructor •() → self::StreamSubscription
     : super core::Object::•()
     ;
 }
 class _BufferingStreamSubscription extends self::StreamSubscription {
-  synthetic constructor •() → self::_BufferingStreamSubscription*
+  synthetic constructor •() → self::_BufferingStreamSubscription
     : super self::StreamSubscription::•()
     ;
 }
 class _BroadcastSubscription extends self::StreamSubscription {
-  synthetic constructor •() → self::_BroadcastSubscription*
+  synthetic constructor •() → self::_BroadcastSubscription
     : super self::StreamSubscription::•()
     ;
 }
 abstract class Stream extends core::Object {
-  synthetic constructor •() → self::Stream*
+  synthetic constructor •() → self::Stream
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foobar() → self::StreamSubscription*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3]  abstract operator ==(dynamic other) → core::bool*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foobar() → self::StreamSubscription;
 }
 abstract class _StreamImpl extends self::Stream {
-  synthetic constructor •() → self::_StreamImpl*
+  synthetic constructor •() → self::_StreamImpl
     : super self::Stream::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foobar() → self::StreamSubscription* {
-    return [@vm.inferred-type.metadata=! (skip check)] this.{self::_StreamImpl::_createSubscription}(){() →* self::StreamSubscription*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foobar() → self::StreamSubscription {
+    return [@vm.inferred-type.metadata=! (skip check)] this.{self::_StreamImpl::_createSubscription}(){() → self::StreamSubscription};
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  method _createSubscription() → self::StreamSubscription* {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method _createSubscription() → self::StreamSubscription {
     return new self::_BufferingStreamSubscription::•();
   }
 }
 class _ControllerStream extends self::_StreamImpl {
-  synthetic constructor •() → self::_ControllerStream*
+  synthetic constructor •() → self::_ControllerStream
     : super self::_StreamImpl::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  method _createSubscription() → self::StreamSubscription* {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method _createSubscription() → self::StreamSubscription {
     return new self::_BroadcastSubscription::•();
   }
 }
 class _GeneratedStreamImpl extends self::_StreamImpl {
-  synthetic constructor •() → self::_GeneratedStreamImpl*
+  synthetic constructor •() → self::_GeneratedStreamImpl
     : super self::_StreamImpl::•()
     ;
 }
 abstract class StreamView extends self::Stream {
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6]  final field self::Stream* _stream;
-  constructor •([@vm.inferred-type.metadata=!] self::Stream* stream) → self::StreamView*
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  final field self::Stream _stream;
+  constructor •([@vm.inferred-type.metadata=!] self::Stream stream) → self::StreamView
     : self::StreamView::_stream = stream, super self::Stream::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foobar() → self::StreamSubscription* {
-    return [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] this.{self::StreamView::_stream}{self::Stream*}.{self::Stream::foobar}(){((dynamic) →* void, {onError: core::Function*}) →* self::StreamSubscription*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foobar() → self::StreamSubscription {
+    return [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] this.{self::StreamView::_stream}{self::Stream}.{self::Stream::foobar}(){((dynamic) →? void, {onError: core::Function?}) → self::StreamSubscription};
   }
 }
 class ByteStream extends self::StreamView {
-  constructor •([@vm.inferred-type.metadata=!] self::Stream* stream) → self::ByteStream*
+  constructor •([@vm.inferred-type.metadata=!] self::Stream stream) → self::ByteStream
     : super self::StreamView::•(stream)
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method super_foobar1() → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method super_foobar1() → dynamic {
     super.{self::StreamView::foobar}();
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method super_foobar2() → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9]  method super_foobar2() → dynamic {
     super.{self::StreamView::foobar}();
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method super_foobar3() → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10,getterSelectorId:11]  method super_foobar3() → dynamic {
     super.{self::StreamView::foobar}();
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:13]  get super_stream() → self::Stream*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:12]  get super_stream() → self::Stream
     return [@vm.inferred-type.metadata=!] super.{self::StreamView::_stream};
 }
 class _HandleErrorStream extends self::Stream {
-  synthetic constructor •() → self::_HandleErrorStream*
+  synthetic constructor •() → self::_HandleErrorStream
     : super self::Stream::•()
     ;
 }
@@ -82,35 +81,35 @@
   new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
 }
 static method round1() → void {
-  self::ByteStream* x = new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
-  [@vm.direct-call.metadata=#lib::ByteStream.super_foobar1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar1}(){((dynamic) →* void) →* dynamic};
+  self::ByteStream x = new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
+  [@vm.direct-call.metadata=#lib::ByteStream.super_foobar1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar1}(){((dynamic) →? void) → dynamic};
 }
 static method round2() → void {
   new self::_ControllerStream::•();
-  self::Stream* x = new self::_GeneratedStreamImpl::•();
+  self::Stream x = new self::_GeneratedStreamImpl::•();
   x = new self::ByteStream::•(x);
-  [@vm.direct-call.metadata=#lib::StreamView.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →* void, {onError: core::Function*}) →* self::StreamSubscription*};
+  [@vm.direct-call.metadata=#lib::StreamView.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →? void, {onError: core::Function?}) → self::StreamSubscription};
 }
 static method round3() → void {
-  self::Stream* x = new self::_GeneratedStreamImpl::•();
+  self::Stream x = new self::_GeneratedStreamImpl::•();
   x = new self::ByteStream::•(x);
   x = new self::_ControllerStream::•();
-  [@vm.direct-call.metadata=#lib::_StreamImpl.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →* void, {onError: core::Function*}) →* self::StreamSubscription*};
+  [@vm.direct-call.metadata=#lib::_StreamImpl.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →? void, {onError: core::Function?}) → self::StreamSubscription};
 }
 static method round4() → void {
-  self::ByteStream* x = new self::ByteStream::•(new self::_ControllerStream::•());
-  self::Stream* y = [@vm.direct-call.metadata=#lib::ByteStream.super_stream] [@vm.inferred-type.metadata=!] x.{self::ByteStream::super_stream}{self::Stream*};
-  self::Stream* z = [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] x.{self::StreamView::_stream}{self::Stream*};
-  if([@vm.direct-call.metadata=dart.core::Object.==] [@vm.inferred-type.metadata=dart.core::bool (skip check) (receiver not int)] y =={self::Stream::==}{(dynamic) →* core::bool*} z) {
-    [@vm.direct-call.metadata=#lib::ByteStream.super_foobar2] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar2}(){((dynamic) →* void) →* dynamic};
+  self::ByteStream x = new self::ByteStream::•(new self::_ControllerStream::•());
+  self::Stream y = [@vm.direct-call.metadata=#lib::ByteStream.super_stream] [@vm.inferred-type.metadata=!] x.{self::ByteStream::super_stream}{self::Stream};
+  self::Stream z = [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] x.{self::StreamView::_stream}{self::Stream};
+  if([@vm.direct-call.metadata=dart.core::Object.==] [@vm.inferred-type.metadata=dart.core::bool (skip check) (receiver not int)] y =={core::Object::==}{(core::Object) → core::bool} z) {
+    [@vm.direct-call.metadata=#lib::ByteStream.super_foobar2] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar2}(){((dynamic) →? void) → dynamic};
   }
 }
 static method round5() → void {
-  self::ByteStream* x = new self::ByteStream::•(new self::_GeneratedStreamImpl::•());
+  self::ByteStream x = new self::ByteStream::•(new self::_GeneratedStreamImpl::•());
   new self::_HandleErrorStream::•();
-  [@vm.direct-call.metadata=#lib::ByteStream.super_foobar3] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar3}(){({onData: (dynamic) →* void, onError: core::Function*}) →* dynamic};
+  [@vm.direct-call.metadata=#lib::ByteStream.super_foobar3] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar3}(){({onData: (dynamic) →? void, onError: core::Function?}) → dynamic};
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   new self::_GeneratedStreamImpl::•();
   self::round0();
   self::round1();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart
index b0ca102..01188a6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 class T1 {}
 
 class T2 {}
@@ -20,7 +18,7 @@
   Object foo() => new T2();
 }
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
index 43bee1f..1723808 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
@@ -1,82 +1,82 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 abstract class A extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → core::Object*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → core::Object;
 }
 class B extends core::Object implements self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → core::Object*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → core::Object
     return new self::T1::•();
 }
 class C extends core::Object implements self::A {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → core::Object*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → core::Object
     return new self::T2::•();
 }
 class DeepCaller1 extends core::Object {
-  synthetic constructor •() → self::DeepCaller1*
+  synthetic constructor •() → self::DeepCaller1
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method barL1() → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL2}(){() →* dynamic};
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL2}(){() → dynamic};
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method barL2() → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL3}(){() →* dynamic};
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL3}(){() → dynamic};
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method barL3() → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL4}(){() →* dynamic};
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL4}(){() → dynamic};
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method barL4() → dynamic
     return self::field1;
 }
 class D extends core::Object {
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  field core::Object* field2;
-  synthetic constructor •() → self::D*
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  field core::Object field2;
+  synthetic constructor •() → self::D
     : self::D::field2 = [@vm.inferred-type.metadata=!] self::getValue(), super core::Object::•()
     ;
 }
 class DeepCaller2 extends core::Object {
-  synthetic constructor •() → self::DeepCaller2*
+  synthetic constructor •() → self::DeepCaller2
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL1([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(dd){(self::D*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL2([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(dd){(self::D*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL3([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(dd){(self::D*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method barL4([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
-    return [@vm.direct-call.metadata=#lib::D.field2] [@vm.inferred-type.metadata=!] dd.{self::D::field2}{core::Object*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL1([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(dd){(self::D) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL2([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(dd){(self::D) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL3([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(dd){(self::D) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method barL4([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+    return [@vm.direct-call.metadata=#lib::D.field2] [@vm.inferred-type.metadata=!] dd.{self::D::field2}{core::Object};
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static field core::Object* field1 = [@vm.inferred-type.metadata=!] self::getValue();
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static field core::Object field1 = [@vm.inferred-type.metadata=!] self::getValue();
 static method getDynamic() → dynamic
   return self::unknown();
-static method getValue() → core::Object* {
-  self::A* aa = self::getDynamic() as{TypeError,ForDynamic} self::A*;
-  return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() →* core::Object*};
+static method getValue() → core::Object {
+  self::A aa = self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A;
+  return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() → core::Object};
 }
-static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1* x) → dynamic
-  return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::DeepCaller1::barL1}(){() →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2* x) → dynamic
-  return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(new self::D::•()){(self::D*) →* dynamic};
+static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1 x) → dynamic
+  return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::DeepCaller1::barL1}(){() → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2 x) → dynamic
+  return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(new self::D::•()){(self::D) → dynamic};
 static method createC() → dynamic {
   new self::C::•();
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   new self::B::•();
   self::use1(new self::DeepCaller1::•());
   self::use2(new self::DeepCaller2::•());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
index 844a585..0bc4332 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 class T1 {}
 
 class T2 {}
@@ -27,7 +25,7 @@
 use1(Intermediate i, A aa) => i.bar(aa);
 use2(Intermediate i, A aa) => i.bar(aa);
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
index 750a33e..e916e0c 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
@@ -1,44 +1,44 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → dynamic;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
     return new self::T1::•();
 }
 class Intermediate extends core::Object {
-  synthetic constructor •() → self::Intermediate*
+  synthetic constructor •() → self::Intermediate
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar([@vm.inferred-type.metadata=#lib::B?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] aa.{self::A::foo}(){() →* dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar([@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] aa.{self::A::foo}(){() → dynamic};
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, [@vm.inferred-type.metadata=#lib::B?] self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, [@vm.inferred-type.metadata=#lib::B?] self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
 static method getDynamic() → dynamic
   return self::unknown();
 static method allocateB() → dynamic {
   new self::B::•();
 }
-static method main(core::List<core::String*>* args) → dynamic {
-  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+static method main(core::List<core::String> args) → dynamic {
+  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
   self::allocateB();
-  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
index d7a751a..ca439fa 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 class T1 {}
 
 class T2 {}
@@ -32,7 +30,7 @@
 use2(Intermediate i, A aa) => i.bar(aa);
 use3(Intermediate i, A aa) => i.bar(aa);
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
index 50f57c2..dc456ee 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
@@ -1,25 +1,25 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → dynamic;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
@@ -28,36 +28,36 @@
 abstract class C extends core::Object implements self::B {
 }
 abstract class D extends core::Object {
-  synthetic constructor •() → self::D*
+  synthetic constructor •() → self::D
     : super core::Object::•()
     ;
 }
 abstract class _E&D&C extends self::D implements self::C /*isAnonymousMixin,isEliminatedMixin*/  {
-  synthetic constructor •() → self::_E&D&C*
+  synthetic constructor •() → self::_E&D&C
     : super self::D::•()
     ;
 }
 class E extends self::_E&D&C {
-  synthetic constructor •() → self::E*
+  synthetic constructor •() → self::E
     : super self::_E&D&C::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
     return new self::T2::•();
 }
 class Intermediate extends core::Object {
-  synthetic constructor •() → self::Intermediate*
+  synthetic constructor •() → self::Intermediate
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar(self::A* aa) → dynamic
-    return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() →* dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method bar(self::A aa) → dynamic
+    return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() → dynamic};
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
-static method use3([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use3([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
 static method getDynamic() → dynamic
   return self::unknown();
 static method allocateB() → dynamic {
@@ -66,10 +66,10 @@
 static method allocateE() → dynamic {
   new self::E::•();
 }
-static method main(core::List<core::String*>* args) → dynamic {
-  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+static method main(core::List<core::String> args) → dynamic {
+  self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
   self::allocateB();
-  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+  self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
   self::allocateE();
-  self::use3(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+  self::use3(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart
index b91b3a3..01417ef 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 class T1 {}
 
 class T2 {}
@@ -29,7 +27,7 @@
 
 use_bazz(dynamic x) => x.bazz();
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
index 13a7d78b..c049955 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
@@ -1,24 +1,24 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 class T3 extends core::Object {
-  synthetic constructor •() → self::T3*
+  synthetic constructor •() → self::T3
     : super core::Object::•()
     ;
 }
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → dynamic
@@ -29,7 +29,7 @@
     return new self::T3::•();
 }
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method foo() → dynamic
@@ -39,7 +39,7 @@
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method bazz() → dynamic
     return new self::T3::•();
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
 static method use_foo1(dynamic x) → dynamic
   return [@vm.inferred-type.metadata=#lib::T1] x{dynamic}.foo();
 static method use_foo2(dynamic x) → dynamic
@@ -56,7 +56,7 @@
 static method allocateB() → dynamic {
   new self::B::•();
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   self::use_foo1(self::getDynamic());
   self::allocateA();
   self::use_foo2(self::getDynamic());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
index 9a5df63..5232b28 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 class T1 {}
 
 class T2 {}
@@ -32,7 +30,7 @@
 use1(DeepCaller1 x, A aa) => x.barL1(aa);
 use2(DeepCaller2 x, A aa) => x.barL1(aa);
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
index 8a434a8..03a3204 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
@@ -1,65 +1,65 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 class A extends core::Object {
 [@vm.inferred-type.metadata=#lib::T1] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  field dynamic field1;
 [@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field dynamic field2;
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : self::A::field1 = new self::T1::•(), self::A::field2 = new self::T1::•(), super core::Object::•()
     ;
 }
 class DeepCaller1 extends core::Object {
-  synthetic constructor •() → self::DeepCaller1*
+  synthetic constructor •() → self::DeepCaller1
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method barL1([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL2}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method barL2([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL3}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method barL3([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL4}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method barL4([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method barL1([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL2}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method barL2([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL3}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method barL3([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL4}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method barL4([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
     return [@vm.direct-call.metadata=#lib::A.field1??] [@vm.inferred-type.metadata=#lib::T1] aa.{self::A::field1}{dynamic};
 }
 class DeepCaller2 extends core::Object {
-  synthetic constructor •() → self::DeepCaller2*
+  synthetic constructor •() → self::DeepCaller2
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL1([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL2([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL3([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method barL4([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method barL1([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method barL2([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method barL3([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+    return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method barL4([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
     return [@vm.direct-call.metadata=#lib::A.field2??] [@vm.inferred-type.metadata=!] aa.{self::A::field2}{dynamic};
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1* x, [@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=#lib::T1 (skip check)] x.{self::DeepCaller1::barL1}(aa){(self::A*) →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2* x, [@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
-  return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(aa){(self::A*) →* dynamic};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1 x, [@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=#lib::T1 (skip check)] x.{self::DeepCaller1::barL1}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2 x, [@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+  return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(aa){(self::A) → dynamic};
 static method getDynamic() → dynamic
   return self::unknown();
-static method setField2([@vm.inferred-type.metadata=#lib::A] self::A* aa, [@vm.inferred-type.metadata=#lib::T2] dynamic value) → void {
+static method setField2([@vm.inferred-type.metadata=#lib::A] self::A aa, [@vm.inferred-type.metadata=#lib::T2] dynamic value) → void {
   [@vm.direct-call.metadata=#lib::A.field2] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::field2} = value;
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   new self::A::•();
   new self::T1::•();
   new self::T2::•();
-  self::use1(new self::DeepCaller1::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
-  self::use2(new self::DeepCaller2::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+  self::use1(new self::DeepCaller1::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
+  self::use2(new self::DeepCaller2::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
   self::setField2(new self::A::•(), new self::T2::•());
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart
index fa5a893..723c228 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart
@@ -4,8 +4,6 @@
 
 // Tests elimination of 'is' tests.
 
-// @dart = 2.12
-
 class A {}
 
 class B extends A {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart b/pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart
similarity index 97%
rename from pkg/vm/testcases/transformations/type_flow/transformer/lists.dart
rename to pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart
index 355f41d3..dcd8253 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart
@@ -2,6 +2,7 @@
 // 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.
 
+// This test needs pre-null-safety semantics.
 // @dart=2.9
 
 nonConstant() => int.parse('1') == 1;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart.expect
similarity index 100%
rename from pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
rename to pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart.expect
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart
index 76fafab..82f93e6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart
@@ -2,9 +2,6 @@
 // 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.
 
-// This test requires non-nullable experiment.
-// @dart = 2.10
-
 nonConstant() => int.parse('1') == 1;
 
 class A {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
index b180b60..d2bc22a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
@@ -4,8 +4,6 @@
 //
 // Test that optimization of named parameters doesn't change evaluation order.
 
-// @dart=2.9
-
 import 'dart:math';
 import 'package:expect/expect.dart';
 
@@ -17,7 +15,7 @@
 // When converting named parameters to positional parameters, we
 // follow alphabetical order. Ensure that argument evaluation order
 // is unchanged.
-void testNamedOrder(int w, {int z, int y, int x}) {
+void testNamedOrder(int w, {int? z, int? y, int? x}) {
   Expect.equals(w, 1);
   Expect.equals(z, 2);
   Expect.equals(y, 3);
@@ -25,7 +23,7 @@
 }
 
 class TestNamedOrderBase {
-  TestNamedOrderBase(w, {int z, int y, int x}) {
+  TestNamedOrderBase(w, {int? z, int? y, int? x}) {
     testNamedOrder(w, z: z, y: y, x: x);
   }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
index fda4bf2..76840f2 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
@@ -9,31 +9,31 @@
 import "package:expect/expect.dart";
 
 abstract class TestNamedOrderBase extends core::Object {
-[@vm.unboxing-info.metadata=(i,i,i,i)->b]  constructor •([@vm.inferred-type.metadata=int] dynamic w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → self::TestNamedOrderBase*
+[@vm.unboxing-info.metadata=(i,i,i,i)->b]  constructor •([@vm.inferred-type.metadata=int] dynamic w, [@vm.inferred-type.metadata=int] core::int? x, [@vm.inferred-type.metadata=int] core::int? y, [@vm.inferred-type.metadata=int] core::int? z) → self::TestNamedOrderBase
     : super core::Object::•() {
-    self::testNamedOrder(_in::unsafeCast<core::int*>(w), x, y, z);
+    self::testNamedOrder(_in::unsafeCast<core::int>(w), x, y, z);
   }
 }
 class TestNamedOrderSub extends self::TestNamedOrderBase {
-[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i]  field core::int* x;
-  constructor •() → self::TestNamedOrderSub*
-    : self::TestNamedOrderSub::x = [@vm.inferred-type.metadata=int] self::dec(), final core::int* #t1 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t2 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t3 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t4 = [@vm.inferred-type.metadata=int] self::dec(), super self::TestNamedOrderBase::•(#t1, #t4, #t3, #t2) {
-    exp::Expect::equals([@vm.direct-call.metadata=#lib::TestNamedOrderSub.x] [@vm.inferred-type.metadata=int] this.{self::TestNamedOrderSub::x}{core::int*}, 0);
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i]  field core::int x;
+  constructor •() → self::TestNamedOrderSub
+    : self::TestNamedOrderSub::x = [@vm.inferred-type.metadata=int] self::dec(), final core::int #t1 = [@vm.inferred-type.metadata=int] self::inc(), final core::int #t2 = [@vm.inferred-type.metadata=int] self::inc(), final core::int #t3 = [@vm.inferred-type.metadata=int] self::inc(), final core::int #t4 = [@vm.inferred-type.metadata=int] self::dec(), super self::TestNamedOrderBase::•(#t1, #t4, #t3, #t2) {
+    exp::Expect::equals([@vm.direct-call.metadata=#lib::TestNamedOrderSub.x] [@vm.inferred-type.metadata=int] this.{self::TestNamedOrderSub::x}{core::int}, 0);
   }
 }
-[@vm.inferred-type.metadata=int?]static field core::int* global = 0;
-[@vm.unboxing-info.metadata=()->i]static method inc() → core::int*
-  return self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::+}(1){(core::num*) →* core::int*};
-[@vm.unboxing-info.metadata=()->i]static method dec() → core::int*
-  return self::global = [@vm.inferred-type.metadata=int] math::max<core::int*>(0, self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.-??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::-}(1){(core::num*) →* core::int*});
-[@vm.unboxing-info.metadata=(i,i,i,i)->b]static method testNamedOrder([@vm.inferred-type.metadata=int] core::int* w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → void {
+[@vm.inferred-type.metadata=int?]static field core::int global = 0;
+[@vm.unboxing-info.metadata=()->i]static method inc() → core::int
+  return self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::+}(1){(core::num) → core::int};
+[@vm.unboxing-info.metadata=()->i]static method dec() → core::int
+  return self::global = [@vm.inferred-type.metadata=int] math::max<core::int>(0, self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.-??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::-}(1){(core::num) → core::int});
+[@vm.unboxing-info.metadata=(i,i,i,i)->b]static method testNamedOrder([@vm.inferred-type.metadata=int] core::int w, [@vm.inferred-type.metadata=int] core::int? x, [@vm.inferred-type.metadata=int] core::int? y, [@vm.inferred-type.metadata=int] core::int? z) → void {
   exp::Expect::equals(w, 1);
   exp::Expect::equals(z, 2);
   exp::Expect::equals(y, 3);
   exp::Expect::equals(x, 2);
 }
 static method main() → dynamic {
-  let final core::int* #t5 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t6 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t7 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t8 = [@vm.inferred-type.metadata=int] self::dec() in self::testNamedOrder(#t5, #t8, #t7, #t6);
+  let final core::int #t5 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int #t6 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int #t7 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int #t8 = [@vm.inferred-type.metadata=int] self::dec() in self::testNamedOrder(#t5, #t8, #t7, #t6);
   self::global = 1;
   new self::TestNamedOrderSub::•();
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart
index e0ab4922..a3c4741 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 class T1 {}
 
 class T2 {}
@@ -71,7 +69,7 @@
 A bb = new B();
 A dd = new D();
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
index 719f96e..657e7ba 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
@@ -1,40 +1,40 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 }
 class T4 extends core::Object {
-  synthetic constructor •() → self::T4*
+  synthetic constructor •() → self::T4
     : super core::Object::•()
     ;
 }
 class T5 extends core::Object {
-  synthetic constructor •() → self::T5*
+  synthetic constructor •() → self::T5
     : super core::Object::•()
     ;
 }
 class T6 extends core::Object {
-  synthetic constructor •() → self::T6*
+  synthetic constructor •() → self::T6
     : super core::Object::•()
     ;
 }
 class T7 extends core::Object {
-  synthetic constructor •() → self::T7*
+  synthetic constructor •() → self::T7
     : super core::Object::•()
     ;
 }
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → dynamic;
@@ -42,88 +42,88 @@
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b]  abstract method bazz(dynamic a1, dynamic a2, dynamic a3, dynamic a4) → dynamic;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T1::•();
   }
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  no-such-method-forwarder get bar() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  no-such-method-forwarder method foo() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b]  no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4) → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 }
 abstract class C extends core::Object {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T2::•();
   }
 }
 class D extends self::C implements self::A {
-  synthetic constructor •() → self::D*
+  synthetic constructor •() → self::D
     : super self::C::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  no-such-method-forwarder get bar() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  no-such-method-forwarder method foo() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b]  no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4) → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 }
 class E extends core::Object implements self::A {
-  synthetic constructor •() → self::E*
+  synthetic constructor •() → self::E
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T4::•();
   }
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  no-such-method-forwarder get bar() → dynamic
-    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E.noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+    return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E.noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
 }
 class F extends core::Object {
-  synthetic constructor •() → self::F*
+  synthetic constructor •() → self::F
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T2::•();
   }
 }
 class G extends core::Object {
-  synthetic constructor •() → self::G*
+  synthetic constructor •() → self::G
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T5::•();
   }
 }
 class H extends core::Object {
-  synthetic constructor •() → self::H*
+  synthetic constructor •() → self::H
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9]  method foo({[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic left = #C7, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic right = #C7}) → dynamic
     return new self::T6::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T7::•();
   }
 }
-[@vm.inferred-type.metadata=#lib::B?]static field self::A* bb = new self::B::•();
-[@vm.inferred-type.metadata=#lib::D?]static field self::A* dd = new self::D::•();
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
+[@vm.inferred-type.metadata=#lib::B?]static field self::A bb = new self::B::•();
+[@vm.inferred-type.metadata=#lib::D?]static field self::A dd = new self::D::•();
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
 static method getDynamic() → dynamic
   return self::unknown();
-static method main(core::List<core::String*>* args) → dynamic {
-  core::print([@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::foo}(){() →* dynamic});
+static method main(core::List<core::String> args) → dynamic {
+  core::print([@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::foo}(){() → dynamic});
   core::print([@vm.direct-call.metadata=#lib::B.bar??] [@vm.inferred-type.metadata=#lib::T1] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bar}{dynamic});
-  core::print([@vm.direct-call.metadata=#lib::B.bazz??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) →* dynamic});
-  core::print([@vm.direct-call.metadata=#lib::D.foo??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::foo}(){() →* dynamic});
+  core::print([@vm.direct-call.metadata=#lib::B.bazz??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) → dynamic});
+  core::print([@vm.direct-call.metadata=#lib::D.foo??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::foo}(){() → dynamic});
   core::print([@vm.direct-call.metadata=#lib::D.bar??] [@vm.inferred-type.metadata=#lib::T2] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::bar}{dynamic});
-  core::print([@vm.direct-call.metadata=#lib::D.bazz??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) →* dynamic});
+  core::print([@vm.direct-call.metadata=#lib::D.bazz??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) → dynamic});
   new self::E::•();
-  self::A* xx = self::getDynamic() as{TypeError,ForDynamic} self::A*;
+  self::A xx = self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A;
   core::print([@vm.inferred-type.metadata=!] xx.{self::A::bar}{dynamic});
   dynamic yy = self::getDynamic();
   core::print([@vm.inferred-type.metadata=!] yy{dynamic}.twoArg(1, 2, 3));
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart
index b529e22..016fff5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Tests elimination of null checks.
-// This test requires non-nullable experiment.
-
-// @dart = 2.10
 
 class A {
   String? nonNullable;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart
index 121f842..e3f12b7 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart
@@ -4,12 +4,10 @@
 
 // Tests elimination of null tests.
 
-// @dart=2.9
-
 class A {
-  String nonNullable;
-  String nullable;
-  String alwaysNull;
+  String? nonNullable;
+  String? nullable;
+  String? alwaysNull;
   A({this.nonNullable, this.nullable, this.alwaysNull});
 }
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
index 11d07aa..461ce24 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
@@ -1,70 +1,70 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
 class A extends core::Object {
-[@vm.inferred-type.metadata=dart.core::_OneByteString] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  field core::String* nonNullable;
-[@vm.inferred-type.metadata=dart.core::_OneByteString?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field core::String* nullable;
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  field core::String* alwaysNull;
-  constructor •([@vm.inferred-type.metadata=dart.core::_OneByteString] core::String* nonNullable, [@vm.inferred-type.metadata=dart.core::_OneByteString?] core::String* nullable) → self::A*
+[@vm.inferred-type.metadata=dart.core::_OneByteString] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  field core::String? nonNullable;
+[@vm.inferred-type.metadata=dart.core::_OneByteString?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field core::String? nullable;
+[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  field core::String? alwaysNull;
+  constructor •([@vm.inferred-type.metadata=dart.core::_OneByteString] core::String? nonNullable, [@vm.inferred-type.metadata=dart.core::_OneByteString?] core::String? nullable) → self::A
     : self::A::nonNullable = nonNullable, self::A::nullable = nullable, self::A::alwaysNull = #C1, super core::Object::•()
     ;
 }
-[@vm.inferred-type.metadata=#lib::A?]static field self::A* staticField = new self::A::•("hi", "bye");
-static method testNonNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
+[@vm.inferred-type.metadata=#lib::A?]static field self::A staticField = new self::A::•("hi", "bye");
+static method testNonNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
   {
-    [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
+    [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String?};
   }
 }
-static method testNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) {
+static method testNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+  if([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String?} == null) {
     core::print("null");
   }
 }
-static method testAlwaysNullIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
+static method testAlwaysNullIf1([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
   {
-    [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
+    [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String?};
     {
       core::print("null");
     }
   }
 }
-static method testNonNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
+static method testNonNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
   if(( block {
-    [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
-  } =>true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+    [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String?};
+  } =>true) && _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
     core::print("not null");
   }
 }
-static method testNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
-  if(!([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+static method testNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+  if(!([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String?} == null) && _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
     core::print("not null");
   }
 }
-static method testAlwaysNullIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
+static method testAlwaysNullIf2([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
   {
-    [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
+    [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String?};
   }
 }
-static method testNonNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
+static method testNonNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
   return block {
-    [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
+    [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String?};
   } =>"not null";
-static method testNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
-  return !([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) ?{core::String*} "not null" : "null";
-static method testAlwaysNullCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
+static method testNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
+  return !([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String?} == null) ?{core::String} "not null" : "null";
+static method testAlwaysNullCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
   return block {
-    [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
+    [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String?};
   } =>"null";
 static method someCondition() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1;
+  return [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1;
 static method main() → void {
-  final core::List<self::A*>* list = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A*>] core::_GrowableList::_literal2<self::A*>(new self::A::•("foo", null), [@vm.inferred-type.metadata=#lib::A?] self::staticField);
+  final core::List<self::A> list = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A>] core::_GrowableList::_literal2<self::A>(new self::A::•("foo", null), [@vm.inferred-type.metadata=#lib::A?] self::staticField);
   {
-    core::Iterator<self::A*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A*>] list.{core::Iterable::iterator}{core::Iterator<self::A*>*};
+    core::Iterator<self::A> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A>] list.{core::Iterable::iterator}{core::Iterator<self::A>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::A* a = [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=#lib::A?] :sync-for-iterator.{core::Iterator::current}{self::A*};
+      self::A a = [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=#lib::A?] :sync-for-iterator.{core::Iterator::current}{self::A};
       {
         self::testNonNullableIf1(a);
         self::testNullableIf1(a);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart
index 4065205..1d07acd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart
@@ -5,8 +5,6 @@
 // This test verifies that inferred types of parameters are valid *before*
 // applying strong mode argument type checks.
 
-// @dart=2.9
-
 abstract class T0 {
   void foo();
 }
@@ -56,7 +54,7 @@
   }
 }
 
-Function unknown;
+late Function unknown;
 
 getDynamic() => unknown.call();
 use(x) => unknown.call(x);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
index 7317c7f3..57eda05 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
@@ -1,63 +1,63 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class T0 extends core::Object {
-  synthetic constructor •() → self::T0*
+  synthetic constructor •() → self::T0
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method foo() → void;
 }
 class T2 extends self::T0 {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super self::T0::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method foo() → void {}
 }
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method method1(self::T0* t0) → void {
-    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  method method1(self::T0 t0) → void {
+    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
   }
 }
 abstract class B extends core::Object {
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  abstract method method2(covariant dynamic arg) → void;
 }
 class C extends core::Object implements self::B {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method method2(covariant self::T0* t0) → void {
-    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method method2(covariant self::T0 t0) → void {
+    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
   }
 }
 class D extends core::Object {
-  synthetic constructor •() → self::D*
+  synthetic constructor •() → self::D
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method method3(self::T0* t0) → void {
-    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method method3(self::T0 t0) → void {
+    [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
   }
 }
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method func1([@vm.inferred-type.metadata=#lib::T2?] self::T0* t0) → void {
-  [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method func1([@vm.inferred-type.metadata=#lib::T2?] self::T0 t0) → void {
+  [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
 }
-static method func2(self::T0* t0) → void {
-  [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+static method func2(self::T0 t0) → void {
+  [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
 }
 static method getDynamic() → dynamic
   return self::unknown();
 static method use(dynamic x) → dynamic
   return self::unknown(x);
-static method main(core::List<core::String*>* args) → dynamic {
-  self::func1(self::getDynamic() as{TypeError,ForDynamic} self::T0*);
+static method main(core::List<core::String> args) → dynamic {
+  self::func1(self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::T0);
   self::use(#C1);
-  self::use(new self::A::•().{self::A::method1}{(self::T0*) →* void});
-  self::B* bb = self::getDynamic() as{TypeError,ForDynamic} self::B*;
-  [@vm.direct-call.metadata=#lib::C.method2??] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B::method2}(self::getDynamic()){(dynamic) →* void};
+  self::use(new self::A::•().{self::A::method1}{(self::T0) → void});
+  self::B bb = self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::B;
+  [@vm.direct-call.metadata=#lib::C.method2??] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B::method2}(self::getDynamic()){(dynamic) → void};
   self::getDynamic(){dynamic}.method3(self::getDynamic());
   new self::T2::•();
   new self::A::•();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
index b52c5dc..c5b7bf4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
@@ -2,8 +2,6 @@
 // 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:test/test.dart';
-
 import 'generated/name_mangling.pb.dart';
 
 main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
index bc4814f..63e55db 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
@@ -3,7 +3,6 @@
 import "generated/name_mangling.pb.dart" as pb;
 import "dart:core" as core;
 
-import "package:test/test.dart";
 import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart";
 
 static method main() → dynamic {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart
index bc79497..03ba604 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart
@@ -4,9 +4,7 @@
 
 // Regression test for https://github.com/dart-lang/sdk/issues/41452.
 // Tests handling of null initializer of covariant field.
-// This test requires non-nullable experiment and NNBD strong mode.
-
-// @dart = 2.10
+// This test requires sound null safety.
 
 class _SplayTreeNode<Node extends _SplayTreeNode<Node>> {
   Node? left;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
index 76df937..add07b4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 import 'dart:math';
 
 import 'package:expect/expect.dart';
@@ -12,12 +10,12 @@
 
 class A {
   @pragma("vm:never-inline")
-  void foo(/* boxed */ int x) => Expect.isTrue(x.isOdd);
+  void foo(/* boxed */ int? x) => Expect.isTrue(x!.isOdd);
 }
 
 class B {
   @pragma("vm:never-inline")
-  void foo(/* unboxed */ int x) => Expect.isTrue(x.isOdd);
+  void foo(/* unboxed */ int? x) => Expect.isTrue(x!.isOdd);
 }
 
 class C extends A implements B {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
index 16d4a2a..9d24274 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
@@ -1,48 +1,49 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "package:expect/expect.dart" as exp;
+import "dart:_internal" as _in;
 import "dart:math" as math;
 
 import "dart:math";
 import "package:expect/expect.dart";
 
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
-  method foo([@vm.inferred-type.metadata=int?] core::int* x) → void
-    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd??] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+  method foo([@vm.inferred-type.metadata=int?] core::int? x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x!.{core::int::isOdd}{core::bool});
 }
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
-  method foo([@vm.inferred-type.metadata=int] core::int* x) → void
-    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+  method foo([@vm.inferred-type.metadata=int] core::int? x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] _in::unsafeCast<core::int>(x).{core::int::isOdd}{core::bool});
 }
 class C extends self::A implements self::B {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super self::A::•()
     ;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2;
 static method main() → dynamic {
-  final math::Random* r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
+  final math::Random r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
   if([@vm.inferred-type.metadata=dart.core::bool?] self::alwaysFalse) {
-    [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
-    [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
-    [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}(null){(core::int*) →* void};
+    [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+    [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+    [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}(null){(core::int?) → void};
   }
-  final core::List<self::B*>* l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B*>] core::_GrowableList::_literal2<self::B*>(new self::B::•(), new self::C::•());
+  final core::List<self::B> l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B>] core::_GrowableList::_literal2<self::B>(new self::B::•(), new self::C::•());
   {
-    core::Iterator<self::B*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B*>] l.{core::Iterable::iterator}{core::Iterator<self::B*>*};
+    core::Iterator<self::B> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B>] l.{core::Iterable::iterator}{core::Iterator<self::B>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::B* b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B*};
+      self::B b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B};
       {
-        b.{self::B::foo}(13){(core::int*) →* void};
+        b.{self::B::foo}(13){(core::int?) → void};
       }
     }
   }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
index 45943ff..01bede8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 import 'dart:math';
 
 import 'package:expect/expect.dart';
@@ -12,12 +10,12 @@
 
 class A {
   @pragma("vm:never-inline")
-  void bar(/* unboxed */ int x) => Expect.isTrue(x.isOdd);
+  void bar(/* unboxed */ int? x) => Expect.isTrue(x!.isOdd);
 }
 
 class B {
   @pragma("vm:never-inline")
-  void bar(/* boxed */ int x) => Expect.isTrue(x.isOdd);
+  void bar(/* boxed */ int? x) => Expect.isTrue(x!.isOdd);
 }
 
 class C extends A implements B {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
index dff8e38..ae6258b 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
@@ -1,48 +1,49 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "package:expect/expect.dart" as exp;
+import "dart:_internal" as _in;
 import "dart:math" as math;
 
 import "dart:math";
 import "package:expect/expect.dart";
 
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
-  method bar([@vm.inferred-type.metadata=int] core::int* x) → void
-    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+  method bar([@vm.inferred-type.metadata=int] core::int? x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] _in::unsafeCast<core::int>(x).{core::int::isOdd}{core::bool});
 }
 class B extends core::Object {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
-  method bar([@vm.inferred-type.metadata=int?] core::int* x) → void
-    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd??] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+  method bar([@vm.inferred-type.metadata=int?] core::int? x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x!.{core::int::isOdd}{core::bool});
 }
 class C extends self::A implements self::B {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : super self::A::•()
     ;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2;
 static method main() → dynamic {
-  final math::Random* r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
+  final math::Random r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
   if([@vm.inferred-type.metadata=dart.core::bool?] self::alwaysFalse) {
-    [@vm.direct-call.metadata=#lib::A.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
-    [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
-    [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}(null){(core::int*) →* void};
+    [@vm.direct-call.metadata=#lib::A.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+    [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+    [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}(null){(core::int?) → void};
   }
-  final core::List<self::B*>* l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B*>] core::_GrowableList::_literal2<self::B*>(new self::B::•(), new self::C::•());
+  final core::List<self::B> l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B>] core::_GrowableList::_literal2<self::B>(new self::B::•(), new self::C::•());
   {
-    core::Iterator<self::B*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B*>] l.{core::Iterable::iterator}{core::Iterator<self::B*>*};
+    core::Iterator<self::B> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B>] l.{core::Iterable::iterator}{core::Iterator<self::B>};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      self::B* b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B*};
+      self::B b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B};
       {
-        b.{self::B::bar}(13){(core::int*) →* void};
+        b.{self::B::bar}(13){(core::int?) → void};
       }
     }
   }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
index 6c4d972..a655aa5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.12
-
 class A {
   void doTest(Z a) {
     print(a.appName);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart
index d50e669..4b25bd4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.12
-
 enum A { a1, a2 }
 
 class B {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart
index fcc1c23..f565760 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart
@@ -5,11 +5,9 @@
 // Regression test for https://github.com/flutter/flutter/issues/16182
 // Verifies that TFA correctly handles calls via fields/getters.
 
-// @dart=2.9
-
 import "package:expect/expect.dart";
 
-bool ok;
+bool? ok;
 
 class T1 {
   // Should be reachable.
@@ -19,7 +17,7 @@
 }
 
 class A1 {
-  T1 foo;
+  T1? foo;
 
   void call([a1, a2, a3, a4, a5]) {
     foo = a5;
@@ -35,7 +33,7 @@
   bb.aa1(1, 2, 3, 4, new T1());
 
   ok = false;
-  bb.aa1.foo.doTest1();
+  bb.aa1.foo!.doTest1();
   Expect.isTrue(ok);
 }
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
index 15a6a84..fa24c7a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
@@ -7,7 +7,7 @@
 import "package:expect/expect.dart";
 
 class T1 extends core::Object {
-  synthetic constructor •() → self::T1*
+  synthetic constructor •() → self::T1
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method doTest1() → void {
@@ -15,22 +15,22 @@
   }
 }
 class A1 extends core::Object {
-[@vm.inferred-type.metadata=#lib::T1?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field self::T1* foo = null;
-  synthetic constructor •() → self::A1*
+[@vm.inferred-type.metadata=#lib::T1?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field self::T1? foo = null;
+  synthetic constructor •() → self::A1
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=#lib::T1?] dynamic a5 = #C1]) → void {
-    [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A1::foo} = _in::unsafeCast<self::T1*>(a5);
+    [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A1::foo} = _in::unsafeCast<self::T1?>(a5);
   }
 }
 class B1 extends core::Object {
-[@vm.inferred-type.metadata=#lib::A1] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  field self::A1* aa1;
-  synthetic constructor •() → self::B1*
+[@vm.inferred-type.metadata=#lib::A1] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  field self::A1 aa1;
+  synthetic constructor •() → self::B1
     : self::B1::aa1 = new self::A1::•(), super core::Object::•()
     ;
 }
 class T2 extends core::Object {
-  synthetic constructor •() → self::T2*
+  synthetic constructor •() → self::T2
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method doTest2() → void {
@@ -39,7 +39,7 @@
 }
 class A2 extends core::Object {
 [@vm.inferred-type.metadata=#lib::T2?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  field dynamic foo = null;
-  synthetic constructor •() → self::A2*
+  synthetic constructor •() → self::A2
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=#lib::T2?] dynamic a6 = #C1]) → void {
@@ -48,14 +48,14 @@
 }
 abstract class B2Base extends core::Object {
 [@vm.inferred-type.metadata=#lib::A2] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  field dynamic _aa;
-  synthetic constructor •() → self::B2Base*
+  synthetic constructor •() → self::B2Base
     : self::B2Base::_aa = new self::A2::•(), super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:17]  get aa2() → dynamic
     return [@vm.direct-call.metadata=#lib::B2Base._aa] [@vm.inferred-type.metadata=#lib::A2] this.{self::B2Base::_aa}{dynamic};
 }
 class B2 extends self::B2Base {
-  synthetic constructor •() → self::B2*
+  synthetic constructor •() → self::B2
     : super self::B2Base::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:18,getterSelectorId:19]  method doSuperCall() → void {
@@ -63,7 +63,7 @@
   }
 }
 class T3 extends core::Object {
-  synthetic constructor •() → self::T3*
+  synthetic constructor •() → self::T3
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:20,getterSelectorId:21]  method doTest3() → void {
@@ -72,7 +72,7 @@
 }
 class A3 extends core::Object {
 [@vm.inferred-type.metadata=#lib::T3?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:22,getterSelectorId:23]  field dynamic foo = null;
-  synthetic constructor •() → self::A3*
+  synthetic constructor •() → self::A3
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:24,getterSelectorId:25]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=#lib::T3?] dynamic a7 = #C1]) → void {
@@ -80,13 +80,13 @@
   }
 }
 class B3 extends core::Object {
-[@vm.inferred-type.metadata=#lib::A3] [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:26,getterSelectorId:27]  field self::A3* aa3;
-  synthetic constructor •() → self::B3*
+[@vm.inferred-type.metadata=#lib::A3] [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:26,getterSelectorId:27]  field self::A3 aa3;
+  synthetic constructor •() → self::B3
     : self::B3::aa3 = new self::A3::•(), super core::Object::•()
     ;
 }
 class T4 extends core::Object {
-  synthetic constructor •() → self::T4*
+  synthetic constructor •() → self::T4
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:28,getterSelectorId:29]  method doTest4() → void {
@@ -95,7 +95,7 @@
 }
 class A4 extends core::Object {
 [@vm.inferred-type.metadata=#lib::T4?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:30,getterSelectorId:31]  field dynamic foo = null;
-  synthetic constructor •() → self::A4*
+  synthetic constructor •() → self::A4
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:32,getterSelectorId:33]  method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a7 = #C1, [@vm.inferred-type.metadata=#lib::T4?] dynamic a8 = #C1]) → void {
@@ -104,27 +104,27 @@
 }
 class B4 extends core::Object {
 [@vm.inferred-type.metadata=#lib::A4] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:34,getterSelectorId:35]  field dynamic _aa;
-  synthetic constructor •() → self::B4*
+  synthetic constructor •() → self::B4
     : self::B4::_aa = new self::A4::•(), super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,getterSelectorId:36]  get aa4() → dynamic
     return [@vm.direct-call.metadata=#lib::B4._aa] [@vm.inferred-type.metadata=#lib::A4] this.{self::B4::_aa}{dynamic};
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static field core::bool* ok;
+[@vm.inferred-type.metadata=dart.core::bool?]static field core::bool? ok;
 [@vm.inferred-type.metadata=#lib::B3?]static field dynamic bb3 = new self::B3::•();
-[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function* unknown3 = () → dynamic => self::bb3;
+[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function unknown3 = () → dynamic => self::bb3;
 [@vm.inferred-type.metadata=#lib::B4?]static field dynamic bb4 = new self::B4::•();
-[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function* unknown4 = () → dynamic => self::bb4;
+[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function unknown4 = () → dynamic => self::bb4;
 static method test1() → void {
-  self::B1* bb = new self::B1::•();
-  let final self::B1* #t1 = bb in let final core::int* #t2 = 1 in let final core::int* #t3 = 2 in let final core::int* #t4 = 3 in let final core::int* #t5 = 4 in let final self::T1* #t6 = new self::T1::•() in [@vm.direct-call.metadata=#lib::A1.call] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] #t1.{self::B1::aa1}{self::A1*}.{self::A1::call}(#t2, #t3, #t4, #t5, #t6){([dynamic, dynamic, dynamic, dynamic, dynamic]) →* void};
+  self::B1 bb = new self::B1::•();
+  let final self::B1 #t1 = bb in let final core::int #t2 = 1 in let final core::int #t3 = 2 in let final core::int #t4 = 3 in let final core::int #t5 = 4 in let final self::T1 #t6 = new self::T1::•() in [@vm.direct-call.metadata=#lib::A1.call] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] #t1.{self::B1::aa1}{self::A1}.{self::A1::call}(#t2, #t3, #t4, #t5, #t6){([dynamic, dynamic, dynamic, dynamic, dynamic]) → void};
   self::ok = false;
-  [@vm.direct-call.metadata=#lib::T1.doTest1??] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=#lib::T1?] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] bb.{self::B1::aa1}{self::A1*}.{self::A1::foo}{self::T1*}.{self::T1::doTest1}(){() →* void};
+  [@vm.direct-call.metadata=#lib::T1.doTest1] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=#lib::T1?] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] bb.{self::B1::aa1}{self::A1}.{self::A1::foo}{self::T1?}!.{self::T1::doTest1}(){() → void};
   exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
 }
 static method test2() → void {
-  self::B2* bb = new self::B2::•();
-  [@vm.direct-call.metadata=#lib::B2.doSuperCall] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B2::doSuperCall}(){() →* void};
+  self::B2 bb = new self::B2::•();
+  [@vm.direct-call.metadata=#lib::B2.doSuperCall] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B2::doSuperCall}(){() → void};
   self::ok = false;
   [@vm.direct-call.metadata=#lib::T2.doTest2??] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A2.foo] [@vm.inferred-type.metadata=#lib::T2? (receiver not int)] [@vm.direct-call.metadata=#lib::B2Base.aa2] [@vm.inferred-type.metadata=#lib::A2] bb.{self::B2Base::aa2}{dynamic}{dynamic}.foo{dynamic}.doTest2();
   exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart
index 717504a..e29f9dd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 A aa = new B();
 
 dynamic knownResult() => new B();
@@ -13,11 +11,11 @@
 }
 
 class B extends A {
-  int foo() => 1 + knownResult().foo(); // Should have metadata.
+  int foo() => 1 + knownResult().foo() as int; // Should have metadata.
 }
 
 class C implements A {
-  int foo() => 2 + knownResult().foo(); // Should be unreachable.
+  int foo() => 2 + knownResult().foo() as int; // Should be unreachable.
 }
 
 class TearOffDynamicMethod {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
index 3483f2c..582555f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
@@ -1,29 +1,29 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
-    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=! (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo() as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*} as{TypeError} core::int*;
+[@vm.procedure-attributes.metadata=hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
+    return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=! (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo() as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num} as{ForNonNullableByDefault} core::int;
 }
 class TearOffDynamicMethod extends core::Object {
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field dynamic bazz;
-  constructor •(dynamic arg) → self::TearOffDynamicMethod*
+  constructor •(dynamic arg) → self::TearOffDynamicMethod
     : self::TearOffDynamicMethod::bazz = arg{dynamic}.foo, super core::Object::•() {
     [@vm.direct-call.metadata=#lib::TearOffDynamicMethod.bazz] this.{self::TearOffDynamicMethod::bazz}{dynamic}{dynamic}.call();
   }
 }
 static method knownResult() → dynamic
   return new self::B::•();
-static method main(core::List<core::String*>* args) → dynamic {
-  core::Function* closure = () → self::B* => new self::B::•();
+static method main(core::List<core::String> args) → dynamic {
+  core::Function closure = () → self::B => new self::B::•();
   new self::TearOffDynamicMethod::•(closure());
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
index 74cf279..603bbf6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 A aa = new B();
 
 dynamic knownResult() => new B();
@@ -13,12 +11,12 @@
 }
 
 class B extends A {
-  int foo() => 1 + knownResult().bar(); // Should have metadata.
+  int foo() => 1 + knownResult().bar() as int; // Should have metadata.
   int bar() => 3;
 }
 
 class C implements A {
-  int foo() => 2 + knownResult().bar(); // Should be unreachable.
+  int foo() => 2 + knownResult().bar() as int; // Should be unreachable.
 }
 
 class TearOffInterfaceMethod {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
index 578e8fb..b34fce5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
@@ -1,31 +1,31 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
-    return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 3) (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.bar())){(core::num*) →* core::num*});
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  method bar() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
+    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 3) (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.bar())){(core::num) → core::num});
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  method bar() → core::int
     return 3;
 }
 class TearOffInterfaceMethod extends core::Object {
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  field dynamic bazz;
-  constructor •([@vm.inferred-type.metadata=#lib::B] self::A* arg) → self::TearOffInterfaceMethod*
-    : self::TearOffInterfaceMethod::bazz = arg.{self::A::foo}{() →* core::int*}, super core::Object::•()
+  constructor •([@vm.inferred-type.metadata=#lib::B] self::A arg) → self::TearOffInterfaceMethod
+    : self::TearOffInterfaceMethod::bazz = arg.{self::A::foo}{() → core::int}, super core::Object::•()
     ;
 }
 static method knownResult() → dynamic
   return new self::B::•();
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   [@vm.direct-call.metadata=#lib::TearOffInterfaceMethod.bazz] new self::TearOffInterfaceMethod::•(new self::B::•()).{self::TearOffInterfaceMethod::bazz}{dynamic}{dynamic}.call();
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
index a63ec2a..2980835 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 A aa = new B();
 
 dynamic knownResult() => new B();
@@ -13,26 +11,26 @@
 }
 
 class B extends A {
-  int foo() => 1 + knownResult().foo(); // Should have metadata.
+  int foo() => 1 + knownResult().foo() as int; // Should have metadata.
 }
 
 class C implements A {
-  int foo() => 2 + knownResult().foo(); // Should be unreachable.
+  int foo() => 2 + knownResult().foo() as int; // Should be unreachable.
 }
 
 class Base {
-  int foo() => 3 + knownResult().foo(); // Should have metadata.
-  int doCall(x) => x();
+  int foo() => 3 + knownResult().foo() as int; // Should have metadata.
+  int? doCall(x) => x();
 }
 
 class TearOffSuperMethod extends Base {
   int foo() {
     // Should be unreachable.
     aa = new C();
-    return 4 + knownResult().foo();
+    return 4 + knownResult().foo() as int;
   }
 
-  int bar() => doCall(super.foo);
+  int? bar() => doCall(super.foo);
 }
 
 main(List<String> args) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
index bc69294..0e44dd5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
@@ -1,41 +1,41 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
 abstract class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract method foo() → core::int;
 }
 class B extends self::A {
-  synthetic constructor •() → self::B*
+  synthetic constructor •() → self::B
     : super self::A::•()
     ;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
-    return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num*) →* core::num*});
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
+    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num) → core::num});
 }
 abstract class Base extends core::Object {
-  synthetic constructor •() → self::Base*
+  synthetic constructor •() → self::Base
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int*
-    return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 3.{core::num::+}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num*) →* core::num*});
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method doCall(dynamic x) → core::int*
-    return x{dynamic}.call() as{TypeError,ForDynamic} core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  method foo() → core::int
+    return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 3.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num) → core::num});
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method doCall(dynamic x) → core::int?
+    return x{dynamic}.call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::int?;
 }
 class TearOffSuperMethod extends self::Base {
-  synthetic constructor •() → self::TearOffSuperMethod*
+  synthetic constructor •() → self::TearOffSuperMethod
     : super self::Base::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method bar() → core::int*
-    return [@vm.direct-call.metadata=#lib::Base.doCall] [@vm.inferred-type.metadata=int? (skip check)] this.{self::Base::doCall}(super.{self::Base::foo}){(dynamic) →* core::int*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  method bar() → core::int?
+    return [@vm.direct-call.metadata=#lib::Base.doCall] [@vm.inferred-type.metadata=int? (skip check)] this.{self::Base::doCall}(super.{self::Base::foo}){(dynamic) → core::int?};
 }
-[@vm.inferred-type.metadata=#lib::B?]static field self::A* aa = new self::B::•();
+[@vm.inferred-type.metadata=#lib::B?]static field self::A aa = new self::B::•();
 static method knownResult() → dynamic
   return new self::B::•();
-static method main(core::List<core::String*>* args) → dynamic {
-  [@vm.direct-call.metadata=#lib::TearOffSuperMethod.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::TearOffSuperMethod::•().{self::TearOffSuperMethod::bar}(){() →* core::int*};
-  [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=!? (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::aa.{self::A::foo}(){() →* core::int*};
+static method main(core::List<core::String> args) → dynamic {
+  [@vm.direct-call.metadata=#lib::TearOffSuperMethod.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::TearOffSuperMethod::•().{self::TearOffSuperMethod::bar}(){() → core::int?};
+  [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=!? (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::aa.{self::A::foo}(){() → core::int};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
index 5f0e8e8..e3a95bd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Tests elimination of type casts.
-// This test requires non-nullable experiment.
-
-// @dart = 2.10
 
 class A<T> {}
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
index c828095..337a57a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
@@ -3,9 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Tests elimination of type casts.
-// This test requires non-nullable experiment and NNBD strong mode.
-
-// @dart = 2.10
+// This test requires sound null safety.
 
 class A<T> {}
 
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
index 65a5a2d..81af9f4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 final bool kTrue = int.parse('1') == 1 ? true : false;
 final bool kFalse = int.parse('1') == 2 ? true : false;
 int get mint => 0xaabbccddaabbccdd;
@@ -15,58 +13,58 @@
 }
 
 abstract class BI1 {
-  int get value;
+  int? get value;
 }
 
 class BI1A implements BI1 {
-  final int value;
+  final int? value;
   BI1A(this.value);
 }
 
 class BI1B implements BI1 {
-  int get value => null;
+  int? get value => null;
 }
 
 abstract class BI2 {
-  int get value;
+  int? get value;
 }
 
 class BI2A implements BI2 {
-  final int value;
+  final int? value;
   BI2A(this.value);
 }
 
 class BI2B implements BI2 {
-  int get value => smiOrMint;
+  int? get value => smiOrMint;
 }
 
 abstract class BI3 {
-  int get value;
-  set value(int value);
+  int? get value;
+  set value(int? value);
 }
 
 class BI3A implements BI3 {
-  int value;
+  int? value;
   BI3A(this.value);
 }
 
 class BI3B implements BI3 {
-  int get value => smiOrMint;
-  set value(int v) {}
+  int? get value => smiOrMint;
+  set value(int? v) {}
 }
 
 abstract class UBI {
-  int value;
+  int? value;
 }
 
 class UBIA implements UBI {
-  int value;
+  int? value;
   UBIA(this.value);
 }
 
 class UBIB implements UBI {
-  int get value => smiOrMint;
-  set value(int v) {}
+  int? get value => smiOrMint;
+  set value(int? v) {}
 }
 
 main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
index 542466c..de01101 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
@@ -1,96 +1,96 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 abstract class BI1 extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  abstract get value() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  abstract get value() → core::int?;
 }
 class BI1A extends core::Object implements self::BI1 {
-[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::int* value;
-[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::BI1A*
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::int? value;
+[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int? value) → self::BI1A
     : self::BI1A::value = value, super core::Object::•()
     ;
 }
 class BI1B extends core::Object implements self::BI1 {
-  synthetic constructor •() → self::BI1B*
+  synthetic constructor •() → self::BI1B
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get value() → core::int?
     return null;
 }
 abstract class BI2 extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  abstract get value() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  abstract get value() → core::int?;
 }
 class BI2A extends core::Object implements self::BI2 {
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  final field core::int* value;
-  constructor •() → self::BI2A*
+[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  final field core::int? value;
+  constructor •() → self::BI2A
     : self::BI2A::value = #C1, super core::Object::•()
     ;
 }
 class BI2B extends core::Object implements self::BI2 {
-  synthetic constructor •() → self::BI2B*
+  synthetic constructor •() → self::BI2B
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  get value() → core::int?
     return [@vm.inferred-type.metadata=int] self::smiOrMint;
 }
 abstract class BI3 extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  abstract get value() → core::int*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  abstract set value(core::int* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  abstract get value() → core::int?;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  abstract set value(core::int? value) → void;
 }
 class BI3A extends core::Object implements self::BI3 {
-[@vm.inferred-type.metadata=int?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field core::int* value;
-[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::BI3A*
+[@vm.inferred-type.metadata=int?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  field core::int? value;
+[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int? value) → self::BI3A
     : self::BI3A::value = value, super core::Object::•()
     ;
 }
 class BI3B extends core::Object implements self::BI3 {
-  synthetic constructor •() → self::BI3B*
+  synthetic constructor •() → self::BI3B
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  get value() → core::int?
     return [@vm.inferred-type.metadata=int] self::smiOrMint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  set value([@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::int* v) → void {}
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4]  set value([@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::int? v) → void {}
 }
 abstract class UBI extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i]  abstract get value() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i]  abstract get /*isLegacy*/ value() → core::int?;
 }
 class UBIA extends core::Object implements self::UBI {
-[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:5] [@vm.unboxing-info.metadata=(i)->i]  field core::int* value;
-[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::UBIA*
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:5] [@vm.unboxing-info.metadata=(i)->i]  field core::int? value;
+[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int? value) → self::UBIA
     : self::UBIA::value = value, super core::Object::•()
     ;
 }
 class UBIB extends core::Object implements self::UBI {
-  synthetic constructor •() → self::UBIB*
+  synthetic constructor •() → self::UBIB
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i]  get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i]  get value() → core::int?
     return [@vm.inferred-type.metadata=int] self::smiOrMint;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
 [@vm.inferred-type.metadata=int?]static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
 static method use([@vm.inferred-type.metadata=int?] dynamic object) → void {
   [@vm.inferred-type.metadata=int?] self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
 static method main() → dynamic {
-  final self::BI1A* bi1a = new self::BI1A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
-  final self::BI1B* bi1b = new self::BI1B::•();
-  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI1*} bi1a : bi1b).{self::BI1::value}{core::int*});
-  final self::BI2A* bi2a = new self::BI2A::•();
-  final self::BI2B* bi2b = new self::BI2B::•();
-  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI2*} bi2a : bi2b).{self::BI2::value}{core::int*});
-  final self::BI3A* bi3a = new self::BI3A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
-  final self::BI3B* bi3b = new self::BI3B::•();
-  ([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3*} bi3a : bi3b).{self::BI3::value} = null;
-  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3*} bi3a : bi3b).{self::BI3::value}{core::int*});
-  final self::UBIA* ubia = new self::UBIA::•([@vm.inferred-type.metadata=int] self::smiOrMint);
-  final self::UBIB* ubib = new self::UBIB::•();
-  self::use([@vm.inferred-type.metadata=int]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::UBI*} ubia : ubib).{self::UBI::value}{core::int*});
+  final self::BI1A bi1a = new self::BI1A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
+  final self::BI1B bi1b = new self::BI1B::•();
+  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI1} bi1a : bi1b).{self::BI1::value}{core::int?});
+  final self::BI2A bi2a = new self::BI2A::•();
+  final self::BI2B bi2b = new self::BI2B::•();
+  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI2} bi2a : bi2b).{self::BI2::value}{core::int?});
+  final self::BI3A bi3a = new self::BI3A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
+  final self::BI3B bi3b = new self::BI3B::•();
+  ([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3} bi3a : bi3b).{self::BI3::value} = null;
+  self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3} bi3a : bi3b).{self::BI3::value}{core::int?});
+  final self::UBIA ubia = new self::UBIA::•([@vm.inferred-type.metadata=int] self::smiOrMint);
+  final self::UBIB ubib = new self::UBIB::•();
+  self::use([@vm.inferred-type.metadata=int]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::UBI} ubia : ubib).{self::UBI::value}{core::int?});
 }
 constants  {
   #C1 = null
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
index 63321f0..f367c3e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 final bool kTrue = int.parse('1') == 1 ? true : false;
 final bool kFalse = int.parse('1') == 2 ? true : false;
 int get mint => 0xaabbccddaabbccdd;
@@ -18,7 +16,7 @@
 
 abstract class Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -28,20 +26,20 @@
       dynamic boxedNullableX,
       dynamic boxedX);
 
-  dynamic returnUnboxedSmi(X ignored);
-  dynamic returnUnboxedInt(X ignored);
-  dynamic returnUnboxedDouble(X ignored);
-  dynamic returnBoxedNullableInt(X ignored);
-  dynamic returnBoxedNullableDouble(X ignored);
-  dynamic returnBoxedIntOrDouble(X ignored);
-  dynamic returnBoxedNullableIntOrDouble(X ignored);
-  dynamic returnBoxedNullableX(X ignored);
-  dynamic returnBoxedX(X ignored);
+  dynamic returnUnboxedSmi(X? ignored);
+  dynamic returnUnboxedInt(X? ignored);
+  dynamic returnUnboxedDouble(X? ignored);
+  dynamic returnBoxedNullableInt(X? ignored);
+  dynamic returnBoxedNullableDouble(X? ignored);
+  dynamic returnBoxedIntOrDouble(X? ignored);
+  dynamic returnBoxedNullableIntOrDouble(X? ignored);
+  dynamic returnBoxedNullableX(X? ignored);
+  dynamic returnBoxedX(X? ignored);
 }
 
 class Impl1 implements Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -60,20 +58,20 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 1;
-  dynamic returnUnboxedInt(X ignored) => 1;
-  dynamic returnUnboxedDouble(X ignored) => 1.1;
-  dynamic returnBoxedNullableInt(X ignored) => null;
-  dynamic returnBoxedNullableDouble(X ignored) => null;
-  dynamic returnBoxedIntOrDouble(X ignored) => 1;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => null;
-  dynamic returnBoxedNullableX(X ignored) => null;
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 1;
+  dynamic returnUnboxedInt(X? ignored) => 1;
+  dynamic returnUnboxedDouble(X? ignored) => 1.1;
+  dynamic returnBoxedNullableInt(X? ignored) => null;
+  dynamic returnBoxedNullableDouble(X? ignored) => null;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 1;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => null;
+  dynamic returnBoxedNullableX(X? ignored) => null;
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 class BaseImpl2 {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -92,20 +90,20 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 2;
-  dynamic returnUnboxedInt(X ignored) => mint;
-  dynamic returnUnboxedDouble(X ignored) => 2.2;
-  dynamic returnBoxedNullableInt(X ignored) => 2;
-  dynamic returnBoxedNullableDouble(X ignored) => 2.2;
-  dynamic returnBoxedIntOrDouble(X ignored) => 2.2;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => 2;
-  dynamic returnBoxedNullableX(X ignored) => X();
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 2;
+  dynamic returnUnboxedInt(X? ignored) => mint;
+  dynamic returnUnboxedDouble(X? ignored) => 2.2;
+  dynamic returnBoxedNullableInt(X? ignored) => 2;
+  dynamic returnBoxedNullableDouble(X? ignored) => 2.2;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 2.2;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => 2;
+  dynamic returnBoxedNullableX(X? ignored) => X();
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 class SubImpl3 extends BaseImpl2 implements Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -124,15 +122,15 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 3;
-  dynamic returnUnboxedInt(X ignored) => mint;
-  dynamic returnUnboxedDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableInt(X ignored) => mint;
-  dynamic returnBoxedNullableDouble(X ignored) => 3.3;
-  dynamic returnBoxedIntOrDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableX(X ignored) => X();
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 3;
+  dynamic returnUnboxedInt(X? ignored) => mint;
+  dynamic returnUnboxedDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableInt(X? ignored) => mint;
+  dynamic returnBoxedNullableDouble(X? ignored) => 3.3;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableX(X? ignored) => X();
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
index 0811f05..40650ad 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
@@ -1,9 +1,9 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
@@ -20,7 +20,7 @@
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  abstract method returnBoxedX() → dynamic;
 }
 class Impl1 extends core::Object implements self::Interface {
-  synthetic constructor •() → self::Impl1*
+  synthetic constructor •() → self::Impl1
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b]  method takePositional([@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
@@ -53,7 +53,7 @@
     return new self::X::•();
 }
 class BaseImpl2 extends core::Object {
-  synthetic constructor •() → self::BaseImpl2*
+  synthetic constructor •() → self::BaseImpl2
     : super core::Object::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b]  method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
@@ -86,7 +86,7 @@
     return new self::X::•();
 }
 class SubImpl3 extends self::BaseImpl2 implements self::Interface {
-  synthetic constructor •() → self::SubImpl3*
+  synthetic constructor •() → self::SubImpl3
     : super self::BaseImpl2::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b]  method takePositional([@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=!] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
@@ -119,55 +119,55 @@
     return new self::X::•();
 }
 static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
 static method main() → dynamic {
-  final core::List<core::Object*>* values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object*>] core::_GrowableList::_literal3<core::Object*>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
-  final self::Impl1* a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int*) →* core::Object*} as self::Impl1*;
-  final self::BaseImpl2* b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int*) →* core::Object*} as self::BaseImpl2*;
-  final self::SubImpl3* c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::SubImpl3*;
-  final self::Interface* d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::Interface*;
-  [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  b.{self::BaseImpl2::takePositional}(2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  d.{self::Interface::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(){(self::X*) →* dynamic});
+  final core::List<core::Object> values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object>] core::_GrowableList::_literal3<core::Object>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
+  final self::Impl1 a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Impl1;
+  final self::BaseImpl2 b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int) → core::Object} as{ForNonNullableByDefault} self::BaseImpl2;
+  final self::SubImpl3 c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::SubImpl3;
+  final self::Interface d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Interface;
+  [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  b.{self::BaseImpl2::takePositional}(2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  d.{self::Interface::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(){(self::X?) → dynamic});
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
index ba97287..f8637c8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 final bool kTrue = int.parse('1') == 1 ? true : false;
 final bool kFalse = int.parse('1') == 2 ? true : false;
 int get mint => 0xaabbccddaabbccdd;
@@ -18,7 +16,7 @@
 
 abstract class Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -28,20 +26,20 @@
       dynamic boxedNullableX,
       dynamic boxedX);
 
-  dynamic returnUnboxedSmi(X ignored);
-  dynamic returnUnboxedInt(X ignored);
-  dynamic returnUnboxedDouble(X ignored);
-  dynamic returnBoxedNullableInt(X ignored);
-  dynamic returnBoxedNullableDouble(X ignored);
-  dynamic returnBoxedIntOrDouble(X ignored);
-  dynamic returnBoxedNullableIntOrDouble(X ignored);
-  dynamic returnBoxedNullableX(X ignored);
-  dynamic returnBoxedX(X ignored);
+  dynamic returnUnboxedSmi(X? ignored);
+  dynamic returnUnboxedInt(X? ignored);
+  dynamic returnUnboxedDouble(X? ignored);
+  dynamic returnBoxedNullableInt(X? ignored);
+  dynamic returnBoxedNullableDouble(X? ignored);
+  dynamic returnBoxedIntOrDouble(X? ignored);
+  dynamic returnBoxedNullableIntOrDouble(X? ignored);
+  dynamic returnBoxedNullableX(X? ignored);
+  dynamic returnBoxedX(X? ignored);
 }
 
 class Impl1 implements Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -60,20 +58,20 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 1;
-  dynamic returnUnboxedInt(X ignored) => 1;
-  dynamic returnUnboxedDouble(X ignored) => 1.1;
-  dynamic returnBoxedNullableInt(X ignored) => null;
-  dynamic returnBoxedNullableDouble(X ignored) => null;
-  dynamic returnBoxedIntOrDouble(X ignored) => 1;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => null;
-  dynamic returnBoxedNullableX(X ignored) => null;
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 1;
+  dynamic returnUnboxedInt(X? ignored) => 1;
+  dynamic returnUnboxedDouble(X? ignored) => 1.1;
+  dynamic returnBoxedNullableInt(X? ignored) => null;
+  dynamic returnBoxedNullableDouble(X? ignored) => null;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 1;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => null;
+  dynamic returnBoxedNullableX(X? ignored) => null;
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 class BaseImpl2 {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -92,20 +90,20 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 2;
-  dynamic returnUnboxedInt(X ignored) => mint;
-  dynamic returnUnboxedDouble(X ignored) => 2.2;
-  dynamic returnBoxedNullableInt(X ignored) => 2;
-  dynamic returnBoxedNullableDouble(X ignored) => 2.2;
-  dynamic returnBoxedIntOrDouble(X ignored) => 2.2;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => 2;
-  dynamic returnBoxedNullableX(X ignored) => X();
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 2;
+  dynamic returnUnboxedInt(X? ignored) => mint;
+  dynamic returnUnboxedDouble(X? ignored) => 2.2;
+  dynamic returnBoxedNullableInt(X? ignored) => 2;
+  dynamic returnBoxedNullableDouble(X? ignored) => 2.2;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 2.2;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => 2;
+  dynamic returnBoxedNullableX(X? ignored) => X();
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 class SubImpl3 extends BaseImpl2 implements Interface {
   void takePositional(
-      int unboxedSmi,
+      int? unboxedSmi,
       dynamic unboxedInt,
       dynamic unboxedDouble,
       dynamic boxedNullableInt,
@@ -124,15 +122,15 @@
     use(boxedX);
   }
 
-  dynamic returnUnboxedSmi(X ignored) => 3;
-  dynamic returnUnboxedInt(X ignored) => mint;
-  dynamic returnUnboxedDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableInt(X ignored) => mint;
-  dynamic returnBoxedNullableDouble(X ignored) => 3.3;
-  dynamic returnBoxedIntOrDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableIntOrDouble(X ignored) => 3.3;
-  dynamic returnBoxedNullableX(X ignored) => X();
-  dynamic returnBoxedX(X ignored) => X();
+  dynamic returnUnboxedSmi(X? ignored) => 3;
+  dynamic returnUnboxedInt(X? ignored) => mint;
+  dynamic returnUnboxedDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableInt(X? ignored) => mint;
+  dynamic returnBoxedNullableDouble(X? ignored) => 3.3;
+  dynamic returnBoxedIntOrDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableIntOrDouble(X? ignored) => 3.3;
+  dynamic returnBoxedNullableX(X? ignored) => X();
+  dynamic returnBoxedX(X? ignored) => X();
 }
 
 main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
index d22492c..2405a88 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
@@ -1,29 +1,29 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
 abstract class Interface extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  abstract method returnUnboxedSmi(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  abstract method returnUnboxedInt(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  abstract method returnUnboxedDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  abstract method returnBoxedNullableInt(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  abstract method returnBoxedNullableDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  abstract method returnBoxedIntOrDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  abstract method returnBoxedNullableIntOrDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  abstract method returnBoxedNullableX(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  abstract method returnBoxedX(self::X* ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  abstract method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  abstract method returnUnboxedSmi(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  abstract method returnUnboxedInt(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  abstract method returnUnboxedDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  abstract method returnBoxedNullableInt(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  abstract method returnBoxedNullableDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  abstract method returnBoxedIntOrDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  abstract method returnBoxedNullableIntOrDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  abstract method returnBoxedNullableX(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  abstract method returnBoxedX(self::X? ignored) → dynamic;
 }
 class Impl1 extends core::Object implements self::Interface {
-  synthetic constructor •() → self::Impl1*
+  synthetic constructor •() → self::Impl1
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
     self::use(unboxedInt);
     self::use(unboxedDouble);
     self::use(boxedNullableInt);
@@ -33,30 +33,30 @@
     self::use(boxedNullableX);
     self::use(boxedX);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi(self::X? ignored) → dynamic
     return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt(self::X? ignored) → dynamic
     return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble(self::X? ignored) → dynamic
     return 1.1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt(self::X? ignored) → dynamic
     return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble(self::X? ignored) → dynamic
     return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble(self::X? ignored) → dynamic
     return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble(self::X? ignored) → dynamic
     return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX(self::X? ignored) → dynamic
     return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX(self::X? ignored) → dynamic
     return new self::X::•();
 }
 class BaseImpl2 extends core::Object {
-  synthetic constructor •() → self::BaseImpl2*
+  synthetic constructor •() → self::BaseImpl2
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] core::int* unboxedSmi, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] core::int? unboxedSmi, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
     self::use(unboxedInt);
     self::use(unboxedDouble);
     self::use(boxedNullableInt);
@@ -66,30 +66,30 @@
     self::use(boxedNullableX);
     self::use(boxedX);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return new self::X::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
     return new self::X::•();
 }
 class SubImpl3 extends self::BaseImpl2 implements self::Interface {
-  synthetic constructor •() → self::SubImpl3*
+  synthetic constructor •() → self::SubImpl3
     : super self::BaseImpl2::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
     self::use(unboxedInt);
     self::use(unboxedDouble);
     self::use(boxedNullableInt);
@@ -99,85 +99,85 @@
     self::use(boxedNullableX);
     self::use(boxedX);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedSmi(self::X? ignored) → dynamic
     return 3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i]  method returnUnboxedInt(self::X? ignored) → dynamic
     return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d]  method returnUnboxedDouble(self::X? ignored) → dynamic
     return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  method returnBoxedNullableInt(self::X? ignored) → dynamic
     return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  method returnBoxedNullableDouble(self::X? ignored) → dynamic
     return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14]  method returnBoxedIntOrDouble(self::X? ignored) → dynamic
     return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16]  method returnBoxedNullableIntOrDouble(self::X? ignored) → dynamic
     return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18]  method returnBoxedNullableX(self::X? ignored) → dynamic
     return new self::X::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20]  method returnBoxedX(self::X? ignored) → dynamic
     return new self::X::•();
 }
 static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
 static method main() → dynamic {
-  final core::List<core::Object*>* values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object*>] core::_GrowableList::_literal3<core::Object*>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
-  final self::Impl1* a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int*) →* core::Object*} as self::Impl1*;
-  final self::BaseImpl2* b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int*) →* core::Object*} as self::BaseImpl2*;
-  final self::SubImpl3* c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::SubImpl3*;
-  final self::Interface* d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::Interface*;
-  [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  b.{self::BaseImpl2::takePositional}(2, 2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  d.{self::Interface::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(null){(self::X*) →* dynamic});
-  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(null){(self::X*) →* dynamic});
-  self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(null){(self::X*) →* dynamic});
-  self::use(d.{self::Interface::takePositional}{(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void});
-  self::use(d.{self::Interface::returnUnboxedSmi}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnUnboxedInt}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnUnboxedDouble}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedNullableInt}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedNullableDouble}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedIntOrDouble}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedNullableIntOrDouble}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedNullableX}{(self::X*) →* dynamic});
-  self::use(d.{self::Interface::returnBoxedX}{(self::X*) →* dynamic});
+  final core::List<core::Object> values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object>] core::_GrowableList::_literal3<core::Object>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
+  final self::Impl1 a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Impl1;
+  final self::BaseImpl2 b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int) → core::Object} as{ForNonNullableByDefault} self::BaseImpl2;
+  final self::SubImpl3 c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::SubImpl3;
+  final self::Interface d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Interface;
+  [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  b.{self::BaseImpl2::takePositional}(2, 2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  d.{self::Interface::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(null){(self::X?) → dynamic});
+  self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(null){(self::X?) → dynamic});
+  self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(null){(self::X?) → dynamic});
+  self::use(d.{self::Interface::takePositional}{(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void});
+  self::use(d.{self::Interface::returnUnboxedSmi}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnUnboxedInt}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnUnboxedDouble}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedNullableInt}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedNullableDouble}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedIntOrDouble}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedNullableIntOrDouble}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedNullableX}{(self::X?) → dynamic});
+  self::use(d.{self::Interface::returnBoxedX}{(self::X?) → dynamic});
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
index 0142249..3522029 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 final bool kTrue = int.parse('1') == 1 ? true : false;
 final bool kFalse = int.parse('1') == 2 ? true : false;
 int get mint => 0xaabbccddaabbccdd;
@@ -17,7 +15,7 @@
 class X {}
 
 void takePositional(
-    int unboxedSmi,
+    int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
@@ -37,7 +35,7 @@
 }
 
 void takeOptional(
-    [int unboxedSmi,
+    [int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
@@ -57,7 +55,7 @@
 }
 
 void takeNamed(
-    {int unboxedSmi,
+    {int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
index 2577681..3615da2 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
@@ -1,19 +1,19 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2 ?{core::bool} true : false;
 static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
@@ -48,33 +48,33 @@
   self::use(boxedX);
 }
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedSmi() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedInt() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
 [@vm.unboxing-info.metadata=()->d]static method returnUnboxedDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2;
 static method returnBoxedNullableInt() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
 static method returnBoxedNullableDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null;
 static method returnBoxedIntOrDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
 static method returnBoxedNullableIntOrDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
 static method returnBoxedNullableX() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null;
 static method returnBoxedX() → dynamic
   return new self::X::•();
 @#C3
-static method returnBoxedSmiFromEntryPoint() → core::int*
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
+static method returnBoxedSmiFromEntryPoint() → core::int
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
 @#C3
-static method takeBoxedSmiFromEntryPoint(core::int* value) → void {}
+static method takeBoxedSmiFromEntryPoint(core::int value) → void {}
 static method main() → dynamic {
-  let final core::int* #t1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t9 = new self::X::•() in self::takePositional(#t2, #t3, #t4, #t5, #t6, #t7, #t8, #t9);
-  let final core::int* #t10 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t11 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t12 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t13 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t14 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t15 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t16 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t17 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t18 = new self::X::•() in self::takeOptional(#t11, #t12, #t13, #t14, #t15, #t16, #t17, #t18);
-  let final core::int* #t19 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t20 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t21 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t22 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t23 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t24 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t25 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t26 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t27 = new self::X::•() in self::takeNamed(#t24, #t23, #t22, #t25, #t26, #t27, #t21, #t20);
-  self::takeBoxedSmiFromEntryPoint([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2);
+  let final core::int #t1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2 in let final core::int #t2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double #t3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2 in let final core::int? #t4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double? #t5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null in let final core::num #t6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num? #t7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X? #t8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null in let final self::X #t9 = new self::X::•() in self::takePositional(#t2, #t3, #t4, #t5, #t6, #t7, #t8, #t9);
+  let final core::int #t10 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2 in let final core::int #t11 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double #t12 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2 in let final core::int? #t13 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double? #t14 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null in let final core::num #t15 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num? #t16 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X? #t17 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null in let final self::X #t18 = new self::X::•() in self::takeOptional(#t11, #t12, #t13, #t14, #t15, #t16, #t17, #t18);
+  let final core::int #t19 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2 in let final core::int #t20 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double #t21 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2 in let final core::int? #t22 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double? #t23 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null in let final core::num #t24 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num? #t25 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X? #t26 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null in let final self::X #t27 = new self::X::•() in self::takeNamed(#t24, #t23, #t22, #t25, #t26, #t27, #t21, #t20);
+  self::takeBoxedSmiFromEntryPoint([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2);
   self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnUnboxedSmi());
   self::use([@vm.inferred-type.metadata=int] self::returnUnboxedInt());
   self::use([@vm.inferred-type.metadata=dart.core::_Double] self::returnUnboxedDouble());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
index 6245c0d..21788ee 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 final bool kTrue = int.parse('1') == 1 ? true : false;
 final bool kFalse = int.parse('1') == 2 ? true : false;
 int get mint => 0xaabbccddaabbccdd;
@@ -17,7 +15,7 @@
 class X {}
 
 void takePositional(
-    int unboxedSmi,
+    int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
@@ -37,7 +35,7 @@
 }
 
 void takeOptional(
-    [int unboxedSmi,
+    [int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
@@ -57,7 +55,7 @@
 }
 
 void takeNamed(
-    {int unboxedSmi,
+    {int? unboxedSmi,
     dynamic unboxedInt,
     dynamic unboxedDouble,
     dynamic boxedNullableInt,
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
index 8167df0..3ab3d19 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
@@ -1,23 +1,23 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class X extends core::Object {
-  synthetic constructor •() → self::X*
+  synthetic constructor •() → self::X
     : super core::Object::•()
     ;
 }
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2 ?{core::bool} true : false;
 static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
   return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
 static method use(dynamic object) → void {
   self::usedObject == null ?{dynamic} self::usedObject = object : null;
 }
-static method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+static method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
   self::use(unboxedInt);
   self::use(unboxedDouble);
   self::use(boxedNullableInt);
@@ -27,7 +27,7 @@
   self::use(boxedNullableX);
   self::use(boxedX);
 }
-static method takeOptional([core::int* unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1]) → void {
+static method takeOptional([core::int? unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1]) → void {
   self::use(unboxedInt);
   self::use(unboxedDouble);
   self::use(boxedNullableInt);
@@ -37,7 +37,7 @@
   self::use(boxedNullableX);
   self::use(boxedX);
 }
-static method takeNamed({core::int* unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1}) → void {
+static method takeNamed({core::int? unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1}) → void {
   self::use(unboxedInt);
   self::use(unboxedDouble);
   self::use(boxedNullableInt);
@@ -48,27 +48,27 @@
   self::use(boxedX);
 }
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedSmi() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedInt() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
 [@vm.unboxing-info.metadata=()->d]static method returnUnboxedDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2;
 static method returnBoxedNullableInt() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
 static method returnBoxedNullableDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null;
 static method returnBoxedIntOrDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
 static method returnBoxedNullableIntOrDouble() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
 static method returnBoxedNullableX() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null;
+  return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null;
 static method returnBoxedX() → dynamic
   return new self::X::•();
 static method main() → dynamic {
-  self::takePositional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
-  self::takeOptional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
-  self::takeNamed(unboxedSmi: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, unboxedInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, unboxedDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, boxedNullableInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, boxedNullableDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, boxedIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, boxedNullableIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, boxedNullableX: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, boxedX: new self::X::•());
+  self::takePositional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, new self::X::•());
+  self::takeOptional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, new self::X::•());
+  self::takeNamed(unboxedSmi: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, unboxedInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, unboxedDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, boxedNullableInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, boxedNullableDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, boxedIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, boxedNullableIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, boxedNullableX: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, boxedX: new self::X::•());
   self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnUnboxedSmi());
   self::use([@vm.inferred-type.metadata=int] self::returnUnboxedInt());
   self::use([@vm.inferred-type.metadata=dart.core::_Double] self::returnUnboxedDouble());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
index 0f85cb8..d7b90d8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
@@ -5,15 +5,13 @@
 // Tests tree shaking of field initializer for a write-only field.
 // Regression test for https://github.com/dart-lang/sdk/issues/35632.
 
-// @dart=2.9
-
 class A {
   A() {
     print('A');
   }
 }
 
-var field = A();
+A? field = A();
 
 class B {
   B() {
@@ -22,7 +20,7 @@
 }
 
 class C {
-  var instanceField = new B();
+  B? instanceField = new B();
 }
 
 void main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
index cc689dc..e544ddf 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
@@ -1,18 +1,18 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class B extends core::Object {
-  constructor •() → self::B*
+  constructor •() → self::B
     : super core::Object::•() {
     core::print("B");
   }
 }
 class C extends core::Object {
-  synthetic constructor •() → self::C*
+  synthetic constructor •() → self::C
     : dynamic #t1 = new self::B::•(), super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  set instanceField(self::B* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  set /*isLegacy*/ instanceField(self::B? value) → void;
 }
 static method main() → void {
   null;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
index ec7e83f..45dd11b 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
@@ -4,8 +4,6 @@
 
 // Test for tree shaking of write-only fields.
 
-// @dart=2.9
-
 import "package:expect/expect.dart";
 
 foo() {}
@@ -33,12 +31,12 @@
 
 class C<T> {
   // Should be replaced with setter.
-  T bar;
+  T? bar;
 }
 
 class D implements C<int> {
   // Should be replaced with setter.
-  int bar;
+  int? bar;
 }
 
 class E {
@@ -61,7 +59,7 @@
 
 class H {
   // Should be replaced with setter.
-  int unused6;
+  int? unused6;
 }
 
 class I extends H {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
index 6e40a3c..057cfe3 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 import "package:expect/expect.dart" as exp;
@@ -6,45 +6,45 @@
 import "package:expect/expect.dart";
 
 class A extends core::Object {
-  synthetic constructor •() → self::A*
+  synthetic constructor •() → self::A
     : dynamic #t1 = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo(), super core::Object::•()
     ;
 }
 class B extends core::Object {
-  constructor •() → self::B*
+  constructor •() → self::B
     : dynamic #t2 = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo(), super core::Object::•()
     ;
 }
-abstract class C<T extends core::Object* = dynamic> extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  abstract set bar(generic-covariant-impl self::C::T* value) → void;
+abstract class C<T extends core::Object? = dynamic> extends core::Object {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  abstract set /*isLegacy*/ bar(generic-covariant-impl self::C::T? value) → void;
 }
-class D extends core::Object implements self::C<core::int*> {
-  synthetic constructor •() → self::D*
+class D extends core::Object implements self::C<core::int> {
+  synthetic constructor •() → self::D
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  set bar(generic-covariant-impl core::int* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1]  set /*isLegacy*/ bar(generic-covariant-impl core::int? value) → void;
 }
 abstract class E extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract get bar() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  abstract get /*isLegacy*/ bar() → core::int;
 }
 class F extends core::Object implements self::E {
-  synthetic constructor •() → self::F*
+  synthetic constructor •() → self::F
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  get bar() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i]  get bar() → core::int
     return 42;
 }
 class G extends core::Object /*hasConstConstructor*/  {
-[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i]  final field core::int* bazz;
+[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i]  final field core::int bazz;
 }
 abstract class H extends core::Object {
-  synthetic constructor •() → self::H*
+  synthetic constructor •() → self::H
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4]  set unused6(core::int* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4]  set /*isLegacy*/ unused6(core::int? value) → void;
 }
 class I extends self::H {
-  synthetic constructor •() → self::I*
+  synthetic constructor •() → self::I
     : super self::H::•()
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method foo() → dynamic {
@@ -55,14 +55,14 @@
 static method main() → void {
   new self::A::•();
   new self::B::•();
-  self::C<core::num*>* c = new self::D::•();
-  exp::Expect::throws<dynamic>(() → Null {
-    [@vm.call-site-attributes.metadata=receiverType:#lib::C<dart.core::num*>*] [@vm.direct-call.metadata=#lib::D.bar] c.{self::C::bar} = 3.14;
+  self::C<core::num> c = new self::D::•();
+  exp::Expect::throws<dynamic>(() → void {
+    [@vm.call-site-attributes.metadata=receiverType:#lib::C<dart.core::num>] [@vm.direct-call.metadata=#lib::D.bar] c.{self::C::bar} = 3.14;
   });
-  self::E* e = new self::F::•();
-  let final core::int* #t3 = [@vm.direct-call.metadata=#lib::F.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] e.{self::E::bar}{core::int*} in exp::Expect::equals();
+  self::E e = new self::F::•();
+  let final core::int #t3 = [@vm.direct-call.metadata=#lib::F.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] e.{self::E::bar}{core::int} in exp::Expect::equals();
   exp::Expect::isTrue(![@vm.inferred-type.metadata=dart.core::bool] core::identical(#C2, #C4));
-  [@vm.direct-call.metadata=#lib::I.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::I::•().{self::I::foo}(){() →* dynamic};
+  [@vm.direct-call.metadata=#lib::I.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::I::•().{self::I::foo}(){() → dynamic};
   5;
 }
 constants  {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart
index ea59290..a777b1b 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test for tree shaking of write-only late fields.
-// This test requires non-nullable experiment.
-
-// @dart = 2.10
 
 foo() {}
 
diff --git a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
index 41fdccc..33f4458 100644
--- a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
+++ b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
@@ -2,14 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 const bool constTrue = const bool.fromEnvironment('test.define.isTrue');
 const bool constFalse = const bool.fromEnvironment('test.define.isFalse');
 const bool constTrue2 = !constFalse;
 const bool constFalse2 = const bool.fromEnvironment('test.define.notDefined');
 
-bool foo() => null;
+bool? foo() => null;
 
 void testSimpleConditions() {
   if (constTrue) {
@@ -27,10 +25,10 @@
 }
 
 void testAndConditions() {
-  if (constTrue && foo()) {
+  if (constTrue && foo()!) {
     print('1_yes');
   }
-  if (constFalse && foo()) {
+  if (constFalse && foo()!) {
     print('2_no');
   }
   if (constTrue && constFalse) {
@@ -42,10 +40,10 @@
 }
 
 void testOrConditions() {
-  if (constTrue || foo()) {
+  if (constTrue || foo()!) {
     print('1_yes');
   }
-  if (constFalse || foo()) {
+  if (constFalse || foo()!) {
     print('2_yes');
   }
   if (constFalse || constFalse2) {
@@ -63,54 +61,54 @@
   if (!constFalse) {
     print('2_yes');
   }
-  if (!(!(!constTrue && foo()) || foo())) {
+  if (!(!(!constTrue && foo()!) || foo()!)) {
     print('3_no');
   }
 }
 
 testConditionalExpressions() {
   print(!constFalse && constTrue ? '1_yes' : '2_no');
-  print(constFalse && foo() ? '3_no' : '4_yes ${foo()}');
+  print(constFalse && foo()! ? '3_no' : '4_yes ${foo()}');
 }
 
 void testAsserts() {
-  assert(foo());
-  assert(!foo(), "oops!");
+  assert(foo()!);
+  assert(!foo()!, "oops!");
 }
 
 class TestAssertInitializer {
-  TestAssertInitializer() : assert(foo()) {}
+  TestAssertInitializer() : assert(foo()!) {}
 }
 
 testRemovalOfStatementBodies() {
-  if (foo()) assert(foo());
-  while (foo()) assert(foo());
-  do assert(foo()); while (foo());
-  for (;;) assert(foo());
-  for (var i in [1, 2]) assert(foo());
+  if (foo()!) assert(foo()!);
+  while (foo()!) assert(foo()!);
+  do assert(foo()!); while (foo()!);
+  for (;;) assert(foo()!);
+  for (var i in [1, 2]) assert(foo()!);
   try {
-    assert(foo());
+    assert(foo()!);
   } finally {
-    assert(foo());
+    assert(foo()!);
   }
   try {
-    assert(foo());
+    assert(foo()!);
   } catch (e) {
-    assert(foo());
+    assert(foo()!);
   }
   try {
-    assert(foo());
+    assert(foo()!);
   } catch (e) {
-    assert(foo());
+    assert(foo()!);
     rethrow;
   }
   switch (42) {
     case 10:
-      assert(foo());
+      assert(foo()!);
   }
   switch (42) {
     default:
-      assert(foo());
+      assert(foo()!);
   }
 }
 
diff --git a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
index e9346d5..4bf2ed9 100644
--- a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
+++ b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
@@ -1,26 +1,16 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
 class TestAssertInitializer extends core::Object {
-  constructor •() → self::TestAssertInitializer*
+  constructor •() → self::TestAssertInitializer
     : super core::Object::•() {}
-  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
-  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
-  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
-  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
-  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
-  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
-  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
-  abstract member-signature method toString() → core::String*; -> core::Object::toString
-  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
-  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static const field core::bool* constTrue = #C1;
-static const field core::bool* constFalse = #C2;
-static const field core::bool* constTrue2 = #C1;
-static const field core::bool* constFalse2 = #C2;
-static method foo() → core::bool*
+static const field core::bool constTrue = #C1;
+static const field core::bool constFalse = #C2;
+static const field core::bool constTrue2 = #C1;
+static const field core::bool constFalse2 = #C2;
+static method foo() → core::bool?
   return null;
 static method testSimpleConditions() → void {
   {
@@ -31,7 +21,7 @@
   }
 }
 static method testAndConditions() → void {
-  if((#C1) && self::foo()) {
+  if((#C1) && self::foo()!) {
     core::print("1_yes");
   }
 }
@@ -39,7 +29,7 @@
   {
     core::print("1_yes");
   }
-  if((#C2) || self::foo()) {
+  if((#C2) || self::foo()!) {
     core::print("2_yes");
   }
   {
@@ -57,25 +47,25 @@
 }
 static method testAsserts() → void {}
 static method testRemovalOfStatementBodies() → dynamic {
-  if(self::foo()) {
+  if(self::foo()!) {
   }
-  while (self::foo()) {
+  while (self::foo()!) {
   }
   do {
   }
-  while (self::foo())
+  while (self::foo()!)
   for (; ; ) {
   }
   {
-    core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal2<core::int*>(1, 2).{core::Iterable::iterator}{core::Iterator<core::int*>*};
+    core::Iterator<core::int> :sync-for-iterator = core::_GrowableList::_literal2<core::int>(1, 2).{core::Iterable::iterator}{core::Iterator<core::int>};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-      core::int* i = :sync-for-iterator.{core::Iterator::current}{core::int*};
+      core::int i = :sync-for-iterator.{core::Iterator::current}{core::int};
     }
   }
   {}
   try {
   }
-  on dynamic catch(final dynamic e) {
+  on core::Object catch(final core::Object e) {
   }
   {}
   switch(42) {
@@ -89,7 +79,7 @@
       {}
   }
 }
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
   self::testSimpleConditions();
   self::testAndConditions();
   self::testOrConditions();
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 0ca25ee..0b72f7f 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -19,6 +19,7 @@
 #include "vm/lockers.h"
 #include "vm/longjump.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/object.h"
 #include "vm/object_graph_copy.h"
 #include "vm/object_store.h"
@@ -123,10 +124,10 @@
           new Message(destination_port_id, handle, Message::kNormalPriority));
       PortMap::PostMessage(std::move(message));
     } else {
-      MessageWriter writer(can_send_any_object);
       // TODO(turnidge): Throw an exception when the return value is false?
-      PortMap::PostMessage(writer.WriteMessage(obj, destination_port_id,
-                                               Message::kNormalPriority));
+      PortMap::PostMessage(WriteMessage(can_send_any_object, obj,
+                                        destination_port_id,
+                                        Message::kNormalPriority));
     }
   }
   return Object::null();
@@ -572,8 +573,7 @@
   if (message->IsRaw()) {
     return Instance::RawCast(message->raw_obj());
   } else {
-    MessageSnapshotReader reader(message, thread);
-    const Object& obj = Object::Handle(zone, reader.ReadObject());
+    const Object& obj = Object::Handle(zone, ReadMessage(thread, message));
     ASSERT(!obj.IsError());
     return Instance::RawCast(obj.ptr());
   }
@@ -792,10 +792,10 @@
       isolate->message_handler()->increment_paused();
     }
     {
-      MessageWriter writer(/*can_send_any_object=*/false);
       // If parent isolate died, we ignore the fact that we cannot notify it.
-      PortMap::PostMessage(writer.WriteMessage(message, state_->parent_port(),
-                                               Message::kNormalPriority));
+      PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
+                                        message, state_->parent_port(),
+                                        Message::kNormalPriority));
     }
 
     return true;
@@ -866,9 +866,9 @@
       // serializable this will throw an exception.
       SerializedObjectBuffer message_buffer;
       {
-        MessageWriter writer(/* can_send_any_object = */ true);
-        message_buffer.set_message(writer.WriteMessage(
-            message, ILLEGAL_PORT, Message::kNormalPriority));
+        message_buffer.set_message(WriteMessage(
+            /* can_send_any_object */ true, message, ILLEGAL_PORT,
+            Message::kNormalPriority));
       }
 
       const char* utf8_package_config =
@@ -951,14 +951,14 @@
   SerializedObjectBuffer arguments_buffer;
   SerializedObjectBuffer message_buffer;
   {
-    MessageWriter writer(/* can_send_any_object = */ false);
-    arguments_buffer.set_message(
-        writer.WriteMessage(args, ILLEGAL_PORT, Message::kNormalPriority));
+    arguments_buffer.set_message(WriteMessage(/* can_send_any_object */ false,
+                                              args, ILLEGAL_PORT,
+                                              Message::kNormalPriority));
   }
   {
-    MessageWriter writer(/* can_send_any_object = */ false);
-    message_buffer.set_message(
-        writer.WriteMessage(message, ILLEGAL_PORT, Message::kNormalPriority));
+    message_buffer.set_message(WriteMessage(/* can_send_any_object */ false,
+                                            message, ILLEGAL_PORT,
+                                            Message::kNormalPriority));
   }
 
   // Canonicalize the uri with respect to the current isolate.
@@ -1031,9 +1031,8 @@
   // Ensure message writer (and it's resources, e.g. forwarding tables) are
   // cleaned up before handling interrupts.
   {
-    MessageWriter writer(false);
-    PortMap::PostMessage(
-        writer.WriteMessage(msg, port.Id(), Message::kOOBPriority));
+    PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, msg,
+                                      port.Id(), Message::kOOBPriority));
   }
 
   // Drain interrupts before running so any IMMEDIATE operations on the current
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index f172831..10fc93a 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -6,6 +6,7 @@
 
 #include "lib/invocation_mirror.h"
 #include "vm/code_patcher.h"
+#include "vm/dart_entry.h"
 #include "vm/exceptions.h"
 #include "vm/heap/heap.h"
 #include "vm/native_entry.h"
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 44d6148..51ff5ea 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -11,6 +11,7 @@
 #include "vm/kernel_isolate.h"
 #include "vm/message.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
 #include "vm/port.h"
@@ -59,10 +60,10 @@
                 Smi::Handle(thread->zone(), Smi::New(Message::kServiceOOBMsg)));
 
   // Serialize message.
-  MessageWriter writer(false);
   // TODO(turnidge): Throw an exception when the return value is false?
-  bool result = PortMap::PostMessage(
-      writer.WriteMessage(message, sp.Id(), Message::kOOBPriority));
+  bool result = PortMap::PostMessage(WriteMessage(
+      /* can_send_any_object */ false, message, sp.Id(),
+      Message::kOOBPriority));
   return Bool::Get(result).ptr();
 #else
   return Object::null();
diff --git a/runtime/tools/dartfuzz/dartfuzz_test.dart b/runtime/tools/dartfuzz/dartfuzz_test.dart
index 639935b..fb826ff 100644
--- a/runtime/tools/dartfuzz/dartfuzz_test.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_test.dart
@@ -420,7 +420,6 @@
           timeoutSeeds.add(seed);
           break;
         default:
-          reportDivergence(result1, result2);
           // Both had an error.
           numSkipped++;
           skippedSeeds.add(seed);
@@ -472,9 +471,7 @@
     var report = generateReport(result1, result2);
     print('\n$isolate: !DIVERGENCE! $version:$seed ($report)');
     if (result1.exitCode == result2.exitCode) {
-      if (result1.exitCode == 254) {
-        print('\ncompile-time error:\n${result1.output}\n${result1.stderr}\n');
-      } else if (numOutputLines > 0) {
+      if (numOutputLines > 0) {
         // Only report the actual output divergence details up to
         // numOutputLines, since this output may be lengthy and should be
         // reproducable anyway.
diff --git a/runtime/vm/allocation.cc b/runtime/vm/allocation.cc
index aa36221..4239026 100644
--- a/runtime/vm/allocation.cc
+++ b/runtime/vm/allocation.cc
@@ -24,7 +24,6 @@
 }
 
 void* ZoneAllocated::operator new(uword size, Zone* zone) {
-  ASSERT(Thread::Current()->ZoneIsOwnedByThread(zone));
   return Allocate(size, zone);
 }
 
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index e2a6869..2b5683b 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -18,6 +18,7 @@
 #include "vm/clustered_snapshot.h"
 #include "vm/dart_api_impl.h"
 #include "vm/datastream.h"
+#include "vm/message_snapshot.h"
 #include "vm/stack_frame.h"
 #include "vm/timer.h"
 
@@ -517,13 +518,12 @@
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
-    MessageWriter writer(true);
-    std::unique_ptr<Message> message = writer.WriteMessage(
-        null_object, ILLEGAL_PORT, Message::kNormalPriority);
+    std::unique_ptr<Message> message =
+        WriteMessage(/* can_send_any_object */ true, null_object, ILLEGAL_PORT,
+                     Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message.get(), thread);
-    reader.ReadObject();
+    ReadMessage(thread, message.get());
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
@@ -540,13 +540,12 @@
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
-    MessageWriter writer(true);
     std::unique_ptr<Message> message =
-        writer.WriteMessage(smi_object, ILLEGAL_PORT, Message::kNormalPriority);
+        WriteMessage(/* can_send_any_object */ true, smi_object, ILLEGAL_PORT,
+                     Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message.get(), thread);
-    reader.ReadObject();
+    ReadMessage(thread, message.get());
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
@@ -565,13 +564,12 @@
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
-    MessageWriter writer(true);
-    std::unique_ptr<Message> message = writer.WriteMessage(
-        array_object, ILLEGAL_PORT, Message::kNormalPriority);
+    std::unique_ptr<Message> message = WriteMessage(
+        /* can_send_any_object */ true, array_object, ILLEGAL_PORT,
+        Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message.get(), thread);
-    reader.ReadObject();
+    ReadMessage(thread, message.get());
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
@@ -599,13 +597,12 @@
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
-    MessageWriter writer(true);
     std::unique_ptr<Message> message =
-        writer.WriteMessage(map, ILLEGAL_PORT, Message::kNormalPriority);
+        WriteMessage(/* can_send_any_object */ true, map, ILLEGAL_PORT,
+                     Message::kNormalPriority);
 
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message.get(), thread);
-    reader.ReadObject();
+    ReadMessage(thread, message.get());
   }
   timer.Stop();
   int64_t elapsed_time = timer.TotalElapsedTime();
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 9eec30d..b3beb4d 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -16,6 +16,7 @@
 #include "vm/compiler/api/print_filter.h"
 #include "vm/compiler/assembler/disassembler.h"
 #include "vm/dart.h"
+#include "vm/dart_entry.h"
 #include "vm/dispatch_table.h"
 #include "vm/flag_list.h"
 #include "vm/growable_array.h"
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 1744e17..7699857 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -24,6 +24,7 @@
 #include "vm/compiler/ffi/native_location.h"
 #include "vm/compiler/ffi/native_type.h"
 #include "vm/compiler/method_recognizer.h"
+#include "vm/dart_entry.h"
 #include "vm/flags.h"
 #include "vm/growable_array.h"
 #include "vm/native_entry.h"
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index fa95787..b0776be 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -8,6 +8,7 @@
 #include "include/dart_api.h"
 #include "include/dart_tools_api.h"
 #include "vm/allocation.h"
+#include "vm/isolate.h"
 #include "vm/snapshot.h"
 
 namespace dart {
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 283841a..86cd097 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -32,6 +32,7 @@
 #include "vm/lockers.h"
 #include "vm/message.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/native_entry.h"
 #include "vm/native_symbol.h"
 #include "vm/object.h"
@@ -2161,17 +2162,10 @@
     return false;
   }
 
-  // Smis and null can be sent without serialization.
-  ObjectPtr raw_obj = Api::UnwrapHandle(handle);
-  if (ApiObjectConverter::CanConvert(raw_obj)) {
-    return PortMap::PostMessage(
-        Message::New(port_id, raw_obj, Message::kNormalPriority));
-  }
-
-  const Object& object = Object::Handle(Z, raw_obj);
-  MessageWriter writer(false);
-  return PortMap::PostMessage(
-      writer.WriteMessage(object, port_id, Message::kNormalPriority));
+  const Object& object = Object::Handle(Z, Api::UnwrapHandle(handle));
+  return PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
+                                           object, port_id,
+                                           Message::kNormalPriority));
 }
 
 DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id) {
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
deleted file mode 100644
index 73df245..0000000
--- a/runtime/vm/dart_api_message.cc
+++ /dev/null
@@ -1,1192 +0,0 @@
-// Copyright (c) 2012, 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.
-
-#include <memory>
-
-#include "vm/dart_api_message.h"
-
-#include "platform/undefined_behavior_sanitizer.h"
-#include "platform/unicode.h"
-#include "vm/object.h"
-#include "vm/snapshot_ids.h"
-#include "vm/symbols.h"
-
-namespace dart {
-
-static const int kNumInitialReferences = 4;
-
-ApiMessageReader::ApiMessageReader(Message* msg)
-    : BaseReader(msg->IsRaw() ? reinterpret_cast<uint8_t*>(
-                                    static_cast<uword>(msg->raw_obj()))
-                              : msg->snapshot(),
-                 msg->snapshot_length()),
-      zone_(NULL),
-      backward_references_(kNumInitialReferences),
-      vm_isolate_references_(kNumInitialReferences),
-      vm_symbol_references_(NULL),
-      finalizable_data_(msg->finalizable_data()) {}
-
-ApiMessageReader::~ApiMessageReader() {}
-
-void ApiMessageReader::Init() {
-  // We need to have an enclosing ApiNativeScope.
-  ASSERT(ApiNativeScope::Current() != NULL);
-  zone_ = ApiNativeScope::Current()->zone();
-  ASSERT(zone_ != NULL);
-
-  // Initialize marker objects used to handle Lists.
-  // TODO(sjesse): Remove this when message serialization format is
-  // updated.
-  memset(&type_arguments_marker, 0, sizeof(type_arguments_marker));
-  memset(&dynamic_type_marker, 0, sizeof(dynamic_type_marker));
-  type_arguments_marker.type =
-      static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kTypeArguments);
-  dynamic_type_marker.type =
-      static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kDynamicType);
-}
-
-Dart_CObject* ApiMessageReader::ReadMessage() {
-  Init();
-  if (PendingBytes() > 0) {
-    // Read the object out of the message.
-    return ReadObject();
-  } else {
-    const ObjectPtr raw_obj = static_cast<const ObjectPtr>(
-        reinterpret_cast<uword>(CurrentBufferAddress()));
-    ASSERT(ApiObjectConverter::CanConvert(raw_obj));
-    Dart_CObject* cobj =
-        reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));
-    ApiObjectConverter::Convert(raw_obj, cobj);
-    return cobj;
-  }
-}
-
-intptr_t ApiMessageReader::LookupInternalClass(intptr_t class_header) {
-  if (IsVMIsolateObject(class_header)) {
-    return GetVMIsolateObjectId(class_header);
-  }
-  ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
-  return SerializedHeaderData::decode(class_header);
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObject(Dart_CObject_Type type) {
-  Dart_CObject* value =
-      reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));
-  ASSERT(value != NULL);
-  value->type = type;
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectUnsupported() {
-  return AllocateDartCObject(Dart_CObject_kUnsupported);
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectNull() {
-  return AllocateDartCObject(Dart_CObject_kNull);
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectBool(bool val) {
-  Dart_CObject* value = AllocateDartCObject(Dart_CObject_kBool);
-  value->value.as_bool = val;
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectInt32(int32_t val) {
-  Dart_CObject* value = AllocateDartCObject(Dart_CObject_kInt32);
-  value->value.as_int32 = val;
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectInt64(int64_t val) {
-  Dart_CObject* value = AllocateDartCObject(Dart_CObject_kInt64);
-  value->value.as_int64 = val;
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectDouble(double val) {
-  Dart_CObject* value = AllocateDartCObject(Dart_CObject_kDouble);
-  value->value.as_double = val;
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectString(intptr_t length) {
-  // Allocate a Dart_CObject structure followed by an array of chars
-  // for the string content. The pointer to the string content is set
-  // up to this area.
-  Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
-      allocator(sizeof(Dart_CObject) + length + 1));
-  ASSERT(value != NULL);
-  value->value.as_string = reinterpret_cast<char*>(value) + sizeof(*value);
-  value->type = Dart_CObject_kString;
-  return value;
-}
-
-static int GetTypedDataSizeInBytes(Dart_TypedData_Type type) {
-  switch (type) {
-    case Dart_TypedData_kInt8:
-    case Dart_TypedData_kUint8:
-    case Dart_TypedData_kUint8Clamped:
-      return 1;
-    case Dart_TypedData_kInt16:
-    case Dart_TypedData_kUint16:
-      return 2;
-    case Dart_TypedData_kInt32:
-    case Dart_TypedData_kUint32:
-    case Dart_TypedData_kFloat32:
-      return 4;
-    case Dart_TypedData_kInt64:
-    case Dart_TypedData_kUint64:
-    case Dart_TypedData_kFloat64:
-      return 8;
-    case Dart_TypedData_kInt32x4:
-    case Dart_TypedData_kFloat32x4:
-    case Dart_TypedData_kFloat64x2:
-      return 16;
-    default:
-      break;
-  }
-  UNREACHABLE();
-  return -1;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectTypedData(
-    Dart_TypedData_Type type,
-    intptr_t length) {
-  // Allocate a Dart_CObject structure followed by an array of bytes
-  // for the byte array content. The pointer to the byte array content
-  // is set up to this area.
-  intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * length;
-  Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
-      allocator(sizeof(Dart_CObject) + length_in_bytes));
-  ASSERT(value != NULL);
-  value->type = Dart_CObject_kTypedData;
-  value->value.as_typed_data.type = type;
-  value->value.as_typed_data.length = length_in_bytes;
-  if (length > 0) {
-    value->value.as_typed_data.values =
-        reinterpret_cast<uint8_t*>(value) + sizeof(*value);
-  } else {
-    value->value.as_typed_data.values = NULL;
-  }
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectArray(intptr_t length) {
-  // Allocate a Dart_CObject structure followed by an array of
-  // pointers to Dart_CObject structures. The pointer to the array
-  // content is set up to this area.
-  Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
-      allocator(sizeof(Dart_CObject) + length * sizeof(value)));
-  ASSERT(value != NULL);
-  value->type = Dart_CObject_kArray;
-  value->value.as_array.length = length;
-  if (length > 0) {
-    value->value.as_array.values = reinterpret_cast<Dart_CObject**>(value + 1);
-  } else {
-    value->value.as_array.values = NULL;
-  }
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectVmIsolateObj(intptr_t id) {
-  ObjectPtr raw = VmIsolateSnapshotObject(id);
-  intptr_t cid = raw->GetClassId();
-  switch (cid) {
-    case kOneByteStringCid: {
-      OneByteStringPtr raw_str = static_cast<OneByteStringPtr>(raw);
-      const char* str = reinterpret_cast<const char*>(raw_str->untag()->data());
-      ASSERT(str != NULL);
-      Dart_CObject* object = NULL;
-      for (intptr_t i = 0; i < vm_isolate_references_.length(); i++) {
-        object = vm_isolate_references_.At(i);
-        if (object->type == Dart_CObject_kString) {
-          if (strcmp(str, object->value.as_string) == 0) {
-            return object;
-          }
-        }
-      }
-      object = CreateDartCObjectString(raw);
-      vm_isolate_references_.Add(object);
-      return object;
-    }
-
-    case kMintCid: {
-      const Mint& obj = Mint::Handle(static_cast<MintPtr>(raw));
-      int64_t value64 = obj.value();
-      if ((kMinInt32 <= value64) && (value64 <= kMaxInt32)) {
-        return GetCanonicalMintObject(Dart_CObject_kInt32, value64);
-      } else {
-        return GetCanonicalMintObject(Dart_CObject_kInt64, value64);
-      }
-    }
-
-    default:
-      UNREACHABLE();
-      return NULL;
-  }
-}
-
-Dart_CObject_Internal* ApiMessageReader::AllocateDartCObjectInternal(
-    Dart_CObject_Internal::Type type) {
-  Dart_CObject_Internal* value = reinterpret_cast<Dart_CObject_Internal*>(
-      allocator(sizeof(Dart_CObject_Internal)));
-  ASSERT(value != NULL);
-  value->type = static_cast<Dart_CObject_Type>(type);
-  return value;
-}
-
-Dart_CObject_Internal* ApiMessageReader::AllocateDartCObjectClass() {
-  return AllocateDartCObjectInternal(Dart_CObject_Internal::kClass);
-}
-
-ApiMessageReader::BackRefNode* ApiMessageReader::AllocateBackRefNode(
-    Dart_CObject* reference,
-    DeserializeState state) {
-  BackRefNode* value =
-      reinterpret_cast<BackRefNode*>(allocator(sizeof(BackRefNode)));
-  value->set_reference(reference);
-  value->set_state(state);
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
-  // Read the class header information and lookup the class.
-  intptr_t class_header = Read<int32_t>();
-  intptr_t tags = ReadTags();
-  USE(tags);
-  intptr_t class_id;
-
-  // There is limited support for reading regular dart instances. Only
-  // typed data views are currently handled.
-  if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
-    Dart_CObject_Internal* object =
-        reinterpret_cast<Dart_CObject_Internal*>(GetBackRef(object_id));
-    if (object == NULL) {
-      object =
-          AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);
-      AddBackRef(object_id, object, kIsDeserialized);
-      // Read class of object.
-      object->cls = reinterpret_cast<Dart_CObject_Internal*>(ReadObjectImpl());
-      ASSERT(object->cls->type ==
-             static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kClass));
-    }
-    ASSERT(object->type == static_cast<Dart_CObject_Type>(
-                               Dart_CObject_Internal::kUninitialized));
-    return object;
-  }
-
-  ASSERT((class_header & kSmiTagMask) != 0);
-  class_id = LookupInternalClass(class_header);
-  if ((class_id == kArrayCid) || (class_id == kImmutableArrayCid)) {
-    intptr_t len = ReadSmiValue();
-    Dart_CObject* value = GetBackRef(object_id);
-    if (value == NULL) {
-      value = AllocateDartCObjectArray(len);
-      AddBackRef(object_id, value, kIsDeserialized);
-    }
-    // Skip type arguments.
-    // TODO(sjesse): Remove this when message serialization format is
-    // updated (currently type_arguments is leaked).
-    Dart_CObject* type_arguments = ReadObjectImpl();
-    if (type_arguments != &type_arguments_marker &&
-        type_arguments->type != Dart_CObject_kNull) {
-      return AllocateDartCObjectUnsupported();
-    }
-    for (int i = 0; i < len; i++) {
-      value->value.as_array.values[i] = ReadObjectRef();
-    }
-    return value;
-  }
-
-  return ReadInternalVMObject(class_id, object_id);
-}
-
-Dart_CObject* ApiMessageReader::ReadPredefinedSymbol(intptr_t object_id) {
-  ASSERT(Symbols::IsPredefinedSymbolId(object_id));
-  intptr_t symbol_id = object_id - kMaxPredefinedObjectIds;
-  Dart_CObject* object;
-  if (vm_symbol_references_ != NULL &&
-      (object = vm_symbol_references_[symbol_id]) != NULL) {
-    return object;
-  }
-
-  if (vm_symbol_references_ == NULL) {
-    intptr_t size =
-        (sizeof(*vm_symbol_references_) * Symbols::kMaxPredefinedId);
-    vm_symbol_references_ = reinterpret_cast<Dart_CObject**>(allocator(size));
-    memset(vm_symbol_references_, 0, size);
-  }
-
-  object = CreateDartCObjectString(Symbols::GetPredefinedSymbol(object_id));
-  ASSERT(vm_symbol_references_[symbol_id] == NULL);
-  vm_symbol_references_[symbol_id] = object;
-  return object;
-}
-
-intptr_t ApiMessageReader::NextAvailableObjectId() const {
-  return backward_references_.length() + kMaxPredefinedObjectIds;
-}
-
-Dart_CObject* ApiMessageReader::CreateDartCObjectString(ObjectPtr raw) {
-  ASSERT(IsOneByteStringClassId(raw->GetClassId()));
-  OneByteStringPtr raw_str = static_cast<OneByteStringPtr>(raw);
-  intptr_t len = Smi::Value(raw_str->untag()->length());
-  Dart_CObject* object = AllocateDartCObjectString(len);
-  char* p = object->value.as_string;
-  memmove(p, raw_str->untag()->data(), len);
-  p[len] = '\0';
-  return object;
-}
-
-Dart_CObject* ApiMessageReader::GetCanonicalMintObject(Dart_CObject_Type type,
-                                                       int64_t value64) {
-  Dart_CObject* object = NULL;
-  for (intptr_t i = 0; i < vm_isolate_references_.length(); i++) {
-    object = vm_isolate_references_.At(i);
-    if (object->type == type) {
-      if (value64 == object->value.as_int64) {
-        return object;
-      }
-    }
-  }
-  if (type == Dart_CObject_kInt32) {
-    object = AllocateDartCObjectInt32(static_cast<int32_t>(value64));
-  } else {
-    object = AllocateDartCObjectInt64(value64);
-  }
-  vm_isolate_references_.Add(object);
-  return object;
-}
-
-Dart_CObject* ApiMessageReader::ReadObjectRef() {
-  int64_t value64 = Read<int64_t>();
-  if ((value64 & kSmiTagMask) == 0) {
-    int64_t untagged_value = value64 >> kSmiTagShift;
-    if ((kMinInt32 <= untagged_value) && (untagged_value <= kMaxInt32)) {
-      return AllocateDartCObjectInt32(static_cast<int32_t>(untagged_value));
-    } else {
-      return AllocateDartCObjectInt64(untagged_value);
-    }
-  }
-  ASSERT((value64 <= kIntptrMax) && (value64 >= kIntptrMin));
-  intptr_t value = static_cast<intptr_t>(value64);
-  if (IsVMIsolateObject(value)) {
-    return ReadVMIsolateObject(value);
-  }
-  if (SerializedHeaderTag::decode(value) == kObjectId) {
-    return ReadIndexedObject(SerializedHeaderData::decode(value));
-  }
-  ASSERT(SerializedHeaderTag::decode(value) == kInlined);
-  // Read the class header information and lookup the class.
-  intptr_t class_header = Read<int32_t>();
-
-  intptr_t object_id = SerializedHeaderData::decode(value);
-  if (object_id == kOmittedObjectId) {
-    object_id = NextAvailableObjectId();
-  }
-
-  intptr_t tags = ReadTags();
-  USE(tags);
-
-  // Reading of regular dart instances has limited support in order to
-  // read typed data views.
-  if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
-    Dart_CObject_Internal* object =
-        AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);
-    AddBackRef(object_id, object, kIsNotDeserialized);
-    // Read class of object.
-    object->cls = reinterpret_cast<Dart_CObject_Internal*>(ReadObjectImpl());
-    ASSERT(object->cls->type ==
-           static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kClass));
-    return object;
-  }
-  ASSERT((class_header & kSmiTagMask) != 0);
-  intptr_t class_id = LookupInternalClass(class_header);
-  if ((class_id == kArrayCid) || (class_id == kImmutableArrayCid)) {
-    ASSERT(GetBackRef(object_id) == NULL);
-    intptr_t len = ReadSmiValue();
-    Dart_CObject* value = AllocateDartCObjectArray(len);
-    AddBackRef(object_id, value, kIsNotDeserialized);
-    return value;
-  }
-  return ReadInternalVMObject(class_id, object_id);
-}
-
-Dart_CObject* ApiMessageReader::ReadVMIsolateObject(intptr_t value) {
-  intptr_t object_id = GetVMIsolateObjectId(value);
-  if (object_id == kNullObject) {
-    return AllocateDartCObjectNull();
-  }
-  if (object_id == kTrueValue) {
-    return AllocateDartCObjectBool(true);
-  }
-  if (object_id == kFalseValue) {
-    return AllocateDartCObjectBool(false);
-  }
-  if (object_id == kDoubleObject) {
-    return AllocateDartCObjectDouble(ReadDouble());
-  }
-  if (Symbols::IsPredefinedSymbolId(object_id)) {
-    return ReadPredefinedSymbol(object_id);
-  }
-  // No other VM isolate objects are supported.
-  return AllocateDartCObjectNull();
-}
-
-Dart_CObject* ApiMessageReader::ReadInternalVMObject(intptr_t class_id,
-                                                     intptr_t object_id) {
-  switch (class_id) {
-    case kClassCid: {
-      Dart_CObject_Internal* object = AllocateDartCObjectClass();
-      AddBackRef(object_id, object, kIsDeserialized);
-      object->internal.as_class.library_url = ReadObjectImpl();
-      ASSERT(object->internal.as_class.library_url->type ==
-             Dart_CObject_kString);
-      object->internal.as_class.class_name = ReadObjectImpl();
-      ASSERT(object->internal.as_class.class_name->type ==
-             Dart_CObject_kString);
-      return object;
-    }
-    case kTypeArgumentsCid: {
-      // TODO(sjesse): Remove this when message serialization format is
-      // updated (currently length is leaked).
-      Dart_CObject* value = &type_arguments_marker;
-      AddBackRef(object_id, value, kIsDeserialized);
-      Dart_CObject* length = ReadObjectImpl();
-      ASSERT(length->type == Dart_CObject_kInt32);
-      // The instantiations_ field is only written to a full snapshot.
-      for (int i = 0; i < length->value.as_int32; i++) {
-        Dart_CObject* type = ReadObjectImpl();
-        if (type != &dynamic_type_marker) {
-          return AllocateDartCObjectUnsupported();
-        }
-      }
-      return value;
-    }
-    case kTypeParameterCid: {
-      Dart_CObject* value = &dynamic_type_marker;
-      AddBackRef(object_id, value, kIsDeserialized);
-      intptr_t index = Read<int32_t>();
-      USE(index);
-      intptr_t token_index = Read<int32_t>();
-      USE(token_index);
-      int8_t type_state = Read<int8_t>();
-      USE(type_state);
-      Dart_CObject* parameterized_class = ReadObjectImpl();
-      // The type parameter is finalized, therefore parameterized_class is null.
-      ASSERT(parameterized_class->type == Dart_CObject_kNull);
-      Dart_CObject* name = ReadObjectImpl();
-      ASSERT(name->type == Dart_CObject_kString);
-      return value;
-    }
-    case kMintCid: {
-      int64_t value64 = Read<int64_t>();
-      Dart_CObject* object;
-      if ((kMinInt32 <= value64) && (value64 <= kMaxInt32)) {
-        object = AllocateDartCObjectInt32(static_cast<int32_t>(value64));
-      } else {
-        object = AllocateDartCObjectInt64(value64);
-      }
-      AddBackRef(object_id, object, kIsDeserialized);
-      return object;
-    }
-    case kDoubleCid: {
-      // Doubles are handled specially when being sent as part of message
-      // snapshots.
-      UNREACHABLE();
-    }
-    case kOneByteStringCid: {
-      intptr_t len = ReadSmiValue();
-      uint8_t* latin1 =
-          reinterpret_cast<uint8_t*>(allocator(len * sizeof(uint8_t)));
-      intptr_t utf8_len = 0;
-      for (intptr_t i = 0; i < len; i++) {
-        latin1[i] = Read<uint8_t>();
-        utf8_len += Utf8::Length(latin1[i]);
-      }
-      Dart_CObject* object = AllocateDartCObjectString(utf8_len);
-      AddBackRef(object_id, object, kIsDeserialized);
-      char* p = object->value.as_string;
-      for (intptr_t i = 0; i < len; i++) {
-        p += Utf8::Encode(latin1[i], p);
-      }
-      *p = '\0';
-      ASSERT(p == (object->value.as_string + utf8_len));
-      return object;
-    }
-    case kTwoByteStringCid: {
-      intptr_t len = ReadSmiValue();
-      uint16_t* utf16 =
-          reinterpret_cast<uint16_t*>(allocator(len * sizeof(uint16_t)));
-      intptr_t utf8_len = 0;
-      // Read all the UTF-16 code units.
-      for (intptr_t i = 0; i < len; i++) {
-        utf16[i] = Read<uint16_t>();
-      }
-      // Calculate the UTF-8 length and check if the string can be
-      // UTF-8 encoded.
-      bool valid = true;
-      intptr_t i = 0;
-      while (i < len && valid) {
-        int32_t ch = Utf16::Next(utf16, &i, len);
-        utf8_len += Utf8::Length(ch);
-        valid = !Utf16::IsSurrogate(ch);
-      }
-      if (!valid) {
-        return AllocateDartCObjectUnsupported();
-      }
-      Dart_CObject* object = AllocateDartCObjectString(utf8_len);
-      AddBackRef(object_id, object, kIsDeserialized);
-      char* p = object->value.as_string;
-      i = 0;
-      while (i < len) {
-        p += Utf8::Encode(Utf16::Next(utf16, &i, len), p);
-      }
-      *p = '\0';
-      ASSERT(p == (object->value.as_string + utf8_len));
-      return object;
-    }
-    case kSendPortCid: {
-      int64_t value64 = Read<int64_t>();
-      int64_t originId = Read<uint64_t>();
-      Dart_CObject* object = AllocateDartCObject(Dart_CObject_kSendPort);
-      object->value.as_send_port.id = value64;
-      object->value.as_send_port.origin_id = originId;
-      AddBackRef(object_id, object, kIsDeserialized);
-      return object;
-    }
-    case kCapabilityCid: {
-      int64_t id = Read<int64_t>();
-      Dart_CObject* object = AllocateDartCObject(Dart_CObject_kCapability);
-      object->value.as_capability.id = id;
-      AddBackRef(object_id, object, kIsDeserialized);
-      return object;
-    }
-
-#define READ_TYPED_DATA(tname, ctype)                                          \
-  {                                                                            \
-    intptr_t len = ReadSmiValue();                                             \
-    auto type = Dart_TypedData_k##tname;                                       \
-    intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * len;            \
-    Dart_CObject* object =                                                     \
-        reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));      \
-    ASSERT(object != NULL);                                                    \
-    object->type = Dart_CObject_kTypedData;                                    \
-    object->value.as_typed_data.type = type;                                   \
-    object->value.as_typed_data.length = length_in_bytes;                      \
-    if (len > 0) {                                                             \
-      Align(Zone::kAlignment);                                                 \
-      object->value.as_typed_data.values =                                     \
-          const_cast<uint8_t*>(CurrentBufferAddress());                        \
-      Advance(length_in_bytes);                                                \
-    } else {                                                                   \
-      object->value.as_typed_data.values = NULL;                               \
-    }                                                                          \
-    AddBackRef(object_id, object, kIsDeserialized);                            \
-    return object;                                                             \
-  }
-
-#define READ_EXTERNAL_TYPED_DATA(tname, ctype)                                 \
-  {                                                                            \
-    intptr_t len = ReadSmiValue();                                             \
-    auto type = Dart_TypedData_k##tname;                                       \
-    intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * len;            \
-    Dart_CObject* object =                                                     \
-        reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));      \
-    ASSERT(object != NULL);                                                    \
-    object->type = Dart_CObject_kTypedData;                                    \
-    object->value.as_typed_data.type = type;                                   \
-    object->value.as_typed_data.length = length_in_bytes;                      \
-    object->value.as_typed_data.values =                                       \
-        reinterpret_cast<uint8_t*>(finalizable_data_->Get().data);             \
-    AddBackRef(object_id, object, kIsDeserialized);                            \
-    return object;                                                             \
-  }
-
-#define READ_TYPED_DATA_VIEW(tname, ctype)                                     \
-  {                                                                            \
-    Dart_CObject_Internal* object =                                            \
-        AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);    \
-    AddBackRef(object_id, object, kIsDeserialized);                            \
-    object->type =                                                             \
-        static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView);          \
-    object->internal.as_view.offset_in_bytes = ReadSmiValue();                 \
-    object->internal.as_view.length = ReadSmiValue();                          \
-    object->internal.as_view.buffer = ReadObjectImpl();                        \
-    Dart_CObject* buffer = object->internal.as_view.buffer;                    \
-    RELEASE_ASSERT(buffer->type == Dart_CObject_kTypedData);                   \
-                                                                               \
-    /* Now turn the view into a byte array.*/                                  \
-    const Dart_TypedData_Type type = Dart_TypedData_k##tname;                  \
-    object->type = Dart_CObject_kTypedData;                                    \
-    object->value.as_typed_data.type = type;                                   \
-    object->value.as_typed_data.length =                                       \
-        object->internal.as_view.length * GetTypedDataSizeInBytes(type);       \
-    object->value.as_typed_data.values =                                       \
-        buffer->value.as_typed_data.values +                                   \
-        object->internal.as_view.offset_in_bytes;                              \
-    return object;                                                             \
-  }
-
-#define TYPED_DATA_LIST(V)                                                     \
-  V(Int8, int8_t)                                                              \
-  V(Uint8, uint8_t)                                                            \
-  V(Uint8Clamped, uint8_t)                                                     \
-  V(Int16, int16_t)                                                            \
-  V(Uint16, uint16_t)                                                          \
-  V(Int32, int32_t)                                                            \
-  V(Uint32, uint32_t)                                                          \
-  V(Int64, int64_t)                                                            \
-  V(Uint64, uint64_t)                                                          \
-  V(Float32, float)                                                            \
-  V(Float64, double)                                                           \
-  V(Int32x4, simd128_value_t)                                                  \
-  V(Float32x4, simd128_value_t)                                                \
-  V(Float64x2, simd128_value_t)
-
-#define EMIT_TYPED_DATA_CASES(type, c_type)                                    \
-  case kTypedData##type##ArrayCid:                                             \
-    READ_TYPED_DATA(type, c_type);                                             \
-  case kExternalTypedData##type##ArrayCid:                                     \
-    READ_EXTERNAL_TYPED_DATA(type, c_type);                                    \
-  case kTypedData##type##ArrayViewCid:                                         \
-    READ_TYPED_DATA_VIEW(type, c_type);
-
-      TYPED_DATA_LIST(EMIT_TYPED_DATA_CASES)
-#undef EMIT_TYPED_DATA_CASES
-#undef TYPED_DATA_LIST
-#undef READ_TYPED_DATA
-#undef READ_EXTERNAL_TYPED_DATA
-#undef READ_TYPED_DATA_VIEW
-
-    case kGrowableObjectArrayCid: {
-      // A GrowableObjectArray is serialized as its type arguments and
-      // length followed by its backing store. The backing store is an
-      // array with a length which might be longer than the length of
-      // the GrowableObjectArray.
-      Dart_CObject* value = GetBackRef(object_id);
-      ASSERT(value == NULL);
-      // Allocate an empty array for the GrowableObjectArray which
-      // will be updated to point to the content when the backing
-      // store has been deserialized.
-      value = AllocateDartCObjectArray(0);
-      AddBackRef(object_id, value, kIsDeserialized);
-
-      // Read and skip the type arguments field.
-      // TODO(sjesse): Remove this when message serialization format is
-      // updated (currently type_arguments is leaked).
-      Dart_CObject* type_arguments = ReadObjectImpl();
-      if (type_arguments != &type_arguments_marker &&
-          type_arguments->type != Dart_CObject_kNull) {
-        return AllocateDartCObjectUnsupported();
-      }
-
-      // Read the length field.
-      intptr_t len = ReadSmiValue();
-
-      // Read the content of the GrowableObjectArray.
-      Dart_CObject* content = ReadObjectRef();
-      ASSERT(content->type == Dart_CObject_kArray);
-      // Make the empty array allocated point to the backing store content.
-      value->value.as_array.length = len;
-      value->value.as_array.values = content->value.as_array.values;
-      return value;
-    }
-    default:
-      // Everything else not supported.
-      Dart_CObject* value = AllocateDartCObjectUnsupported();
-      AddBackRef(object_id, value, kIsDeserialized);
-      return value;
-  }
-}
-
-Dart_CObject* ApiMessageReader::ReadIndexedObject(intptr_t object_id) {
-  if (object_id >= kFirstTypeSnapshotId && object_id <= kLastTypeSnapshotId) {
-    // Always return dynamic type (this is only a marker).
-    return &dynamic_type_marker;
-  }
-  if (object_id >= kFirstTypeArgumentsSnapshotId &&
-      object_id <= kLastTypeArgumentsSnapshotId) {
-    return &type_arguments_marker;
-  }
-
-  intptr_t index = object_id - kMaxPredefinedObjectIds;
-  ASSERT((0 <= index) && (index < backward_references_.length()));
-  ASSERT(backward_references_[index]->reference() != NULL);
-  return backward_references_[index]->reference();
-}
-
-Dart_CObject* ApiMessageReader::ReadObject() {
-  Dart_CObject* value = ReadObjectImpl();
-  for (intptr_t i = 0; i < backward_references_.length(); i++) {
-    if (!backward_references_[i]->is_deserialized()) {
-      ReadObjectImpl();
-      backward_references_[i]->set_state(kIsDeserialized);
-    }
-  }
-  return value;
-}
-
-Dart_CObject* ApiMessageReader::ReadObjectImpl() {
-  int64_t value64 = Read<int64_t>();
-  if ((value64 & kSmiTagMask) == 0) {
-    int64_t untagged_value = value64 >> kSmiTagShift;
-    if ((kMinInt32 <= untagged_value) && (untagged_value <= kMaxInt32)) {
-      return AllocateDartCObjectInt32(static_cast<int32_t>(untagged_value));
-    } else {
-      return AllocateDartCObjectInt64(untagged_value);
-    }
-  }
-  ASSERT((value64 <= kIntptrMax) && (value64 >= kIntptrMin));
-  intptr_t value = static_cast<intptr_t>(value64);
-  if (IsVMIsolateObject(value)) {
-    return ReadVMIsolateObject(value);
-  }
-  if (SerializedHeaderTag::decode(value) == kObjectId) {
-    return ReadIndexedObject(SerializedHeaderData::decode(value));
-  }
-  ASSERT(SerializedHeaderTag::decode(value) == kInlined);
-
-  intptr_t object_id = SerializedHeaderData::decode(value);
-  if (object_id == kOmittedObjectId) {
-    object_id = NextAvailableObjectId();
-  }
-  return ReadInlinedObject(object_id);
-}
-
-void ApiMessageReader::AddBackRef(intptr_t id,
-                                  Dart_CObject* obj,
-                                  DeserializeState state) {
-  intptr_t index = (id - kMaxPredefinedObjectIds);
-  ASSERT(index == backward_references_.length());
-  BackRefNode* node = AllocateBackRefNode(obj, state);
-  ASSERT(node != NULL);
-  backward_references_.Add(node);
-}
-
-Dart_CObject* ApiMessageReader::GetBackRef(intptr_t id) {
-  ASSERT(id >= kMaxPredefinedObjectIds);
-  intptr_t index = (id - kMaxPredefinedObjectIds);
-  if (index < backward_references_.length()) {
-    return backward_references_[index]->reference();
-  }
-  return NULL;
-}
-
-ApiMessageWriter::ApiMessageWriter()
-    : BaseWriter(kInitialSize),
-      object_id_(0),
-      forward_list_(NULL),
-      forward_list_length_(0),
-      forward_id_(0),
-      finalizable_data_(new MessageFinalizableData()) {
-  ASSERT(kDartCObjectTypeMask >= Dart_CObject_kNumberOfTypes - 1);
-}
-
-ApiMessageWriter::~ApiMessageWriter() {
-  ::free(forward_list_);
-  delete finalizable_data_;
-}
-
-NO_SANITIZE_UNDEFINED(
-    "enum")  // TODO(https://github.com/dart-lang/sdk/issues/39427)
-void ApiMessageWriter::MarkCObject(Dart_CObject* object, intptr_t object_id) {
-  // Mark the object as serialized by adding the object id to the
-  // upper bits of the type field in the Dart_CObject structure. Add
-  // an offset for making marking of object id 0 possible.
-  ASSERT(!IsCObjectMarked(object));
-  intptr_t mark_value = object_id + kDartCObjectMarkOffset;
-  object->type = static_cast<Dart_CObject_Type>(
-      ((mark_value) << kDartCObjectTypeBits) | object->type);
-}
-
-NO_SANITIZE_UNDEFINED(
-    "enum")  // TODO(https://github.com/dart-lang/sdk/issues/39427)
-void ApiMessageWriter::UnmarkCObject(Dart_CObject* object) {
-  ASSERT(IsCObjectMarked(object));
-  object->type =
-      static_cast<Dart_CObject_Type>(object->type & kDartCObjectTypeMask);
-}
-
-NO_SANITIZE_UNDEFINED(
-    "enum")  // TODO(https://github.com/dart-lang/sdk/issues/39427)
-bool ApiMessageWriter::IsCObjectMarked(Dart_CObject* object) {
-  return (object->type & kDartCObjectMarkMask) != 0;
-}
-
-NO_SANITIZE_UNDEFINED(
-    "enum")  // TODO(https://github.com/dart-lang/sdk/issues/39427)
-intptr_t ApiMessageWriter::GetMarkedCObjectMark(Dart_CObject* object) {
-  ASSERT(IsCObjectMarked(object));
-  intptr_t mark_value =
-      ((object->type & kDartCObjectMarkMask) >> kDartCObjectTypeBits);
-  // An offset was added to object id for making marking object id 0 possible.
-  return mark_value - kDartCObjectMarkOffset;
-}
-
-void ApiMessageWriter::UnmarkAllCObjects(Dart_CObject* object) {
-  if (!IsCObjectMarked(object)) return;
-  UnmarkCObject(object);
-  if (object->type == Dart_CObject_kArray) {
-    for (int i = 0; i < object->value.as_array.length; i++) {
-      Dart_CObject* element = object->value.as_array.values[i];
-      UnmarkAllCObjects(element);
-    }
-  }
-}
-
-void ApiMessageWriter::AddToForwardList(Dart_CObject* object) {
-  if (forward_id_ >= forward_list_length_) {
-    void* new_list = NULL;
-    if (forward_list_length_ == 0) {
-      forward_list_length_ = 4;
-      intptr_t new_size = forward_list_length_ * sizeof(object);
-      new_list = dart::malloc(new_size);
-    } else {
-      forward_list_length_ *= 2;
-      intptr_t new_size = (forward_list_length_ * sizeof(object));
-      new_list = dart::realloc(forward_list_, new_size);
-    }
-    ASSERT(new_list != NULL);
-    forward_list_ = reinterpret_cast<Dart_CObject**>(new_list);
-  }
-  forward_list_[forward_id_] = object;
-  forward_id_ += 1;
-}
-
-void ApiMessageWriter::WriteSmi(int64_t value) {
-  ASSERT(Smi::IsValid(value));
-  Write<ObjectPtr>(Smi::New(static_cast<intptr_t>(value)));
-}
-
-void ApiMessageWriter::WriteNullObject() {
-  WriteVMIsolateObject(kNullObject);
-}
-
-void ApiMessageWriter::WriteMint(Dart_CObject* object, int64_t value) {
-  ASSERT(!Smi::IsValid(value));
-  // Write out the serialization header value for mint object.
-  WriteInlinedHeader(object);
-  // Write out the class and tags information.
-  WriteIndexedObject(kMintCid);
-  WriteTags(0);
-  // Write the 64-bit value.
-  Write<int64_t>(value);
-}
-
-void ApiMessageWriter::WriteInt32(Dart_CObject* object) {
-  int64_t value = object->value.as_int32;
-  if (Smi::IsValid(value)) {
-    WriteSmi(value);
-  } else {
-    WriteMint(object, value);
-  }
-}
-
-void ApiMessageWriter::WriteInt64(Dart_CObject* object) {
-  int64_t value = object->value.as_int64;
-  if (Smi::IsValid(value)) {
-    WriteSmi(value);
-  } else {
-    WriteMint(object, value);
-  }
-}
-
-void ApiMessageWriter::WriteInlinedHeader(Dart_CObject* object) {
-  // Write out the serialization header value for this object.
-  WriteInlinedObjectHeader(kMaxPredefinedObjectIds + object_id_);
-  // Mark object with its object id.
-  MarkCObject(object, object_id_);
-  // Advance object id.
-  object_id_++;
-}
-
-bool ApiMessageWriter::WriteCObject(Dart_CObject* object) {
-  if (IsCObjectMarked(object)) {
-    intptr_t object_id = GetMarkedCObjectMark(object);
-    WriteIndexedObject(kMaxPredefinedObjectIds + object_id);
-    return true;
-  }
-
-  Dart_CObject_Type type = object->type;
-  if (type == Dart_CObject_kArray) {
-    const intptr_t array_length = object->value.as_array.length;
-    if (!Array::IsValidLength(array_length)) {
-      return false;
-    }
-
-    // Write out the serialization header value for this object.
-    WriteInlinedHeader(object);
-    // Write out the class and tags information.
-    WriteIndexedObject(kArrayCid);
-    WriteTags(0);
-    // Write out the length information.
-    WriteSmi(array_length);
-    // Write out the type arguments.
-    WriteNullObject();
-    // Write out array elements.
-    for (int i = 0; i < array_length; i++) {
-      bool success = WriteCObjectRef(object->value.as_array.values[i]);
-      if (!success) return false;
-    }
-    return true;
-  }
-  return WriteCObjectInlined(object, type);
-}
-
-bool ApiMessageWriter::WriteCObjectRef(Dart_CObject* object) {
-  if (IsCObjectMarked(object)) {
-    intptr_t object_id = GetMarkedCObjectMark(object);
-    WriteIndexedObject(kMaxPredefinedObjectIds + object_id);
-    return true;
-  }
-
-  Dart_CObject_Type type = object->type;
-  if (type == Dart_CObject_kArray) {
-    const intptr_t array_length = object->value.as_array.length;
-    if (!Array::IsValidLength(array_length)) {
-      return false;
-    }
-    // Write out the serialization header value for this object.
-    WriteInlinedHeader(object);
-    // Write out the class information.
-    WriteIndexedObject(kArrayCid);
-    WriteTags(0);
-    // Write out the length information.
-    WriteSmi(array_length);
-    // Add object to forward list so that this object is serialized later.
-    AddToForwardList(object);
-    return true;
-  }
-  return WriteCObjectInlined(object, type);
-}
-
-NO_SANITIZE_UNDEFINED(
-    "enum")  // TODO(https://github.com/dart-lang/sdk/issues/39427)
-bool ApiMessageWriter::WriteForwardedCObject(Dart_CObject* object) {
-  ASSERT(IsCObjectMarked(object));
-  Dart_CObject_Type type =
-      static_cast<Dart_CObject_Type>(object->type & kDartCObjectTypeMask);
-  ASSERT(type == Dart_CObject_kArray);
-  const intptr_t array_length = object->value.as_array.length;
-  if (!Array::IsValidLength(array_length)) {
-    return false;
-  }
-
-  // Write out the serialization header value for this object.
-  intptr_t object_id = GetMarkedCObjectMark(object);
-  WriteInlinedObjectHeader(kMaxPredefinedObjectIds + object_id);
-  // Write out the class and tags information.
-  WriteIndexedObject(kArrayCid);
-  WriteTags(0);
-  // Write out the length information.
-  WriteSmi(array_length);
-  // Write out the type arguments.
-  WriteNullObject();
-  // Write out array elements.
-  for (int i = 0; i < array_length; i++) {
-    bool success = WriteCObjectRef(object->value.as_array.values[i]);
-    if (!success) return false;
-  }
-  return true;
-}
-
-bool ApiMessageWriter::WriteCObjectInlined(Dart_CObject* object,
-                                           Dart_CObject_Type type) {
-  switch (type) {
-    case Dart_CObject_kNull:
-      WriteNullObject();
-      break;
-    case Dart_CObject_kBool:
-      if (object->value.as_bool) {
-        WriteVMIsolateObject(kTrueValue);
-      } else {
-        WriteVMIsolateObject(kFalseValue);
-      }
-      break;
-    case Dart_CObject_kInt32:
-      WriteInt32(object);
-      break;
-    case Dart_CObject_kInt64:
-      WriteInt64(object);
-      break;
-    case Dart_CObject_kDouble:
-      WriteVMIsolateObject(kDoubleObject);
-      WriteDouble(object->value.as_double);
-      break;
-    case Dart_CObject_kString: {
-      const uint8_t* utf8_str =
-          reinterpret_cast<const uint8_t*>(object->value.as_string);
-      intptr_t utf8_len = strlen(object->value.as_string);
-      if (!Utf8::IsValid(utf8_str, utf8_len)) {
-        return false;
-      }
-
-      Utf8::Type type = Utf8::kLatin1;
-      intptr_t len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
-      if (len > String::kMaxElements) {
-        return false;
-      }
-
-      // Write out the serialization header value for this object.
-      WriteInlinedHeader(object);
-      // Write out the class and tags information.
-      WriteIndexedObject(type == Utf8::kLatin1 ? kOneByteStringCid
-                                               : kTwoByteStringCid);
-      WriteTags(0);
-      // Write string length and content.
-      WriteSmi(len);
-      if (type == Utf8::kLatin1) {
-        uint8_t* latin1_str =
-            reinterpret_cast<uint8_t*>(dart::malloc(len * sizeof(uint8_t)));
-        bool success =
-            Utf8::DecodeToLatin1(utf8_str, utf8_len, latin1_str, len);
-        ASSERT(success);
-        for (intptr_t i = 0; i < len; i++) {
-          Write<uint8_t>(latin1_str[i]);
-        }
-        ::free(latin1_str);
-      } else {
-        uint16_t* utf16_str =
-            reinterpret_cast<uint16_t*>(dart::malloc(len * sizeof(uint16_t)));
-        bool success = Utf8::DecodeToUTF16(utf8_str, utf8_len, utf16_str, len);
-        ASSERT(success);
-        for (intptr_t i = 0; i < len; i++) {
-          Write<uint16_t>(utf16_str[i]);
-        }
-        ::free(utf16_str);
-      }
-      break;
-    }
-    case Dart_CObject_kTypedData: {
-      // Write out the serialization header value for this object.
-      WriteInlinedHeader(object);
-      // Write out the class and tags information.
-      intptr_t class_id;
-      switch (object->value.as_typed_data.type) {
-        case Dart_TypedData_kInt8:
-          class_id = kTypedDataInt8ArrayCid;
-          break;
-        case Dart_TypedData_kUint8:
-          class_id = kTypedDataUint8ArrayCid;
-          break;
-        case Dart_TypedData_kUint32:
-          class_id = kTypedDataUint32ArrayCid;
-          break;
-        default:
-          class_id = kTypedDataUint8ArrayCid;
-          UNIMPLEMENTED();
-      }
-
-      intptr_t len = object->value.as_typed_data.length;
-      if (len < 0 || len > TypedData::MaxElements(class_id)) {
-        return false;
-      }
-
-      WriteIndexedObject(class_id);
-      WriteTags(0);
-      WriteSmi(len);
-      switch (class_id) {
-        case kTypedDataInt8ArrayCid:
-        case kTypedDataUint8ArrayCid: {
-          uint8_t* bytes = object->value.as_typed_data.values;
-          Align(Zone::kAlignment);
-          WriteBytes(bytes, len);
-          break;
-        }
-        case kTypedDataUint32ArrayCid: {
-          uint8_t* bytes = object->value.as_typed_data.values;
-          Align(Zone::kAlignment);
-          WriteBytes(bytes, len * sizeof(uint32_t));
-          break;
-        }
-        default:
-          UNIMPLEMENTED();
-      }
-      break;
-    }
-    case Dart_CObject_kExternalTypedData: {
-      // TODO(ager): we are writing C pointers into the message in
-      // order to post external arrays through ports. We need to make
-      // sure that messages containing pointers can never be posted
-      // to other processes.
-
-      // Write out serialization header value for this object.
-      WriteInlinedHeader(object);
-      // Write out the class and tag information.
-      WriteIndexedObject(kExternalTypedDataUint8ArrayCid);
-      WriteTags(0);
-      intptr_t length = object->value.as_external_typed_data.length;
-      if (length < 0 || length > ExternalTypedData::MaxElements(
-                                     kExternalTypedDataUint8ArrayCid)) {
-        return false;
-      }
-      uint8_t* data = object->value.as_external_typed_data.data;
-      void* peer = object->value.as_external_typed_data.peer;
-      Dart_HandleFinalizer callback =
-          object->value.as_external_typed_data.callback;
-      if (callback == NULL) {
-        return false;
-      }
-      WriteSmi(length);
-      finalizable_data_->Put(length, reinterpret_cast<void*>(data), peer,
-                             callback);
-      break;
-    }
-    case Dart_CObject_kSendPort: {
-      WriteInlinedHeader(object);
-      WriteIndexedObject(kSendPortCid);
-      WriteTags(0);
-      Write<int64_t>(object->value.as_send_port.id);
-      Write<uint64_t>(object->value.as_send_port.origin_id);
-      break;
-    }
-    case Dart_CObject_kCapability: {
-      WriteInlinedHeader(object);
-      WriteIndexedObject(kCapabilityCid);
-      WriteTags(0);
-      Write<uint64_t>(object->value.as_capability.id);
-      break;
-    }
-    default:
-      FATAL1("Unexpected Dart_CObject_Type %d\n", type);
-  }
-
-  return true;
-}
-
-std::unique_ptr<Message> ApiMessageWriter::WriteCMessage(
-    Dart_CObject* object,
-    Dart_Port dest_port,
-    Message::Priority priority) {
-  bool success = WriteCObject(object);
-  if (!success) {
-    UnmarkAllCObjects(object);
-    intptr_t unused;
-    free(Steal(&unused));
-    return nullptr;
-  }
-
-  // Write out all objects that were added to the forward list and have
-  // not been serialized yet. These would typically be fields of arrays.
-  // NOTE: The forward list might grow as we process the list.
-  for (intptr_t i = 0; i < forward_id_; i++) {
-    success = WriteForwardedCObject(forward_list_[i]);
-    if (!success) {
-      UnmarkAllCObjects(object);
-      intptr_t unused;
-      free(Steal(&unused));
-      return nullptr;
-    }
-  }
-
-  UnmarkAllCObjects(object);
-  MessageFinalizableData* finalizable_data = finalizable_data_;
-  finalizable_data_ = nullptr;
-  intptr_t size;
-  uint8_t* buffer = Steal(&size);
-  return Message::New(dest_port, buffer, size, finalizable_data, priority);
-}
-
-}  // namespace dart
diff --git a/runtime/vm/dart_api_message.h b/runtime/vm/dart_api_message.h
index ace7dd3..f5994ce 100644
--- a/runtime/vm/dart_api_message.h
+++ b/runtime/vm/dart_api_message.h
@@ -15,185 +15,6 @@
 
 namespace dart {
 
-// Use this C structure for reading internal objects in the serialized
-// data. These are objects that we need to process in order to
-// generate the Dart_CObject graph but that we don't want to expose in
-// that graph.
-struct Dart_CObject_Internal : public Dart_CObject {
-  enum Type {
-    kTypeArguments = Dart_CObject_kNumberOfTypes,
-    kDynamicType,
-    kClass,
-    kView,
-    kUninitialized,
-  };
-  struct Dart_CObject_Internal* cls;
-  union {
-    struct {
-      struct _Dart_CObject* library_url;
-      struct _Dart_CObject* class_name;
-    } as_class;
-    struct {
-      struct _Dart_CObject* buffer;
-      int offset_in_bytes;
-      int length;
-    } as_view;
-  } internal;
-};
-
-// Reads a message snapshot into a C structure.
-class ApiMessageReader : public BaseReader {
- public:
-  // The ApiMessageReader object must be enclosed by an ApiNativeScope.
-  // Allocation of all C Heap objects is done in the zone associated with
-  // the enclosing ApiNativeScope.
-  explicit ApiMessageReader(Message* message);
-  ~ApiMessageReader();
-
-  Dart_CObject* ReadMessage();
-
- private:
-  class BackRefNode {
-   public:
-    BackRefNode(Dart_CObject* reference, DeserializeState state)
-        : reference_(reference), state_(state) {}
-    Dart_CObject* reference() const { return reference_; }
-    void set_reference(Dart_CObject* reference) { reference_ = reference; }
-    bool is_deserialized() const { return state_ == kIsDeserialized; }
-    void set_state(DeserializeState value) { state_ = value; }
-
-   private:
-    Dart_CObject* reference_;
-    DeserializeState state_;
-
-    DISALLOW_COPY_AND_ASSIGN(BackRefNode);
-  };
-
-  // Allocates a Dart_CObject object.
-  Dart_CObject* AllocateDartCObject();
-  // Allocates a Dart_CObject object with the specified type.
-  Dart_CObject* AllocateDartCObject(Dart_CObject_Type type);
-  // Allocates a Dart_CObject object representing an unsupported
-  // object in the API message.
-  Dart_CObject* AllocateDartCObjectUnsupported();
-  // Allocates a Dart_CObject object for the null object.
-  Dart_CObject* AllocateDartCObjectNull();
-  // Allocates a Dart_CObject object for a boolean object.
-  Dart_CObject* AllocateDartCObjectBool(bool value);
-  // Allocates a Dart_CObject object for for a 32-bit integer.
-  Dart_CObject* AllocateDartCObjectInt32(int32_t value);
-  // Allocates a Dart_CObject object for for a 64-bit integer.
-  Dart_CObject* AllocateDartCObjectInt64(int64_t value);
-  // Allocates a Dart_CObject object for a double.
-  Dart_CObject* AllocateDartCObjectDouble(double value);
-  // Allocates a Dart_CObject object for string data.
-  Dart_CObject* AllocateDartCObjectString(intptr_t length);
-  // Allocates a C Dart_CObject object for a typed data.
-  Dart_CObject* AllocateDartCObjectTypedData(Dart_TypedData_Type type,
-                                             intptr_t length);
-  // Allocates a C array of Dart_CObject objects.
-  Dart_CObject* AllocateDartCObjectArray(intptr_t length);
-  // Allocate a C Dart_CObject object for a VM isolate object.
-  Dart_CObject* AllocateDartCObjectVmIsolateObj(intptr_t id);
-  // Allocates a Dart_CObject_Internal object with the specified type.
-  Dart_CObject_Internal* AllocateDartCObjectInternal(
-      Dart_CObject_Internal::Type type);
-  // Allocates a Dart_CObject_Internal object for a class object.
-  Dart_CObject_Internal* AllocateDartCObjectClass();
-  // Allocates a backwards reference node.
-  BackRefNode* AllocateBackRefNode(Dart_CObject* ref, DeserializeState state);
-
-  void Init();
-
-  intptr_t LookupInternalClass(intptr_t class_header);
-  Dart_CObject* ReadVMIsolateObject(intptr_t value);
-  Dart_CObject* ReadInternalVMObject(intptr_t class_id, intptr_t object_id);
-  Dart_CObject* ReadInlinedObject(intptr_t object_id);
-  Dart_CObject* ReadObjectImpl();
-  Dart_CObject* ReadIndexedObject(intptr_t object_id);
-  Dart_CObject* ReadPredefinedSymbol(intptr_t object_id);
-  Dart_CObject* ReadObjectRef();
-  Dart_CObject* ReadObject();
-
-  // Add object to backward references.
-  void AddBackRef(intptr_t id, Dart_CObject* obj, DeserializeState state);
-
-  // Get an object from the backward references list.
-  Dart_CObject* GetBackRef(intptr_t id);
-
-  intptr_t NextAvailableObjectId() const;
-
-  Dart_CObject_Internal* AsInternal(Dart_CObject* object) {
-    ASSERT(object->type >= Dart_CObject_kNumberOfTypes);
-    return reinterpret_cast<Dart_CObject_Internal*>(object);
-  }
-
-  ObjectPtr VmIsolateSnapshotObject(intptr_t index) const {
-    return Object::vm_isolate_snapshot_object_table().At(index);
-  }
-
-  Dart_CObject* CreateDartCObjectString(ObjectPtr raw);
-  Dart_CObject* GetCanonicalMintObject(Dart_CObject_Type type, int64_t value64);
-
-  uint8_t* allocator(intptr_t size) {
-    return zone_->Realloc<uint8_t>(NULL, 0, size);
-  }
-
-  Zone* zone_;  // Zone in which C heap objects are allocated.
-  ApiGrowableArray<BackRefNode*> backward_references_;
-  ApiGrowableArray<Dart_CObject*> vm_isolate_references_;
-  Dart_CObject** vm_symbol_references_;
-
-  Dart_CObject type_arguments_marker;
-  Dart_CObject dynamic_type_marker;
-
-  MessageFinalizableData* finalizable_data_;
-};
-
-class ApiMessageWriter : public BaseWriter {
- public:
-  static const intptr_t kInitialSize = 512;
-  ApiMessageWriter();
-  ~ApiMessageWriter();
-
-  // Writes a message with a single object.
-  std::unique_ptr<Message> WriteCMessage(Dart_CObject* object,
-                                         Dart_Port dest_port,
-                                         Message::Priority priority);
-
- private:
-  static const intptr_t kDartCObjectTypeBits = 4;
-  static const intptr_t kDartCObjectTypeMask = (1 << kDartCObjectTypeBits) - 1;
-  static const intptr_t kDartCObjectMarkMask = ~kDartCObjectTypeMask;
-  static const intptr_t kDartCObjectMarkOffset = 1;
-
-  void MarkCObject(Dart_CObject* object, intptr_t object_id);
-  void UnmarkCObject(Dart_CObject* object);
-  bool IsCObjectMarked(Dart_CObject* object);
-  intptr_t GetMarkedCObjectMark(Dart_CObject* object);
-  void UnmarkAllCObjects(Dart_CObject* object);
-  void AddToForwardList(Dart_CObject* object);
-
-  void WriteSmi(int64_t value);
-  void WriteNullObject();
-  void WriteMint(Dart_CObject* object, int64_t value);
-  void WriteInt32(Dart_CObject* object);
-  void WriteInt64(Dart_CObject* object);
-  void WriteInlinedHeader(Dart_CObject* object);
-  bool WriteCObject(Dart_CObject* object);
-  bool WriteCObjectRef(Dart_CObject* object);
-  bool WriteForwardedCObject(Dart_CObject* object);
-  bool WriteCObjectInlined(Dart_CObject* object, Dart_CObject_Type type);
-
-  intptr_t object_id_;
-  Dart_CObject** forward_list_;
-  intptr_t forward_list_length_;
-  intptr_t forward_id_;
-  MessageFinalizableData* finalizable_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(ApiMessageWriter);
-};
-
 // This class handles translation of certain RawObjects to CObjects for
 // NativeMessageHandlers.
 //
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 57025df..5740337 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -180,8 +180,6 @@
   // A cache of VM heap allocated arguments descriptors.
   static ArrayPtr cached_args_descriptors_[kCachedDescriptorCount];
 
-  friend class SnapshotReader;
-  friend class SnapshotWriter;
   friend class Serializer;
   friend class Deserializer;
   friend class Simulator;
diff --git a/runtime/vm/handles.h b/runtime/vm/handles.h
index ca6b5f4..ed4e9db 100644
--- a/runtime/vm/handles.h
+++ b/runtime/vm/handles.h
@@ -100,6 +100,13 @@
     return scoped_blocks_->AllocateHandle();
   }
 
+  bool IsEmpty() const {
+    if (zone_blocks_ != nullptr) return false;
+    if (first_scoped_block_.HandleCount() != 0) return false;
+    if (scoped_blocks_ != &first_scoped_block_) return false;
+    return true;
+  }
+
  protected:
   // Returns a count of active handles (used for testing purposes).
   int CountScopedHandles() const;
diff --git a/runtime/vm/heap/heap_test.cc b/runtime/vm/heap/heap_test.cc
index 20dc038..e1f9c82 100644
--- a/runtime/vm/heap/heap_test.cc
+++ b/runtime/vm/heap/heap_test.cc
@@ -16,6 +16,7 @@
 #include "vm/heap/become.h"
 #include "vm/heap/heap.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/object_graph.h"
 #include "vm/port.h"
 #include "vm/symbols.h"
@@ -544,8 +545,7 @@
       isolate()->group()->api_state()->FreePersistentHandle(handle);
     } else {
       Thread* thread = Thread::Current();
-      MessageSnapshotReader reader(message.get(), thread);
-      response_obj = reader.ReadObject();
+      response_obj = ReadMessage(thread, message.get());
     }
     if (response_obj.IsString()) {
       String& response = String::Handle();
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index ed36fe1..810a26e 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -12,6 +12,7 @@
 #include "vm/flags.h"
 #include "vm/globals.h"
 #include "vm/heap/spaces.h"
+#include "vm/isolate.h"
 #include "vm/lockers.h"
 #include "vm/raw_object.h"
 #include "vm/ring_buffer.h"
diff --git a/runtime/vm/heap/weak_table.cc b/runtime/vm/heap/weak_table.cc
index 4070590..36c903004 100644
--- a/runtime/vm/heap/weak_table.cc
+++ b/runtime/vm/heap/weak_table.cc
@@ -30,7 +30,7 @@
 }
 
 void WeakTable::SetValueExclusive(ObjectPtr key, intptr_t val) {
-  intptr_t mask = size() - 1;
+  const intptr_t mask = size() - 1;
   intptr_t idx = Hash(key) & mask;
   intptr_t empty_idx = -1;
   ObjectPtr obj = ObjectAtExclusive(idx);
@@ -74,6 +74,46 @@
   }
 }
 
+bool WeakTable::MarkValueExclusive(ObjectPtr key, intptr_t val) {
+  const intptr_t mask = size() - 1;
+  intptr_t idx = Hash(key) & mask;
+  intptr_t empty_idx = -1;
+  ObjectPtr obj = ObjectAtExclusive(idx);
+
+  while (obj != static_cast<ObjectPtr>(kNoEntry)) {
+    if (obj == key) {
+      return false;
+    } else if ((empty_idx < 0) &&
+               (static_cast<intptr_t>(obj) == kDeletedEntry)) {
+      empty_idx = idx;  // Insert at this location if not found.
+    }
+    idx = (idx + 1) & mask;
+    obj = ObjectAtExclusive(idx);
+  }
+
+  ASSERT(val != 0);
+
+  if (empty_idx >= 0) {
+    // We will be reusing a slot below.
+    set_used(used() - 1);
+    idx = empty_idx;
+  }
+
+  ASSERT(!IsValidEntryAtExclusive(idx));
+  // Set the key and value.
+  SetObjectAt(idx, key);
+  SetValueAt(idx, val);
+  // Update the counts.
+  set_used(used() + 1);
+  set_count(count() + 1);
+
+  // Rehash if needed to ensure that there are empty slots available.
+  if (used_ >= limit()) {
+    Rehash();
+  }
+  return true;
+}
+
 void WeakTable::Reset() {
   intptr_t* old_data = data_;
   used_ = 0;
diff --git a/runtime/vm/heap/weak_table.h b/runtime/vm/heap/weak_table.h
index 3062b53..ade129d 100644
--- a/runtime/vm/heap/weak_table.h
+++ b/runtime/vm/heap/weak_table.h
@@ -104,6 +104,7 @@
   }
 
   void SetValueExclusive(ObjectPtr key, intptr_t val);
+  bool MarkValueExclusive(ObjectPtr key, intptr_t val);
 
   intptr_t GetValueExclusive(ObjectPtr key) const {
     intptr_t mask = size() - 1;
@@ -203,7 +204,9 @@
 
   void Rehash();
 
-  static uword Hash(ObjectPtr key) { return static_cast<uword>(key) * 92821; }
+  static uword Hash(ObjectPtr key) {
+    return (static_cast<uword>(key) * 92821) ^ (static_cast<uword>(key) >> 8);
+  }
 
   Mutex mutex_;
 
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 2f5c24c..d7e8fcb 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -31,6 +31,7 @@
 #include "vm/lockers.h"
 #include "vm/log.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/object.h"
 #include "vm/object_id_ring.h"
 #include "vm/object_store.h"
@@ -123,18 +124,14 @@
 
 static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
                                                  const Instance& obj) {
-  if (ApiObjectConverter::CanConvert(obj.ptr())) {
-    return Message::New(dest_port, obj.ptr(), Message::kNormalPriority);
-  } else {
-    MessageWriter writer(false);
-    return writer.WriteMessage(obj, dest_port, Message::kNormalPriority);
-  }
+  return WriteMessage(/* can_send_any_object */ false, obj, dest_port,
+                      Message::kNormalPriority);
 }
 
-static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
+static std::unique_ptr<Message> SerializeMessage(Zone* zone,
+                                                 Dart_Port dest_port,
                                                  Dart_CObject* obj) {
-  ApiMessageWriter writer;
-  return writer.WriteCMessage(obj, dest_port, Message::kNormalPriority);
+  return WriteApiMessage(zone, obj, dest_port, Message::kNormalPriority);
 }
 
 void IsolateGroupSource::add_loaded_blob(
@@ -1008,9 +1005,8 @@
   element = Capability::New(capability);
   msg.SetAt(2, element);
 
-  MessageWriter writer(false);
-  PortMap::PostMessage(
-      writer.WriteMessage(msg, main_port(), Message::kOOBPriority));
+  PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, msg,
+                                    main_port(), Message::kOOBPriority));
 }
 
 void IsolateGroup::set_object_store(ObjectStore* object_store) {
@@ -1330,11 +1326,7 @@
 
   // Parse the message.
   Object& msg_obj = Object::Handle(zone);
-  if (message->IsRaw()) {
-    msg_obj = message->raw_obj();
-    // We should only be sending RawObjects that can be converted to CObjects.
-    ASSERT(ApiObjectConverter::CanConvert(msg_obj.ptr()));
-  } else if (message->IsPersistentHandle()) {
+  if (message->IsPersistentHandle()) {
     // msg_array = [<message>, <object-in-message-to-rehash>]
     const auto& msg_array = Array::Handle(
         zone, Array::RawCast(message->persistent_handle()->ptr()));
@@ -1348,8 +1340,7 @@
       }
     }
   } else {
-    MessageSnapshotReader reader(message.get(), thread);
-    msg_obj = reader.ReadObject();
+    msg_obj = ReadMessage(thread, message.get());
   }
   if (msg_obj.IsError()) {
     // An error occurred while reading the message.
@@ -2360,7 +2351,7 @@
     listener ^= listeners.At(i);
     if (!listener.IsNull()) {
       Dart_Port port_id = listener.Id();
-      PortMap::PostMessage(SerializeMessage(port_id, &arr));
+      PortMap::PostMessage(SerializeMessage(current_zone(), port_id, &arr));
     }
   }
   return listeners.Length() > 0;
@@ -3297,9 +3288,9 @@
     msg.SetAt(1, element);
     element = Smi::New(Isolate::kBeforeNextEventAction);
     msg.SetAt(2, element);
-    MessageWriter writer(false);
-    std::unique_ptr<Message> message =
-        writer.WriteMessage(msg, main_port(), Message::kOOBPriority);
+    std::unique_ptr<Message> message = WriteMessage(
+        /* can_send_any_object */ false, msg, main_port(),
+        Message::kOOBPriority);
     bool posted = PortMap::PostMessage(std::move(message));
     ASSERT(posted);
   }
@@ -3543,9 +3534,9 @@
   list_values[3] = &imm;
 
   {
-    ApiMessageWriter writer;
-    std::unique_ptr<Message> message =
-        writer.WriteCMessage(&kill_msg, main_port(), Message::kOOBPriority);
+    AllocOnlyStackZone zone;
+    std::unique_ptr<Message> message = WriteApiMessage(
+        zone.GetZone(), &kill_msg, main_port(), Message::kOOBPriority);
     ASSERT(message != nullptr);
 
     // Post the message at the given port.
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
new file mode 100644
index 0000000..ae7a6ad
--- /dev/null
+++ b/runtime/vm/message_snapshot.cc
@@ -0,0 +1,3616 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/message_snapshot.h"
+
+#include <memory>
+
+#include "platform/assert.h"
+#include "platform/unicode.h"
+#include "vm/class_finalizer.h"
+#include "vm/class_id.h"
+#include "vm/dart_api_message.h"
+#include "vm/dart_api_state.h"
+#include "vm/dart_entry.h"
+#include "vm/flags.h"
+#include "vm/growable_array.h"
+#include "vm/heap/heap.h"
+#include "vm/heap/weak_table.h"
+#include "vm/longjump.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/symbols.h"
+#include "vm/type_testing_stubs.h"
+
+namespace dart {
+
+static Dart_CObject cobj_null = {.type = Dart_CObject_kNull,
+                                 .value = {.as_int64 = 0}};
+static Dart_CObject cobj_sentinel = {.type = Dart_CObject_kUnsupported};
+static Dart_CObject cobj_transition_sentinel = {.type =
+                                                    Dart_CObject_kUnsupported};
+static Dart_CObject cobj_empty_array = {
+    .type = Dart_CObject_kArray,
+    .value = {.as_array = {.length = 0, .values = nullptr}}};
+static Dart_CObject cobj_zero_array_element = {.type = Dart_CObject_kInt32,
+                                               .value = {.as_int32 = 0}};
+static Dart_CObject* cobj_zero_array_values[1] = {&cobj_zero_array_element};
+static Dart_CObject cobj_zero_array = {
+    .type = Dart_CObject_kArray,
+    .value = {.as_array = {.length = 1, .values = &cobj_zero_array_values[0]}}};
+static Dart_CObject cobj_dynamic_type = {.type = Dart_CObject_kUnsupported};
+static Dart_CObject cobj_void_type = {.type = Dart_CObject_kUnsupported};
+static Dart_CObject cobj_empty_type_arguments = {.type =
+                                                     Dart_CObject_kUnsupported};
+static Dart_CObject cobj_true = {.type = Dart_CObject_kBool,
+                                 .value = {.as_bool = true}};
+static Dart_CObject cobj_false = {.type = Dart_CObject_kBool,
+                                  .value = {.as_bool = false}};
+
+enum class MessagePhase {
+  kBeforeTypes = 0,
+  kTypes = 1,
+  kCanonicalInstances = 2,
+  kNonCanonicalInstances = 3,
+
+  kNumPhases = 4,
+};
+
+class MessageSerializer;
+class MessageDeserializer;
+class ApiMessageSerializer;
+class ApiMessageDeserializer;
+class WeakPropertyMessageSerializationCluster;
+
+class MessageSerializationCluster : public ZoneAllocated {
+ public:
+  explicit MessageSerializationCluster(const char* name,
+                                       MessagePhase phase,
+                                       intptr_t cid,
+                                       bool is_canonical = false)
+      : name_(name), phase_(phase), cid_(cid), is_canonical_(is_canonical) {}
+  virtual ~MessageSerializationCluster() {}
+
+  virtual void Trace(MessageSerializer* s, Object* object) = 0;
+  virtual void WriteNodes(MessageSerializer* s) = 0;
+  virtual void WriteEdges(MessageSerializer* s) {}
+
+  virtual void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {}
+  virtual void WriteNodesApi(ApiMessageSerializer* s) {}
+  virtual void WriteEdgesApi(ApiMessageSerializer* s) {}
+
+  const char* name() const { return name_; }
+  MessagePhase phase() const { return phase_; }
+  intptr_t cid() const { return cid_; }
+  bool is_canonical() const { return is_canonical_; }
+
+ protected:
+  const char* const name_;
+  const MessagePhase phase_;
+  const intptr_t cid_;
+  const bool is_canonical_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessageSerializationCluster);
+};
+
+class MessageDeserializationCluster : public ZoneAllocated {
+ public:
+  explicit MessageDeserializationCluster(const char* name,
+                                         bool is_canonical = false)
+      : name_(name),
+        is_canonical_(is_canonical),
+        start_index_(0),
+        stop_index_(0) {}
+  virtual ~MessageDeserializationCluster() {}
+
+  virtual void ReadNodes(MessageDeserializer* d) = 0;
+  virtual void ReadEdges(MessageDeserializer* d) {}
+  virtual ObjectPtr PostLoad(MessageDeserializer* d) { return nullptr; }
+  virtual void ReadNodesApi(ApiMessageDeserializer* d) {}
+  virtual void ReadEdgesApi(ApiMessageDeserializer* d) {}
+  virtual void PostLoadApi(ApiMessageDeserializer* d) {}
+
+  void ReadNodesWrapped(MessageDeserializer* d);
+  void ReadNodesWrappedApi(ApiMessageDeserializer* d);
+
+  const char* name() const { return name_; }
+  bool is_canonical() const { return is_canonical_; }
+
+ protected:
+  ObjectPtr PostLoadAbstractType(MessageDeserializer* d);
+  ObjectPtr PostLoadLinkedHash(MessageDeserializer* d);
+
+  const char* const name_;
+  const bool is_canonical_;
+  // The range of the ref array that belongs to this cluster.
+  intptr_t start_index_;
+  intptr_t stop_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessageDeserializationCluster);
+};
+
+class BaseSerializer : public StackResource {
+ public:
+  BaseSerializer(Thread* thread, Zone* zone);
+  ~BaseSerializer();
+
+  // Writes raw data to the stream (basic type).
+  // sizeof(T) must be in {1,2,4,8}.
+  template <typename T>
+  void Write(T value) {
+    BaseWriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
+  }
+  void WriteUnsigned(intptr_t value) { stream_.WriteUnsigned(value); }
+  void WriteWordWith32BitWrites(uword value) {
+    stream_.WriteWordWith32BitWrites(value);
+  }
+  void WriteBytes(const uint8_t* addr, intptr_t len) {
+    stream_.WriteBytes(addr, len);
+  }
+  void WriteAscii(const String& str) {
+    intptr_t len = str.Length();
+    WriteUnsigned(len);
+    for (intptr_t i = 0; i < len; i++) {
+      int64_t c = str.CharAt(i);
+      ASSERT(c < 128);
+      Write<uint8_t>(c);
+    }
+    Write<uint8_t>(0);
+  }
+
+  MessageSerializationCluster* NewClusterForClass(intptr_t cid,
+                                                  bool is_canonical);
+  void WriteCluster(MessageSerializationCluster* cluster);
+
+  std::unique_ptr<Message> Finish(Dart_Port dest_port,
+                                  Message::Priority priority) {
+    MessageFinalizableData* finalizable_data = finalizable_data_;
+    finalizable_data_ = nullptr;
+    finalizable_data->SerializationSucceeded();
+    intptr_t size;
+    uint8_t* buffer = stream_.Steal(&size);
+    return Message::New(dest_port, buffer, size, finalizable_data, priority);
+  }
+
+  Zone* zone() const { return zone_; }
+  MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
+  intptr_t next_ref_index() const { return next_ref_index_; }
+
+ protected:
+  Zone* const zone_;
+  MallocWriteStream stream_;
+  MessageFinalizableData* finalizable_data_;
+  GrowableArray<MessageSerializationCluster*> clusters_;
+  WeakPropertyMessageSerializationCluster* ephemeron_cluster_;
+  intptr_t num_base_objects_;
+  intptr_t num_written_objects_;
+  intptr_t next_ref_index_;
+};
+
+class MessageSerializer : public BaseSerializer {
+ public:
+  MessageSerializer(Thread* thread, bool can_send_any_object);
+  ~MessageSerializer();
+
+  bool MarkObjectId(ObjectPtr object, intptr_t id) {
+    ASSERT(id != WeakTable::kNoValue);
+    WeakTable* table;
+    if (!object->IsSmiOrOldObject()) {
+      table = isolate()->forward_table_new();
+    } else {
+      table = isolate()->forward_table_old();
+    }
+    return table->MarkValueExclusive(object, id);
+  }
+
+  void SetObjectId(ObjectPtr object, intptr_t id) {
+    ASSERT(id != WeakTable::kNoValue);
+    WeakTable* table;
+    if (!object->IsSmiOrOldObject()) {
+      table = isolate()->forward_table_new();
+    } else {
+      table = isolate()->forward_table_old();
+    }
+    table->SetValueExclusive(object, id);
+  }
+
+  intptr_t GetObjectId(ObjectPtr object) const {
+    const WeakTable* table;
+    if (!object->IsSmiOrOldObject()) {
+      table = isolate()->forward_table_new();
+    } else {
+      table = isolate()->forward_table_old();
+    }
+    return table->GetValueExclusive(object);
+  }
+
+  DART_NOINLINE void AddBaseObject(ObjectPtr base_object) {
+    AssignRef(base_object);
+    num_base_objects_++;
+  }
+  DART_NOINLINE void AssignRef(ObjectPtr object) {
+    SetObjectId(object, next_ref_index_);
+    next_ref_index_++;
+  }
+  void AssignRef(Object* object) { AssignRef(object->ptr()); }
+
+  void Push(ObjectPtr object);
+
+  void Trace(Object* object);
+
+  void IllegalObject(const Object& object, const char* message);
+
+  void AddBaseObjects();
+  void Serialize(const Object& root);
+
+  DART_NOINLINE void WriteRef(ObjectPtr object) {
+    intptr_t index = GetObjectId(object);
+    ASSERT(index != WeakTable::kNoValue);
+    WriteUnsigned(index);
+  }
+
+  bool can_send_any_object() const { return can_send_any_object_; }
+  const char* exception_message() const { return exception_message_; }
+  Thread* thread() const {
+    return static_cast<Thread*>(StackResource::thread());
+  }
+  Isolate* isolate() const { return thread()->isolate(); }
+  IsolateGroup* isolate_group() const { return thread()->isolate_group(); }
+
+  bool HasRef(ObjectPtr object) const {
+    return GetObjectId(object) != WeakTable::kNoValue;
+  }
+
+ private:
+  WeakTable* forward_table_new_;
+  WeakTable* forward_table_old_;
+  GrowableArray<Object*> stack_;
+  bool const can_send_any_object_;
+  const char* exception_message_;
+};
+
+class ApiMessageSerializer : public BaseSerializer {
+ public:
+  explicit ApiMessageSerializer(Zone* zone);
+  ~ApiMessageSerializer();
+
+  bool MarkObjectId(Dart_CObject* object, intptr_t id) {
+    ASSERT(id != WeakTable::kNoValue);
+    return forward_table_.MarkValueExclusive(
+        static_cast<ObjectPtr>(reinterpret_cast<uword>(object)), id);
+  }
+
+  void SetObjectId(Dart_CObject* object, intptr_t id) {
+    ASSERT(id != WeakTable::kNoValue);
+    forward_table_.SetValueExclusive(
+        static_cast<ObjectPtr>(reinterpret_cast<uword>(object)), id);
+  }
+
+  intptr_t GetObjectId(Dart_CObject* object) const {
+    return forward_table_.GetValueExclusive(
+        static_cast<ObjectPtr>(reinterpret_cast<uword>(object)));
+  }
+
+  DART_NOINLINE void AddBaseObject(Dart_CObject* base_object) {
+    AssignRef(base_object);
+    num_base_objects_++;
+  }
+  DART_NOINLINE intptr_t AssignRef(Dart_CObject* object) {
+    SetObjectId(object, next_ref_index_);
+    return next_ref_index_++;
+  }
+  void ForwardRef(Dart_CObject* old, Dart_CObject* nue) {
+    intptr_t id = GetObjectId(nue);
+    ASSERT(id != WeakTable::kNoValue);
+    SetObjectId(old, id);
+    num_written_objects_--;
+  }
+
+  void Push(Dart_CObject* object);
+
+  bool Trace(Dart_CObject* object);
+
+  void AddBaseObjects();
+  bool Serialize(Dart_CObject* root);
+
+  void WriteRef(Dart_CObject* object) {
+    intptr_t index = GetObjectId(object);
+    ASSERT(index != WeakTable::kNoValue);
+    WriteUnsigned(index);
+  }
+
+  bool Fail(const char* message) {
+    exception_message_ = message;
+    return false;
+  }
+
+ private:
+  WeakTable forward_table_;
+  GrowableArray<Dart_CObject*> stack_;
+  const char* exception_message_;
+};
+
+class BaseDeserializer : public ValueObject {
+ public:
+  BaseDeserializer(Zone* zone, Message* message);
+  ~BaseDeserializer();
+
+  // Reads raw data (for basic types).
+  // sizeof(T) must be in {1,2,4,8}.
+  template <typename T>
+  T Read() {
+    return ReadStream::Raw<sizeof(T), T>::Read(&stream_);
+  }
+  intptr_t ReadUnsigned() { return stream_.ReadUnsigned(); }
+  uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); }
+  void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); }
+  const char* ReadAscii() {
+    intptr_t len = ReadUnsigned();
+    const char* result = reinterpret_cast<const char*>(CurrentBufferAddress());
+    Advance(len + 1);
+    return result;
+  }
+
+  const uint8_t* CurrentBufferAddress() const {
+    return stream_.AddressOfCurrentPosition();
+  }
+
+  void Advance(intptr_t value) { stream_.Advance(value); }
+
+  MessageDeserializationCluster* ReadCluster();
+
+  Zone* zone() const { return zone_; }
+  intptr_t next_index() const { return next_ref_index_; }
+  MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
+
+ protected:
+  Zone* zone_;
+  ReadStream stream_;
+  MessageFinalizableData* finalizable_data_;
+  intptr_t next_ref_index_;
+};
+
+class MessageDeserializer : public BaseDeserializer {
+ public:
+  MessageDeserializer(Thread* thread, Message* message)
+      : BaseDeserializer(thread->zone(), message),
+        thread_(thread),
+        refs_(Array::Handle(thread->zone())) {}
+  ~MessageDeserializer() {}
+
+  DART_NOINLINE void AddBaseObject(ObjectPtr base_object) {
+    AssignRef(base_object);
+  }
+  void AssignRef(ObjectPtr object) {
+    refs_.untag()->set_element(next_ref_index_, object);
+    next_ref_index_++;
+  }
+
+  ObjectPtr Ref(intptr_t index) const {
+    ASSERT(index > 0);
+    ASSERT(index <= next_ref_index_);
+    return refs_.At(index);
+  }
+  void UpdateRef(intptr_t index, const Object& new_object) {
+    ASSERT(index > 0);
+    ASSERT(index <= next_ref_index_);
+    refs_.SetAt(index, new_object);
+  }
+
+  ObjectPtr ReadRef() { return Ref(ReadUnsigned()); }
+
+  void AddBaseObjects();
+  ObjectPtr Deserialize();
+
+  Thread* thread() const { return thread_; }
+  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
+  ArrayPtr refs() const { return refs_.ptr(); }
+
+ private:
+  Thread* const thread_;
+  Array& refs_;
+};
+
+class ApiMessageDeserializer : public BaseDeserializer {
+ public:
+  ApiMessageDeserializer(Zone* zone, Message* message)
+      : BaseDeserializer(zone, message), refs_(nullptr) {}
+  ~ApiMessageDeserializer() {}
+
+  void AddBaseObject(Dart_CObject* base_object) { AssignRef(base_object); }
+  void AssignRef(Dart_CObject* object) {
+    refs_[next_ref_index_] = object;
+    next_ref_index_++;
+  }
+
+  Dart_CObject* Allocate(Dart_CObject_Type type) {
+    Dart_CObject* result = zone()->Alloc<Dart_CObject>(1);
+    result->type = type;
+    return result;
+  }
+
+  Dart_CObject* Ref(intptr_t index) const {
+    ASSERT(index > 0);
+    ASSERT(index <= next_ref_index_);
+    return refs_[index];
+  }
+
+  Dart_CObject* ReadRef() { return Ref(ReadUnsigned()); }
+
+  void AddBaseObjects();
+  Dart_CObject* Deserialize();
+
+ private:
+  Dart_CObject** refs_;
+};
+
+void MessageDeserializationCluster::ReadNodesWrapped(MessageDeserializer* d) {
+  start_index_ = d->next_index();
+  this->ReadNodes(d);
+  stop_index_ = d->next_index();
+}
+
+void MessageDeserializationCluster::ReadNodesWrappedApi(
+    ApiMessageDeserializer* d) {
+  start_index_ = d->next_index();
+  this->ReadNodesApi(d);
+  stop_index_ = d->next_index();
+}
+
+ObjectPtr MessageDeserializationCluster::PostLoadAbstractType(
+    MessageDeserializer* d) {
+  ClassFinalizer::FinalizationKind finalization =
+      is_canonical() ? ClassFinalizer::kCanonicalize
+                     : ClassFinalizer::kFinalize;
+  AbstractType& type = AbstractType::Handle(d->zone());
+  Code& code = Code::Handle(d->zone());
+  for (intptr_t id = start_index_; id < stop_index_; id++) {
+    type ^= d->Ref(id);
+
+    code = TypeTestingStubGenerator::DefaultCodeForType(type);
+    type.InitializeTypeTestingStubNonAtomic(code);
+
+    type ^= ClassFinalizer::FinalizeType(type, finalization);
+    d->UpdateRef(id, type);
+  }
+  return nullptr;
+}
+
+ObjectPtr MessageDeserializationCluster::PostLoadLinkedHash(
+    MessageDeserializer* d) {
+  ASSERT(!is_canonical());
+  Array& maps = Array::Handle(d->zone(), d->refs());
+  maps = maps.Slice(start_index_, stop_index_ - start_index_,
+                    /*with_type_argument=*/false);
+  return DartLibraryCalls::RehashObjects(d->thread(), maps);
+}
+
+class ClassMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  ClassMessageSerializationCluster()
+      : MessageSerializationCluster("Class",
+                                    MessagePhase::kBeforeTypes,
+                                    kClassCid),
+        objects_() {}
+  ~ClassMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Class* cls = static_cast<Class*>(object);
+    objects_.Add(cls);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    Library& lib = Library::Handle(s->zone());
+    String& str = String::Handle(s->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      Class* cls = objects_[i];
+      s->AssignRef(cls);
+      intptr_t cid = cls->id();
+      if (cid < kNumPredefinedCids) {
+        ASSERT(cid != 0);
+        s->WriteUnsigned(cid);
+      } else {
+        s->WriteUnsigned(0);
+        lib = cls->library();
+        str = lib.url();
+        s->WriteAscii(str);
+        str = cls->Name();
+        s->WriteAscii(str);
+      }
+    }
+  }
+
+ private:
+  GrowableArray<Class*> objects_;
+};
+
+class ClassMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  ClassMessageDeserializationCluster()
+      : MessageDeserializationCluster("Class") {}
+  ~ClassMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    auto* class_table = d->isolate_group()->class_table();
+    String& str = String::Handle(d->zone());
+    Library& lib = Library::Handle(d->zone());
+    Class& cls = Class::Handle(d->zone());
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t cid = d->ReadUnsigned();
+      if (cid != 0) {
+        cls = class_table->At(cid);
+      } else {
+        str = String::New(d->ReadAscii());  // Library URI.
+        lib = Library::LookupLibrary(d->thread(), str);
+        RELEASE_ASSERT(!lib.IsNull());
+        str = String::New(d->ReadAscii());  // Class name.
+        if (str.Equals(Symbols::TopLevel())) {
+          cls = lib.toplevel_class();
+        } else {
+          cls = lib.LookupClass(str);
+        }
+        RELEASE_ASSERT(!cls.IsNull());
+        cls.EnsureIsFinalized(d->thread());
+      }
+      d->AssignRef(cls.ptr());
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t cid = d->ReadUnsigned();
+      if (cid == 0) {
+        d->ReadAscii();  // Library URI.
+        d->ReadAscii();  // Class name.
+      }
+      d->AssignRef(nullptr);
+    }
+  }
+};
+
+class TypeArgumentsMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit TypeArgumentsMessageSerializationCluster(bool is_canonical)
+      : MessageSerializationCluster("TypeArguments",
+                                    MessagePhase::kTypes,
+                                    kTypeArgumentsCid,
+                                    is_canonical) {}
+  ~TypeArgumentsMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    TypeArguments* type_args = static_cast<TypeArguments*>(object);
+    objects_.Add(type_args);
+
+    s->Push(type_args->untag()->instantiations());
+    intptr_t length = Smi::Value(type_args->untag()->length());
+    for (intptr_t i = 0; i < length; i++) {
+      s->Push(type_args->untag()->element(i));
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TypeArguments* type_args = objects_[i];
+      s->AssignRef(type_args);
+      intptr_t length = Smi::Value(type_args->untag()->length());
+      s->WriteUnsigned(length);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      TypeArguments* type_args = objects_[i];
+      intptr_t hash = Smi::Value(type_args->untag()->hash());
+      s->Write<int32_t>(hash);
+      const intptr_t nullability =
+          Smi::Value(type_args->untag()->nullability());
+      s->WriteUnsigned(nullability);
+
+      intptr_t length = Smi::Value(type_args->untag()->length());
+      s->WriteUnsigned(length);
+      for (intptr_t j = 0; j < length; j++) {
+        s->WriteRef(type_args->untag()->element(j));
+      }
+    }
+  }
+
+ private:
+  GrowableArray<TypeArguments*> objects_;
+};
+
+class TypeArgumentsMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit TypeArgumentsMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("TypeArguments", is_canonical) {}
+  ~TypeArgumentsMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      d->AssignRef(TypeArguments::New(length));
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      TypeArgumentsPtr type_args = static_cast<TypeArgumentsPtr>(d->Ref(id));
+
+      type_args->untag()->hash_ = Smi::New(d->Read<int32_t>());
+      type_args->untag()->nullability_ = Smi::New(d->ReadUnsigned());
+
+      intptr_t length = d->ReadUnsigned();
+      for (intptr_t j = 0; j < length; j++) {
+        type_args->untag()->types()[j] =
+            static_cast<AbstractTypePtr>(d->ReadRef());
+      }
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    if (is_canonical()) {
+      TypeArguments& type_args = TypeArguments::Handle(d->zone());
+      for (intptr_t id = start_index_; id < stop_index_; id++) {
+        type_args ^= d->Ref(id);
+        type_args ^= type_args.Canonicalize(d->thread());
+        d->UpdateRef(id, type_args);
+      }
+    }
+    return nullptr;
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->ReadUnsigned();  // Length.
+      d->AssignRef(nullptr);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      d->Read<int32_t>();  // Hash.
+      d->ReadUnsigned();   // Nullability.
+      intptr_t length = d->ReadUnsigned();
+      for (intptr_t j = 0; j < length; j++) {
+        d->ReadRef();  // Element.
+      }
+    }
+  }
+};
+
+class FunctionMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  FunctionMessageSerializationCluster()
+      : MessageSerializationCluster("Function",
+                                    MessagePhase::kBeforeTypes,
+                                    kFunctionCid) {}
+  ~FunctionMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Function* func = static_cast<Function*>(object);
+    objects_.Add(func);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    Library& lib = Library::Handle(s->zone());
+    Class& cls = Class::Handle(s->zone());
+    String& str = String::Handle(s->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      Function* func = objects_[i];
+      s->AssignRef(func);
+      cls ^= func->Owner();
+      lib = cls.library();
+      str = lib.url();
+      s->WriteAscii(str);
+      str = cls.Name();
+      s->WriteAscii(str);
+      str = func->name();
+      s->WriteAscii(str);
+    }
+  }
+
+ private:
+  GrowableArray<Function*> objects_;
+};
+
+class FunctionMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  FunctionMessageDeserializationCluster()
+      : MessageDeserializationCluster("Function") {}
+  ~FunctionMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    String& str = String::Handle(d->zone());
+    Library& lib = Library::Handle(d->zone());
+    Class& cls = Class::Handle(d->zone());
+    Function& func = Function::Handle(d->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      str = String::New(d->ReadAscii());  // Library URI.
+      lib = Library::LookupLibrary(d->thread(), str);
+      RELEASE_ASSERT(!lib.IsNull());
+      str = String::New(d->ReadAscii());  // Class name.
+      if (str.Equals(Symbols::TopLevel())) {
+        cls = lib.toplevel_class();
+      } else {
+        cls = lib.LookupClass(str);
+      }
+      RELEASE_ASSERT(!cls.IsNull());
+      cls.EnsureIsFinalized(d->thread());
+      str = String::New(d->ReadAscii());  // Function name.
+      func = cls.LookupStaticFunction(str);
+      RELEASE_ASSERT(!func.IsNull());
+      d->AssignRef(func.ptr());
+    }
+  }
+};
+
+class InstanceMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  InstanceMessageSerializationCluster(bool is_canonical, intptr_t cid)
+      : MessageSerializationCluster("Instance",
+                                    is_canonical
+                                        ? MessagePhase::kCanonicalInstances
+                                        : MessagePhase::kNonCanonicalInstances,
+                                    cid,
+                                    is_canonical),
+        cls_(Class::Handle()) {
+    cls_ = IsolateGroup::Current()->class_table()->At(cid);
+    next_field_offset_ = cls_.host_next_field_offset();
+  }
+  ~InstanceMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Instance* instance = static_cast<Instance*>(object);
+    objects_.Add(instance);
+
+    const intptr_t next_field_offset = next_field_offset_;
+    const auto unboxed_fields_bitmap =
+        s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
+    for (intptr_t offset = Instance::NextFieldOffset();
+         offset < next_field_offset; offset += kCompressedWordSize) {
+      if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+        continue;
+      }
+      s->Push(reinterpret_cast<CompressedObjectPtr*>(
+                  reinterpret_cast<uword>(instance->untag()) + offset)
+                  ->Decompress(instance->untag()->heap_base()));
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    s->WriteRef(cls_.ptr());
+
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Instance* instance = objects_[i];
+      s->AssignRef(instance);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      Instance* instance = objects_[i];
+
+      const intptr_t next_field_offset = next_field_offset_;
+      const auto unboxed_fields_bitmap =
+          s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
+      for (intptr_t offset = Instance::NextFieldOffset();
+           offset < next_field_offset; offset += kCompressedWordSize) {
+        if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+          // Writes 32 bits of the unboxed value at a time
+          const uword value = *reinterpret_cast<compressed_uword*>(
+              reinterpret_cast<uword>(instance->untag()) + offset);
+          s->WriteWordWith32BitWrites(value);
+        } else {
+          s->WriteRef(reinterpret_cast<CompressedObjectPtr*>(
+                          reinterpret_cast<uword>(instance->untag()) + offset)
+                          ->Decompress(instance->untag()->heap_base()));
+        }
+      }
+    }
+  }
+
+ private:
+  Class& cls_;
+  intptr_t next_field_offset_;
+  GrowableArray<Instance*> objects_;
+};
+
+class InstanceMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit InstanceMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("Instance", is_canonical),
+        cls_(Class::Handle()) {}
+  ~InstanceMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    cls_ ^= d->ReadRef();
+
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(Instance::New(cls_));
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    const intptr_t next_field_offset = cls_.host_next_field_offset();
+    const intptr_t type_argument_field_offset =
+        cls_.host_type_arguments_field_offset();
+    const auto unboxed_fields_bitmap =
+        d->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
+            cls_.id());
+    const bool use_field_guards = d->isolate_group()->use_field_guards();
+    const Array& field_map = Array::Handle(d->zone(), cls_.OffsetToFieldMap());
+    Instance& instance = Instance::Handle(d->zone());
+    Object& value = Object::Handle(d->zone());
+    Field& field = Field::Handle(d->zone());
+
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      instance ^= d->Ref(id);
+      for (intptr_t offset = Instance::NextFieldOffset();
+           offset < next_field_offset; offset += kCompressedWordSize) {
+        if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+          compressed_uword* p = reinterpret_cast<compressed_uword*>(
+              reinterpret_cast<uword>(instance.untag()) + offset);
+          // Reads 32 bits of the unboxed value at a time
+          *p = d->ReadWordWith32BitReads();
+        } else {
+          value = d->ReadRef();
+          instance.SetFieldAtOffset(offset, value);
+          if (use_field_guards && (offset != type_argument_field_offset) &&
+              (value.ptr() != Object::sentinel().ptr())) {
+            field ^= field_map.At(offset >> kCompressedWordSizeLog2);
+            ASSERT(!field.IsNull());
+            ASSERT(field.HostOffset() == offset);
+            field.RecordStore(value);
+          }
+        }
+      }
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    if (is_canonical()) {
+      SafepointMutexLocker ml(
+          d->isolate_group()->constant_canonicalization_mutex());
+      Instance& instance = Instance::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        instance ^= d->Ref(i);
+        instance = instance.CanonicalizeLocked(d->thread());
+        d->UpdateRef(i, instance);
+      }
+    }
+
+    if (cls_.ptr() == d->isolate_group()->object_store()->expando_class()) {
+      Instance& instance = Instance::Handle(d->zone());
+      const String& selector = Library::PrivateCoreLibName(Symbols::_rehash());
+      Array& args = Array::Handle(d->zone(), Array::New(1));
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        instance ^= d->Ref(i);
+        args.SetAt(0, instance);
+        ObjectPtr error = instance.Invoke(selector, args, Object::empty_array(),
+                                          false, false);
+        if (error != Object::null()) {
+          return error;
+        }
+      }
+    }
+    return nullptr;
+  }
+
+ private:
+  Class& cls_;
+};
+
+class TypeMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit TypeMessageSerializationCluster(bool is_canonical)
+      : MessageSerializationCluster("Type",
+                                    MessagePhase::kTypes,
+                                    kTypeCid,
+                                    is_canonical) {}
+  ~TypeMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Type* type = static_cast<Type*>(object);
+    objects_.Add(type);
+
+    s->Push(type->type_class());
+    s->Push(type->arguments());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Type* type = objects_[i];
+      s->AssignRef(type);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      Type* type = objects_[i];
+      s->WriteRef(type->type_class());
+      s->WriteRef(type->arguments());
+      s->Write<uint8_t>(static_cast<uint8_t>(type->nullability()));
+    }
+  }
+
+ private:
+  GrowableArray<Type*> objects_;
+};
+
+class TypeMessageDeserializationCluster : public MessageDeserializationCluster {
+ public:
+  explicit TypeMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("Type", is_canonical) {}
+  ~TypeMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(Type::New());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    Class& cls = Class::Handle(d->zone());
+    Type& type = Type::Handle(d->zone());
+    TypeArguments& type_args = TypeArguments::Handle(d->zone());
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      type ^= d->Ref(id);
+      cls ^= d->ReadRef();
+      type.set_type_class(cls);
+      type_args ^= d->ReadRef();
+      type.set_arguments(type_args);
+      type.untag()->set_hash(Smi::New(0));
+      type.set_nullability(static_cast<Nullability>(d->Read<uint8_t>()));
+      type.SetIsFinalized();
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) { return PostLoadAbstractType(d); }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(nullptr);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      d->ReadRef();        // Class.
+      d->ReadRef();        // Type arguments.
+      d->Read<uint8_t>();  // Nullability.
+    }
+  }
+};
+
+class TypeRefMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit TypeRefMessageSerializationCluster(bool is_canonical)
+      : MessageSerializationCluster("TypeRef",
+                                    MessagePhase::kTypes,
+                                    kTypeRefCid,
+                                    is_canonical) {}
+  ~TypeRefMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    TypeRef* type = static_cast<TypeRef*>(object);
+    objects_.Add(type);
+
+    s->Push(type->type());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TypeRef* type = objects_[i];
+      s->AssignRef(type);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      TypeRef* type = objects_[i];
+      s->WriteRef(type->type());
+    }
+  }
+
+ private:
+  GrowableArray<TypeRef*> objects_;
+};
+
+class TypeRefMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit TypeRefMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("TypeRef", is_canonical) {}
+  ~TypeRefMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(TypeRef::New());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      TypeRefPtr type = static_cast<TypeRefPtr>(d->Ref(id));
+      type->untag()->set_type(static_cast<AbstractTypePtr>(d->ReadRef()));
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    ClassFinalizer::FinalizationKind finalization =
+        is_canonical() ? ClassFinalizer::kCanonicalize
+                       : ClassFinalizer::kFinalize;
+    Code& code = Code::Handle(d->zone());
+    TypeRef& type = TypeRef::Handle(d->zone());
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      type ^= d->Ref(id);
+      type ^= ClassFinalizer::FinalizeType(type, finalization);
+      d->UpdateRef(id, type);
+
+      code = TypeTestingStubGenerator::DefaultCodeForType(type);
+      type.InitializeTypeTestingStubNonAtomic(code);
+    }
+    return nullptr;
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(nullptr);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      d->ReadRef();  // Type.
+    }
+  }
+};
+
+class ClosureMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit ClosureMessageSerializationCluster(bool is_canonical)
+      : MessageSerializationCluster("Closure",
+                                    MessagePhase::kCanonicalInstances,
+                                    kClosureCid,
+                                    is_canonical) {}
+  ~ClosureMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Closure* closure = static_cast<Closure*>(object);
+
+    if (!s->can_send_any_object() ||
+        !Function::IsImplicitStaticClosureFunction(closure->function())) {
+      const char* message = OS::SCreate(
+          s->zone(),
+          "Illegal argument in isolate message : (object is a closure - %s)",
+          Function::Handle(closure->function()).ToCString());
+      s->IllegalObject(*object, message);
+    }
+
+    objects_.Add(closure);
+
+    s->Push(closure->function());
+    s->Push(closure->delayed_type_arguments());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Closure* closure = objects_[i];
+      s->AssignRef(closure);
+      s->WriteRef(closure->function());
+      s->WriteRef(closure->delayed_type_arguments());
+    }
+  }
+
+ private:
+  GrowableArray<Closure*> objects_;
+};
+
+class ClosureMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit ClosureMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("Closure", is_canonical) {}
+  ~ClosureMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    const Context& null_context = Context::Handle(d->zone());
+    TypeArguments& delayed_type_arguments = TypeArguments::Handle(d->zone());
+    Function& func = Function::Handle(d->zone());
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      func ^= d->ReadRef();
+      ASSERT(func.is_static());
+      func = func.ImplicitClosureFunction();
+      delayed_type_arguments ^= d->ReadRef();
+      if (delayed_type_arguments.IsNull()) {
+        d->AssignRef(func.ImplicitStaticClosure());
+      } else {
+        // If delayed type arguments were provided, create and return new
+        // closure with those, otherwise return associated implicit static
+        // closure. Note that static closures can't have instantiator or
+        // function types since statics can't refer to class type arguments,
+        // don't have outer functions.
+        d->AssignRef(Closure::New(
+            /*instantiator_type_arguments=*/Object::null_type_arguments(),
+            /*function_type_arguments=*/Object::null_type_arguments(),
+            delayed_type_arguments, func, null_context, Heap::kOld));
+      }
+    }
+  }
+};
+
+class SmiMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit SmiMessageSerializationCluster(Zone* zone)
+      : MessageSerializationCluster("Smi",
+                                    MessagePhase::kBeforeTypes,
+                                    kSmiCid,
+                                    true),
+        objects_(zone, 0) {}
+  ~SmiMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Smi* smi = static_cast<Smi*>(object);
+    objects_.Add(smi);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Smi* smi = static_cast<Smi*>(objects_[i]);
+      s->AssignRef(smi);
+      s->Write<intptr_t>(smi->Value());
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<Smi*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* smi = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(smi);
+      intptr_t value = smi->type == Dart_CObject_kInt32 ? smi->value.as_int32
+                                                        : smi->value.as_int64;
+      s->Write<intptr_t>(value);
+    }
+  }
+
+ private:
+  GrowableArray<Smi*> objects_;
+};
+
+class SmiMessageDeserializationCluster : public MessageDeserializationCluster {
+ public:
+  SmiMessageDeserializationCluster()
+      : MessageDeserializationCluster("Smi", true) {}
+  ~SmiMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(Smi::New(d->Read<intptr_t>()));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t value = d->Read<intptr_t>();
+      Dart_CObject* smi;
+      if ((kMinInt32 <= value) && (value <= kMaxInt32)) {
+        smi = d->Allocate(Dart_CObject_kInt32);
+        smi->value.as_int32 = value;
+      } else {
+        smi = d->Allocate(Dart_CObject_kInt64);
+        smi->value.as_int64 = value;
+      }
+      d->AssignRef(smi);
+    }
+  }
+};
+
+class MintMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit MintMessageSerializationCluster(Zone* zone, bool is_canonical)
+      : MessageSerializationCluster("Mint",
+                                    MessagePhase::kBeforeTypes,
+                                    kMintCid,
+                                    is_canonical),
+        objects_(zone, 0) {}
+  ~MintMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Mint* mint = static_cast<Mint*>(object);
+    objects_.Add(mint);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Mint* mint = static_cast<Mint*>(objects_[i]);
+      s->AssignRef(mint);
+      s->Write<int64_t>(mint->value());
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<Mint*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* mint = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(mint);
+      int64_t value = mint->type == Dart_CObject_kInt32 ? mint->value.as_int32
+                                                        : mint->value.as_int64;
+      s->Write<int64_t>(value);
+    }
+  }
+
+ private:
+  GrowableArray<Mint*> objects_;
+};
+
+class MintMessageDeserializationCluster : public MessageDeserializationCluster {
+ public:
+  explicit MintMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("int", is_canonical) {}
+  ~MintMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      int64_t value = d->Read<int64_t>();
+      d->AssignRef(is_canonical() ? Mint::NewCanonical(value)
+                                  : Mint::New(value));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      int64_t value = d->Read<int64_t>();
+      Dart_CObject* mint;
+      if ((kMinInt32 <= value) && (value <= kMaxInt32)) {
+        mint = d->Allocate(Dart_CObject_kInt32);
+        mint->value.as_int32 = value;
+      } else {
+        mint = d->Allocate(Dart_CObject_kInt64);
+        mint->value.as_int64 = value;
+      }
+      d->AssignRef(mint);
+    }
+  }
+};
+
+class DoubleMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit DoubleMessageSerializationCluster(Zone* zone, bool is_canonical)
+      : MessageSerializationCluster("double",
+                                    MessagePhase::kBeforeTypes,
+                                    kDoubleCid,
+                                    is_canonical),
+        objects_(zone, 0) {}
+
+  ~DoubleMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Double* dbl = static_cast<Double*>(object);
+    objects_.Add(dbl);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Double* dbl = objects_[i];
+      s->AssignRef(dbl);
+      s->Write<double>(dbl->untag()->value_);
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<Double*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* dbl = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(dbl);
+      s->Write<double>(dbl->value.as_double);
+    }
+  }
+
+ private:
+  GrowableArray<Double*> objects_;
+};
+
+class DoubleMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit DoubleMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("double", is_canonical) {}
+  ~DoubleMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      double value = d->Read<double>();
+      d->AssignRef(is_canonical() ? Double::NewCanonical(value)
+                                  : Double::New(value));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* dbl = d->Allocate(Dart_CObject_kDouble);
+      dbl->value.as_double = d->Read<double>();
+      d->AssignRef(dbl);
+    }
+  }
+};
+
+class GrowableObjectArrayMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  GrowableObjectArrayMessageSerializationCluster()
+      : MessageSerializationCluster("GrowableObjectArray",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kGrowableObjectArrayCid) {}
+  ~GrowableObjectArrayMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    GrowableObjectArray* array = static_cast<GrowableObjectArray*>(object);
+    objects_.Add(array);
+
+    s->Push(array->GetTypeArguments());
+    for (intptr_t i = 0, n = array->Length(); i < n; i++) {
+      s->Push(array->At(i));
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      GrowableObjectArray* array = objects_[i];
+      s->WriteUnsigned(array->Length());
+      s->AssignRef(array);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      GrowableObjectArray* array = objects_[i];
+      s->WriteRef(array->GetTypeArguments());
+      for (intptr_t i = 0, n = array->Length(); i < n; i++) {
+        s->WriteRef(array->At(i));
+      }
+    }
+  }
+
+ private:
+  GrowableArray<GrowableObjectArray*> objects_;
+};
+
+class GrowableObjectArrayMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  GrowableObjectArrayMessageDeserializationCluster()
+      : MessageDeserializationCluster("GrowableObjectArray") {}
+  ~GrowableObjectArrayMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    GrowableObjectArray& array = GrowableObjectArray::Handle(d->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      array = GrowableObjectArray::New(length);  // Here length is capacity.
+      array.SetLength(length);
+      d->AssignRef(array.ptr());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    GrowableObjectArray& array = GrowableObjectArray::Handle(d->zone());
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      array ^= d->Ref(id);
+      array.untag()->set_type_arguments(
+          static_cast<TypeArgumentsPtr>(d->ReadRef()));
+      for (intptr_t i = 0, n = array.Length(); i < n; i++) {
+        array.untag()->data()->untag()->set_element(i, d->ReadRef());
+      }
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    ASSERT(!is_canonical());
+    return nullptr;
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* array = d->Allocate(Dart_CObject_kArray);
+      intptr_t length = d->ReadUnsigned();
+      array->value.as_array.length = length;
+      if (length > 0) {
+        array->value.as_array.values = d->zone()->Alloc<Dart_CObject*>(length);
+      } else {
+        ASSERT(length == 0);
+        array->value.as_array.values = NULL;
+      }
+      d->AssignRef(array);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      Dart_CObject* array = d->Ref(id);
+      intptr_t length = array->value.as_array.length;
+      d->ReadRef();  // type_arguments
+      for (intptr_t i = 0; i < length; i++) {
+        array->value.as_array.values[i] = d->ReadRef();
+      }
+    }
+  }
+};
+
+class TypedDataMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit TypedDataMessageSerializationCluster(Zone* zone, intptr_t cid)
+      : MessageSerializationCluster("TypedData",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    cid),
+        objects_(zone, 0) {}
+  ~TypedDataMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    TypedData* data = static_cast<TypedData*>(object);
+    objects_.Add(data);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TypedData* data = objects_[i];
+      s->AssignRef(data);
+      intptr_t length = data->Length();
+      s->WriteUnsigned(length);
+      NoSafepointScope no_safepoint;
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(data->untag()->data());
+      s->WriteBytes(cdata, length * element_size);
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<TypedData*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* data = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(data);
+      intptr_t length = data->value.as_external_typed_data.length;
+      s->WriteUnsigned(length);
+      uint8_t* cdata =
+          reinterpret_cast<uint8_t*>(data->value.as_typed_data.values);
+      s->WriteBytes(cdata, length * element_size);
+    }
+  }
+
+ private:
+  GrowableArray<TypedData*> objects_;
+};
+
+class TypedDataMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit TypedDataMessageDeserializationCluster(intptr_t cid)
+      : MessageDeserializationCluster("TypedData"), cid_(cid) {}
+  ~TypedDataMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+    intptr_t count = d->ReadUnsigned();
+    TypedData& data = TypedData::Handle(d->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      data = TypedData::New(cid_, length);
+      d->AssignRef(data.ptr());
+      const intptr_t length_in_bytes = length * element_size;
+      NoSafepointScope no_safepoint;
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(data.untag()->data());
+      d->ReadBytes(cdata, length_in_bytes);
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    Dart_TypedData_Type type;
+    switch (cid_) {
+      case kTypedDataInt8ArrayCid:
+        type = Dart_TypedData_kInt8;
+        break;
+      case kTypedDataUint8ArrayCid:
+        type = Dart_TypedData_kUint8;
+        break;
+      case kTypedDataUint8ClampedArrayCid:
+        type = Dart_TypedData_kUint8Clamped;
+        break;
+      case kTypedDataInt16ArrayCid:
+        type = Dart_TypedData_kInt16;
+        break;
+      case kTypedDataUint16ArrayCid:
+        type = Dart_TypedData_kUint16;
+        break;
+      case kTypedDataInt32ArrayCid:
+        type = Dart_TypedData_kInt32;
+        break;
+      case kTypedDataUint32ArrayCid:
+        type = Dart_TypedData_kUint32;
+        break;
+      case kTypedDataInt64ArrayCid:
+        type = Dart_TypedData_kInt64;
+        break;
+      case kTypedDataUint64ArrayCid:
+        type = Dart_TypedData_kUint64;
+        break;
+      case kTypedDataFloat32ArrayCid:
+        type = Dart_TypedData_kFloat32;
+        break;
+      case kTypedDataFloat64ArrayCid:
+        type = Dart_TypedData_kFloat64;
+        break;
+      case kTypedDataInt32x4ArrayCid:
+        type = Dart_TypedData_kInt32x4;
+        break;
+      case kTypedDataFloat32x4ArrayCid:
+        type = Dart_TypedData_kFloat32x4;
+        break;
+      case kTypedDataFloat64x2ArrayCid:
+        type = Dart_TypedData_kFloat64x2;
+        break;
+      default:
+        UNREACHABLE();
+    }
+
+    intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* data = d->Allocate(Dart_CObject_kTypedData);
+      intptr_t length = d->ReadUnsigned();
+      data->value.as_typed_data.type = type;
+      data->value.as_typed_data.length = length * element_size;
+      if (length == 0) {
+        data->value.as_typed_data.values = NULL;
+      } else {
+        const intptr_t length_in_bytes = length * element_size;
+        uint8_t* cdata = d->zone()->Alloc<uint8_t>(length_in_bytes);
+        data->value.as_typed_data.values = cdata;
+        d->ReadBytes(cdata, length_in_bytes);
+      }
+      d->AssignRef(data);
+    }
+  }
+
+ private:
+  const intptr_t cid_;
+};
+
+// This function's name can appear in Observatory.
+static void IsolateMessageTypedDataFinalizer(void* isolate_callback_data,
+                                             void* buffer) {
+  free(buffer);
+}
+
+class ExternalTypedDataMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit ExternalTypedDataMessageSerializationCluster(Zone* zone,
+                                                        intptr_t cid)
+      : MessageSerializationCluster("ExternalTypedData",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    cid),
+        objects_(zone, 0) {}
+  ~ExternalTypedDataMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    ExternalTypedData* data = static_cast<ExternalTypedData*>(object);
+    objects_.Add(data);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      ExternalTypedData* data = objects_[i];
+      s->AssignRef(data);
+      intptr_t length = Smi::Value(data->untag()->length_);
+      s->WriteUnsigned(length);
+
+      intptr_t length_in_bytes = length * element_size;
+      void* passed_data = malloc(length_in_bytes);
+      memmove(passed_data, data->untag()->data_, length_in_bytes);
+      s->finalizable_data()->Put(length_in_bytes,
+                                 passed_data,  // data
+                                 passed_data,  // peer,
+                                 IsolateMessageTypedDataFinalizer);
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<ExternalTypedData*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* data = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(data);
+
+      intptr_t length = data->value.as_external_typed_data.length;
+      s->WriteUnsigned(length);
+
+      s->finalizable_data()->Put(length * element_size,
+                                 data->value.as_external_typed_data.data,
+                                 data->value.as_external_typed_data.peer,
+                                 data->value.as_external_typed_data.callback);
+    }
+  }
+
+ private:
+  GrowableArray<ExternalTypedData*> objects_;
+};
+
+class ExternalTypedDataMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit ExternalTypedDataMessageDeserializationCluster(intptr_t cid)
+      : MessageDeserializationCluster("ExternalTypedData"), cid_(cid) {}
+  ~ExternalTypedDataMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+    intptr_t count = d->ReadUnsigned();
+    ExternalTypedData& data = ExternalTypedData::Handle(d->zone());
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      FinalizableData finalizable_data = d->finalizable_data()->Take();
+      data = ExternalTypedData::New(
+          cid_, reinterpret_cast<uint8_t*>(finalizable_data.data), length);
+      intptr_t external_size = length * element_size;
+      data.AddFinalizer(finalizable_data.peer, finalizable_data.callback,
+                        external_size);
+      d->AssignRef(data.ptr());
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+    Dart_TypedData_Type type;
+    switch (cid_) {
+      case kExternalTypedDataInt8ArrayCid:
+        type = Dart_TypedData_kInt8;
+        break;
+      case kExternalTypedDataUint8ArrayCid:
+        type = Dart_TypedData_kUint8;
+        break;
+      case kExternalTypedDataUint8ClampedArrayCid:
+        type = Dart_TypedData_kUint8Clamped;
+        break;
+      case kExternalTypedDataInt16ArrayCid:
+        type = Dart_TypedData_kInt16;
+        break;
+      case kExternalTypedDataUint16ArrayCid:
+        type = Dart_TypedData_kUint16;
+        break;
+      case kExternalTypedDataInt32ArrayCid:
+        type = Dart_TypedData_kInt32;
+        break;
+      case kExternalTypedDataUint32ArrayCid:
+        type = Dart_TypedData_kUint32;
+        break;
+      case kExternalTypedDataInt64ArrayCid:
+        type = Dart_TypedData_kInt64;
+        break;
+      case kExternalTypedDataUint64ArrayCid:
+        type = Dart_TypedData_kUint64;
+        break;
+      case kExternalTypedDataFloat32ArrayCid:
+        type = Dart_TypedData_kFloat32;
+        break;
+      case kExternalTypedDataFloat64ArrayCid:
+        type = Dart_TypedData_kFloat64;
+        break;
+      case kExternalTypedDataInt32x4ArrayCid:
+        type = Dart_TypedData_kInt32x4;
+        break;
+      case kExternalTypedDataFloat32x4ArrayCid:
+        type = Dart_TypedData_kFloat32x4;
+        break;
+      case kExternalTypedDataFloat64x2ArrayCid:
+        type = Dart_TypedData_kFloat64x2;
+        break;
+      default:
+        UNREACHABLE();
+    }
+
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* data = d->Allocate(Dart_CObject_kTypedData);
+      intptr_t length = d->ReadUnsigned();
+      FinalizableData finalizable_data = d->finalizable_data()->Get();
+      data->value.as_typed_data.type = type;
+      data->value.as_typed_data.length = length * element_size;
+      data->value.as_typed_data.values =
+          reinterpret_cast<uint8_t*>(finalizable_data.data);
+      d->AssignRef(data);
+    }
+  }
+
+ private:
+  const intptr_t cid_;
+};
+
+class TypedDataViewMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit TypedDataViewMessageSerializationCluster(Zone* zone, intptr_t cid)
+      : MessageSerializationCluster("TypedDataView",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    cid),
+        objects_(zone, 0) {}
+  ~TypedDataViewMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    TypedDataView* view = static_cast<TypedDataView*>(object);
+    objects_.Add(view);
+
+    s->Push(view->untag()->length());
+    s->Push(view->untag()->typed_data());
+    s->Push(view->untag()->offset_in_bytes());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TypedDataView* view = objects_[i];
+      s->AssignRef(view);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      TypedDataView* view = objects_[i];
+      s->WriteRef(view->untag()->length());
+      s->WriteRef(view->untag()->typed_data());
+      s->WriteRef(view->untag()->offset_in_bytes());
+    }
+  }
+
+ private:
+  GrowableArray<TypedDataView*> objects_;
+};
+
+class TypedDataViewMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit TypedDataViewMessageDeserializationCluster(intptr_t cid)
+      : MessageDeserializationCluster("TypedDataView"), cid_(cid) {}
+  ~TypedDataViewMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(TypedDataView::New(cid_));
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id));
+      view->untag()->set_length(static_cast<SmiPtr>(d->ReadRef()));
+      view->untag()->set_typed_data(
+          static_cast<TypedDataBasePtr>(d->ReadRef()));
+      view->untag()->set_offset_in_bytes(static_cast<SmiPtr>(d->ReadRef()));
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id));
+      view->untag()->RecomputeDataField();
+    }
+    return nullptr;
+  }
+
+  struct Dart_CTypedDataView : public Dart_CObject {
+    Dart_CObject* length;
+    Dart_CObject* typed_data;
+    Dart_CObject* offset_in_bytes;
+  };
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CTypedDataView* view = d->zone()->Alloc<Dart_CTypedDataView>(1);
+      d->AssignRef(view);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      Dart_CTypedDataView* view = static_cast<Dart_CTypedDataView*>(d->Ref(id));
+      view->length = d->ReadRef();
+      view->typed_data = d->ReadRef();
+      view->offset_in_bytes = d->ReadRef();
+    }
+  }
+
+  void PostLoadApi(ApiMessageDeserializer* d) {
+    intptr_t element_size = TypedDataView::ElementSizeInBytes(cid_);
+    Dart_TypedData_Type type;
+    switch (cid_) {
+      case kTypedDataInt8ArrayViewCid:
+        type = Dart_TypedData_kInt8;
+        break;
+      case kTypedDataUint8ArrayViewCid:
+        type = Dart_TypedData_kUint8;
+        break;
+      case kTypedDataUint8ClampedArrayViewCid:
+        type = Dart_TypedData_kUint8Clamped;
+        break;
+      case kTypedDataInt16ArrayViewCid:
+        type = Dart_TypedData_kInt16;
+        break;
+      case kTypedDataUint16ArrayViewCid:
+        type = Dart_TypedData_kUint16;
+        break;
+      case kTypedDataInt32ArrayViewCid:
+        type = Dart_TypedData_kInt32;
+        break;
+      case kTypedDataUint32ArrayViewCid:
+        type = Dart_TypedData_kUint32;
+        break;
+      case kTypedDataInt64ArrayViewCid:
+        type = Dart_TypedData_kInt64;
+        break;
+      case kTypedDataUint64ArrayViewCid:
+        type = Dart_TypedData_kUint64;
+        break;
+      case kTypedDataFloat32ArrayViewCid:
+        type = Dart_TypedData_kFloat32;
+        break;
+      case kTypedDataFloat64ArrayViewCid:
+        type = Dart_TypedData_kFloat64;
+        break;
+      case kTypedDataInt32x4ArrayViewCid:
+        type = Dart_TypedData_kInt32x4;
+        break;
+      case kTypedDataFloat32x4ArrayViewCid:
+        type = Dart_TypedData_kFloat32x4;
+        break;
+      case kTypedDataFloat64x2ArrayViewCid:
+        type = Dart_TypedData_kFloat64x2;
+        break;
+      default:
+        UNREACHABLE();
+    }
+
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      Dart_CTypedDataView* view = static_cast<Dart_CTypedDataView*>(d->Ref(id));
+      if (view->typed_data->type == Dart_CObject_kTypedData) {
+        view->type = Dart_CObject_kTypedData;
+        view->value.as_typed_data.type = type;
+        //            view->typed_data->value.as_typed_data.type;
+        view->value.as_typed_data.length =
+            view->length->value.as_int32 * element_size;
+        view->value.as_typed_data.values =
+            view->typed_data->value.as_typed_data.values +
+            view->offset_in_bytes->value.as_int32;
+      } else if (view->typed_data->type == Dart_CObject_kExternalTypedData) {
+        UNREACHABLE();  ///???
+        view->type = Dart_CObject_kTypedData;
+        view->value.as_typed_data.type = type;
+        //            view->typed_data->value.as_external_typed_data.type;
+        view->value.as_typed_data.length =
+            view->length->value.as_int32 * element_size;
+        view->value.as_typed_data.values =
+            view->typed_data->value.as_external_typed_data.data +
+            view->offset_in_bytes->value.as_int32;
+      } else {
+        UNREACHABLE();
+      }
+    }
+  }
+
+ private:
+  const intptr_t cid_;
+};
+
+class TransferableTypedDataMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  TransferableTypedDataMessageSerializationCluster()
+      : MessageSerializationCluster("TransferableTypedData",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kTransferableTypedDataCid) {}
+  ~TransferableTypedDataMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    TransferableTypedData* transferable =
+        static_cast<TransferableTypedData*>(object);
+    objects_.Add(transferable);
+
+    void* peer = s->thread()->heap()->GetPeer(transferable->ptr());
+    // Assume that object's Peer is only used to track transferrability state.
+    ASSERT(peer != nullptr);
+    TransferableTypedDataPeer* tpeer =
+        reinterpret_cast<TransferableTypedDataPeer*>(peer);
+    if (tpeer->data() == nullptr) {
+      s->IllegalObject(
+          *object,
+          "Illegal argument in isolate message"
+          " : (TransferableTypedData has been transferred already)");
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      TransferableTypedData* transferable = objects_[i];
+      s->AssignRef(transferable);
+
+      void* peer = s->thread()->heap()->GetPeer(transferable->ptr());
+      // Assume that object's Peer is only used to track transferrability state.
+      ASSERT(peer != nullptr);
+      TransferableTypedDataPeer* tpeer =
+          reinterpret_cast<TransferableTypedDataPeer*>(peer);
+      intptr_t length = tpeer->length();  // In bytes.
+      void* data = tpeer->data();
+      ASSERT(data != nullptr);
+      s->WriteUnsigned(length);
+      s->finalizable_data()->Put(
+          length, data, tpeer,
+          // Finalizer does nothing - in case of failure to serialize,
+          // [data] remains wrapped in sender's [TransferableTypedData].
+          [](void* data, void* peer) {},
+          // This is invoked on successful serialization of the message
+          [](void* data, void* peer) {
+            TransferableTypedDataPeer* ttpeer =
+                reinterpret_cast<TransferableTypedDataPeer*>(peer);
+            ttpeer->handle()->EnsureFreedExternal(IsolateGroup::Current());
+            ttpeer->ClearData();
+          });
+    }
+  }
+
+ private:
+  GrowableArray<TransferableTypedData*> objects_;
+};
+
+class TransferableTypedDataMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  TransferableTypedDataMessageDeserializationCluster()
+      : MessageDeserializationCluster("TransferableTypedData") {}
+  ~TransferableTypedDataMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      const FinalizableData finalizable_data = d->finalizable_data()->Take();
+      d->AssignRef(TransferableTypedData::New(
+          reinterpret_cast<uint8_t*>(finalizable_data.data), length));
+    }
+  }
+};
+
+class RegExpMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  RegExpMessageSerializationCluster()
+      : MessageSerializationCluster("RegExp",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kRegExpCid) {}
+  ~RegExpMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    RegExp* regexp = static_cast<RegExp*>(object);
+    objects_.Add(regexp);
+
+    s->Push(regexp->capture_name_map());
+    s->Push(regexp->pattern());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      RegExp* regexp = objects_[i];
+      s->AssignRef(regexp);
+      s->WriteRef(regexp->capture_name_map());
+      s->WriteRef(regexp->pattern());
+      s->Write<int32_t>(regexp->num_bracket_expressions());
+      s->Write<int32_t>(regexp->num_registers(true));
+      s->Write<int32_t>(regexp->num_registers(false));
+      s->Write<int>(regexp->flags().value());
+    }
+  }
+
+ private:
+  GrowableArray<RegExp*> objects_;
+};
+
+class RegExpMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  RegExpMessageDeserializationCluster()
+      : MessageDeserializationCluster("RegExp") {}
+  ~RegExpMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    RegExp& regexp = RegExp::Handle(d->zone());
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      regexp = RegExp::New(d->zone());
+      d->AssignRef(regexp.ptr());
+      regexp.untag()->set_capture_name_map(static_cast<ArrayPtr>(d->ReadRef()));
+      regexp.untag()->set_pattern(static_cast<StringPtr>(d->ReadRef()));
+      regexp.set_num_bracket_expressions(d->Read<int32_t>());
+      regexp.set_num_registers(true, d->Read<int32_t>());
+      regexp.set_num_registers(false, d->Read<int32_t>());
+      regexp.set_flags(RegExpFlags(d->Read<int>()));
+    }
+  }
+};
+
+class SendPortMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  explicit SendPortMessageSerializationCluster(Zone* zone)
+      : MessageSerializationCluster("SendPort",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kSendPortCid),
+        objects_(zone, 0) {}
+  ~SendPortMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    SendPort* port = static_cast<SendPort*>(object);
+    objects_.Add(port);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      SendPort* port = objects_[i];
+      s->AssignRef(port);
+      s->Write<Dart_Port>(port->untag()->id_);
+      s->Write<Dart_Port>(port->untag()->origin_id_);
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<SendPort*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* port = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(port);
+      s->Write<Dart_Port>(port->value.as_send_port.id);
+      s->Write<Dart_Port>(port->value.as_send_port.origin_id);
+    }
+  }
+
+ private:
+  GrowableArray<SendPort*> objects_;
+};
+
+class SendPortMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  SendPortMessageDeserializationCluster()
+      : MessageDeserializationCluster("SendPort") {}
+  ~SendPortMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_Port id = d->Read<Dart_Port>();
+      Dart_Port origin_id = d->Read<Dart_Port>();
+      d->AssignRef(SendPort::New(id, origin_id));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* port = d->Allocate(Dart_CObject_kSendPort);
+      port->value.as_send_port.id = d->Read<Dart_Port>();
+      port->value.as_send_port.origin_id = d->Read<Dart_Port>();
+      d->AssignRef(port);
+    }
+  }
+};
+
+class CapabilityMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit CapabilityMessageSerializationCluster(Zone* zone)
+      : MessageSerializationCluster("Capability",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kCapabilityCid),
+        objects_(zone, 0) {}
+  ~CapabilityMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Capability* cap = static_cast<Capability*>(object);
+    objects_.Add(cap);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Capability* cap = objects_[i];
+      s->AssignRef(cap);
+      s->Write<uint64_t>(cap->untag()->id_);
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<Capability*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* cap = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(cap);
+      s->Write<Dart_Port>(cap->value.as_capability.id);
+    }
+  }
+
+ private:
+  GrowableArray<Capability*> objects_;
+};
+
+class CapabilityMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  CapabilityMessageDeserializationCluster()
+      : MessageDeserializationCluster("Capability") {}
+  ~CapabilityMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      uint64_t id = d->Read<uint64_t>();
+      d->AssignRef(Capability::New(id));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* cap = d->Allocate(Dart_CObject_kCapability);
+      cap->value.as_capability.id = d->Read<uint64_t>();
+      d->AssignRef(cap);
+    }
+  }
+};
+
+class WeakPropertyMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  WeakPropertyMessageSerializationCluster()
+      : MessageSerializationCluster("WeakProperty",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kWeakPropertyCid) {}
+  ~WeakPropertyMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    WeakProperty* property = static_cast<WeakProperty*>(object);
+    objects_.Add(property);
+  }
+
+  void RetraceEphemerons(MessageSerializer* s) {
+    for (intptr_t i = 0; i < objects_.length(); i++) {
+      WeakProperty* property = objects_[i];
+      if (s->HasRef(property->untag()->key())) {
+        s->Push(property->untag()->value());
+      }
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      WeakProperty* property = objects_[i];
+      s->AssignRef(property);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      WeakProperty* property = objects_[i];
+      if (s->HasRef(property->untag()->key())) {
+        s->WriteRef(property->untag()->key());
+        s->WriteRef(property->untag()->value());
+      } else {
+        s->WriteRef(Object::null());
+        s->WriteRef(Object::null());
+      }
+    }
+  }
+
+ private:
+  GrowableArray<WeakProperty*> objects_;
+};
+
+class WeakPropertyMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  WeakPropertyMessageDeserializationCluster()
+      : MessageDeserializationCluster("WeakProperty") {}
+  ~WeakPropertyMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(WeakProperty::New());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    ASSERT(!is_canonical());  // Never canonical.
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      WeakPropertyPtr property = static_cast<WeakPropertyPtr>(d->Ref(id));
+      property->untag()->set_key(d->ReadRef());
+      property->untag()->set_value(d->ReadRef());
+    }
+  }
+};
+
+class LinkedHashMapMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  LinkedHashMapMessageSerializationCluster()
+      : MessageSerializationCluster("LinkedHashMap",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kLinkedHashMapCid) {}
+  ~LinkedHashMapMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    LinkedHashMap* map = static_cast<LinkedHashMap*>(object);
+    objects_.Add(map);
+
+    s->Push(map->untag()->type_arguments());
+    s->Push(map->untag()->data());
+    s->Push(map->untag()->used_data());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      LinkedHashMap* map = objects_[i];
+      s->AssignRef(map);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      LinkedHashMap* map = objects_[i];
+      s->WriteRef(map->untag()->type_arguments());
+      s->WriteRef(map->untag()->data());
+      s->WriteRef(map->untag()->used_data());
+    }
+  }
+
+ private:
+  GrowableArray<LinkedHashMap*> objects_;
+};
+
+class LinkedHashMapMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit LinkedHashMapMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("LinkedHashMap", is_canonical) {}
+  ~LinkedHashMapMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(LinkedHashMap::NewUninitialized());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      LinkedHashMapPtr map = static_cast<LinkedHashMapPtr>(d->Ref(id));
+      map->untag()->set_hash_mask(Smi::New(0));
+      map->untag()->set_type_arguments(
+          static_cast<TypeArgumentsPtr>(d->ReadRef()));
+      map->untag()->set_data(static_cast<ArrayPtr>(d->ReadRef()));
+      map->untag()->set_used_data(static_cast<SmiPtr>(d->ReadRef()));
+      map->untag()->set_deleted_keys(Smi::New(0));
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) { return PostLoadLinkedHash(d); }
+};
+
+class LinkedHashSetMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  LinkedHashSetMessageSerializationCluster()
+      : MessageSerializationCluster("LinkedHashSet",
+                                    MessagePhase::kNonCanonicalInstances,
+                                    kLinkedHashSetCid) {}
+  ~LinkedHashSetMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    LinkedHashSet* map = static_cast<LinkedHashSet*>(object);
+    objects_.Add(map);
+
+    s->Push(map->untag()->type_arguments());
+    s->Push(map->untag()->data());
+    s->Push(map->untag()->used_data());
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      LinkedHashSet* map = objects_[i];
+      s->AssignRef(map);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      LinkedHashSet* map = objects_[i];
+      s->WriteRef(map->untag()->type_arguments());
+      s->WriteRef(map->untag()->data());
+      s->WriteRef(map->untag()->used_data());
+    }
+  }
+
+ private:
+  GrowableArray<LinkedHashSet*> objects_;
+};
+
+class LinkedHashSetMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit LinkedHashSetMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("LinkedHashSet", is_canonical) {}
+  ~LinkedHashSetMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(LinkedHashSet::NewUninitialized());
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      LinkedHashSetPtr map = static_cast<LinkedHashSetPtr>(d->Ref(id));
+      map->untag()->set_hash_mask(Smi::New(0));
+      map->untag()->set_type_arguments(
+          static_cast<TypeArgumentsPtr>(d->ReadRef()));
+      map->untag()->set_data(static_cast<ArrayPtr>(d->ReadRef()));
+      map->untag()->set_used_data(static_cast<SmiPtr>(d->ReadRef()));
+      map->untag()->set_deleted_keys(Smi::New(0));
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) { return PostLoadLinkedHash(d); }
+};
+
+class ArrayMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+  ArrayMessageSerializationCluster(Zone* zone, bool is_canonical, intptr_t cid)
+      : MessageSerializationCluster("Array",
+                                    is_canonical
+                                        ? MessagePhase::kCanonicalInstances
+                                        : MessagePhase::kNonCanonicalInstances,
+                                    cid,
+                                    is_canonical),
+        objects_(zone, 0) {}
+  ~ArrayMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    Array* array = static_cast<Array*>(object);
+    objects_.Add(array);
+
+    s->Push(array->untag()->type_arguments());
+    intptr_t length = Smi::Value(array->untag()->length());
+    for (intptr_t i = 0; i < length; i++) {
+      s->Push(array->untag()->element(i));
+    }
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Array* array = objects_[i];
+      s->AssignRef(array);
+      intptr_t length = Smi::Value(array->untag()->length());
+      s->WriteUnsigned(length);
+    }
+  }
+
+  void WriteEdges(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      Array* array = objects_[i];
+      intptr_t length = array->Length();
+      s->WriteRef(array->untag()->type_arguments());
+      for (intptr_t j = 0; j < length; j++) {
+        s->WriteRef(array->untag()->element(j));
+      }
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<Array*>(object));
+
+    for (intptr_t i = 0, n = object->value.as_array.length; i < n; i++) {
+      s->Push(object->value.as_array.values[i]);
+    }
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* array = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(array);
+      s->WriteUnsigned(array->value.as_array.length);
+    }
+  }
+
+  void WriteEdgesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* array = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      intptr_t length = array->value.as_array.length;
+      s->WriteRef(&cobj_null);  // TypeArguments
+      for (intptr_t j = 0; j < length; j++) {
+        s->WriteRef(array->value.as_array.values[j]);
+      }
+    }
+  }
+
+ private:
+  GrowableArray<Array*> objects_;
+};
+
+class ArrayMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit ArrayMessageDeserializationCluster(bool is_canonical, intptr_t cid)
+      : MessageDeserializationCluster("Array", is_canonical), cid_(cid) {}
+  ~ArrayMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      d->AssignRef(Array::New(cid_, length));
+    }
+  }
+
+  void ReadEdges(MessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      ArrayPtr array = static_cast<ArrayPtr>(d->Ref(id));
+      intptr_t length = Smi::Value(array->untag()->length());
+      array->untag()->set_type_arguments(
+          static_cast<TypeArgumentsPtr>(d->ReadRef()));
+      for (intptr_t j = 0; j < length; j++) {
+        array->untag()->set_element(j, d->ReadRef());
+      }
+    }
+  }
+
+  ObjectPtr PostLoad(MessageDeserializer* d) {
+    if (is_canonical()) {
+      SafepointMutexLocker ml(
+          d->isolate_group()->constant_canonicalization_mutex());
+      Instance& instance = Instance::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        instance ^= d->Ref(i);
+        instance = instance.CanonicalizeLocked(d->thread());
+        d->UpdateRef(i, instance);
+      }
+    }
+    return nullptr;
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* array = d->Allocate(Dart_CObject_kArray);
+      intptr_t length = d->ReadUnsigned();
+      array->value.as_array.length = length;
+      if (length == 0) {
+        array->value.as_array.values = NULL;
+      } else {
+        array->value.as_array.values = d->zone()->Alloc<Dart_CObject*>(length);
+      }
+      d->AssignRef(array);
+    }
+  }
+
+  void ReadEdgesApi(ApiMessageDeserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      Dart_CObject* array = d->Ref(id);
+      intptr_t length = array->value.as_array.length;
+      d->ReadRef();  // type_arguments
+      for (intptr_t i = 0; i < length; i++) {
+        array->value.as_array.values[i] = d->ReadRef();
+      }
+    }
+  }
+
+ private:
+  const intptr_t cid_;
+};
+
+class OneByteStringMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit OneByteStringMessageSerializationCluster(Zone* zone,
+                                                    bool is_canonical)
+      : MessageSerializationCluster("OneByteString",
+                                    MessagePhase::kBeforeTypes,
+                                    kOneByteStringCid,
+                                    is_canonical),
+        objects_(zone, 0) {}
+  ~OneByteStringMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    String* str = static_cast<String*>(object);
+    objects_.Add(str);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      String* str = objects_[i];
+      s->AssignRef(str);
+      intptr_t length = str->Length();
+      s->WriteUnsigned(length);
+      NoSafepointScope no_safepoint;
+      s->WriteBytes(OneByteString::DataStart(*str), length * sizeof(uint8_t));
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<String*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* str = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(str);
+
+      const uint8_t* utf8_str =
+          reinterpret_cast<const uint8_t*>(str->value.as_string);
+      intptr_t utf8_len = strlen(str->value.as_string);
+      Utf8::Type type = Utf8::kLatin1;
+      intptr_t latin1_len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
+
+      uint8_t* latin1_str = reinterpret_cast<uint8_t*>(
+          dart::malloc(latin1_len * sizeof(uint8_t)));
+      bool success =
+          Utf8::DecodeToLatin1(utf8_str, utf8_len, latin1_str, latin1_len);
+      ASSERT(success);
+      s->WriteUnsigned(latin1_len);
+      s->WriteBytes(latin1_str, latin1_len);
+      ::free(latin1_str);
+    }
+  }
+
+ private:
+  GrowableArray<String*> objects_;
+};
+
+class OneByteStringMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit OneByteStringMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("OneByteString", is_canonical) {}
+  ~OneByteStringMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      const uint8_t* data = d->CurrentBufferAddress();
+      d->Advance(length * sizeof(uint8_t));
+      d->AssignRef(is_canonical()
+                       ? Symbols::FromLatin1(d->thread(), data, length)
+                       : String::FromLatin1(data, length));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* str = d->Allocate(Dart_CObject_kString);
+      intptr_t latin1_length = d->ReadUnsigned();
+      const uint8_t* data = d->CurrentBufferAddress();
+
+      d->Advance(latin1_length * sizeof(uint8_t));
+
+      intptr_t utf8_len = 0;
+      for (intptr_t i = 0; i < latin1_length; i++) {
+        utf8_len += Utf8::Length(data[i]);
+      }
+      char* utf8_data = d->zone()->Alloc<char>(utf8_len + 1);
+      str->value.as_string = utf8_data;
+      for (intptr_t i = 0; i < latin1_length; i++) {
+        utf8_data += Utf8::Encode(data[i], utf8_data);
+      }
+      *utf8_data = '\0';
+
+      d->AssignRef(str);
+    }
+  }
+};
+
+class TwoByteStringMessageSerializationCluster
+    : public MessageSerializationCluster {
+ public:
+  explicit TwoByteStringMessageSerializationCluster(Zone* zone,
+                                                    bool is_canonical)
+      : MessageSerializationCluster("TwoByteString",
+                                    MessagePhase::kBeforeTypes,
+                                    kTwoByteStringCid,
+                                    is_canonical),
+        objects_(zone, 0) {}
+  ~TwoByteStringMessageSerializationCluster() {}
+
+  void Trace(MessageSerializer* s, Object* object) {
+    String* str = static_cast<String*>(object);
+    objects_.Add(str);
+  }
+
+  void WriteNodes(MessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      String* str = objects_[i];
+      s->AssignRef(str);
+      intptr_t length = str->Length();
+      s->WriteUnsigned(length);
+      NoSafepointScope no_safepoint;
+      uint16_t* utf16 = TwoByteString::DataStart(*str);
+      s->WriteBytes(reinterpret_cast<const uint8_t*>(utf16),
+                    length * sizeof(uint16_t));
+    }
+  }
+
+  void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+    objects_.Add(reinterpret_cast<String*>(object));
+  }
+
+  void WriteNodesApi(ApiMessageSerializer* s) {
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      Dart_CObject* str = reinterpret_cast<Dart_CObject*>(objects_[i]);
+      s->AssignRef(str);
+
+      const uint8_t* utf8_str =
+          reinterpret_cast<const uint8_t*>(str->value.as_string);
+      intptr_t utf8_len = strlen(str->value.as_string);
+      Utf8::Type type = Utf8::kLatin1;
+      intptr_t utf16_len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
+
+      uint16_t* utf16_str = reinterpret_cast<uint16_t*>(
+          dart::malloc(utf16_len * sizeof(uint16_t)));
+      bool success =
+          Utf8::DecodeToUTF16(utf8_str, utf8_len, utf16_str, utf16_len);
+      ASSERT(success);
+      s->WriteUnsigned(utf16_len);
+      s->WriteBytes(reinterpret_cast<const uint8_t*>(utf16_str),
+                    utf16_len * sizeof(uint16_t));
+      ::free(utf16_str);
+    }
+  }
+
+ private:
+  GrowableArray<String*> objects_;
+};
+
+class TwoByteStringMessageDeserializationCluster
+    : public MessageDeserializationCluster {
+ public:
+  explicit TwoByteStringMessageDeserializationCluster(bool is_canonical)
+      : MessageDeserializationCluster("TwoByteString", is_canonical) {}
+  ~TwoByteStringMessageDeserializationCluster() {}
+
+  void ReadNodes(MessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      intptr_t length = d->ReadUnsigned();
+      const uint16_t* data =
+          reinterpret_cast<const uint16_t*>(d->CurrentBufferAddress());
+      d->Advance(length * sizeof(uint16_t));
+      d->AssignRef(is_canonical()
+                       ? Symbols::FromUTF16(d->thread(), data, length)
+                       : String::FromUTF16(data, length));
+    }
+  }
+
+  void ReadNodesApi(ApiMessageDeserializer* d) {
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t j = 0; j < count; j++) {
+      // Read all the UTF-16 code units.
+      intptr_t utf16_length = d->ReadUnsigned();
+      const uint16_t* utf16 =
+          reinterpret_cast<const uint16_t*>(d->CurrentBufferAddress());
+      d->Advance(utf16_length * sizeof(uint16_t));
+
+      // Calculate the UTF-8 length and check if the string can be
+      // UTF-8 encoded.
+      intptr_t utf8_len = 0;
+      bool valid = true;
+      intptr_t i = 0;
+      while (i < utf16_length && valid) {
+        int32_t ch = Utf16::Next(utf16, &i, utf16_length);
+        utf8_len += Utf8::Length(ch);
+        valid = !Utf16::IsSurrogate(ch);
+      }
+      if (!valid) {
+        d->AssignRef(d->Allocate(Dart_CObject_kUnsupported));
+      } else {
+        Dart_CObject* str = d->Allocate(Dart_CObject_kString);
+        char* utf8 = d->zone()->Alloc<char>(utf8_len + 1);
+        str->value.as_string = utf8;
+        i = 0;
+        while (i < utf16_length) {
+          utf8 += Utf8::Encode(Utf16::Next(utf16, &i, utf16_length), utf8);
+        }
+        *utf8 = '\0';
+        d->AssignRef(str);
+      }
+    }
+  }
+};
+
+static const intptr_t kFirstReference = 1;
+static const intptr_t kUnallocatedReference = -1;
+
+BaseSerializer::BaseSerializer(Thread* thread, Zone* zone)
+    : StackResource(thread),
+      zone_(zone),
+      stream_(100),
+      finalizable_data_(new MessageFinalizableData()),
+      clusters_(zone, 0),
+      ephemeron_cluster_(nullptr),
+      num_base_objects_(0),
+      num_written_objects_(0),
+      next_ref_index_(kFirstReference) {}
+
+BaseSerializer::~BaseSerializer() {
+  delete finalizable_data_;
+}
+
+MessageSerializer::MessageSerializer(Thread* thread, bool can_send_any_object)
+    : BaseSerializer(thread, thread->zone()),
+      forward_table_new_(),
+      forward_table_old_(),
+      stack_(thread->zone(), 0),
+      can_send_any_object_(can_send_any_object),
+      exception_message_(nullptr) {
+  isolate()->set_forward_table_new(new WeakTable());
+  isolate()->set_forward_table_old(new WeakTable());
+}
+
+MessageSerializer::~MessageSerializer() {
+  isolate()->set_forward_table_new(nullptr);
+  isolate()->set_forward_table_old(nullptr);
+}
+
+ApiMessageSerializer::ApiMessageSerializer(Zone* zone)
+    : BaseSerializer(nullptr, zone), forward_table_(), stack_(zone, 0) {}
+
+ApiMessageSerializer::~ApiMessageSerializer() {}
+
+void MessageSerializer::Push(ObjectPtr object) {
+  if (MarkObjectId(object, kUnallocatedReference)) {
+    stack_.Add(&Object::ZoneHandle(zone_, object));
+    num_written_objects_++;
+  }
+}
+
+void ApiMessageSerializer::Push(Dart_CObject* object) {
+  if (MarkObjectId(object, kUnallocatedReference)) {
+    stack_.Add(object);
+    num_written_objects_++;
+  }
+}
+
+void MessageSerializer::Trace(Object* object) {
+  intptr_t cid;
+  bool is_canonical;
+  if (!object->ptr()->IsHeapObject()) {
+    cid = kSmiCid;
+    is_canonical = true;
+  } else {
+    cid = object->GetClassId();
+    is_canonical = object->ptr()->untag()->IsCanonical();
+  }
+
+  MessageSerializationCluster* cluster = nullptr;
+  for (MessageSerializationCluster* c : clusters_) {
+    if ((c->cid() == cid) && (c->is_canonical() == is_canonical)) {
+      cluster = c;
+      break;
+    }
+  }
+  if (cluster == nullptr) {
+    if (cid >= kNumPredefinedCids || cid == kInstanceCid) {
+      const Class& clazz =
+          Class::Handle(zone(), isolate_group()->class_table()->At(cid));
+      if (!can_send_any_object()) {
+        ObjectStore* object_store = isolate_group()->object_store();
+        if ((clazz.library() != object_store->core_library()) &&
+            (clazz.library() != object_store->collection_library()) &&
+            (clazz.library() != object_store->typed_data_library())) {
+          IllegalObject(*object,
+                        "Illegal argument in isolate message"
+                        " : (object is a regular Dart Instance)");
+        }
+      }
+      if (clazz.num_native_fields() != 0) {
+        char* chars = OS::SCreate(thread()->zone(),
+                                  "Illegal argument in isolate message"
+                                  " : (object extends NativeWrapper - %s)",
+                                  clazz.ToCString());
+        IllegalObject(*object, chars);
+      }
+    }
+#define ILLEGAL(type)                                                          \
+  if (cid == k##type##Cid) {                                                   \
+    IllegalObject(*object,                                                     \
+                  "Illegal argument in isolate message"                        \
+                  " : (object is a " #type ")");                               \
+  }
+
+    ILLEGAL(FunctionType)
+    ILLEGAL(DynamicLibrary)
+    ILLEGAL(MirrorReference)
+    ILLEGAL(Pointer)
+    ILLEGAL(ReceivePort)
+    ILLEGAL(StackTrace)
+    ILLEGAL(UserTag)
+#undef ILLEGAL
+
+    switch (cid) {
+#define ILLEGAL(type) case kFfi##type##Cid:
+      CLASS_LIST_FFI(ILLEGAL)
+#undef ILLEGAL
+      IllegalObject(*object,
+                    "Native objects (from dart:ffi) such as Pointers and "
+                    "Structs cannot be passed between isolates.");
+    }
+
+    if (cid >= kNumPredefinedCids || cid == kInstanceCid ||
+        cid == kByteBufferCid) {
+      Push(isolate_group()->class_table()->At(cid));
+    }
+    cluster = NewClusterForClass(cid, is_canonical);
+    clusters_.Add(cluster);
+  }
+
+  cluster->Trace(this, object);
+}
+
+bool ApiMessageSerializer::Trace(Dart_CObject* object) {
+  const bool is_canonical = false;
+  intptr_t cid;
+  switch (object->type) {
+    case Dart_CObject_kNull:
+      ForwardRef(object, &cobj_null);
+      return true;
+    case Dart_CObject_kBool:
+      ForwardRef(object, object->value.as_bool ? &cobj_true : &cobj_false);
+      return true;
+    case Dart_CObject_kInt32:
+      cid = Smi::IsValid(object->value.as_int32) ? kSmiCid : kMintCid;
+      break;
+    case Dart_CObject_kInt64:
+      cid = Smi::IsValid(object->value.as_int64) ? kSmiCid : kMintCid;
+      break;
+    case Dart_CObject_kDouble:
+      cid = kDoubleCid;
+      break;
+    case Dart_CObject_kString: {
+      const uint8_t* utf8_str =
+          reinterpret_cast<const uint8_t*>(object->value.as_string);
+      intptr_t utf8_len = strlen(object->value.as_string);
+      if (!Utf8::IsValid(utf8_str, utf8_len)) {
+        return Fail("invalid utf8");
+      }
+      Utf8::Type type = Utf8::kLatin1;
+      intptr_t len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
+      if (len > String::kMaxElements) {
+        return Fail("invalid string length");
+      }
+      cid = type == Utf8::kLatin1 ? kOneByteStringCid : kTwoByteStringCid;
+      break;
+    }
+    case Dart_CObject_kArray:
+      cid = kArrayCid;
+      if (!Array::IsValidLength(object->value.as_array.length)) {
+        return Fail("invalid array length");
+      }
+      break;
+    case Dart_CObject_kTypedData:
+      switch (object->value.as_typed_data.type) {
+        case Dart_TypedData_kInt8:
+          cid = kTypedDataInt8ArrayCid;
+          break;
+        case Dart_TypedData_kUint8:
+          cid = kTypedDataUint8ArrayCid;
+          break;
+        case Dart_TypedData_kUint8Clamped:
+          cid = kTypedDataUint8ClampedArrayCid;
+          break;
+        case Dart_TypedData_kInt16:
+          cid = kTypedDataInt16ArrayCid;
+          break;
+        case Dart_TypedData_kUint16:
+          cid = kTypedDataUint16ArrayCid;
+          break;
+        case Dart_TypedData_kInt32:
+          cid = kTypedDataInt32ArrayCid;
+          break;
+        case Dart_TypedData_kUint32:
+          cid = kTypedDataUint32ArrayCid;
+          break;
+        case Dart_TypedData_kInt64:
+          cid = kTypedDataInt64ArrayCid;
+          break;
+        case Dart_TypedData_kUint64:
+          cid = kTypedDataUint64ArrayCid;
+          break;
+        case Dart_TypedData_kFloat32:
+          cid = kTypedDataFloat32ArrayCid;
+          break;
+        case Dart_TypedData_kFloat64:
+          cid = kTypedDataFloat64ArrayCid;
+          break;
+        case Dart_TypedData_kInt32x4:
+          cid = kTypedDataInt32x4ArrayCid;
+          break;
+        case Dart_TypedData_kFloat32x4:
+          cid = kTypedDataFloat32x4ArrayCid;
+          break;
+        case Dart_TypedData_kFloat64x2:
+          cid = kTypedDataFloat64x2ArrayCid;
+          break;
+        default:
+          return Fail("invalid TypedData type");
+      }
+      {
+        intptr_t len = object->value.as_typed_data.length;
+        if (len < 0 || len > TypedData::MaxElements(cid)) {
+          return Fail("invalid typeddata length");
+        }
+      }
+      break;
+    case Dart_CObject_kExternalTypedData:
+      switch (object->value.as_external_typed_data.type) {
+        case Dart_TypedData_kInt8:
+          cid = kExternalTypedDataInt8ArrayCid;
+          break;
+        case Dart_TypedData_kUint8:
+          cid = kExternalTypedDataUint8ArrayCid;
+          break;
+        case Dart_TypedData_kUint8Clamped:
+          cid = kExternalTypedDataUint8ClampedArrayCid;
+          break;
+        case Dart_TypedData_kInt16:
+          cid = kExternalTypedDataInt16ArrayCid;
+          break;
+        case Dart_TypedData_kUint16:
+          cid = kExternalTypedDataUint16ArrayCid;
+          break;
+        case Dart_TypedData_kInt32:
+          cid = kExternalTypedDataInt32ArrayCid;
+          break;
+        case Dart_TypedData_kUint32:
+          cid = kExternalTypedDataUint32ArrayCid;
+          break;
+        case Dart_TypedData_kInt64:
+          cid = kExternalTypedDataInt64ArrayCid;
+          break;
+        case Dart_TypedData_kUint64:
+          cid = kExternalTypedDataUint64ArrayCid;
+          break;
+        case Dart_TypedData_kFloat32:
+          cid = kExternalTypedDataFloat32ArrayCid;
+          break;
+        case Dart_TypedData_kFloat64:
+          cid = kExternalTypedDataFloat64ArrayCid;
+          break;
+        case Dart_TypedData_kInt32x4:
+          cid = kExternalTypedDataInt32x4ArrayCid;
+          break;
+        case Dart_TypedData_kFloat32x4:
+          cid = kExternalTypedDataFloat32x4ArrayCid;
+          break;
+        case Dart_TypedData_kFloat64x2:
+          cid = kExternalTypedDataFloat64x2ArrayCid;
+          break;
+        default:
+          return Fail("invalid TypedData type");
+      }
+      {
+        intptr_t len = object->value.as_typed_data.length;
+        if (len < 0 || len > ExternalTypedData::MaxElements(cid)) {
+          return Fail("invalid typeddata length");
+        }
+      }
+      break;
+    case Dart_CObject_kSendPort:
+      cid = kSendPortCid;
+      break;
+    case Dart_CObject_kCapability:
+      cid = kCapabilityCid;
+      break;
+    default:
+      return Fail("invalid Dart_CObject type");
+  }
+
+  MessageSerializationCluster* cluster = nullptr;
+  for (MessageSerializationCluster* c : clusters_) {
+    if (c->cid() == cid) {
+      cluster = c;
+      break;
+    }
+  }
+  if (cluster == nullptr) {
+    cluster = NewClusterForClass(cid, is_canonical);
+    clusters_.Add(cluster);
+  }
+
+  cluster->TraceApi(this, object);
+  return true;
+}
+
+void MessageSerializer::IllegalObject(const Object& object,
+                                      const char* message) {
+  exception_message_ = message;
+  thread()->long_jump_base()->Jump(1, Object::snapshot_writer_error());
+}
+
+BaseDeserializer::BaseDeserializer(Zone* zone, Message* message)
+    : zone_(zone),
+      stream_(message->snapshot(), message->snapshot_length()),
+      finalizable_data_(message->finalizable_data()),
+      next_ref_index_(kFirstReference) {}
+
+BaseDeserializer::~BaseDeserializer() {}
+
+MessageSerializationCluster* BaseSerializer::NewClusterForClass(
+    intptr_t cid,
+    bool is_canonical) {
+  Zone* Z = zone_;
+  if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid) ||
+      (cid == kByteBufferCid)) {
+    return new (Z) InstanceMessageSerializationCluster(is_canonical, cid);
+  }
+  if (IsTypedDataViewClassId(cid) || cid == kByteDataViewCid) {
+    return new (Z) TypedDataViewMessageSerializationCluster(Z, cid);
+  }
+  if (IsExternalTypedDataClassId(cid)) {
+    return new (Z) ExternalTypedDataMessageSerializationCluster(Z, cid);
+  }
+  if (IsTypedDataClassId(cid)) {
+    return new (Z) TypedDataMessageSerializationCluster(Z, cid);
+  }
+
+  switch (cid) {
+    case kClassCid:
+      return new (Z) ClassMessageSerializationCluster();
+    case kTypeArgumentsCid:
+      return new (Z) TypeArgumentsMessageSerializationCluster(is_canonical);
+    case kFunctionCid:
+      return new (Z) FunctionMessageSerializationCluster();
+    case kTypeCid:
+      return new (Z) TypeMessageSerializationCluster(is_canonical);
+    case kTypeRefCid:
+      return new (Z) TypeRefMessageSerializationCluster(is_canonical);
+    case kClosureCid:
+      return new (Z) ClosureMessageSerializationCluster(is_canonical);
+    case kSmiCid:
+      return new (Z) SmiMessageSerializationCluster(Z);
+    case kMintCid:
+      return new (Z) MintMessageSerializationCluster(Z, is_canonical);
+    case kDoubleCid:
+      return new (Z) DoubleMessageSerializationCluster(Z, is_canonical);
+    case kGrowableObjectArrayCid:
+      return new (Z) GrowableObjectArrayMessageSerializationCluster();
+    case kRegExpCid:
+      return new (Z) RegExpMessageSerializationCluster();
+    case kSendPortCid:
+      return new (Z) SendPortMessageSerializationCluster(Z);
+    case kCapabilityCid:
+      return new (Z) CapabilityMessageSerializationCluster(Z);
+    case kTransferableTypedDataCid:
+      return new (Z) TransferableTypedDataMessageSerializationCluster();
+    case kWeakPropertyCid:
+      ephemeron_cluster_ = new (Z) WeakPropertyMessageSerializationCluster();
+      return ephemeron_cluster_;
+    case kLinkedHashMapCid:
+      return new (Z) LinkedHashMapMessageSerializationCluster();
+    case kLinkedHashSetCid:
+      return new (Z) LinkedHashSetMessageSerializationCluster();
+    case kArrayCid:
+    case kImmutableArrayCid:
+      return new (Z) ArrayMessageSerializationCluster(Z, is_canonical, cid);
+    case kOneByteStringCid:
+      return new (Z) OneByteStringMessageSerializationCluster(Z, is_canonical);
+    case kTwoByteStringCid:
+      return new (Z) TwoByteStringMessageSerializationCluster(Z, is_canonical);
+    default:
+      break;
+  }
+
+  FATAL("No cluster defined for cid %" Pd, cid);
+  return nullptr;
+}
+
+void BaseSerializer::WriteCluster(MessageSerializationCluster* cluster) {
+  uint64_t cid_and_canonical = (static_cast<uint64_t>(cluster->cid()) << 1) |
+                               (cluster->is_canonical() ? 0x1 : 0x0);
+  WriteUnsigned(cid_and_canonical);
+}
+
+MessageDeserializationCluster* BaseDeserializer::ReadCluster() {
+  const uint64_t cid_and_canonical = ReadUnsigned();
+  const intptr_t cid = (cid_and_canonical >> 1) & kMaxUint32;
+  const bool is_canonical = (cid_and_canonical & 0x1) == 0x1;
+
+  Zone* Z = zone_;
+  if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid) ||
+      (cid == kByteBufferCid)) {
+    return new (Z) InstanceMessageDeserializationCluster(is_canonical);
+  }
+  if (IsTypedDataViewClassId(cid) || cid == kByteDataViewCid) {
+    ASSERT(!is_canonical);
+    return new (Z) TypedDataViewMessageDeserializationCluster(cid);
+  }
+  if (IsExternalTypedDataClassId(cid)) {
+    ASSERT(!is_canonical);
+    return new (Z) ExternalTypedDataMessageDeserializationCluster(cid);
+  }
+  if (IsTypedDataClassId(cid)) {
+    ASSERT(!is_canonical);
+    return new (Z) TypedDataMessageDeserializationCluster(cid);
+  }
+
+  switch (cid) {
+    case kClassCid:
+      ASSERT(!is_canonical);
+      return new (Z) ClassMessageDeserializationCluster();
+    case kTypeArgumentsCid:
+      return new (Z) TypeArgumentsMessageDeserializationCluster(is_canonical);
+    case kFunctionCid:
+      ASSERT(!is_canonical);
+      return new (Z) FunctionMessageDeserializationCluster();
+    case kTypeCid:
+      return new (Z) TypeMessageDeserializationCluster(is_canonical);
+    case kTypeRefCid:
+      return new (Z) TypeRefMessageDeserializationCluster(is_canonical);
+    case kClosureCid:
+      return new (Z) ClosureMessageDeserializationCluster(is_canonical);
+    case kSmiCid:
+      ASSERT(is_canonical);
+      return new (Z) SmiMessageDeserializationCluster();
+    case kMintCid:
+      return new (Z) MintMessageDeserializationCluster(is_canonical);
+    case kDoubleCid:
+      return new (Z) DoubleMessageDeserializationCluster(is_canonical);
+    case kGrowableObjectArrayCid:
+      ASSERT(!is_canonical);
+      return new (Z) GrowableObjectArrayMessageDeserializationCluster();
+    case kRegExpCid:
+      ASSERT(!is_canonical);
+      return new (Z) RegExpMessageDeserializationCluster();
+    case kSendPortCid:
+      ASSERT(!is_canonical);
+      return new (Z) SendPortMessageDeserializationCluster();
+    case kCapabilityCid:
+      ASSERT(!is_canonical);
+      return new (Z) CapabilityMessageDeserializationCluster();
+    case kTransferableTypedDataCid:
+      ASSERT(!is_canonical);
+      return new (Z) TransferableTypedDataMessageDeserializationCluster();
+    case kWeakPropertyCid:
+      ASSERT(!is_canonical);
+      return new (Z) WeakPropertyMessageDeserializationCluster();
+    case kLinkedHashMapCid:
+      return new (Z) LinkedHashMapMessageDeserializationCluster(is_canonical);
+    case kLinkedHashSetCid:
+      return new (Z) LinkedHashSetMessageDeserializationCluster(is_canonical);
+    case kArrayCid:
+    case kImmutableArrayCid:
+      return new (Z) ArrayMessageDeserializationCluster(is_canonical, cid);
+    case kOneByteStringCid:
+      return new (Z) OneByteStringMessageDeserializationCluster(is_canonical);
+    case kTwoByteStringCid:
+      return new (Z) TwoByteStringMessageDeserializationCluster(is_canonical);
+    default:
+      break;
+  }
+
+  FATAL("No cluster defined for cid %" Pd, cid);
+  return nullptr;
+}
+
+void MessageSerializer::AddBaseObjects() {
+  AddBaseObject(Object::null());
+  AddBaseObject(Object::sentinel().ptr());
+  AddBaseObject(Object::transition_sentinel().ptr());
+  AddBaseObject(Object::empty_array().ptr());
+  AddBaseObject(Object::zero_array().ptr());
+  AddBaseObject(Object::dynamic_type().ptr());
+  AddBaseObject(Object::void_type().ptr());
+  AddBaseObject(Object::empty_type_arguments().ptr());
+  AddBaseObject(Bool::True().ptr());
+  AddBaseObject(Bool::False().ptr());
+}
+
+void MessageDeserializer::AddBaseObjects() {
+  AddBaseObject(Object::null());
+  AddBaseObject(Object::sentinel().ptr());
+  AddBaseObject(Object::transition_sentinel().ptr());
+  AddBaseObject(Object::empty_array().ptr());
+  AddBaseObject(Object::zero_array().ptr());
+  AddBaseObject(Object::dynamic_type().ptr());
+  AddBaseObject(Object::void_type().ptr());
+  AddBaseObject(Object::empty_type_arguments().ptr());
+  AddBaseObject(Bool::True().ptr());
+  AddBaseObject(Bool::False().ptr());
+}
+
+void ApiMessageSerializer::AddBaseObjects() {
+  AddBaseObject(&cobj_null);
+  AddBaseObject(&cobj_sentinel);
+  AddBaseObject(&cobj_transition_sentinel);
+  AddBaseObject(&cobj_empty_array);
+  AddBaseObject(&cobj_zero_array);
+  AddBaseObject(&cobj_dynamic_type);
+  AddBaseObject(&cobj_void_type);
+  AddBaseObject(&cobj_empty_type_arguments);
+  AddBaseObject(&cobj_true);
+  AddBaseObject(&cobj_false);
+}
+
+void ApiMessageDeserializer::AddBaseObjects() {
+  AddBaseObject(&cobj_null);
+  AddBaseObject(&cobj_sentinel);
+  AddBaseObject(&cobj_transition_sentinel);
+  AddBaseObject(&cobj_empty_array);
+  AddBaseObject(&cobj_zero_array);
+  AddBaseObject(&cobj_dynamic_type);
+  AddBaseObject(&cobj_void_type);
+  AddBaseObject(&cobj_empty_type_arguments);
+  AddBaseObject(&cobj_true);
+  AddBaseObject(&cobj_false);
+}
+
+void MessageSerializer::Serialize(const Object& root) {
+  AddBaseObjects();
+
+  Push(root.ptr());
+
+  while (stack_.length() > 0) {
+    // Strong references.
+    while (stack_.length() > 0) {
+      Trace(stack_.RemoveLast());
+    }
+
+    // Ephemeron references.
+    if (ephemeron_cluster_ != nullptr) {
+      ephemeron_cluster_->RetraceEphemerons(this);
+    }
+  }
+
+  intptr_t num_objects = num_base_objects_ + num_written_objects_;
+  WriteUnsigned(num_base_objects_);
+  WriteUnsigned(num_objects);
+
+  for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+       i++) {
+    intptr_t num_clusters = 0;
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      num_clusters++;
+    }
+    WriteUnsigned(num_clusters);
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      WriteCluster(cluster);
+      cluster->WriteNodes(this);
+    }
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      cluster->WriteEdges(this);
+    }
+  }
+
+  // We should have assigned a ref to every object we pushed.
+  ASSERT((next_ref_index_ - 1) == num_objects);
+
+  WriteRef(root.ptr());
+}
+
+bool ApiMessageSerializer::Serialize(Dart_CObject* root) {
+  AddBaseObjects();
+
+  Push(root);
+
+  // Strong references only.
+  while (stack_.length() > 0) {
+    if (!Trace(stack_.RemoveLast())) {
+      return false;
+    }
+  }
+
+  intptr_t num_objects = num_base_objects_ + num_written_objects_;
+  WriteUnsigned(num_base_objects_);
+  WriteUnsigned(num_objects);
+
+  for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+       i++) {
+    intptr_t num_clusters = 0;
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      num_clusters++;
+    }
+    WriteUnsigned(num_clusters);
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      WriteCluster(cluster);
+      cluster->WriteNodesApi(this);
+    }
+    for (MessageSerializationCluster* cluster : clusters_) {
+      if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+      cluster->WriteEdgesApi(this);
+    }
+  }
+
+  // We should have assigned a ref to every object we pushed.
+  ASSERT((next_ref_index_ - 1) == num_objects);
+
+  WriteRef(root);
+  return true;
+}
+
+ObjectPtr MessageDeserializer::Deserialize() {
+  intptr_t num_base_objects = ReadUnsigned();
+  intptr_t num_objects = ReadUnsigned();
+
+  refs_ = Array::New(num_objects + kFirstReference);
+
+  AddBaseObjects();
+
+  // Writer and reader must agree on number of base objects.
+  ASSERT_EQUAL(num_base_objects, (next_ref_index_ - kFirstReference));
+
+  Object& error = Object::Handle(zone());
+  for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+       i++) {
+    intptr_t num_clusters = ReadUnsigned();
+    MessageDeserializationCluster** clusters =
+        zone()->Alloc<MessageDeserializationCluster*>(num_clusters);
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      clusters[i] = ReadCluster();
+      clusters[i]->ReadNodesWrapped(this);
+    }
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      clusters[i]->ReadEdges(this);
+    }
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      error = clusters[i]->PostLoad(this);
+      if (error.IsError()) {
+        return error.ptr();  // E.g., an UnwindError during rehashing.
+      }
+    }
+  }
+
+  // We should have completely filled the ref array.
+  ASSERT_EQUAL(next_ref_index_ - kFirstReference, num_objects);
+
+  return ReadRef();
+}
+
+Dart_CObject* ApiMessageDeserializer::Deserialize() {
+  intptr_t num_base_objects = ReadUnsigned();
+  intptr_t num_objects = ReadUnsigned();
+
+  refs_ = zone()->Alloc<Dart_CObject*>(num_objects + kFirstReference);
+
+  AddBaseObjects();
+
+  // Writer and reader must agree on number of base objects.
+  ASSERT_EQUAL(num_base_objects, (next_ref_index_ - kFirstReference));
+
+  for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+       i++) {
+    intptr_t num_clusters = ReadUnsigned();
+    MessageDeserializationCluster** clusters =
+        zone()->Alloc<MessageDeserializationCluster*>(num_clusters);
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      clusters[i] = ReadCluster();
+      clusters[i]->ReadNodesWrappedApi(this);
+    }
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      clusters[i]->ReadEdgesApi(this);
+    }
+    for (intptr_t i = 0; i < num_clusters; i++) {
+      clusters[i]->PostLoadApi(this);
+    }
+  }
+
+  // We should have completely filled the ref array.
+  ASSERT_EQUAL(next_ref_index_ - kFirstReference, num_objects);
+
+  return ReadRef();
+}
+
+std::unique_ptr<Message> WriteMessage(bool can_send_any_object,
+                                      const Object& obj,
+                                      Dart_Port dest_port,
+                                      Message::Priority priority) {
+  if (ApiObjectConverter::CanConvert(obj.ptr())) {
+    return Message::New(dest_port, obj.ptr(), priority);
+  }
+
+  Thread* thread = Thread::Current();
+  MessageSerializer serializer(thread, can_send_any_object);
+
+  volatile bool has_exception = false;
+  {
+    LongJumpScope jump;
+    if (setjmp(*jump.Set()) == 0) {
+      serializer.Serialize(obj);
+    } else {
+      has_exception = true;
+    }
+  }
+
+  if (has_exception) {
+    {
+      NoSafepointScope no_safepoint;
+      ErrorPtr error = thread->StealStickyError();
+      ASSERT(error == Object::snapshot_writer_error().ptr());
+    }
+
+    const String& msg_obj =
+        String::Handle(String::New(serializer.exception_message()));
+    const Array& args = Array::Handle(Array::New(1));
+    args.SetAt(0, msg_obj);
+    Exceptions::ThrowByType(Exceptions::kArgument, args);
+  }
+
+  return serializer.Finish(dest_port, priority);
+}
+
+std::unique_ptr<Message> WriteApiMessage(Zone* zone,
+                                         Dart_CObject* obj,
+                                         Dart_Port dest_port,
+                                         Message::Priority priority) {
+  ApiMessageSerializer serializer(zone);
+  if (!serializer.Serialize(obj)) {
+    return nullptr;
+  }
+  return serializer.Finish(dest_port, priority);
+}
+
+ObjectPtr ReadMessage(Thread* thread, Message* message) {
+  if (message->IsRaw()) {
+    return message->raw_obj();
+  } else {
+    RELEASE_ASSERT(message->IsSnapshot());
+    MessageDeserializer deserializer(thread, message);
+    return deserializer.Deserialize();
+  }
+}
+
+Dart_CObject* ReadApiMessage(Zone* zone, Message* message) {
+  if (message->IsRaw()) {
+    Dart_CObject* result = zone->Alloc<Dart_CObject>(1);
+    ApiObjectConverter::Convert(message->raw_obj(), result);
+    return result;
+  } else {
+    RELEASE_ASSERT(message->IsSnapshot());
+    ApiMessageDeserializer deserializer(zone, message);
+    return deserializer.Deserialize();
+  }
+}
+
+}  // namespace dart
diff --git a/runtime/vm/message_snapshot.h b/runtime/vm/message_snapshot.h
new file mode 100644
index 0000000..d06640e
--- /dev/null
+++ b/runtime/vm/message_snapshot.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_MESSAGE_SNAPSHOT_H_
+#define RUNTIME_VM_MESSAGE_SNAPSHOT_H_
+
+#include <memory>
+
+#include "include/dart_native_api.h"
+#include "vm/message.h"
+#include "vm/object.h"
+
+namespace dart {
+
+std::unique_ptr<Message> WriteMessage(bool can_send_any_object,
+                                      const Object& obj,
+                                      Dart_Port dest_port,
+                                      Message::Priority priority);
+
+std::unique_ptr<Message> WriteApiMessage(Zone* zone,
+                                         Dart_CObject* obj,
+                                         Dart_Port dest_port,
+                                         Message::Priority priority);
+
+ObjectPtr ReadMessage(Thread* thread, Message* message);
+
+Dart_CObject* ReadApiMessage(Zone* zone, Message* message);
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_MESSAGE_SNAPSHOT_H_
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index 20f7748..132ac95 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -12,6 +12,7 @@
 #include "vm/dart_api_message.h"
 #include "vm/dart_api_state.h"
 #include "vm/message.h"
+#include "vm/message_snapshot.h"
 #include "vm/native_message_handler.h"
 #include "vm/port.h"
 #include "vm/service_isolate.h"
@@ -43,9 +44,9 @@
 };
 
 static bool PostCObjectHelper(Dart_Port port_id, Dart_CObject* message) {
-  ApiMessageWriter writer;
-  std::unique_ptr<Message> msg =
-      writer.WriteCMessage(message, port_id, Message::kNormalPriority);
+  AllocOnlyStackZone zone;
+  std::unique_ptr<Message> msg = WriteApiMessage(
+      zone.GetZone(), message, port_id, Message::kNormalPriority);
 
   if (msg == nullptr) {
     return false;
diff --git a/runtime/vm/native_message_handler.cc b/runtime/vm/native_message_handler.cc
index 65d97fd..31639e9 100644
--- a/runtime/vm/native_message_handler.cc
+++ b/runtime/vm/native_message_handler.cc
@@ -9,6 +9,7 @@
 #include "vm/dart_api_message.h"
 #include "vm/isolate.h"
 #include "vm/message.h"
+#include "vm/message_snapshot.h"
 #include "vm/snapshot.h"
 
 namespace dart {
@@ -37,9 +38,7 @@
   // All allocation of objects for decoding the message is done in the
   // zone associated with this scope.
   ApiNativeScope scope;
-  Dart_CObject* object;
-  ApiMessageReader reader(message.get());
-  object = reader.ReadMessage();
+  Dart_CObject* object = ReadApiMessage(scope.zone(), message.get());
   (*func())(message->dest_port(), object);
   return kOK;
 }
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 68a8470..3e1f788 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -11610,14 +11610,14 @@
 
 void Field::RecordStore(const Object& value) const {
   ASSERT(IsOriginal());
-  if (!IsolateGroup::Current()->use_field_guards()) {
+  Thread* const thread = Thread::Current();
+  if (!thread->isolate_group()->use_field_guards()) {
     return;
   }
 
   // We should never try to record a sentinel.
   ASSERT(value.ptr() != Object::sentinel().ptr());
 
-  Thread* const thread = Thread::Current();
   SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   if ((guarded_cid() == kDynamicCid) ||
       (is_nullable() && value.ptr() == Object::null())) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 5caf25f..5f0f6dc 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -215,11 +215,9 @@
 #define OBJECT_SERVICE_SUPPORT(object) protected: /* NOLINT */
 #endif                                            // !PRODUCT
 
-#define SNAPSHOT_READER_SUPPORT(object)                                        \
-  static object##Ptr ReadFrom(SnapshotReader* reader, intptr_t object_id,      \
-                              intptr_t tags, Snapshot::Kind,                   \
-                              bool as_reference);                              \
-  friend class SnapshotReader;
+#define SNAPSHOT_SUPPORT(object)                                               \
+  friend class object##MessageSerializationCluster;                            \
+  friend class object##MessageDeserializationCluster;
 
 #define OBJECT_IMPLEMENTATION(object, super)                                   \
  public: /* NOLINT */                                                          \
@@ -243,7 +241,7 @@
     ASSERT(ptr() != null());                                                   \
     return const_cast<Untagged##object*>(ptr()->untag());                      \
   }                                                                            \
-  SNAPSHOT_READER_SUPPORT(object)                                              \
+  SNAPSHOT_SUPPORT(object)                                                     \
   friend class StackFrame;                                                     \
   friend class Thread;
 
@@ -268,7 +266,7 @@
     return const_cast<Untagged##object*>(ptr()->untag());                      \
   }                                                                            \
   static intptr_t NextFieldOffset() { return -kWordSize; }                     \
-  SNAPSHOT_READER_SUPPORT(rettype)                                             \
+  SNAPSHOT_SUPPORT(rettype)                                                    \
   friend class Object;                                                         \
   friend class StackFrame;                                                     \
   friend class Thread;
@@ -860,7 +858,6 @@
   friend void ClassTable::Register(const Class& cls);
   friend void UntaggedObject::Validate(IsolateGroup* isolate_group) const;
   friend class Closure;
-  friend class SnapshotReader;
   friend class InstanceDeserializationCluster;
   friend class OneByteString;
   friend class TwoByteString;
@@ -2482,7 +2479,6 @@
   friend class VMDeserializationRoots;
   friend class ICDataTestTask;
   friend class VMSerializationRoots;
-  friend class SnapshotWriter;
 };
 
 // Often used constants for number of free function type parameters.
@@ -3805,7 +3801,6 @@
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
   friend class Class;
-  friend class SnapshotWriter;
   friend class Parser;  // For set_eval_script.
   // UntaggedFunction::VisitFunctionPointers accesses the private constructor of
   // Function.
@@ -3849,7 +3844,6 @@
   FINAL_HEAP_OBJECT_IMPLEMENTATION(ClosureData, Object);
   friend class Class;
   friend class Function;
-  friend class HeapProfiler;
   friend class Precompiler;  // To wrap parent functions in WSRs.
 };
 
@@ -3890,7 +3884,6 @@
   FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
   friend class Class;
   friend class Function;
-  friend class HeapProfiler;
 };
 
 class Field : public Object {
@@ -4451,7 +4444,6 @@
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Field, Object);
   friend class Class;
-  friend class HeapProfiler;
   friend class UntaggedField;
   friend class FieldSerializationCluster;
   friend class FieldDeserializationCluster;
@@ -6703,7 +6695,6 @@
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Code, Object);
   friend class Class;
   friend class CodeTestHelper;
-  friend class SnapshotWriter;
   friend class StubCode;     // for set_object_pool
   friend class Precompiler;  // for set_object_pool
   friend class FunctionSerializationCluster;
@@ -7495,7 +7486,6 @@
   friend class Pointer;
   friend class DeferredObject;
   friend class RegExp;
-  friend class SnapshotWriter;
   friend class StubCode;
   friend class TypedDataView;
   friend class InstanceSerializationCluster;
@@ -9079,6 +9069,7 @@
  protected:
   // Only Integer::NewXXX is allowed to call Mint::NewXXX directly.
   friend class Integer;
+  friend class MintMessageDeserializationCluster;
 
   static MintPtr New(int64_t value, Heap::Space space = Heap::kNew);
 
@@ -9489,14 +9480,6 @@
     ASSERT(hash_set == value);
   }
 
-  template <typename HandleType, typename ElementType, typename CallbackType>
-  static void ReadFromImpl(SnapshotReader* reader,
-                           String* str_obj,
-                           intptr_t len,
-                           intptr_t tags,
-                           CallbackType new_symbol,
-                           Snapshot::Kind kind);
-
   FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance);
 
   friend class Class;
@@ -9666,20 +9649,14 @@
     return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
   }
 
-  static OneByteStringPtr ReadFrom(SnapshotReader* reader,
-                                   intptr_t object_id,
-                                   intptr_t tags,
-                                   Snapshot::Kind kind,
-                                   bool as_reference);
-
   friend class Class;
   friend class ExternalOneByteString;
   friend class ImageWriter;
-  friend class SnapshotReader;
   friend class String;
   friend class StringHasher;
   friend class Symbols;
   friend class Utf8;
+  friend class OneByteStringMessageSerializationCluster;
 };
 
 class TwoByteString : public AllStatic {
@@ -9792,18 +9769,12 @@
     return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
   }
 
-  static TwoByteStringPtr ReadFrom(SnapshotReader* reader,
-                                   intptr_t object_id,
-                                   intptr_t tags,
-                                   Snapshot::Kind kind,
-                                   bool as_reference);
-
   friend class Class;
   friend class ImageWriter;
-  friend class SnapshotReader;
   friend class String;
   friend class StringHasher;
   friend class Symbols;
+  friend class TwoByteStringMessageSerializationCluster;
 };
 
 class ExternalOneByteString : public AllStatic {
@@ -9887,12 +9858,6 @@
                        Dart_WeakPersistentHandle handle,
                        void* peer);
 
-  static ExternalOneByteStringPtr ReadFrom(SnapshotReader* reader,
-                                           intptr_t object_id,
-                                           intptr_t tags,
-                                           Snapshot::Kind kind,
-                                           bool as_reference);
-
   static intptr_t NextFieldOffset() {
     // Indicates this class cannot be extended by dart code.
     return -kWordSize;
@@ -9901,7 +9866,6 @@
   friend class Class;
   friend class String;
   friend class StringHasher;
-  friend class SnapshotReader;
   friend class Symbols;
   friend class Utf8;
 };
@@ -9983,12 +9947,6 @@
                        Dart_WeakPersistentHandle handle,
                        void* peer);
 
-  static ExternalTwoByteStringPtr ReadFrom(SnapshotReader* reader,
-                                           intptr_t object_id,
-                                           intptr_t tags,
-                                           Snapshot::Kind kind,
-                                           bool as_reference);
-
   static intptr_t NextFieldOffset() {
     // Indicates this class cannot be extended by dart code.
     return -kWordSize;
@@ -9997,7 +9955,6 @@
   friend class Class;
   friend class String;
   friend class StringHasher;
-  friend class SnapshotReader;
   friend class Symbols;
 };
 
@@ -10233,6 +10190,7 @@
   friend class ImmutableArray;
   friend class Object;
   friend class String;
+  friend class MessageDeserializer;
 };
 
 class ImmutableArray : public AllStatic {
@@ -10243,12 +10201,6 @@
 
   static ImmutableArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew);
 
-  static ImmutableArrayPtr ReadFrom(SnapshotReader* reader,
-                                    intptr_t object_id,
-                                    intptr_t tags,
-                                    Snapshot::Kind kind,
-                                    bool as_reference);
-
   static const ClassId kClassId = kImmutableArrayCid;
 
   static intptr_t InstanceSize() { return Array::InstanceSize(); }
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 2f404f5..7fe26f1 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -6,6 +6,7 @@
 
 #include "platform/unaligned.h"
 #include "vm/code_patcher.h"
+#include "vm/dart_entry.h"
 #include "vm/hash_table.h"
 #include "vm/isolate_reload.h"
 #include "vm/log.h"
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 47e7abc..33bede3 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -307,6 +307,10 @@
   ASSERT(!cls.IsNull());
   set_error_class(cls);
 
+  cls = core_lib.LookupClassAllowPrivate(Symbols::Expando());
+  ASSERT(!cls.IsNull());
+  set_expando_class(cls);
+
   // Cache the core private functions used for fast instance of checks.
   simple_instance_of_function_ =
       PrivateObjectLookup(Symbols::_simpleInstanceOf());
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 64dabde..a944d89 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -141,6 +141,7 @@
   RW(Class, int32x4_class)                                                     \
   RW(Class, float64x2_class)                                                   \
   RW(Class, error_class)                                                       \
+  RW(Class, expando_class)                                                     \
   RW(Class, weak_property_class)                                               \
   ARW_AR(Array, symbol_table)                                                  \
   RW(Array, canonical_types)                                                   \
@@ -535,7 +536,6 @@
       case Snapshot::kFullJIT:
       case Snapshot::kFullAOT:
         return reinterpret_cast<ObjectPtr*>(&slow_tts_stub_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index ac076be..3d442b2 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -18,8 +18,10 @@
 #include "vm/pointer_tagging.h"
 #include "vm/snapshot.h"
 #include "vm/tagged_pointer.h"
+#include "vm/thread.h"
 #include "vm/token.h"
 #include "vm/token_position.h"
+#include "vm/visitor.h"
 
 // Currently we have two different axes for offset generation:
 //
@@ -118,17 +120,10 @@
 #undef V
 };
 
-#define SNAPSHOT_WRITER_SUPPORT()                                              \
-  void WriteTo(SnapshotWriter* writer, intptr_t object_id,                     \
-               Snapshot::Kind kind, bool as_reference);                        \
-  friend class SnapshotWriter;
-
 #define VISITOR_SUPPORT(object)                                                \
   static intptr_t Visit##object##Pointers(object##Ptr raw_obj,                 \
                                           ObjectPointerVisitor* visitor);
 
-#define HEAP_PROFILER_SUPPORT() friend class HeapProfiler;
-
 #define RAW_OBJECT_IMPLEMENTATION(object)                                      \
  private: /* NOLINT */                                                         \
   VISITOR_SUPPORT(object)                                                      \
@@ -144,10 +139,10 @@
 #define RAW_HEAP_OBJECT_IMPLEMENTATION(object)                                 \
  private:                                                                      \
   RAW_OBJECT_IMPLEMENTATION(object);                                           \
-  SNAPSHOT_WRITER_SUPPORT()                                                    \
-  HEAP_PROFILER_SUPPORT()                                                      \
   friend class object##SerializationCluster;                                   \
   friend class object##DeserializationCluster;                                 \
+  friend class object##MessageSerializationCluster;                            \
+  friend class object##MessageDeserializationCluster;                          \
   friend class Serializer;                                                     \
   friend class Deserializer;                                                   \
   template <typename Base>                                                     \
@@ -547,6 +542,8 @@
     }
   }
 
+  friend class MessageDeserializer;  // bogus
+
   template <typename type,
             typename compressed_type,
             std::memory_order order = std::memory_order_relaxed>
@@ -760,9 +757,7 @@
   friend class ImageWriter;
   friend class AssemblyImageWriter;
   friend class BlobImageWriter;
-  friend class SnapshotReader;
   friend class Deserializer;
-  friend class SnapshotWriter;
   friend class String;
   friend class WeakProperty;            // StorePointer
   friend class Instance;                // StorePointer
@@ -840,8 +835,8 @@
   }                                                                            \
   template <std::memory_order order = std::memory_order_relaxed>               \
   void set_##name(type value) {                                                \
-    StoreArrayPointer<Compressed##type, order>(&name##_,                       \
-                                               Compressed##type(value));       \
+    StoreCompressedArrayPointer<type, Compressed##type, order>(&name##_,       \
+                                                               value);         \
   }                                                                            \
                                                                                \
  protected:                                                                    \
@@ -1015,7 +1010,6 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
         return reinterpret_cast<CompressedObjectPtr*>(&dependent_code_);
 #endif
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1062,7 +1056,7 @@
   friend class UntaggedInstance;
   friend class UntaggedInstructions;
   friend class UntaggedTypeArguments;
-  friend class SnapshotReader;
+  friend class MessageSerializer;
   friend class InstanceSerializationCluster;
   friend class TypeSerializationCluster;
   friend class CidRewriteVisitor;
@@ -1088,7 +1082,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&library_kernel_data_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1272,7 +1265,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&data_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1417,7 +1409,6 @@
       case Snapshot::kFullJIT:
       case Snapshot::kFullAOT:
         return reinterpret_cast<CompressedObjectPtr*>(&initializer_function_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1491,7 +1482,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&kernel_program_info_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1583,7 +1573,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&kernel_data_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -1636,7 +1625,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&owner_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -2191,7 +2179,6 @@
   VARIABLE_POINTER_FIELDS(ObjectPtr, element, data)
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 class UntaggedContextScope : public UntaggedObject {
@@ -2267,7 +2254,6 @@
 
   friend class Object;
   friend class UntaggedClosureData;
-  friend class SnapshotReader;
 };
 
 class UntaggedSentinel : public UntaggedObject {
@@ -2333,7 +2319,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return to();
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -2428,7 +2413,6 @@
 class UntaggedInstance : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Instance);
   friend class Object;
-  friend class SnapshotReader;
 
  public:
 #if defined(DART_COMPRESSED_POINTERS)
@@ -2457,7 +2441,6 @@
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<CompressedObjectPtr*>(&importer_);
-      case Snapshot::kMessage:
       case Snapshot::kNone:
       case Snapshot::kInvalid:
         break;
@@ -2484,7 +2467,6 @@
   COMPRESSED_VARIABLE_POINTER_FIELDS(AbstractTypePtr, element, types)
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 class UntaggedTypeParameters : public UntaggedObject {
@@ -2503,7 +2485,6 @@
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   friend class Object;
-  friend class SnapshotReader;
 };
 
 class UntaggedAbstractType : public UntaggedInstance {
@@ -2715,7 +2696,6 @@
   friend class Api;
   friend class Class;
   friend class Integer;
-  friend class SnapshotReader;
 };
 COMPILE_ASSERT(sizeof(UntaggedMint) == 16);
 
@@ -2726,7 +2706,6 @@
   ALIGN8 double value_;
 
   friend class Api;
-  friend class SnapshotReader;
   friend class Class;
 };
 COMPILE_ASSERT(sizeof(UntaggedDouble) == 16);
@@ -2762,9 +2741,7 @@
   uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
   const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
 
-  friend class ApiMessageReader;
   friend class RODataSerializationCluster;
-  friend class SnapshotReader;
   friend class String;
 };
 
@@ -2777,7 +2754,6 @@
   const uint16_t* data() const { OPEN_ARRAY_START(uint16_t, uint16_t); }
 
   friend class RODataSerializationCluster;
-  friend class SnapshotReader;
   friend class String;
 };
 
@@ -2861,7 +2837,6 @@
   friend class ObjectPoolDeserializationCluster;
   friend class ObjectPoolSerializationCluster;
   friend class UntaggedObjectPool;
-  friend class SnapshotReader;
 };
 
 // All _*ArrayView/_ByteDataView classes share the same layout.
@@ -2925,7 +2900,6 @@
   friend class GCCompactor;
   template <bool>
   friend class ScavengerVisitorBase;
-  friend class SnapshotReader;
 };
 
 class UntaggedExternalOneByteString : public UntaggedString {
@@ -2971,7 +2945,6 @@
   friend class Deserializer;
   friend class UntaggedCode;
   friend class UntaggedImmutableArray;
-  friend class SnapshotReader;
   friend class GrowableObjectArray;
   friend class LinkedHashMap;
   friend class UntaggedLinkedHashMap;
@@ -2988,8 +2961,6 @@
 
 class UntaggedImmutableArray : public UntaggedArray {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ImmutableArray);
-
-  friend class SnapshotReader;
 };
 
 class UntaggedGrowableObjectArray : public UntaggedInstance {
@@ -3002,7 +2973,6 @@
   VISIT_TO(data)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
-  friend class SnapshotReader;
   friend class ReversePc;
 };
 
@@ -3026,14 +2996,10 @@
 
 class UntaggedLinkedHashMap : public UntaggedLinkedHashBase {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashMap);
-
-  friend class SnapshotReader;
 };
 
 class UntaggedLinkedHashSet : public UntaggedLinkedHashBase {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashSet);
-
-  friend class SnapshotReader;
 };
 
 class UntaggedFloat32x4 : public UntaggedInstance {
@@ -3042,7 +3008,6 @@
 
   ALIGN8 float value_[4];
 
-  friend class SnapshotReader;
   friend class Class;
 
  public:
@@ -3059,7 +3024,6 @@
 
   ALIGN8 int32_t value_[4];
 
-  friend class SnapshotReader;
 
  public:
   int32_t x() const { return value_[0]; }
@@ -3075,7 +3039,6 @@
 
   ALIGN8 double value_[2];
 
-  friend class SnapshotReader;
   friend class Class;
 
  public:
@@ -3264,7 +3227,6 @@
   // Isolate unique tag.
   uword tag_;
 
-  friend class SnapshotReader;
   friend class Object;
 
  public:
@@ -3277,8 +3239,6 @@
   COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_arguments)
   VISIT_FROM(type_arguments)
   VISIT_TO(type_arguments)
-
-  friend class SnapshotReader;
 };
 
 #undef WSR_COMPRESSED_POINTER_FIELD
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
deleted file mode 100644
index 82f51c6..0000000
--- a/runtime/vm/raw_object_snapshot.cc
+++ /dev/null
@@ -1,1798 +0,0 @@
-// Copyright (c) 2012, 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.
-
-#include "vm/dart_api_state.h"
-#include "vm/message.h"
-#include "vm/native_entry.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/regexp.h"
-#include "vm/snapshot.h"
-#include "vm/stub_code.h"
-#include "vm/symbols.h"
-#include "vm/type_testing_stubs.h"
-#include "vm/visitor.h"
-
-namespace dart {
-
-// TODO(dartbug.com/34796): enable or remove this optimization.
-DEFINE_FLAG(
-    uint64_t,
-    externalize_typed_data_threshold,
-    kMaxUint64,
-    "Convert TypedData to ExternalTypedData when sending through a message"
-    " port after it exceeds certain size in bytes.");
-
-#define OFFSET_OF_FROM(obj)                                                    \
-  obj.ptr()->from() - reinterpret_cast<ObjectPtr*>(obj.ptr()->untag())
-
-#define READ_OBJECT_FIELDS(object, from, to, as_reference)                     \
-  intptr_t num_flds = (to) - (from);                                           \
-  for (intptr_t i = 0; i <= num_flds; i++) {                                   \
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(as_reference);   \
-    object.StorePointer(((from) + i), reader->PassiveObjectHandle()->ptr());   \
-  }
-
-#define READ_COMPRESSED_OBJECT_FIELDS(object, from, to, as_reference)          \
-  intptr_t num_flds = (to) - (from);                                           \
-  for (intptr_t i = 0; i <= num_flds; i++) {                                   \
-    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(as_reference);   \
-    object.StoreCompressedPointer(((from) + i),                                \
-                                  reader->PassiveObjectHandle()->ptr());       \
-  }
-
-ClassPtr Class::ReadFrom(SnapshotReader* reader,
-                         intptr_t object_id,
-                         intptr_t tags,
-                         Snapshot::Kind kind,
-                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  Class& cls = Class::ZoneHandle(reader->zone(), Class::null());
-  cls = reader->ReadClassId(object_id);
-  return cls.ptr();
-}
-
-void UntaggedClass::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kClassCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  if (writer->can_send_any_object() ||
-      writer->AllowObjectsInDartLibrary(library())) {
-    writer->WriteClassId(this);
-  } else {
-    // We do not allow regular dart instances in isolate messages.
-    writer->SetWriteException(Exceptions::kArgument,
-                              "Illegal argument in isolate message"
-                              " : (object is a regular Dart Instance)");
-  }
-}
-
-TypePtr Type::ReadFrom(SnapshotReader* reader,
-                       intptr_t object_id,
-                       intptr_t tags,
-                       Snapshot::Kind kind,
-                       bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Determine if the type class of this type is in the full snapshot.
-  reader->Read<bool>();
-
-  // Allocate type object.
-  Type& type = Type::ZoneHandle(reader->zone(), Type::New());
-  bool is_canonical = UntaggedObject::IsCanonical(tags);
-  reader->AddBackRef(object_id, &type, kIsDeserialized);
-
-  // Set all non object fields.
-  const uint8_t combined = reader->Read<uint8_t>();
-  type.set_type_state(combined >> 4);
-  type.set_nullability(static_cast<Nullability>(combined & 0xf));
-
-  // Read the code object for the type testing stub and set its entrypoint.
-  reader->EnqueueTypePostprocessing(type);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(type, type.ptr()->untag()->from(),
-                                type.ptr()->untag()->to(), as_reference);
-
-  // Read in the type class.
-  (*reader->ClassHandle()) =
-      Class::RawCast(reader->ReadObjectImpl(as_reference));
-  type.set_type_class(*reader->ClassHandle());
-
-  // Fill in the type testing stub.
-  Code& code = *reader->CodeHandle();
-  code = TypeTestingStubGenerator::DefaultCodeForType(type);
-  type.InitializeTypeTestingStubNonAtomic(code);
-
-  if (is_canonical) {
-    type ^= type.Canonicalize(Thread::Current(), nullptr);
-  }
-
-  return type.ptr();
-}
-
-void UntaggedType::WriteTo(SnapshotWriter* writer,
-                           intptr_t object_id,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Only resolved and finalized types should be written to a snapshot.
-  ASSERT((type_state_ == UntaggedType::kFinalizedInstantiated) ||
-         (type_state_ == UntaggedType::kFinalizedUninstantiated));
-  ASSERT(type_class_id() != Object::null());
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kTypeCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  if (type_class_id()->IsHeapObject()) {
-    // Type class is still an unresolved class.
-    UNREACHABLE();
-  }
-
-  // Lookup the type class.
-  SmiPtr raw_type_class_id = Smi::RawCast(type_class_id());
-  ClassPtr type_class =
-      writer->isolate_group()->class_table()->At(Smi::Value(raw_type_class_id));
-
-  // Write out typeclass_is_in_fullsnapshot first as this will
-  // help the reader decide on how to canonicalize the type object.
-  intptr_t tags = writer->GetObjectTags(type_class);
-  bool typeclass_is_in_fullsnapshot =
-      (ClassIdTag::decode(tags) == kClassCid) &&
-      Class::IsInFullSnapshot(static_cast<ClassPtr>(type_class));
-  writer->Write<bool>(typeclass_is_in_fullsnapshot);
-
-  // Write out all the non object pointer fields.
-  const uint8_t combined = (type_state_ << 4) | nullability_;
-  ASSERT(type_state_ == (combined >> 4));
-  ASSERT(nullability_ == (combined & 0xf));
-  writer->Write<uint8_t>(combined);
-
-  // Write out all the object pointer fields.
-  ASSERT(type_class_id() != Object::null());
-  SnapshotWriterVisitor visitor(writer, as_reference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-
-  // Write out the type class.
-  writer->WriteObjectImpl(type_class, as_reference);
-}
-
-TypeRefPtr TypeRef::ReadFrom(SnapshotReader* reader,
-                             intptr_t object_id,
-                             intptr_t tags,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate type ref object.
-  TypeRef& type_ref = TypeRef::ZoneHandle(reader->zone(), TypeRef::New());
-  reader->AddBackRef(object_id, &type_ref, kIsDeserialized);
-
-  // Read the code object for the type testing stub and set its entrypoint.
-  reader->EnqueueTypePostprocessing(type_ref);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(type_ref, type_ref.ptr()->untag()->from(),
-                                type_ref.ptr()->untag()->to(), kAsReference);
-
-  // Fill in the type testing stub.
-  Code& code = *reader->CodeHandle();
-  code = TypeTestingStubGenerator::DefaultCodeForType(type_ref);
-  type_ref.InitializeTypeTestingStubNonAtomic(code);
-
-  return type_ref.ptr();
-}
-
-void UntaggedTypeRef::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kTypeRefCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-TypeParameterPtr TypeParameter::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate type parameter object.
-  TypeParameter& type_parameter =
-      TypeParameter::ZoneHandle(reader->zone(), TypeParameter::New());
-  bool is_canonical = UntaggedObject::IsCanonical(tags);
-  reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
-
-  // Set all non object fields.
-  type_parameter.set_base(reader->Read<uint8_t>());
-  type_parameter.set_index(reader->Read<uint8_t>());
-  const uint8_t combined = reader->Read<uint8_t>();
-  type_parameter.set_flags(combined >> 4);
-  type_parameter.set_nullability(static_cast<Nullability>(combined & 0xf));
-
-  // Read the code object for the type testing stub and set its entrypoint.
-  reader->EnqueueTypePostprocessing(type_parameter);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(
-      type_parameter, type_parameter.ptr()->untag()->from(),
-      type_parameter.ptr()->untag()->to(), kAsReference);
-
-  // Read in the parameterized class.
-  (*reader->ClassHandle()) =
-      Class::RawCast(reader->ReadObjectImpl(kAsReference));
-  if (reader->ClassHandle()->id() == kFunctionCid) {
-    (*reader->ClassHandle()) = Class::null();
-  }
-  type_parameter.set_parameterized_class(*reader->ClassHandle());
-
-  // Fill in the type testing stub.
-  Code& code = *reader->CodeHandle();
-  code = TypeTestingStubGenerator::DefaultCodeForType(type_parameter);
-  type_parameter.InitializeTypeTestingStubNonAtomic(code);
-
-  if (is_canonical) {
-    type_parameter ^= type_parameter.Canonicalize(Thread::Current(), nullptr);
-  }
-
-  return type_parameter.ptr();
-}
-
-void UntaggedTypeParameter::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Only finalized type parameters should be written to a snapshot.
-  ASSERT(FinalizedBit::decode(flags_));
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kTypeParameterCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the non object pointer fields.
-  writer->Write<uint8_t>(base_);
-  writer->Write<uint8_t>(index_);
-  const uint8_t combined = (flags_ << 4) | nullability_;
-  ASSERT(flags_ == (combined >> 4));
-  ASSERT(nullability_ == (combined & 0xf));
-  writer->Write<uint8_t>(combined);
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-
-  // Write out the parameterized class (or Function if cid == kFunctionCid).
-  ClassPtr param_class =
-      writer->isolate_group()->class_table()->At(parameterized_class_id_);
-  writer->WriteObjectImpl(param_class, kAsReference);
-}
-
-TypeParametersPtr TypeParameters::ReadFrom(SnapshotReader* reader,
-                                           intptr_t object_id,
-                                           intptr_t tags,
-                                           Snapshot::Kind kind,
-                                           bool as_reference) {
-  ASSERT(reader != NULL);
-
-  TypeParameters& type_parameters =
-      TypeParameters::ZoneHandle(reader->zone(), TypeParameters::New());
-  reader->AddBackRef(object_id, &type_parameters, kIsDeserialized);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(
-      type_parameters, type_parameters.ptr()->untag()->from(),
-      type_parameters.ptr()->untag()->to(), kAsReference);
-
-  return type_parameters.ptr();
-}
-
-void UntaggedTypeParameters::WriteTo(SnapshotWriter* writer,
-                                     intptr_t object_id,
-                                     Snapshot::Kind kind,
-                                     bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kTypeParametersCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-TypeArgumentsPtr TypeArguments::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Read the length so that we can determine instance size to allocate.
-  intptr_t len = reader->ReadSmiValue();
-
-  TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(reader->zone(), TypeArguments::New(len));
-  bool is_canonical = UntaggedObject::IsCanonical(tags);
-  reader->AddBackRef(object_id, &type_arguments, kIsDeserialized);
-
-  // Set the instantiations field, which is only read from a full snapshot.
-  type_arguments.set_instantiations(Object::zero_array());
-
-  // Now set all the type fields.
-  for (intptr_t i = 0; i < len; i++) {
-    *reader->TypeHandle() ^= reader->ReadObjectImpl(as_reference);
-    type_arguments.SetTypeAt(i, *reader->TypeHandle());
-  }
-
-  // Set the canonical bit.
-  if (is_canonical) {
-    type_arguments = type_arguments.Canonicalize(Thread::Current(), nullptr);
-  }
-
-  return type_arguments.ptr();
-}
-
-void UntaggedTypeArguments::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kTypeArgumentsCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the length field.
-  writer->Write<ObjectPtr>(length());
-
-  // Write out the individual types.
-  intptr_t len = Smi::Value(length());
-  for (intptr_t i = 0; i < len; i++) {
-    // The Dart VM reuses type argument lists across instances in order
-    // to reduce memory footprint, this can sometimes lead to a type from
-    // such a shared type argument list being sent over to another isolate.
-    // In such scenarios where it is not appropriate to send the types
-    // across (isolates spawned using spawnURI) we send them as dynamic.
-    if (!writer->can_send_any_object()) {
-      // Lookup the type class.
-      TypePtr raw_type = Type::RawCast(element(i));
-      SmiPtr raw_type_class_id =
-          Smi::RawCast(raw_type->untag()->type_class_id());
-      ClassPtr type_class = writer->isolate_group()->class_table()->At(
-          Smi::Value(raw_type_class_id));
-      if (!writer->AllowObjectsInDartLibrary(type_class->untag()->library())) {
-        writer->WriteVMIsolateObject(kDynamicType);
-      } else {
-        writer->WriteObjectImpl(element(i), as_reference);
-      }
-    } else {
-      writer->WriteObjectImpl(element(i), as_reference);
-    }
-  }
-}
-
-ClosurePtr Closure::ReadFrom(SnapshotReader* reader,
-                             intptr_t object_id,
-                             intptr_t tags,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  UNREACHABLE();
-  return Closure::null();
-}
-
-void UntaggedClosure::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  ASSERT(writer != NULL);
-  ASSERT(kind == Snapshot::kMessage);
-
-  // Check if closure is serializable, throw an exception otherwise.
-  FunctionPtr func = writer->IsSerializableClosure(ClosurePtr(this));
-  if (func != Function::null()) {
-    writer->WriteStaticImplicitClosure(
-        object_id, func, writer->GetObjectTags(this), delayed_type_arguments());
-    return;
-  }
-
-  UNREACHABLE();
-}
-
-ContextPtr Context::ReadFrom(SnapshotReader* reader,
-                             intptr_t object_id,
-                             intptr_t tags,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate context object.
-  int32_t num_vars = reader->Read<int32_t>();
-  Context& context = Context::ZoneHandle(reader->zone());
-  reader->AddBackRef(object_id, &context, kIsDeserialized);
-  if (num_vars != 0) {
-    context = Context::New(num_vars);
-
-    // Set all the object fields.
-    // TODO(5411462): Need to assert No GC can happen here, even though
-    // allocations may happen.
-    intptr_t num_flds =
-        (context.ptr()->untag()->to(num_vars) - context.ptr()->untag()->from());
-    for (intptr_t i = 0; i <= num_flds; i++) {
-      (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
-      context.StorePointer((context.ptr()->untag()->from() + i),
-                           reader->PassiveObjectHandle()->ptr());
-    }
-  }
-  return context.ptr();
-}
-
-void UntaggedContext::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kContextCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out num of variables in the context.
-  const int32_t num_variables = num_variables_;
-  writer->Write<int32_t>(num_variables);
-  if (num_variables != 0) {
-    // Write out all the object pointer fields.
-    SnapshotWriterVisitor visitor(writer, kAsReference);
-    visitor.VisitPointers(from(), to(num_variables));
-  }
-}
-
-ContextScopePtr ContextScope::ReadFrom(SnapshotReader* reader,
-                                       intptr_t object_id,
-                                       intptr_t tags,
-                                       Snapshot::Kind kind,
-                                       bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate context object.
-  bool is_implicit = reader->Read<bool>();
-  if (is_implicit) {
-    ContextScope& context_scope = ContextScope::ZoneHandle(reader->zone());
-    context_scope = ContextScope::New(1, true);
-    reader->AddBackRef(object_id, &context_scope, kIsDeserialized);
-
-    *reader->TypeHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-
-    // Create a descriptor for 'this' variable.
-    context_scope.SetTokenIndexAt(0, TokenPosition::kMinSource);
-    context_scope.SetDeclarationTokenIndexAt(0, TokenPosition::kMinSource);
-    context_scope.SetNameAt(0, Symbols::This());
-    context_scope.SetIsFinalAt(0, true);
-    context_scope.SetIsConstAt(0, false);
-    context_scope.SetTypeAt(0, *reader->TypeHandle());
-    context_scope.SetContextIndexAt(0, 0);
-    context_scope.SetContextLevelAt(0, 0);
-    return context_scope.ptr();
-  }
-  UNREACHABLE();
-  return NULL;
-}
-
-void UntaggedContextScope::WriteTo(SnapshotWriter* writer,
-                                   intptr_t object_id,
-                                   Snapshot::Kind kind,
-                                   bool as_reference) {
-  ASSERT(writer != NULL);
-
-  if (is_implicit_) {
-    ASSERT(num_variables_ == 1);
-    const VariableDesc* var = VariableDescAddr(0);
-
-    // Write out the serialization header value for this object.
-    writer->WriteInlinedObjectHeader(object_id);
-
-    // Write out the class and tags information.
-    writer->WriteVMIsolateObject(kContextScopeCid);
-    writer->WriteTags(writer->GetObjectTags(this));
-
-    // Write out is_implicit flag for the context scope.
-    writer->Write<bool>(true);
-
-    // Write out the type of 'this' the variable.
-    writer->WriteObjectImpl(var->type.Decompress(heap_base()),
-                            kAsInlinedObject);
-
-    return;
-  }
-  UNREACHABLE();
-}
-
-#define MESSAGE_SNAPSHOT_UNREACHABLE(type)                                     \
-  type##Ptr type::ReadFrom(SnapshotReader* reader, intptr_t object_id,         \
-                           intptr_t tags, Snapshot::Kind kind,                 \
-                           bool as_reference) {                                \
-    UNREACHABLE();                                                             \
-    return type::null();                                                       \
-  }                                                                            \
-  void Untagged##type::WriteTo(SnapshotWriter* writer, intptr_t object_id,     \
-                               Snapshot::Kind kind, bool as_reference) {       \
-    UNREACHABLE();                                                             \
-  }
-
-#define MESSAGE_SNAPSHOT_ILLEGAL(type)                                         \
-  type##Ptr type::ReadFrom(SnapshotReader* reader, intptr_t object_id,         \
-                           intptr_t tags, Snapshot::Kind kind,                 \
-                           bool as_reference) {                                \
-    UNREACHABLE();                                                             \
-    return type::null();                                                       \
-  }                                                                            \
-  void Untagged##type::WriteTo(SnapshotWriter* writer, intptr_t object_id,     \
-                               Snapshot::Kind kind, bool as_reference) {       \
-    writer->SetWriteException(Exceptions::kArgument,                           \
-                              "Illegal argument in isolate message"            \
-                              " : (object is a " #type ")");                   \
-  }
-
-MESSAGE_SNAPSHOT_UNREACHABLE(AbstractType);
-MESSAGE_SNAPSHOT_UNREACHABLE(Bool);
-MESSAGE_SNAPSHOT_UNREACHABLE(ClosureData);
-MESSAGE_SNAPSHOT_UNREACHABLE(Code);
-MESSAGE_SNAPSHOT_UNREACHABLE(CodeSourceMap);
-MESSAGE_SNAPSHOT_UNREACHABLE(CompressedStackMaps);
-MESSAGE_SNAPSHOT_UNREACHABLE(Error);
-MESSAGE_SNAPSHOT_UNREACHABLE(ExceptionHandlers);
-MESSAGE_SNAPSHOT_UNREACHABLE(FfiTrampolineData);
-MESSAGE_SNAPSHOT_UNREACHABLE(Field);
-MESSAGE_SNAPSHOT_UNREACHABLE(Function);
-MESSAGE_SNAPSHOT_UNREACHABLE(CallSiteData);
-MESSAGE_SNAPSHOT_UNREACHABLE(ICData);
-MESSAGE_SNAPSHOT_UNREACHABLE(Instructions);
-MESSAGE_SNAPSHOT_UNREACHABLE(InstructionsSection);
-MESSAGE_SNAPSHOT_UNREACHABLE(InstructionsTable);
-MESSAGE_SNAPSHOT_UNREACHABLE(KernelProgramInfo);
-MESSAGE_SNAPSHOT_UNREACHABLE(Library);
-MESSAGE_SNAPSHOT_UNREACHABLE(LibraryPrefix);
-MESSAGE_SNAPSHOT_UNREACHABLE(LocalVarDescriptors);
-MESSAGE_SNAPSHOT_UNREACHABLE(MegamorphicCache);
-MESSAGE_SNAPSHOT_UNREACHABLE(Namespace);
-MESSAGE_SNAPSHOT_UNREACHABLE(ObjectPool);
-MESSAGE_SNAPSHOT_UNREACHABLE(PatchClass);
-MESSAGE_SNAPSHOT_UNREACHABLE(PcDescriptors);
-MESSAGE_SNAPSHOT_UNREACHABLE(Script);
-MESSAGE_SNAPSHOT_UNREACHABLE(Sentinel);
-MESSAGE_SNAPSHOT_UNREACHABLE(SingleTargetCache);
-MESSAGE_SNAPSHOT_UNREACHABLE(String);
-MESSAGE_SNAPSHOT_UNREACHABLE(SubtypeTestCache);
-MESSAGE_SNAPSHOT_UNREACHABLE(LoadingUnit);
-MESSAGE_SNAPSHOT_UNREACHABLE(TypedDataBase);
-MESSAGE_SNAPSHOT_UNREACHABLE(UnlinkedCall);
-MESSAGE_SNAPSHOT_UNREACHABLE(MonomorphicSmiableCall);
-MESSAGE_SNAPSHOT_UNREACHABLE(UnwindError);
-MESSAGE_SNAPSHOT_UNREACHABLE(FutureOr);
-MESSAGE_SNAPSHOT_UNREACHABLE(WeakSerializationReference);
-
-MESSAGE_SNAPSHOT_ILLEGAL(FunctionType)
-MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
-MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
-MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
-MESSAGE_SNAPSHOT_ILLEGAL(ReceivePort);
-MESSAGE_SNAPSHOT_ILLEGAL(StackTrace);
-MESSAGE_SNAPSHOT_ILLEGAL(UserTag);
-
-ApiErrorPtr ApiError::ReadFrom(SnapshotReader* reader,
-                               intptr_t object_id,
-                               intptr_t tags,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate ApiError object.
-  ApiError& api_error = ApiError::ZoneHandle(reader->zone(), ApiError::New());
-  reader->AddBackRef(object_id, &api_error, kIsDeserialized);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(api_error, api_error.ptr()->untag()->from(),
-                                api_error.ptr()->untag()->to(), kAsReference);
-
-  return api_error.ptr();
-}
-
-void UntaggedApiError::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kApiErrorCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-LanguageErrorPtr LanguageError::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate LanguageError object.
-  LanguageError& language_error =
-      LanguageError::ZoneHandle(reader->zone(), LanguageError::New());
-  reader->AddBackRef(object_id, &language_error, kIsDeserialized);
-
-  // Set all non object fields.
-  language_error.set_token_pos(
-      TokenPosition::Deserialize(reader->Read<int32_t>()));
-  language_error.set_report_after_token(reader->Read<bool>());
-  language_error.set_kind(reader->Read<uint8_t>());
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(
-      language_error, language_error.ptr()->untag()->from(),
-      language_error.ptr()->untag()->to(), kAsReference);
-
-  return language_error.ptr();
-}
-
-void UntaggedLanguageError::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kLanguageErrorCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the non object fields.
-  writer->Write<int32_t>(token_pos_.Serialize());
-  writer->Write<bool>(report_after_token_);
-  writer->Write<uint8_t>(kind_);
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-UnhandledExceptionPtr UnhandledException::ReadFrom(SnapshotReader* reader,
-                                                   intptr_t object_id,
-                                                   intptr_t tags,
-                                                   Snapshot::Kind kind,
-                                                   bool as_reference) {
-  UnhandledException& result =
-      UnhandledException::ZoneHandle(reader->zone(), UnhandledException::New());
-  reader->AddBackRef(object_id, &result, kIsDeserialized);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(result, result.ptr()->untag()->from(),
-                                result.ptr()->untag()->to(), kAsReference);
-
-  return result.ptr();
-}
-
-void UntaggedUnhandledException::WriteTo(SnapshotWriter* writer,
-                                         intptr_t object_id,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteVMIsolateObject(kUnhandledExceptionCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-InstancePtr Instance::ReadFrom(SnapshotReader* reader,
-                               intptr_t object_id,
-                               intptr_t tags,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Create an Instance object or get canonical one if it is a canonical
-  // constant.
-  Instance& obj = Instance::ZoneHandle(reader->zone(), Instance::null());
-  obj ^= Object::Allocate(kInstanceCid, Instance::InstanceSize(), Heap::kNew,
-                          Instance::ContainsCompressedPointers());
-  if (UntaggedObject::IsCanonical(tags)) {
-    obj = obj.Canonicalize(reader->thread());
-  }
-  reader->AddBackRef(object_id, &obj, kIsDeserialized);
-
-  return obj.ptr();
-}
-
-void UntaggedInstance::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kInstanceCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-}
-
-IntegerPtr Mint::ReadFrom(SnapshotReader* reader,
-                          intptr_t object_id,
-                          intptr_t tags,
-                          Snapshot::Kind kind,
-                          bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Read the 64 bit value for the object.
-  int64_t value = reader->Read<int64_t>();
-
-  // Check if the value could potentially fit in a Smi in our current
-  // architecture, if so return the object as a Smi.
-  if (Smi::IsValid(value)) {
-    Smi& smi =
-        Smi::ZoneHandle(reader->zone(), Smi::New(static_cast<intptr_t>(value)));
-    reader->AddBackRef(object_id, &smi, kIsDeserialized);
-    return smi.ptr();
-  }
-
-  // Create a Mint object or get canonical one if it is a canonical constant.
-  Mint& mint = Mint::ZoneHandle(reader->zone(), Mint::null());
-  // When reading a script snapshot we need to canonicalize only those object
-  // references that are objects from the core library (loaded from a
-  // full snapshot). Objects that are only in the script need not be
-  // canonicalized as they are already canonical.
-  // When reading a message snapshot we always have to canonicalize.
-  if (UntaggedObject::IsCanonical(tags)) {
-    mint = Mint::NewCanonical(value);
-    ASSERT(mint.IsCanonical());
-  } else {
-    mint = Mint::New(value);
-  }
-  reader->AddBackRef(object_id, &mint, kIsDeserialized);
-  return mint.ptr();
-}
-
-void UntaggedMint::WriteTo(SnapshotWriter* writer,
-                           intptr_t object_id,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kMintCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the 64 bit value.
-  writer->Write<int64_t>(value_);
-}
-
-DoublePtr Double::ReadFrom(SnapshotReader* reader,
-                           intptr_t object_id,
-                           intptr_t tags,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
-  ASSERT(reader != NULL);
-  ASSERT(kind != Snapshot::kMessage);
-  // Read the double value for the object.
-  double value = reader->ReadDouble();
-
-  // Create a Double object or get canonical one if it is a canonical constant.
-  Double& dbl = Double::ZoneHandle(reader->zone(), Double::null());
-  // When reading a script snapshot we need to canonicalize only those object
-  // references that are objects from the core library (loaded from a
-  // full snapshot). Objects that are only in the script need not be
-  // canonicalized as they are already canonical.
-  if (UntaggedObject::IsCanonical(tags)) {
-    dbl = Double::NewCanonical(value);
-    ASSERT(dbl.IsCanonical());
-  } else {
-    dbl = Double::New(value);
-  }
-  reader->AddBackRef(object_id, &dbl, kIsDeserialized);
-  return dbl.ptr();
-}
-
-void UntaggedDouble::WriteTo(SnapshotWriter* writer,
-                             intptr_t object_id,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kDoubleCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the double value.
-  writer->WriteDouble(value_);
-}
-
-template <typename StringType, typename CharacterType, typename CallbackType>
-void String::ReadFromImpl(SnapshotReader* reader,
-                          String* str_obj,
-                          intptr_t len,
-                          intptr_t tags,
-                          CallbackType new_symbol,
-                          Snapshot::Kind kind) {
-  ASSERT(reader != NULL);
-  if (UntaggedObject::IsCanonical(tags)) {
-    // Set up canonical string object.
-    ASSERT(reader != NULL);
-    CharacterType* ptr = reader->zone()->Alloc<CharacterType>(len);
-    for (intptr_t i = 0; i < len; i++) {
-      ptr[i] = reader->Read<CharacterType>();
-    }
-    *str_obj = (*new_symbol)(reader->thread(), ptr, len);
-  } else {
-    // Set up the string object.
-    *str_obj = StringType::New(len, Heap::kNew);
-    str_obj->SetHash(0);  // Will get computed when needed.
-    if (len == 0) {
-      return;
-    }
-    NoSafepointScope no_safepoint;
-    CharacterType* str_addr = StringType::DataStart(*str_obj);
-    for (intptr_t i = 0; i < len; i++) {
-      *str_addr = reader->Read<CharacterType>();
-      str_addr++;
-    }
-  }
-}
-
-OneByteStringPtr OneByteString::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  // Read the length so that we can determine instance size to allocate.
-  ASSERT(reader != NULL);
-  intptr_t len = reader->ReadSmiValue();
-  String& str_obj = String::ZoneHandle(reader->zone(), String::null());
-
-  String::ReadFromImpl<OneByteString, uint8_t>(reader, &str_obj, len, tags,
-                                               Symbols::FromLatin1, kind);
-  reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
-  return raw(str_obj);
-}
-
-TwoByteStringPtr TwoByteString::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  // Read the length so that we can determine instance size to allocate.
-  ASSERT(reader != NULL);
-  intptr_t len = reader->ReadSmiValue();
-  String& str_obj = String::ZoneHandle(reader->zone(), String::null());
-
-  String::ReadFromImpl<TwoByteString, uint16_t>(reader, &str_obj, len, tags,
-                                                Symbols::FromUTF16, kind);
-  reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
-  return raw(str_obj);
-}
-
-template <typename T>
-static void StringWriteTo(SnapshotWriter* writer,
-                          intptr_t object_id,
-                          Snapshot::Kind kind,
-                          intptr_t class_id,
-                          intptr_t tags,
-                          SmiPtr length,
-                          T* data) {
-  ASSERT(writer != NULL);
-  intptr_t len = Smi::Value(length);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(class_id);
-  writer->WriteTags(tags);
-
-  // Write out the length field.
-  writer->Write<ObjectPtr>(length);
-
-  // Write out the string.
-  if (len > 0) {
-    if (class_id == kOneByteStringCid) {
-      writer->WriteBytes(reinterpret_cast<const uint8_t*>(data), len);
-    } else {
-      for (intptr_t i = 0; i < len; i++) {
-        writer->Write(data[i]);
-      }
-    }
-  }
-}
-
-void UntaggedOneByteString::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  StringWriteTo(writer, object_id, kind, kOneByteStringCid,
-                writer->GetObjectTags(this), length(), data());
-}
-
-void UntaggedTwoByteString::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  StringWriteTo(writer, object_id, kind, kTwoByteStringCid,
-                writer->GetObjectTags(this), length(), data());
-}
-
-ExternalOneByteStringPtr ExternalOneByteString::ReadFrom(SnapshotReader* reader,
-                                                         intptr_t object_id,
-                                                         intptr_t tags,
-                                                         Snapshot::Kind kind,
-                                                         bool as_reference) {
-  UNREACHABLE();
-  return ExternalOneByteString::null();
-}
-
-ExternalTwoByteStringPtr ExternalTwoByteString::ReadFrom(SnapshotReader* reader,
-                                                         intptr_t object_id,
-                                                         intptr_t tags,
-                                                         Snapshot::Kind kind,
-                                                         bool as_reference) {
-  UNREACHABLE();
-  return ExternalTwoByteString::null();
-}
-
-void UntaggedExternalOneByteString::WriteTo(SnapshotWriter* writer,
-                                            intptr_t object_id,
-                                            Snapshot::Kind kind,
-                                            bool as_reference) {
-  // Serialize as a non-external one byte string.
-  StringWriteTo(writer, object_id, kind, kOneByteStringCid,
-                writer->GetObjectTags(this), length(), external_data_);
-}
-
-void UntaggedExternalTwoByteString::WriteTo(SnapshotWriter* writer,
-                                            intptr_t object_id,
-                                            Snapshot::Kind kind,
-                                            bool as_reference) {
-  // Serialize as a non-external two byte string.
-  StringWriteTo(writer, object_id, kind, kTwoByteStringCid,
-                writer->GetObjectTags(this), length(), external_data_);
-}
-
-ArrayPtr Array::ReadFrom(SnapshotReader* reader,
-                         intptr_t object_id,
-                         intptr_t tags,
-                         Snapshot::Kind kind,
-                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Read the length so that we can determine instance size to allocate.
-  intptr_t len = reader->ReadSmiValue();
-  Array* array = NULL;
-  DeserializeState state;
-  if (!as_reference) {
-    array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
-    state = kIsDeserialized;
-  } else {
-    state = kIsNotDeserialized;
-  }
-  if (array == NULL) {
-    array = &(Array::ZoneHandle(reader->zone(), Array::New(len)));
-    reader->AddBackRef(object_id, array, state);
-  }
-  if (!as_reference) {
-    // Read all the individual elements for inlined objects.
-    ASSERT(!UntaggedObject::IsCanonical(tags));
-    reader->ArrayReadFrom(object_id, *array, len, tags);
-  }
-  return array->ptr();
-}
-
-ImmutableArrayPtr ImmutableArray::ReadFrom(SnapshotReader* reader,
-                                           intptr_t object_id,
-                                           intptr_t tags,
-                                           Snapshot::Kind kind,
-                                           bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Read the length so that we can determine instance size to allocate.
-  intptr_t len = reader->ReadSmiValue();
-  Array* array = NULL;
-  DeserializeState state;
-  if (!as_reference) {
-    array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
-    state = kIsDeserialized;
-  } else {
-    state = kIsNotDeserialized;
-  }
-  if (array == NULL) {
-    array = &(Array::ZoneHandle(reader->zone(), ImmutableArray::New(len)));
-    reader->AddBackRef(object_id, array, state);
-  }
-  if (!as_reference) {
-    // Read all the individual elements for inlined objects.
-    reader->ArrayReadFrom(object_id, *array, len, tags);
-    if (UntaggedObject::IsCanonical(tags)) {
-      *array ^= array->Canonicalize(reader->thread());
-    }
-  }
-  return raw(*array);
-}
-
-void UntaggedArray::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
-  ASSERT(!this->IsCanonical());
-  writer->ArrayWriteTo(object_id, kArrayCid, writer->GetObjectTags(this),
-                       length(), type_arguments(), data(), as_reference);
-}
-
-void UntaggedImmutableArray::WriteTo(SnapshotWriter* writer,
-                                     intptr_t object_id,
-                                     Snapshot::Kind kind,
-                                     bool as_reference) {
-  writer->ArrayWriteTo(object_id, kImmutableArrayCid,
-                       writer->GetObjectTags(this), length(), type_arguments(),
-                       data(), as_reference);
-}
-
-GrowableObjectArrayPtr GrowableObjectArray::ReadFrom(SnapshotReader* reader,
-                                                     intptr_t object_id,
-                                                     intptr_t tags,
-                                                     Snapshot::Kind kind,
-                                                     bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Read the length so that we can determine instance size to allocate.
-  GrowableObjectArray& array = GrowableObjectArray::ZoneHandle(
-      reader->zone(), GrowableObjectArray::null());
-  array = GrowableObjectArray::New(0);
-  reader->AddBackRef(object_id, &array, kIsDeserialized);
-
-  // Read type arguments of growable array object.
-  *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-  array.StoreCompressedPointer(&array.untag()->type_arguments_,
-                               reader->TypeArgumentsHandle()->ptr());
-
-  // Read length of growable array object.
-  array.SetLength(reader->ReadSmiValue());
-
-  // Read the backing array of growable array object.
-  *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference);
-  array.SetData(*(reader->ArrayHandle()));
-
-  return array.ptr();
-}
-
-void UntaggedGrowableObjectArray::WriteTo(SnapshotWriter* writer,
-                                          intptr_t object_id,
-                                          Snapshot::Kind kind,
-                                          bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kGrowableObjectArrayCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the type arguments field.
-  writer->WriteObjectImpl(type_arguments(), kAsInlinedObject);
-
-  // Write out the used length field.
-  writer->Write<ObjectPtr>(length());
-
-  // Write out the Array object.
-  writer->WriteObjectImpl(data(), kAsReference);
-}
-
-LinkedHashMapPtr LinkedHashMap::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  LinkedHashMap& map =
-      LinkedHashMap::ZoneHandle(reader->zone(), LinkedHashMap::null());
-  // Since the map might contain itself as a key or value, allocate first.
-  map = LinkedHashMap::NewUninitialized();
-  reader->AddBackRef(object_id, &map, kIsDeserialized);
-
-  reader->MapReadFrom(object_id, map, tags);
-
-  return map.ptr();
-}
-
-void UntaggedLinkedHashMap::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  ASSERT(writer != NULL);
-  ASSERT(!this->IsCanonical());
-  writer->MapWriteTo(object_id, kLinkedHashMapCid, writer->GetObjectTags(this),
-                     type_arguments(), used_data(), deleted_keys(), data(),
-                     as_reference);
-}
-
-LinkedHashSetPtr LinkedHashSet::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  ASSERT(reader != NULL);
-
-  LinkedHashSet& set =
-      LinkedHashSet::ZoneHandle(reader->zone(), LinkedHashSet::null());
-  // Since the set might contain itself as a key or value, allocate first.
-  set = LinkedHashSet::NewUninitialized();
-  reader->AddBackRef(object_id, &set, kIsDeserialized);
-
-  reader->SetReadFrom(object_id, set, tags);
-
-  return set.ptr();
-}
-
-void UntaggedLinkedHashSet::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  ASSERT(writer != NULL);
-  ASSERT(!this->IsCanonical());
-  writer->SetWriteTo(object_id, kLinkedHashSetCid, writer->GetObjectTags(this),
-                     type_arguments(), used_data(), deleted_keys(), data(),
-                     as_reference);
-}
-
-Float32x4Ptr Float32x4::ReadFrom(SnapshotReader* reader,
-                                 intptr_t object_id,
-                                 intptr_t tags,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  ASSERT(reader != NULL);
-  // Read the values.
-  float value0 = reader->Read<float>();
-  float value1 = reader->Read<float>();
-  float value2 = reader->Read<float>();
-  float value3 = reader->Read<float>();
-
-  // Create a Float32x4 object.
-  Float32x4& simd = Float32x4::ZoneHandle(reader->zone(), Float32x4::null());
-  simd = Float32x4::New(value0, value1, value2, value3);
-  reader->AddBackRef(object_id, &simd, kIsDeserialized);
-  return simd.ptr();
-}
-
-void UntaggedFloat32x4::WriteTo(SnapshotWriter* writer,
-                                intptr_t object_id,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kFloat32x4Cid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the float values.
-  writer->Write<float>(value_[0]);
-  writer->Write<float>(value_[1]);
-  writer->Write<float>(value_[2]);
-  writer->Write<float>(value_[3]);
-}
-
-Int32x4Ptr Int32x4::ReadFrom(SnapshotReader* reader,
-                             intptr_t object_id,
-                             intptr_t tags,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  ASSERT(reader != NULL);
-  // Read the values.
-  uint32_t value0 = reader->Read<uint32_t>();
-  uint32_t value1 = reader->Read<uint32_t>();
-  uint32_t value2 = reader->Read<uint32_t>();
-  uint32_t value3 = reader->Read<uint32_t>();
-
-  // Create a Float32x4 object.
-  Int32x4& simd = Int32x4::ZoneHandle(reader->zone(), Int32x4::null());
-  simd = Int32x4::New(value0, value1, value2, value3);
-  reader->AddBackRef(object_id, &simd, kIsDeserialized);
-  return simd.ptr();
-}
-
-void UntaggedInt32x4::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kInt32x4Cid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the mask values.
-  writer->Write<uint32_t>(value_[0]);
-  writer->Write<uint32_t>(value_[1]);
-  writer->Write<uint32_t>(value_[2]);
-  writer->Write<uint32_t>(value_[3]);
-}
-
-Float64x2Ptr Float64x2::ReadFrom(SnapshotReader* reader,
-                                 intptr_t object_id,
-                                 intptr_t tags,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  ASSERT(reader != NULL);
-  // Read the values.
-  double value0 = reader->Read<double>();
-  double value1 = reader->Read<double>();
-
-  // Create a Float64x2 object.
-  Float64x2& simd = Float64x2::ZoneHandle(reader->zone(), Float64x2::null());
-  simd = Float64x2::New(value0, value1);
-  reader->AddBackRef(object_id, &simd, kIsDeserialized);
-  return simd.ptr();
-}
-
-void UntaggedFloat64x2::WriteTo(SnapshotWriter* writer,
-                                intptr_t object_id,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kFloat64x2Cid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out the float values.
-  writer->Write<double>(value_[0]);
-  writer->Write<double>(value_[1]);
-}
-
-TypedDataPtr TypedData::ReadFrom(SnapshotReader* reader,
-                                 intptr_t object_id,
-                                 intptr_t tags,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  ASSERT(reader != NULL);
-
-  intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
-  intptr_t len = reader->ReadSmiValue();
-  TypedData& result =
-      TypedData::ZoneHandle(reader->zone(), TypedData::New(cid, len));
-  reader->AddBackRef(object_id, &result, kIsDeserialized);
-
-  // Setup the array elements.
-  intptr_t element_size = ElementSizeInBytes(cid);
-  intptr_t length_in_bytes = len * element_size;
-  NoSafepointScope no_safepoint;
-  uint8_t* data = reinterpret_cast<uint8_t*>(result.DataAddr(0));
-  reader->Align(Zone::kAlignment);
-  reader->ReadBytes(data, length_in_bytes);
-
-  // If it is a canonical constant make it one.
-  // When reading a full snapshot we don't need to canonicalize the object
-  // as it would already be a canonical object.
-  // When reading a script snapshot or a message snapshot we always have
-  // to canonicalize the object.
-  if (UntaggedObject::IsCanonical(tags)) {
-    result ^= result.Canonicalize(reader->thread());
-    ASSERT(!result.IsNull());
-    ASSERT(result.IsCanonical());
-  }
-  return result.ptr();
-}
-
-ExternalTypedDataPtr ExternalTypedData::ReadFrom(SnapshotReader* reader,
-                                                 intptr_t object_id,
-                                                 intptr_t tags,
-                                                 Snapshot::Kind kind,
-                                                 bool as_reference) {
-  ASSERT(!Snapshot::IsFull(kind));
-  intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
-  intptr_t length = reader->ReadSmiValue();
-
-  FinalizableData finalizable_data =
-      static_cast<MessageSnapshotReader*>(reader)->finalizable_data()->Take();
-  uint8_t* data = reinterpret_cast<uint8_t*>(finalizable_data.data);
-  ExternalTypedData& obj =
-      ExternalTypedData::ZoneHandle(ExternalTypedData::New(cid, data, length));
-  reader->AddBackRef(object_id, &obj, kIsDeserialized);
-  intptr_t external_size = obj.LengthInBytes();
-  obj.AddFinalizer(finalizable_data.peer, finalizable_data.callback,
-                   external_size);
-  return obj.ptr();
-}
-
-// This function's name can appear in Observatory.
-static void IsolateMessageTypedDataFinalizer(void* isolate_callback_data,
-                                             void* buffer) {
-  free(buffer);
-}
-
-void UntaggedTypedData::WriteTo(SnapshotWriter* writer,
-                                intptr_t object_id,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
-  ASSERT(writer != NULL);
-  intptr_t cid = this->GetClassId();
-  intptr_t length = Smi::Value(this->length());  // In elements.
-  intptr_t external_cid;
-  intptr_t bytes;
-  switch (cid) {
-    case kTypedDataInt8ArrayCid:
-      external_cid = kExternalTypedDataInt8ArrayCid;
-      bytes = length * sizeof(int8_t);
-      break;
-    case kTypedDataUint8ArrayCid:
-      external_cid = kExternalTypedDataUint8ArrayCid;
-      bytes = length * sizeof(uint8_t);
-      break;
-    case kTypedDataUint8ClampedArrayCid:
-      external_cid = kExternalTypedDataUint8ClampedArrayCid;
-      bytes = length * sizeof(uint8_t);
-      break;
-    case kTypedDataInt16ArrayCid:
-      external_cid = kExternalTypedDataInt16ArrayCid;
-      bytes = length * sizeof(int16_t);
-      break;
-    case kTypedDataUint16ArrayCid:
-      external_cid = kExternalTypedDataUint16ArrayCid;
-      bytes = length * sizeof(uint16_t);
-      break;
-    case kTypedDataInt32ArrayCid:
-      external_cid = kExternalTypedDataInt32ArrayCid;
-      bytes = length * sizeof(int32_t);
-      break;
-    case kTypedDataUint32ArrayCid:
-      external_cid = kExternalTypedDataUint32ArrayCid;
-      bytes = length * sizeof(uint32_t);
-      break;
-    case kTypedDataInt64ArrayCid:
-      external_cid = kExternalTypedDataInt64ArrayCid;
-      bytes = length * sizeof(int64_t);
-      break;
-    case kTypedDataUint64ArrayCid:
-      external_cid = kExternalTypedDataUint64ArrayCid;
-      bytes = length * sizeof(uint64_t);
-      break;
-    case kTypedDataFloat32ArrayCid:
-      external_cid = kExternalTypedDataFloat32ArrayCid;
-      bytes = length * sizeof(float);
-      break;
-    case kTypedDataFloat64ArrayCid:
-      external_cid = kExternalTypedDataFloat64ArrayCid;
-      bytes = length * sizeof(double);
-      break;
-    case kTypedDataInt32x4ArrayCid:
-      external_cid = kExternalTypedDataInt32x4ArrayCid;
-      bytes = length * sizeof(int32_t) * 4;
-      break;
-    case kTypedDataFloat32x4ArrayCid:
-      external_cid = kExternalTypedDataFloat32x4ArrayCid;
-      bytes = length * sizeof(float) * 4;
-      break;
-    case kTypedDataFloat64x2ArrayCid:
-      external_cid = kExternalTypedDataFloat64x2ArrayCid;
-      bytes = length * sizeof(double) * 2;
-      break;
-    default:
-      external_cid = kIllegalCid;
-      bytes = 0;
-      UNREACHABLE();
-  }
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  if ((kind == Snapshot::kMessage) &&
-      (static_cast<uint64_t>(bytes) >= FLAG_externalize_typed_data_threshold)) {
-    // Write as external.
-    writer->WriteIndexedObject(external_cid);
-    writer->WriteTags(writer->GetObjectTags(this));
-    writer->Write<ObjectPtr>(this->length());
-    uint8_t* data = reinterpret_cast<uint8_t*>(this->data());
-    void* passed_data = malloc(bytes);
-    memmove(passed_data, data, bytes);
-    static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
-        bytes,
-        passed_data,  // data
-        passed_data,  // peer,
-        IsolateMessageTypedDataFinalizer);
-  } else {
-    // Write as internal.
-    writer->WriteIndexedObject(cid);
-    writer->WriteTags(writer->GetObjectTags(this));
-    writer->Write<ObjectPtr>(this->length());
-    uint8_t* data = reinterpret_cast<uint8_t*>(this->data());
-    writer->Align(Zone::kAlignment);
-    writer->WriteBytes(data, bytes);
-  }
-}
-
-void UntaggedExternalTypedData::WriteTo(SnapshotWriter* writer,
-                                        intptr_t object_id,
-                                        Snapshot::Kind kind,
-                                        bool as_reference) {
-  ASSERT(writer != NULL);
-  intptr_t cid = this->GetClassId();
-  intptr_t length = Smi::Value(this->length());  // In elements.
-  intptr_t bytes;
-  switch (cid) {
-    case kExternalTypedDataInt8ArrayCid:
-      bytes = length * sizeof(int8_t);
-      break;
-    case kExternalTypedDataUint8ArrayCid:
-      bytes = length * sizeof(uint8_t);
-      break;
-    case kExternalTypedDataUint8ClampedArrayCid:
-      bytes = length * sizeof(uint8_t);
-      break;
-    case kExternalTypedDataInt16ArrayCid:
-      bytes = length * sizeof(int16_t);
-      break;
-    case kExternalTypedDataUint16ArrayCid:
-      bytes = length * sizeof(uint16_t);
-      break;
-    case kExternalTypedDataInt32ArrayCid:
-      bytes = length * sizeof(int32_t);
-      break;
-    case kExternalTypedDataUint32ArrayCid:
-      bytes = length * sizeof(uint32_t);
-      break;
-    case kExternalTypedDataInt64ArrayCid:
-      bytes = length * sizeof(int64_t);
-      break;
-    case kExternalTypedDataUint64ArrayCid:
-      bytes = length * sizeof(uint64_t);
-      break;
-    case kExternalTypedDataFloat32ArrayCid:
-      bytes = length * sizeof(float);  // NOLINT.
-      break;
-    case kExternalTypedDataFloat64ArrayCid:
-      bytes = length * sizeof(double);  // NOLINT.
-      break;
-    case kExternalTypedDataInt32x4ArrayCid:
-      bytes = length * sizeof(int32_t) * 4;
-      break;
-    case kExternalTypedDataFloat32x4ArrayCid:
-      bytes = length * sizeof(float) * 4;
-      break;
-    case kExternalTypedDataFloat64x2ArrayCid:
-      bytes = length * sizeof(double) * 2;
-      break;
-    default:
-      bytes = 0;
-      UNREACHABLE();
-  }
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write as external.
-  writer->WriteIndexedObject(cid);
-  writer->WriteTags(writer->GetObjectTags(this));
-  writer->Write<ObjectPtr>(this->length());
-  uint8_t* data = reinterpret_cast<uint8_t*>(data_);
-  void* passed_data = malloc(bytes);
-  memmove(passed_data, data, bytes);
-  static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
-      bytes,
-      passed_data,  // data
-      passed_data,  // peer,
-      IsolateMessageTypedDataFinalizer);
-}
-
-void UntaggedTypedDataView::WriteTo(SnapshotWriter* writer,
-                                    intptr_t object_id,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  // Views have always a backing store.
-  ASSERT(typed_data() != Object::null());
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(GetClassId());
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write members.
-  writer->Write<ObjectPtr>(offset_in_bytes());
-  writer->Write<ObjectPtr>(length());
-  writer->WriteObjectImpl(typed_data(), as_reference);
-}
-
-TypedDataViewPtr TypedDataView::ReadFrom(SnapshotReader* reader,
-                                         intptr_t object_id,
-                                         intptr_t tags,
-                                         Snapshot::Kind kind,
-                                         bool as_reference) {
-  auto& typed_data = *reader->TypedDataBaseHandle();
-  const classid_t cid = UntaggedObject::ClassIdTag::decode(tags);
-
-  auto& view = *reader->TypedDataViewHandle();
-  view = TypedDataView::New(cid);
-  reader->AddBackRef(object_id, &view, kIsDeserialized);
-
-  const intptr_t offset_in_bytes = reader->ReadSmiValue();
-  const intptr_t length = reader->ReadSmiValue();
-  typed_data ^= reader->ReadObjectImpl(as_reference);
-  view.InitializeWith(typed_data, offset_in_bytes, length);
-
-  return view.ptr();
-}
-
-CapabilityPtr Capability::ReadFrom(SnapshotReader* reader,
-                                   intptr_t object_id,
-                                   intptr_t tags,
-                                   Snapshot::Kind kind,
-                                   bool as_reference) {
-  uint64_t id = reader->Read<uint64_t>();
-
-  Capability& result =
-      Capability::ZoneHandle(reader->zone(), Capability::New(id));
-  reader->AddBackRef(object_id, &result, kIsDeserialized);
-  return result.ptr();
-}
-
-void UntaggedCapability::WriteTo(SnapshotWriter* writer,
-                                 intptr_t object_id,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kCapabilityCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  writer->Write<uint64_t>(id_);
-}
-
-SendPortPtr SendPort::ReadFrom(SnapshotReader* reader,
-                               intptr_t object_id,
-                               intptr_t tags,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  ASSERT(kind == Snapshot::kMessage);
-
-  uint64_t id = reader->Read<uint64_t>();
-  uint64_t origin_id = reader->Read<uint64_t>();
-
-  SendPort& result =
-      SendPort::ZoneHandle(reader->zone(), SendPort::New(id, origin_id));
-  reader->AddBackRef(object_id, &result, kIsDeserialized);
-  return result.ptr();
-}
-
-void UntaggedSendPort::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kSendPortCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  writer->Write<uint64_t>(id_);
-  writer->Write<uint64_t>(origin_id_);
-}
-
-TransferableTypedDataPtr TransferableTypedData::ReadFrom(SnapshotReader* reader,
-                                                         intptr_t object_id,
-                                                         intptr_t tags,
-                                                         Snapshot::Kind kind,
-                                                         bool as_reference) {
-  ASSERT(reader != nullptr);
-
-  ASSERT(!Snapshot::IsFull(kind));
-  const intptr_t length = reader->Read<int64_t>();
-
-  const FinalizableData finalizable_data =
-      static_cast<MessageSnapshotReader*>(reader)->finalizable_data()->Take();
-  uint8_t* data = reinterpret_cast<uint8_t*>(finalizable_data.data);
-  auto& transferableTypedData = TransferableTypedData::ZoneHandle(
-      reader->zone(), TransferableTypedData::New(data, length));
-  reader->AddBackRef(object_id, &transferableTypedData, kIsDeserialized);
-  return transferableTypedData.ptr();
-}
-
-void UntaggedTransferableTypedData::WriteTo(SnapshotWriter* writer,
-                                            intptr_t object_id,
-                                            Snapshot::Kind kind,
-                                            bool as_reference) {
-  ASSERT(writer != nullptr);
-  ASSERT(GetClassId() == kTransferableTypedDataCid);
-  void* peer = writer->thread()->heap()->GetPeer(ObjectPtr(this));
-  // Assume that object's Peer is only used to track transferrability state.
-  ASSERT(peer != nullptr);
-  TransferableTypedDataPeer* tpeer =
-      reinterpret_cast<TransferableTypedDataPeer*>(peer);
-  intptr_t length = tpeer->length();  // In bytes.
-  void* data = tpeer->data();
-  if (data == nullptr) {
-    writer->SetWriteException(
-        Exceptions::kArgument,
-        "Illegal argument in isolate message"
-        " : (TransferableTypedData has been transferred already)");
-    return;
-  }
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  writer->WriteIndexedObject(GetClassId());
-  writer->WriteTags(writer->GetObjectTags(this));
-  writer->Write<int64_t>(length);
-
-  static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
-      length, data, tpeer,
-      // Finalizer does nothing - in case of failure to serialize,
-      // [data] remains wrapped in sender's [TransferableTypedData].
-      [](void* data, void* peer) {},
-      // This is invoked on successful serialization of the message
-      [](void* data, void* peer) {
-        TransferableTypedDataPeer* tpeer =
-            reinterpret_cast<TransferableTypedDataPeer*>(peer);
-        tpeer->handle()->EnsureFreedExternal(IsolateGroup::Current());
-        tpeer->ClearData();
-      });
-}
-
-RegExpPtr RegExp::ReadFrom(SnapshotReader* reader,
-                           intptr_t object_id,
-                           intptr_t tags,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
-  ASSERT(reader != NULL);
-  // Allocate RegExp object.
-  RegExp& regex =
-      RegExp::ZoneHandle(reader->zone(), RegExp::New(reader->zone()));
-  reader->AddBackRef(object_id, &regex, kIsDeserialized);
-
-  // Read and Set all the other fields.
-  *reader->ArrayHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-  regex.set_capture_name_map(*reader->ArrayHandle());
-  *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-  regex.set_pattern(*reader->StringHandle());
-
-  regex.StoreNonPointer(&regex.untag()->num_bracket_expressions_,
-                        reader->Read<int32_t>());
-  regex.StoreNonPointer(&regex.untag()->num_one_byte_registers_,
-                        reader->Read<int32_t>());
-  regex.StoreNonPointer(&regex.untag()->num_two_byte_registers_,
-                        reader->Read<int32_t>());
-  regex.StoreNonPointer(&regex.untag()->type_flags_, reader->Read<int8_t>());
-  return regex.ptr();
-}
-
-void UntaggedRegExp::WriteTo(SnapshotWriter* writer,
-                             intptr_t object_id,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kRegExpCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the other fields.
-  writer->WriteObjectImpl(capture_name_map(), kAsInlinedObject);
-  writer->WriteObjectImpl(pattern(), kAsInlinedObject);
-  writer->Write<int32_t>(num_bracket_expressions_);
-  writer->Write<int32_t>(num_one_byte_registers_);
-  writer->Write<int32_t>(num_two_byte_registers_);
-  writer->Write<int8_t>(type_flags_);
-}
-
-WeakPropertyPtr WeakProperty::ReadFrom(SnapshotReader* reader,
-                                       intptr_t object_id,
-                                       intptr_t tags,
-                                       Snapshot::Kind kind,
-                                       bool as_reference) {
-  ASSERT(reader != NULL);
-
-  // Allocate the weak property object.
-  WeakProperty& weak_property =
-      WeakProperty::ZoneHandle(reader->zone(), WeakProperty::New());
-  reader->AddBackRef(object_id, &weak_property, kIsDeserialized);
-
-  // Set all the object fields.
-  READ_COMPRESSED_OBJECT_FIELDS(
-      weak_property, weak_property.ptr()->untag()->from(),
-      weak_property.ptr()->untag()->to(), kAsReference);
-
-  return weak_property.ptr();
-}
-
-void UntaggedWeakProperty::WriteTo(SnapshotWriter* writer,
-                                   intptr_t object_id,
-                                   Snapshot::Kind kind,
-                                   bool as_reference) {
-  ASSERT(writer != NULL);
-
-  // Write out the serialization header value for this object.
-  writer->WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  writer->WriteIndexedObject(kWeakPropertyCid);
-  writer->WriteTags(writer->GetObjectTags(this));
-
-  // Write out all the object pointer fields.
-  SnapshotWriterVisitor visitor(writer, kAsReference);
-  visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-}  // namespace dart
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 2decacb..b9552b5 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -30,6 +30,7 @@
 #include "vm/malloc_hooks.h"
 #include "vm/message.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/native_arguments.h"
 #include "vm/native_entry.h"
 #include "vm/native_symbol.h"
@@ -1018,9 +1019,9 @@
     message.value.as_array.length = 2;
     message.value.as_array.values = elements;
 
-    ApiMessageWriter writer;
-    std::unique_ptr<Message> msg = writer.WriteCMessage(
-        &message, ServiceIsolate::Port(), Message::kNormalPriority);
+    std::unique_ptr<Message> msg =
+        WriteApiMessage(thread->zone(), &message, ServiceIsolate::Port(),
+                        Message::kNormalPriority);
     if (msg == nullptr) {
       result = false;
     } else {
@@ -1188,9 +1189,10 @@
   json_cobj.value.as_string = const_cast<char*>(event->ToCString());
   list_values[1] = &json_cobj;
 
-  ApiMessageWriter writer;
-  std::unique_ptr<Message> msg = writer.WriteCMessage(
-      &list_cobj, ServiceIsolate::Port(), Message::kNormalPriority);
+  AllocOnlyStackZone zone;
+  std::unique_ptr<Message> msg =
+      WriteApiMessage(zone.GetZone(), &list_cobj, ServiceIsolate::Port(),
+                      Message::kNormalPriority);
   if (msg != nullptr) {
     PortMap::PostMessage(std::move(msg));
   }
@@ -2017,8 +2019,7 @@
   if (message->IsRaw()) {
     return message->raw_obj();
   } else {
-    MessageSnapshotReader reader(message, thread);
-    return reader.ReadObject();
+    return ReadMessage(thread, message);
   }
 }
 
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index c243b02b..d840e7b 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -12,6 +12,7 @@
 #include "vm/lockers.h"
 #include "vm/message.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/native_arguments.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
@@ -91,9 +92,8 @@
       sp, VM_SERVICE_SERVER_INFO_MESSAGE_ID, false /* ignored */,
       Bool::Handle() /* ignored */));
   ASSERT(!message.IsNull());
-  MessageWriter writer(false);
-  PortMap::PostMessage(
-      writer.WriteMessage(message, port_, Message::kNormalPriority));
+  PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, message,
+                                    port_, Message::kNormalPriority));
 }
 
 void ServiceIsolate::ControlWebServer(const SendPort& sp,
@@ -102,9 +102,8 @@
   const Array& message = Array::Handle(MakeServerControlMessage(
       sp, VM_SERVICE_WEB_SERVER_CONTROL_MESSAGE_ID, enable, silenceOutput));
   ASSERT(!message.IsNull());
-  MessageWriter writer(false);
-  PortMap::PostMessage(
-      writer.WriteMessage(message, port_, Message::kNormalPriority));
+  PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, message,
+                                    port_, Message::kNormalPriority));
 }
 
 void ServiceIsolate::SetServerAddress(const char* address) {
@@ -223,14 +222,13 @@
   const Array& list = Array::Handle(MakeServiceControlMessage(
       Dart_GetMainPortId(), VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID, name));
   ASSERT(!list.IsNull());
-  MessageWriter writer(false);
   if (FLAG_trace_service) {
     OS::PrintErr(DART_VM_SERVICE_ISOLATE_NAME ": Isolate %s %" Pd64
                                               " registered.\n",
                  name.ToCString(), Dart_GetMainPortId());
   }
-  return PortMap::PostMessage(
-      writer.WriteMessage(list, port_, Message::kNormalPriority));
+  return PortMap::PostMessage(WriteMessage(
+      /* can_send_any_object */ false, list, port_, Message::kNormalPriority));
 }
 
 bool ServiceIsolate::SendIsolateShutdownMessage() {
@@ -249,14 +247,13 @@
   const Array& list = Array::Handle(MakeServiceControlMessage(
       Dart_GetMainPortId(), VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID, name));
   ASSERT(!list.IsNull());
-  MessageWriter writer(false);
   if (FLAG_trace_service) {
     OS::PrintErr(DART_VM_SERVICE_ISOLATE_NAME ": Isolate %s %" Pd64
                                               " deregistered.\n",
                  name.ToCString(), Dart_GetMainPortId());
   }
-  return PortMap::PostMessage(
-      writer.WriteMessage(list, port_, Message::kNormalPriority));
+  return PortMap::PostMessage(WriteMessage(
+      /* can_send_any_object */ false, list, port_, Message::kNormalPriority));
 }
 
 void ServiceIsolate::SendServiceExitMessage() {
@@ -278,9 +275,9 @@
   message.value.as_array.length = 1;
   message.value.as_array.values = values;
 
-  ApiMessageWriter writer;
-  PortMap::PostMessage(
-      writer.WriteCMessage(&message, port_, Message::kNormalPriority));
+  AllocOnlyStackZone zone;
+  PortMap::PostMessage(WriteApiMessage(zone.GetZone(), &message, port_,
+                                       Message::kNormalPriority));
 }
 
 void ServiceIsolate::SetServicePort(Dart_Port port) {
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 7dec0a8..2800565 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -14,6 +14,7 @@
 #include "vm/globals.h"
 #include "vm/heap/safepoint.h"
 #include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
 #include "vm/object_id_ring.h"
 #include "vm/os.h"
 #include "vm/port.h"
@@ -50,8 +51,7 @@
       response_obj = message->raw_obj();
     } else {
       Thread* thread = Thread::Current();
-      MessageSnapshotReader reader(message.get(), thread);
-      response_obj = reader.ReadObject();
+      response_obj = ReadMessage(thread, message.get());
     }
     if (response_obj.IsString()) {
       String& response = String::Handle();
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index ca45f4d..f9b3cdc 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -5,229 +5,10 @@
 #include "vm/snapshot.h"
 
 #include "platform/assert.h"
-#include "vm/bootstrap.h"
-#include "vm/class_finalizer.h"
 #include "vm/dart.h"
-#include "vm/exceptions.h"
-#include "vm/heap/heap.h"
-#include "vm/longjump.h"
-#include "vm/message.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/snapshot_ids.h"
-#include "vm/stub_code.h"
-#include "vm/symbols.h"
-#include "vm/timeline.h"
-#include "vm/type_testing_stubs.h"
-#include "vm/version.h"
-
-// We currently only expect the Dart mutator to read snapshots.
-#define ASSERT_NO_SAFEPOINT_SCOPE()                                            \
-  isolate()->AssertCurrentThreadIsMutator();                                   \
-  ASSERT(thread()->no_safepoint_scope_depth() != 0)
 
 namespace dart {
 
-static const int kNumInitialReferences = 32;
-
-static bool IsSingletonClassId(intptr_t class_id) {
-  // Check if this is a singleton object class which is shared by all isolates.
-  return ((class_id >= kClassCid && class_id <= kUnwindErrorCid) ||
-          (class_id == kTypeArgumentsCid) ||
-          (class_id >= kNullCid && class_id <= kVoidCid));
-}
-
-static bool IsBootstrapedClassId(intptr_t class_id) {
-  // Check if this is a class which is created during bootstrapping.
-  return (class_id == kObjectCid ||
-          (class_id >= kInstanceCid && class_id <= kUserTagCid) ||
-          class_id == kArrayCid || class_id == kImmutableArrayCid ||
-          class_id == kLinkedHashMapCid || class_id == kLinkedHashSetCid ||
-          IsStringClassId(class_id) || IsTypedDataClassId(class_id) ||
-          IsExternalTypedDataClassId(class_id) ||
-          IsTypedDataViewClassId(class_id) || class_id == kNullCid ||
-          class_id == kNeverCid || class_id == kTransferableTypedDataCid);
-}
-
-static bool IsObjectStoreTypeId(intptr_t index) {
-  // Check if this is a type which is stored in the object store.
-  static_assert(kFirstTypeArgumentsSnapshotId == kLastTypeSnapshotId + 1,
-                "Type and type arguments snapshot ids should be adjacent");
-  return index >= kFirstTypeSnapshotId && index <= kLastTypeArgumentsSnapshotId;
-}
-
-static bool IsSplitClassId(intptr_t class_id) {
-  // Return whether this class is serialized in two steps: first a reference,
-  // with sufficient information to allocate a correctly sized object, and then
-  // later inline with complete contents.
-  return class_id >= kNumPredefinedCids || class_id == kArrayCid ||
-         class_id == kImmutableArrayCid || class_id == kObjectPoolCid ||
-         IsImplicitFieldClassId(class_id);
-}
-
-static intptr_t ClassIdFromObjectId(intptr_t object_id) {
-  ASSERT(object_id > kClassIdsOffset);
-  intptr_t class_id = (object_id - kClassIdsOffset);
-  return class_id;
-}
-
-static intptr_t ObjectIdFromClassId(intptr_t class_id) {
-  ASSERT((class_id > kIllegalCid) && (class_id < kNumPredefinedCids));
-  return (class_id + kClassIdsOffset);
-}
-
-static ObjectPtr GetType(ObjectStore* object_store, intptr_t index) {
-  switch (index) {
-    case kLegacyObjectType:
-      return object_store->legacy_object_type();
-    case kNullableObjectType:
-      return object_store->nullable_object_type();
-    case kNullType:
-      return object_store->null_type();
-    case kNeverType:
-      return object_store->never_type();
-    case kLegacyFunctionType:
-      return object_store->legacy_function_type();
-    case kLegacyNumberType:
-      return object_store->legacy_number_type();
-    case kLegacySmiType:
-      return object_store->legacy_smi_type();
-    case kLegacyMintType:
-      return object_store->legacy_mint_type();
-    case kLegacyDoubleType:
-      return object_store->legacy_double_type();
-    case kLegacyIntType:
-      return object_store->legacy_int_type();
-    case kLegacyBoolType:
-      return object_store->legacy_bool_type();
-    case kLegacyStringType:
-      return object_store->legacy_string_type();
-    case kLegacyArrayType:
-      return object_store->legacy_array_type();
-    case kLegacyIntTypeArguments:
-      return object_store->type_argument_legacy_int();
-    case kLegacyDoubleTypeArguments:
-      return object_store->type_argument_legacy_double();
-    case kLegacyStringTypeArguments:
-      return object_store->type_argument_legacy_string();
-    case kLegacyStringDynamicTypeArguments:
-      return object_store->type_argument_legacy_string_dynamic();
-    case kLegacyStringLegacyStringTypeArguments:
-      return object_store->type_argument_legacy_string_legacy_string();
-    case kNonNullableObjectType:
-      return object_store->non_nullable_object_type();
-    case kNonNullableFunctionType:
-      return object_store->non_nullable_function_type();
-    case kNonNullableNumberType:
-      return object_store->non_nullable_number_type();
-    case kNonNullableSmiType:
-      return object_store->non_nullable_smi_type();
-    case kNonNullableMintType:
-      return object_store->non_nullable_mint_type();
-    case kNonNullableDoubleType:
-      return object_store->non_nullable_double_type();
-    case kNonNullableIntType:
-      return object_store->non_nullable_int_type();
-    case kNonNullableBoolType:
-      return object_store->non_nullable_bool_type();
-    case kNonNullableStringType:
-      return object_store->non_nullable_string_type();
-    case kNonNullableArrayType:
-      return object_store->non_nullable_array_type();
-    case kNonNullableIntTypeArguments:
-      return object_store->type_argument_non_nullable_int();
-    case kNonNullableDoubleTypeArguments:
-      return object_store->type_argument_non_nullable_double();
-    case kNonNullableStringTypeArguments:
-      return object_store->type_argument_non_nullable_string();
-    case kNonNullableStringDynamicTypeArguments:
-      return object_store->type_argument_non_nullable_string_dynamic();
-    case kNonNullableStringNonNullableStringTypeArguments:
-      return object_store
-          ->type_argument_non_nullable_string_non_nullable_string();
-    default:
-      break;
-  }
-  UNREACHABLE();
-  return Type::null();
-}
-
-static intptr_t GetTypeIndex(ObjectStore* object_store,
-                             const ObjectPtr raw_type) {
-  if (raw_type == object_store->legacy_object_type()) {
-    return kLegacyObjectType;
-  } else if (raw_type == object_store->nullable_object_type()) {
-    return kNullableObjectType;
-  } else if (raw_type == object_store->null_type()) {
-    return kNullType;
-  } else if (raw_type == object_store->never_type()) {
-    return kNeverType;
-  } else if (raw_type == object_store->legacy_function_type()) {
-    return kLegacyFunctionType;
-  } else if (raw_type == object_store->legacy_number_type()) {
-    return kLegacyNumberType;
-  } else if (raw_type == object_store->legacy_smi_type()) {
-    return kLegacySmiType;
-  } else if (raw_type == object_store->legacy_mint_type()) {
-    return kLegacyMintType;
-  } else if (raw_type == object_store->legacy_double_type()) {
-    return kLegacyDoubleType;
-  } else if (raw_type == object_store->legacy_int_type()) {
-    return kLegacyIntType;
-  } else if (raw_type == object_store->legacy_bool_type()) {
-    return kLegacyBoolType;
-  } else if (raw_type == object_store->legacy_string_type()) {
-    return kLegacyStringType;
-  } else if (raw_type == object_store->legacy_array_type()) {
-    return kLegacyArrayType;
-  } else if (raw_type == object_store->type_argument_legacy_int()) {
-    return kLegacyIntTypeArguments;
-  } else if (raw_type == object_store->type_argument_legacy_double()) {
-    return kLegacyDoubleTypeArguments;
-  } else if (raw_type == object_store->type_argument_legacy_string()) {
-    return kLegacyStringTypeArguments;
-  } else if (raw_type == object_store->type_argument_legacy_string_dynamic()) {
-    return kLegacyStringDynamicTypeArguments;
-  } else if (raw_type ==
-             object_store->type_argument_legacy_string_legacy_string()) {
-    return kLegacyStringLegacyStringTypeArguments;
-  } else if (raw_type == object_store->non_nullable_object_type()) {
-    return kNonNullableObjectType;
-  } else if (raw_type == object_store->non_nullable_function_type()) {
-    return kNonNullableFunctionType;
-  } else if (raw_type == object_store->non_nullable_number_type()) {
-    return kNonNullableNumberType;
-  } else if (raw_type == object_store->non_nullable_smi_type()) {
-    return kNonNullableSmiType;
-  } else if (raw_type == object_store->non_nullable_mint_type()) {
-    return kNonNullableMintType;
-  } else if (raw_type == object_store->non_nullable_double_type()) {
-    return kNonNullableDoubleType;
-  } else if (raw_type == object_store->non_nullable_int_type()) {
-    return kNonNullableIntType;
-  } else if (raw_type == object_store->non_nullable_bool_type()) {
-    return kNonNullableBoolType;
-  } else if (raw_type == object_store->non_nullable_string_type()) {
-    return kNonNullableStringType;
-  } else if (raw_type == object_store->non_nullable_array_type()) {
-    return kNonNullableArrayType;
-  } else if (raw_type == object_store->type_argument_non_nullable_int()) {
-    return kNonNullableIntTypeArguments;
-  } else if (raw_type == object_store->type_argument_non_nullable_double()) {
-    return kNonNullableDoubleTypeArguments;
-  } else if (raw_type == object_store->type_argument_non_nullable_string()) {
-    return kNonNullableStringTypeArguments;
-  } else if (raw_type ==
-             object_store->type_argument_non_nullable_string_dynamic()) {
-    return kNonNullableStringDynamicTypeArguments;
-  } else if (raw_type ==
-             object_store
-                 ->type_argument_non_nullable_string_non_nullable_string()) {
-    return kNonNullableStringNonNullableStringTypeArguments;
-  }
-  return kInvalidIndex;
-}
-
 const char* Snapshot::KindToCString(Kind kind) {
   switch (kind) {
     case kFull:
@@ -238,8 +19,6 @@
       return "full-jit";
     case kFullAOT:
       return "full-aot";
-    case kMessage:
-      return "message";
     case kNone:
       return "none";
     case kInvalid:
@@ -263,97 +42,7 @@
   return snapshot;
 }
 
-SmiPtr BaseReader::ReadAsSmi() {
-  SmiPtr value = static_cast<SmiPtr>(Read<intptr_t>());
-  ASSERT((static_cast<uword>(value) & kSmiTagMask) == kSmiTag);
-  return value;
-}
-
-intptr_t BaseReader::ReadSmiValue() {
-  return Smi::Value(ReadAsSmi());
-}
-
-SnapshotReader::SnapshotReader(const uint8_t* buffer,
-                               intptr_t size,
-                               Snapshot::Kind kind,
-                               ZoneGrowableArray<BackRefNode>* backward_refs,
-                               Thread* thread)
-    : BaseReader(buffer, size),
-      kind_(kind),
-      thread_(thread),
-      zone_(thread->zone()),
-      heap_(isolate_group()->heap()),
-      old_space_(isolate_group()->heap()->old_space()),
-      cls_(Class::Handle(zone_)),
-      code_(Code::Handle(zone_)),
-      instance_(Instance::Handle(zone_)),
-      instructions_(Instructions::Handle(zone_)),
-      obj_(Object::Handle(zone_)),
-      pobj_(PassiveObject::Handle(zone_)),
-      array_(Array::Handle(zone_)),
-      field_(Field::Handle(zone_)),
-      str_(String::Handle(zone_)),
-      library_(Library::Handle(zone_)),
-      type_(AbstractType::Handle(zone_)),
-      type_arguments_(TypeArguments::Handle(zone_)),
-      tokens_(GrowableObjectArray::Handle(zone_)),
-      data_(ExternalTypedData::Handle(zone_)),
-      typed_data_base_(TypedDataBase::Handle(zone_)),
-      typed_data_(TypedData::Handle(zone_)),
-      typed_data_view_(TypedDataView::Handle(zone_)),
-      function_(Function::Handle(zone_)),
-      smi_(Smi::Handle(zone_)),
-      error_(UnhandledException::Handle(zone_)),
-      set_class_(Class::ZoneHandle(
-          zone_,
-          thread_->isolate_group()->object_store()->linked_hash_set_class())),
-      max_vm_isolate_object_id_(
-          (Snapshot::IsFull(kind))
-              ? Object::vm_isolate_snapshot_object_table().Length()
-              : 0),
-      backward_references_(backward_refs),
-      types_to_postprocess_(GrowableObjectArray::Handle(zone_)),
-      objects_to_rehash_(GrowableObjectArray::Handle(zone_)) {}
-
-ObjectPtr SnapshotReader::ReadObject() {
-  // Setup for long jump in case there is an exception while reading.
-  LongJumpScope jump;
-  if (setjmp(*jump.Set()) == 0) {
-    PassiveObject& obj =
-        PassiveObject::Handle(zone(), ReadObjectImpl(kAsInlinedObject));
-    for (intptr_t i = 0; i < backward_references_->length(); i++) {
-      if (!(*backward_references_)[i].is_deserialized()) {
-        ReadObjectImpl(kAsInlinedObject);
-        (*backward_references_)[i].set_state(kIsDeserialized);
-      }
-    }
-    Object& result = Object::Handle(zone_);
-    if (backward_references_->length() > 0) {
-      result = (*backward_references_)[0].reference()->ptr();
-    } else {
-      result = obj.ptr();
-    }
-    RunDelayedTypePostprocessing();
-    const Object& ok =
-        Object::Handle(zone_, RunDelayedRehashingOfMapsAndSets());
-    objects_to_rehash_ = GrowableObjectArray::null();
-    if (!ok.IsNull()) {
-      return ok.ptr();
-    }
-    return result.ptr();
-  } else {
-    // An error occurred while reading, return the error object.
-    return Thread::Current()->StealStickyError();
-  }
-}
-
-void SnapshotReader::EnqueueTypePostprocessing(const AbstractType& type) {
-  if (types_to_postprocess_.IsNull()) {
-    types_to_postprocess_ = GrowableObjectArray::New();
-  }
-  types_to_postprocess_.Add(type);
-}
-
+#if 0
 void SnapshotReader::RunDelayedTypePostprocessing() {
   if (types_to_postprocess_.IsNull()) {
     return;
@@ -367,1453 +56,6 @@
     type.InitializeTypeTestingStubNonAtomic(code);
   }
 }
-
-void SnapshotReader::EnqueueRehashingOfMap(const LinkedHashMap& map) {
-  ASSERT(!map.IsCanonical());
-  if (objects_to_rehash_.IsNull()) {
-    objects_to_rehash_ = GrowableObjectArray::New();
-  }
-  objects_to_rehash_.Add(map);
-}
-
-ObjectPtr SnapshotReader::RunDelayedRehashingOfMapsAndSets() {
-  if (!objects_to_rehash_.IsNull()) {
-    return DartLibraryCalls::RehashObjects(thread(), objects_to_rehash_);
-  }
-  return Object::null();
-}
-
-ClassPtr SnapshotReader::ReadClassId(intptr_t object_id) {
-  ASSERT(!Snapshot::IsFull(kind_));
-  // Read the class header information and lookup the class.
-  intptr_t class_header = Read<int32_t>();
-  ASSERT((class_header & kSmiTagMask) != kSmiTag);
-  ASSERT(!IsVMIsolateObject(class_header) ||
-         !IsSingletonClassId(GetVMIsolateObjectId(class_header)));
-  ASSERT((SerializedHeaderTag::decode(class_header) != kObjectId) ||
-         !IsBootstrapedClassId(SerializedHeaderData::decode(class_header)));
-  Class& cls = Class::ZoneHandle(zone(), Class::null());
-  AddBackRef(object_id, &cls, kIsDeserialized);
-  // Read the library/class information and lookup the class.
-  str_ ^= ReadObjectImpl(class_header, kAsInlinedObject);
-  library_ = Library::LookupLibrary(thread(), str_);
-  if (library_.IsNull() || !library_.Loaded()) {
-    SetReadException(
-        "Invalid object found in message: library is not found or loaded.");
-  }
-  str_ ^= ReadObjectImpl(kAsInlinedObject);
-  if (str_.ptr() == Symbols::TopLevel().ptr()) {
-    cls = library_.toplevel_class();
-  } else {
-    str_ = String::New(String::ScrubName(str_));
-    cls = library_.LookupClassAllowPrivate(str_);
-  }
-  if (cls.IsNull()) {
-    SetReadException("Invalid object found in message: class not found");
-  }
-  cls.EnsureIsFinalized(thread());
-  return cls.ptr();
-}
-
-ObjectPtr SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id,
-                                                    intptr_t class_header) {
-  ASSERT(!Snapshot::IsFull(kind_));
-
-  // First create a function object and associate it with the specified
-  // 'object_id'.
-  Function& func = Function::Handle(zone(), Function::null());
-  Instance& obj = Instance::ZoneHandle(zone(), Instance::null());
-  AddBackRef(object_id, &obj, kIsDeserialized);
-
-  // Read the library/class/function information and lookup the function.
-  // Note: WriteStaticImplicitClosure is *not* scrubbing the names before
-  // writing them into the snapshot, because scrubbing requires allocation.
-  // This means that names we read here might be mangled with private
-  // keys. These keys need to be scrubbed before performing lookups
-  // otherwise lookups might fail.
-  str_ ^= ReadObjectImpl(kAsInlinedObject);
-  library_ = Library::LookupLibrary(thread(), str_);
-  if (library_.IsNull() || !library_.Loaded()) {
-    SetReadException("Invalid Library object found in message.");
-  }
-  str_ ^= ReadObjectImpl(kAsInlinedObject);
-  if (str_.Equals(Symbols::TopLevel())) {
-    str_ ^= ReadObjectImpl(kAsInlinedObject);
-    str_ = String::New(String::ScrubName(str_));
-    func = library_.LookupFunctionAllowPrivate(str_);
-  } else {
-    str_ = String::New(String::ScrubName(str_));
-    cls_ = library_.LookupClassAllowPrivate(str_);
-    if (cls_.IsNull()) {
-      OS::PrintErr("Name of class not found %s\n", str_.ToCString());
-      SetReadException("Invalid Class object found in message.");
-    }
-    cls_.EnsureIsFinalized(thread());
-    str_ ^= ReadObjectImpl(kAsInlinedObject);
-    str_ = String::New(String::ScrubName(str_));
-    func = cls_.LookupFunctionAllowPrivate(str_);
-  }
-  if (func.IsNull()) {
-    SetReadException("Invalid function object found in message.");
-  }
-  TypeArguments& delayed_type_arguments = TypeArguments::Handle(zone());
-  delayed_type_arguments ^= ReadObjectImpl(kAsInlinedObject);
-
-  func = func.ImplicitClosureFunction();
-  ASSERT(!func.IsNull());
-
-  // If delayedtype arguments were provided, create and return new closure with
-  // those, otherwise return associated implicit static closure.
-  // Note that static closures can't have instantiator or function types since
-  // statics can't refer to class type arguments, don't have outer functions.
-  if (!delayed_type_arguments.IsNull()) {
-    const Context& context = Context::Handle(zone());
-    obj = Closure::New(
-        /*instantiator_type_arguments=*/Object::null_type_arguments(),
-        /*function_type_arguments=*/Object::null_type_arguments(),
-        delayed_type_arguments, func, context, Heap::kOld);
-  } else {
-    obj = func.ImplicitStaticClosure();
-  }
-  return obj.ptr();
-}
-
-intptr_t SnapshotReader::NextAvailableObjectId() const {
-  return backward_references_->length() + kMaxPredefinedObjectIds +
-         max_vm_isolate_object_id_;
-}
-
-void SnapshotReader::SetReadException(const char* msg) {
-  const String& error_str = String::Handle(zone(), String::New(msg));
-  const Array& args = Array::Handle(zone(), Array::New(1));
-  args.SetAt(0, error_str);
-  Object& result = Object::Handle(zone());
-  const Library& library = Library::Handle(zone(), Library::CoreLibrary());
-  result = DartLibraryCalls::InstanceCreate(library, Symbols::ArgumentError(),
-                                            Symbols::Dot(), args);
-  const StackTrace& stacktrace = StackTrace::Handle(zone());
-  const UnhandledException& error = UnhandledException::Handle(
-      zone(), UnhandledException::New(Instance::Cast(result), stacktrace));
-  thread()->long_jump_base()->Jump(1, error);
-}
-
-ObjectPtr SnapshotReader::VmIsolateSnapshotObject(intptr_t index) const {
-  return Object::vm_isolate_snapshot_object_table().At(index);
-}
-
-bool SnapshotReader::is_vm_isolate() const {
-  return isolate_group() == Dart::vm_isolate_group();
-}
-
-ObjectPtr SnapshotReader::ReadObjectImpl(bool as_reference) {
-  int64_t header_value = Read<int64_t>();
-  if ((header_value & kSmiTagMask) == kSmiTag) {
-    return NewInteger(header_value);
-  }
-  ASSERT((header_value <= kIntptrMax) && (header_value >= kIntptrMin));
-  return ReadObjectImpl(static_cast<intptr_t>(header_value), as_reference);
-}
-
-ObjectPtr SnapshotReader::ReadObjectImpl(intptr_t header_value,
-                                         bool as_reference) {
-  if (IsVMIsolateObject(header_value)) {
-    return ReadVMIsolateObject(header_value);
-  }
-  if (SerializedHeaderTag::decode(header_value) == kObjectId) {
-    return ReadIndexedObject(SerializedHeaderData::decode(header_value));
-  }
-  ASSERT(SerializedHeaderTag::decode(header_value) == kInlined);
-  intptr_t object_id = SerializedHeaderData::decode(header_value);
-  if (object_id == kOmittedObjectId) {
-    object_id = NextAvailableObjectId();
-  }
-
-  // Read the class header information.
-  intptr_t class_header = Read<int32_t>();
-  intptr_t tags = ReadTags();
-  bool read_as_reference = as_reference && !UntaggedObject::IsCanonical(tags);
-  intptr_t header_id = SerializedHeaderData::decode(class_header);
-  if (header_id == kInstanceObjectId) {
-    return ReadInstance(object_id, tags, read_as_reference);
-  } else if (header_id == kStaticImplicitClosureObjectId) {
-    // We skip the tags that have been written as the implicit static
-    // closure is going to be created in this isolate or the canonical
-    // version already created in the isolate will be used.
-    return ReadStaticImplicitClosure(object_id, class_header);
-  }
-  ASSERT((class_header & kSmiTagMask) != kSmiTag);
-
-  intptr_t class_id = LookupInternalClass(class_header);
-  switch (class_id) {
-#define SNAPSHOT_READ(clazz)                                                   \
-  case clazz::kClassId: {                                                      \
-    pobj_ = clazz::ReadFrom(this, object_id, tags, kind_, read_as_reference);  \
-    break;                                                                     \
-  }
-    CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kTypedData##clazz##Cid:
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-      tags = UntaggedObject::ClassIdTag::update(class_id, tags);
-      pobj_ =
-          TypedData::ReadFrom(this, object_id, tags, kind_, read_as_reference);
-      break;
-    }
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kExternalTypedData##clazz##Cid:
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-      tags = UntaggedObject::ClassIdTag::update(class_id, tags);
-      pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_, true);
-      break;
-    }
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kTypedData##clazz##ViewCid:
-
-    case kByteDataViewCid:
-      CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-        tags = UntaggedObject::ClassIdTag::update(class_id, tags);
-        pobj_ = TypedDataView::ReadFrom(this, object_id, tags, kind_, true);
-        break;
-      }
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kFfi##clazz##Cid:
-
-      CLASS_LIST_FFI(SNAPSHOT_READ) { UNREACHABLE(); }
-#undef SNAPSHOT_READ
-    default:
-      UNREACHABLE();
-      break;
-  }
-  return pobj_.ptr();
-}
-
-void SnapshotReader::EnqueueRehashingOfSet(const LinkedHashSet& set) {
-  ASSERT(!set.IsCanonical());
-  if (objects_to_rehash_.IsNull()) {
-    objects_to_rehash_ = GrowableObjectArray::New();
-  }
-  objects_to_rehash_.Add(set);
-}
-
-ObjectPtr SnapshotReader::ReadInstance(intptr_t object_id,
-                                       intptr_t tags,
-                                       bool as_reference) {
-  // Object is regular dart instance.
-  intptr_t instance_size = 0;
-  Instance* result = NULL;
-  DeserializeState state;
-  if (!as_reference) {
-    result = reinterpret_cast<Instance*>(GetBackRef(object_id));
-    state = kIsDeserialized;
-  } else {
-    state = kIsNotDeserialized;
-  }
-  if (result == NULL) {
-    result = &(Instance::ZoneHandle(zone(), Instance::null()));
-    AddBackRef(object_id, result, state);
-    cls_ ^= ReadObjectImpl(kAsInlinedObject);
-    ASSERT(!cls_.IsNull());
-    // Closure instances are handled by Closure::ReadFrom().
-    ASSERT(!cls_.IsClosureClass());
-    instance_size = cls_.host_instance_size();
-    ASSERT(instance_size > 0);
-    // Allocate the instance and read in all the fields for the object.
-    *result ^= Object::Allocate(cls_.id(), instance_size, Heap::kNew,
-                                Instance::ContainsCompressedPointers());
-  } else {
-    cls_ ^= ReadObjectImpl(kAsInlinedObject);
-    ASSERT(!cls_.IsNull());
-    instance_size = cls_.host_instance_size();
-  }
-  if (!as_reference) {
-    // Read all the individual fields for inlined objects.
-    intptr_t next_field_offset = cls_.host_next_field_offset();
-
-    intptr_t type_argument_field_offset =
-        cls_.host_type_arguments_field_offset();
-    ASSERT(next_field_offset > 0);
-    // Instance::NextFieldOffset() returns the offset of the first field in
-    // a Dart object.
-    bool read_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-    intptr_t offset = Instance::NextFieldOffset();
-    intptr_t result_cid = result->GetClassId();
-
-    const auto unboxed_fields =
-        isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            result_cid);
-
-    while (offset < next_field_offset) {
-      if (unboxed_fields.Get(offset / kCompressedWordSize)) {
-        compressed_uword* p = reinterpret_cast<compressed_uword*>(
-            result->raw_value() - kHeapObjectTag + offset);
-        // Reads 32 bits of the unboxed value at a time
-        *p = ReadWordWith32BitReads();
-      } else {
-        pobj_ = ReadObjectImpl(read_as_reference);
-        result->SetFieldAtOffset(offset, pobj_);
-        if ((offset != type_argument_field_offset) &&
-            (kind_ == Snapshot::kMessage) &&
-            isolate_group()->use_field_guards() &&
-            (pobj_.ptr() != Object::sentinel().ptr())) {
-          // TODO(fschneider): Consider hoisting these lookups out of the loop.
-          // This would involve creating a handle, since cls_ can't be reused
-          // across the call to ReadObjectImpl.
-          cls_ = isolate_group()->class_table()->At(result_cid);
-          array_ = cls_.OffsetToFieldMap();
-          field_ ^= array_.At(offset >> kCompressedWordSizeLog2);
-          ASSERT(!field_.IsNull());
-          ASSERT(field_.HostOffset() == offset);
-          obj_ = pobj_.ptr();
-          field_.RecordStore(obj_);
-        }
-        // TODO(fschneider): Verify the guarded cid and length for other kinds
-        // of snapshot (kFull, kScript) with asserts.
-      }
-      offset += kCompressedWordSize;
-    }
-    if (UntaggedObject::IsCanonical(tags)) {
-      *result = result->Canonicalize(thread());
-      ASSERT(!result->IsNull());
-    }
-  }
-  return result->ptr();
-}
-
-void SnapshotReader::AddBackRef(intptr_t id,
-                                Object* obj,
-                                DeserializeState state) {
-  intptr_t index = (id - kMaxPredefinedObjectIds);
-  ASSERT(index >= max_vm_isolate_object_id_);
-  index -= max_vm_isolate_object_id_;
-  ASSERT(index == backward_references_->length());
-  BackRefNode node(obj, state);
-  backward_references_->Add(node);
-}
-
-Object* SnapshotReader::GetBackRef(intptr_t id) {
-  ASSERT(id >= kMaxPredefinedObjectIds);
-  intptr_t index = (id - kMaxPredefinedObjectIds);
-  ASSERT(index >= max_vm_isolate_object_id_);
-  index -= max_vm_isolate_object_id_;
-  if (index < backward_references_->length()) {
-    return (*backward_references_)[index].reference();
-  }
-  return NULL;
-}
-
-ApiErrorPtr SnapshotReader::VerifyVersionAndFeatures(
-    IsolateGroup* isolate_group) {
-  // If the version string doesn't match, return an error.
-  // Note: New things are allocated only if we're going to return an error.
-
-  const char* expected_version = Version::SnapshotString();
-  ASSERT(expected_version != NULL);
-  const intptr_t version_len = strlen(expected_version);
-  if (PendingBytes() < version_len) {
-    const intptr_t kMessageBufferSize = 128;
-    char message_buffer[kMessageBufferSize];
-    Utils::SNPrint(message_buffer, kMessageBufferSize,
-                   "No full snapshot version found, expected '%s'",
-                   expected_version);
-    // This can also fail while bringing up the VM isolate, so make sure to
-    // allocate the error message in old space.
-    const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
-    return ApiError::New(msg, Heap::kOld);
-  }
-
-  const char* version = reinterpret_cast<const char*>(CurrentBufferAddress());
-  ASSERT(version != NULL);
-  if (strncmp(version, expected_version, version_len) != 0) {
-    const intptr_t kMessageBufferSize = 256;
-    char message_buffer[kMessageBufferSize];
-    char* actual_version = Utils::StrNDup(version, version_len);
-    Utils::SNPrint(message_buffer, kMessageBufferSize,
-                   "Wrong %s snapshot version, expected '%s' found '%s'",
-                   (Snapshot::IsFull(kind_)) ? "full" : "script",
-                   expected_version, actual_version);
-    free(actual_version);
-    // This can also fail while bringing up the VM isolate, so make sure to
-    // allocate the error message in old space.
-    const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
-    return ApiError::New(msg, Heap::kOld);
-  }
-  Advance(version_len);
-
-  const char* expected_features =
-      Dart::FeaturesString(isolate_group, false, kind_);
-  ASSERT(expected_features != NULL);
-  const intptr_t expected_len = strlen(expected_features);
-
-  const char* features = reinterpret_cast<const char*>(CurrentBufferAddress());
-  ASSERT(features != NULL);
-  intptr_t buffer_len = Utils::StrNLen(features, PendingBytes());
-  if ((buffer_len != expected_len) ||
-      (strncmp(features, expected_features, expected_len) != 0)) {
-    const intptr_t kMessageBufferSize = 256;
-    char message_buffer[kMessageBufferSize];
-    char* actual_features =
-        Utils::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
-    Utils::SNPrint(message_buffer, kMessageBufferSize,
-                   "Snapshot not compatible with the current VM configuration: "
-                   "the snapshot requires '%s' but the VM has '%s'",
-                   actual_features, expected_features);
-    free(const_cast<char*>(expected_features));
-    free(actual_features);
-    // This can also fail while bringing up the VM isolate, so make sure to
-    // allocate the error message in old space.
-    const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
-    return ApiError::New(msg, Heap::kOld);
-  }
-  free(const_cast<char*>(expected_features));
-  Advance(expected_len + 1);
-  return ApiError::null();
-}
-
-ObjectPtr SnapshotReader::NewInteger(int64_t value) {
-  ASSERT((value & kSmiTagMask) == kSmiTag);
-  value = value >> kSmiTagShift;
-  if (Smi::IsValid(value)) {
-    return Smi::New(static_cast<intptr_t>(value));
-  }
-  return Mint::NewCanonical(value);
-}
-
-intptr_t SnapshotReader::LookupInternalClass(intptr_t class_header) {
-  // If the header is an object Id, lookup singleton VM classes or classes
-  // stored in the object store.
-  if (IsVMIsolateObject(class_header)) {
-    intptr_t class_id = GetVMIsolateObjectId(class_header);
-    ASSERT(IsSingletonClassId(class_id));
-    return class_id;
-  }
-  ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
-  intptr_t class_id = SerializedHeaderData::decode(class_header);
-  ASSERT(IsBootstrapedClassId(class_id) || IsSingletonClassId(class_id));
-  return class_id;
-}
-
-#define READ_VM_SINGLETON_OBJ(id, obj)                                         \
-  if (object_id == id) {                                                       \
-    return obj;                                                                \
-  }
-
-ObjectPtr SnapshotReader::ReadVMIsolateObject(intptr_t header_value) {
-  intptr_t object_id = GetVMIsolateObjectId(header_value);
-
-  // First check if it is one of the singleton objects.
-  READ_VM_SINGLETON_OBJ(kNullObject, Object::null());
-  READ_VM_SINGLETON_OBJ(kSentinelObject, Object::sentinel().ptr());
-  READ_VM_SINGLETON_OBJ(kTransitionSentinelObject,
-                        Object::transition_sentinel().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyArrayObject, Object::empty_array().ptr());
-  READ_VM_SINGLETON_OBJ(kZeroArrayObject, Object::zero_array().ptr());
-  READ_VM_SINGLETON_OBJ(kDynamicType, Object::dynamic_type().ptr());
-  READ_VM_SINGLETON_OBJ(kVoidType, Object::void_type().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyTypeArguments,
-                        Object::empty_type_arguments().ptr());
-  READ_VM_SINGLETON_OBJ(kTrueValue, Bool::True().ptr());
-  READ_VM_SINGLETON_OBJ(kFalseValue, Bool::False().ptr());
-  READ_VM_SINGLETON_OBJ(kExtractorParameterTypes,
-                        Object::extractor_parameter_types().ptr());
-  READ_VM_SINGLETON_OBJ(kExtractorParameterNames,
-                        Object::extractor_parameter_names().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyContextScopeObject,
-                        Object::empty_context_scope().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyObjectPool, Object::empty_object_pool().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyDescriptors, Object::empty_descriptors().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyVarDescriptors,
-                        Object::empty_var_descriptors().ptr());
-  READ_VM_SINGLETON_OBJ(kEmptyExceptionHandlers,
-                        Object::empty_exception_handlers().ptr());
-
-  // Check if it is a double.
-  if (object_id == kDoubleObject) {
-    ASSERT(kind_ == Snapshot::kMessage);
-    return Double::New(ReadDouble());
-  }
-
-  // Check it is a singleton class object.
-  intptr_t class_id = ClassIdFromObjectId(object_id);
-  if (IsSingletonClassId(class_id)) {
-    return isolate_group()->class_table()->At(
-        class_id);  // get singleton class.
-  }
-
-  // Check if it is a singleton Argument descriptor object.
-  for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
-    if (object_id == (kCachedArgumentsDescriptor0 + i)) {
-      return ArgumentsDescriptor::cached_args_descriptors_[i];
-    }
-  }
-
-  // Check if it is a singleton ICData array object.
-  for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
-    if (object_id == (kCachedICDataArray0 + i)) {
-      return ICData::cached_icdata_arrays_[i];
-    }
-  }
-
-  ASSERT(Symbols::IsPredefinedSymbolId(object_id));
-  return Symbols::GetPredefinedSymbol(object_id);  // return VM symbol.
-}
-
-ObjectPtr SnapshotReader::ReadIndexedObject(intptr_t object_id) {
-  intptr_t class_id = ClassIdFromObjectId(object_id);
-  if (IsBootstrapedClassId(class_id)) {
-    return isolate_group()->class_table()->At(
-        class_id);  // get singleton class.
-  }
-  if (IsObjectStoreTypeId(object_id)) {
-    return GetType(object_store(), object_id);  // return type obj.
-  }
-  ASSERT(object_id >= kMaxPredefinedObjectIds);
-  intptr_t index = (object_id - kMaxPredefinedObjectIds);
-  if (index < max_vm_isolate_object_id_) {
-    return VmIsolateSnapshotObject(index);
-  }
-  return GetBackRef(object_id)->ptr();
-}
-
-void SnapshotReader::ArrayReadFrom(intptr_t object_id,
-                                   const Array& result,
-                                   intptr_t len,
-                                   intptr_t tags) {
-  // Setup the object fields.
-  *TypeArgumentsHandle() ^= ReadObjectImpl(kAsInlinedObject);
-  result.SetTypeArguments(*TypeArgumentsHandle());
-
-  bool as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-  for (intptr_t i = 0; i < len; i++) {
-    *PassiveObjectHandle() = ReadObjectImpl(as_reference);
-    result.SetAt(i, *PassiveObjectHandle());
-  }
-}
-
-void SnapshotReader::MapReadFrom(intptr_t object_id,
-                                 const LinkedHashMap& map,
-                                 intptr_t tags) {
-  // Read the type arguments.
-  *TypeArgumentsHandle() ^= ReadObjectImpl(kAsInlinedObject);
-  map.SetTypeArguments(*TypeArgumentsHandle());
-
-  // Read the number of key/value pairs.
-  intptr_t len = ReadSmiValue();
-  intptr_t used_data = (len << 1);
-  map.SetUsedData(used_data);
-
-  // Allocate the data array.
-  intptr_t data_size =
-      Utils::Maximum(Utils::RoundUpToPowerOfTwo(used_data),
-                     static_cast<uintptr_t>(LinkedHashMap::kInitialIndexSize));
-  Array& data = Array::ZoneHandle(zone(), Array::New(data_size));
-  map.SetData(data);
-  map.SetDeletedKeys(0);
-
-  // The index and hashMask is regenerated by the maps themselves on demand.
-  // Thus, the index will probably be allocated in new space (unless it's huge).
-  // TODO(koda): Eagerly rehash here when no keys have user-defined '==', and
-  // in particular, if/when (const) maps are needed in the VM isolate snapshot.
-  ASSERT(isolate_group() != Dart::vm_isolate_group());
-  map.SetHashMask(0);  // Prefer sentinel 0 over null for better type feedback.
-
-  // Read the keys and values.
-  bool read_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-  for (intptr_t i = 0; i < used_data; i++) {
-    *PassiveObjectHandle() = ReadObjectImpl(read_as_reference);
-    data.SetAt(i, *PassiveObjectHandle());
-  }
-
-  // TODO(http://dartbug.com/45908): Treat immutable, canonical maps.
-  ASSERT(!UntaggedObject::IsCanonical(tags));
-  // Can have user-defined hashCode for keys, compute in Dart.
-  EnqueueRehashingOfMap(map);
-}
-
-void SnapshotReader::SetReadFrom(intptr_t object_id,
-                                 const LinkedHashSet& set,
-                                 intptr_t tags) {
-  // Read the type arguments.
-  *TypeArgumentsHandle() ^= ReadObjectImpl(kAsInlinedObject);
-  set.SetTypeArguments(*TypeArgumentsHandle());
-
-  intptr_t used_data = ReadSmiValue();
-  set.SetUsedData(used_data);
-
-  // Allocate the data array.
-  intptr_t data_size =
-      Utils::Maximum(Utils::RoundUpToPowerOfTwo(used_data),
-                     static_cast<uintptr_t>(LinkedHashSet::kInitialIndexSize));
-  Array& data = Array::ZoneHandle(zone(), Array::New(data_size));
-  set.SetData(data);
-  set.SetDeletedKeys(0);
-
-  // The index and hashMask is regenerated by the sets themselves on demand.
-  // Thus, the index will probably be allocated in new space (unless it's huge).
-  // TODO(koda): Eagerly rehash here when no keys have user-defined '==', and
-  // in particular, if/when (const) sets are needed in the VM isolate snapshot.
-  ASSERT(isolate_group() != Dart::vm_isolate_group());
-  set.SetHashMask(0);  // Prefer sentinel 0 over null for better type feedback.
-
-  // Read the keys and values.
-  bool read_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-  for (intptr_t i = 0; i < used_data; i++) {
-    *PassiveObjectHandle() = ReadObjectImpl(read_as_reference);
-    data.SetAt(i, *PassiveObjectHandle());
-  }
-
-  // TODO(http://dartbug.com/45908): Treat immutable, canonical sets.
-  ASSERT(!UntaggedObject::IsCanonical(tags));
-  // Can have user-defined hashCode for keys, compute in Dart.
-  EnqueueRehashingOfSet(set);
-}
-
-MessageSnapshotReader::MessageSnapshotReader(Message* message, Thread* thread)
-    : SnapshotReader(message->snapshot(),
-                     message->snapshot_length(),
-                     Snapshot::kMessage,
-                     new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
-                     thread),
-      finalizable_data_(message->finalizable_data()) {}
-
-MessageSnapshotReader::~MessageSnapshotReader() {
-  ResetBackwardReferenceTable();
-}
-
-SnapshotWriter::SnapshotWriter(Thread* thread,
-                               Snapshot::Kind kind,
-                               intptr_t initial_size,
-                               ForwardList* forward_list,
-                               bool can_send_any_object)
-    : BaseWriter(initial_size),
-      thread_(thread),
-      kind_(kind),
-      object_store_(isolate_group()->object_store()),
-      class_table_(isolate_group()->class_table()),
-      forward_list_(forward_list),
-      exception_type_(Exceptions::kNone),
-      exception_msg_(NULL),
-      can_send_any_object_(can_send_any_object) {
-  ASSERT(forward_list_ != NULL);
-}
-
-void SnapshotWriter::WriteObject(ObjectPtr rawobj) {
-  WriteObjectImpl(rawobj, kAsInlinedObject);
-  WriteForwardedObjects();
-}
-
-uint32_t SnapshotWriter::GetObjectTags(ObjectPtr raw) {
-  uword tags = raw->untag()->tags_;
-#if defined(HASH_IN_OBJECT_HEADER)
-  // Clear hash to make the narrowing cast safe / appease UBSAN.
-  tags = UntaggedObject::HashTag::update(0, tags);
 #endif
-  return tags;
-}
-
-uint32_t SnapshotWriter::GetObjectTags(UntaggedObject* raw) {
-  uword tags = raw->tags_;
-#if defined(HASH_IN_OBJECT_HEADER)
-  // Clear hash to make the narrowing cast safe / appease UBSAN.
-  tags = UntaggedObject::HashTag::update(0, tags);
-#endif
-  return tags;
-}
-
-uword SnapshotWriter::GetObjectTagsAndHash(ObjectPtr raw) {
-  return raw->untag()->tags_;
-}
-
-#define VM_OBJECT_CLASS_LIST(V)                                                \
-  V(OneByteString)                                                             \
-  V(TwoByteString)                                                             \
-  V(Mint)                                                                      \
-  V(Double)                                                                    \
-  V(ImmutableArray)
-
-#define VM_OBJECT_WRITE(clazz)                                                 \
-  case clazz::kClassId: {                                                      \
-    object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);       \
-    clazz##Ptr raw_obj = static_cast<clazz##Ptr>(rawobj);                      \
-    raw_obj->untag()->WriteTo(this, object_id, kind(), false);                 \
-    return true;                                                               \
-  }
-
-#define WRITE_VM_SINGLETON_OBJ(obj, id)                                        \
-  if (rawobj == obj) {                                                         \
-    WriteVMIsolateObject(id);                                                  \
-    return true;                                                               \
-  }
-
-bool SnapshotWriter::HandleVMIsolateObject(ObjectPtr rawobj) {
-  // Check if it is one of the singleton VM objects.
-  WRITE_VM_SINGLETON_OBJ(Object::null(), kNullObject);
-  WRITE_VM_SINGLETON_OBJ(Object::sentinel().ptr(), kSentinelObject);
-  WRITE_VM_SINGLETON_OBJ(Object::transition_sentinel().ptr(),
-                         kTransitionSentinelObject);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_array().ptr(), kEmptyArrayObject);
-  WRITE_VM_SINGLETON_OBJ(Object::zero_array().ptr(), kZeroArrayObject);
-  WRITE_VM_SINGLETON_OBJ(Object::dynamic_type().ptr(), kDynamicType);
-  WRITE_VM_SINGLETON_OBJ(Object::void_type().ptr(), kVoidType);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_type_arguments().ptr(),
-                         kEmptyTypeArguments);
-  WRITE_VM_SINGLETON_OBJ(Bool::True().ptr(), kTrueValue);
-  WRITE_VM_SINGLETON_OBJ(Bool::False().ptr(), kFalseValue);
-  WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_types().ptr(),
-                         kExtractorParameterTypes);
-  WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_names().ptr(),
-                         kExtractorParameterNames);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_context_scope().ptr(),
-                         kEmptyContextScopeObject);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_object_pool().ptr(), kEmptyObjectPool);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_descriptors().ptr(), kEmptyDescriptors);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_var_descriptors().ptr(),
-                         kEmptyVarDescriptors);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_exception_handlers().ptr(),
-                         kEmptyExceptionHandlers);
-
-  // Check if it is a singleton class object which is shared by
-  // all isolates.
-  intptr_t id = rawobj->GetClassId();
-  if (id == kClassCid) {
-    ClassPtr raw_class = static_cast<ClassPtr>(rawobj);
-    intptr_t class_id = raw_class->untag()->id_;
-    if (IsSingletonClassId(class_id)) {
-      intptr_t object_id = ObjectIdFromClassId(class_id);
-      WriteVMIsolateObject(object_id);
-      return true;
-    }
-  }
-
-  // Check if it is a singleton Argument descriptor object.
-  for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
-    if (rawobj == ArgumentsDescriptor::cached_args_descriptors_[i]) {
-      WriteVMIsolateObject(kCachedArgumentsDescriptor0 + i);
-      return true;
-    }
-  }
-
-  // Check if it is a singleton ICData array object.
-  for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
-    if (rawobj == ICData::cached_icdata_arrays_[i]) {
-      WriteVMIsolateObject(kCachedICDataArray0 + i);
-      return true;
-    }
-  }
-
-  // In the case of script snapshots or for messages we do not use
-  // the index into the vm isolate snapshot object table, instead we
-  // explicitly write the object out.
-  intptr_t object_id = forward_list_->FindObject(rawobj);
-  if (object_id != -1) {
-    WriteIndexedObject(object_id);
-    return true;
-  } else {
-    // We do this check down here, because it's quite expensive.
-    if (!rawobj->untag()->InVMIsolateHeap()) {
-      return false;
-    }
-
-    switch (id) {
-      VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE)
-      case kTypedDataUint32ArrayCid: {
-        object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);
-        TypedDataPtr raw_obj = static_cast<TypedDataPtr>(rawobj);
-        raw_obj->untag()->WriteTo(this, object_id, kind(), false);
-        return true;
-      }
-      default:
-        OS::PrintErr("class id = %" Pd "\n", id);
-        break;
-    }
-  }
-
-  const Object& obj = Object::Handle(rawobj);
-  FATAL1("Unexpected reference to object in VM isolate: %s\n", obj.ToCString());
-  return false;
-}
-
-#undef VM_OBJECT_WRITE
-
-ForwardList::ForwardList(Thread* thread, intptr_t first_object_id)
-    : thread_(thread),
-      first_object_id_(first_object_id),
-      nodes_(),
-      first_unprocessed_object_id_(first_object_id) {
-  ASSERT(first_object_id > 0);
-  isolate()->set_forward_table_new(new WeakTable());
-  isolate()->set_forward_table_old(new WeakTable());
-}
-
-ForwardList::~ForwardList() {
-  isolate()->set_forward_table_new(nullptr);
-  isolate()->set_forward_table_old(nullptr);
-}
-
-intptr_t ForwardList::AddObject(Zone* zone,
-                                ObjectPtr raw,
-                                SerializeState state) {
-  NoSafepointScope no_safepoint;
-  intptr_t object_id = next_object_id();
-  ASSERT(object_id > 0 && object_id <= kMaxObjectId);
-  const Object& obj = Object::ZoneHandle(zone, raw);
-  Node* node = new Node(&obj, state);
-  ASSERT(node != NULL);
-  nodes_.Add(node);
-  ASSERT(object_id != 0);
-  SetObjectId(raw, object_id);
-  return object_id;
-}
-
-intptr_t ForwardList::FindObject(ObjectPtr raw) {
-  NoSafepointScope no_safepoint;
-  intptr_t id = GetObjectId(raw);
-  ASSERT(id == 0 || NodeForObjectId(id)->obj()->ptr() == raw);
-  return (id == 0) ? static_cast<intptr_t>(kInvalidIndex) : id;
-}
-
-void ForwardList::SetObjectId(ObjectPtr object, intptr_t id) {
-  if (object->IsNewObject()) {
-    isolate()->forward_table_new()->SetValueExclusive(object, id);
-  } else {
-    isolate()->forward_table_old()->SetValueExclusive(object, id);
-  }
-}
-
-intptr_t ForwardList::GetObjectId(ObjectPtr object) {
-  if (object->IsNewObject()) {
-    return isolate()->forward_table_new()->GetValueExclusive(object);
-  } else {
-    return isolate()->forward_table_old()->GetValueExclusive(object);
-  }
-}
-
-bool SnapshotWriter::CheckAndWritePredefinedObject(ObjectPtr rawobj) {
-  // Check if object can be written in one of the following ways:
-  // - Smi: the Smi value is written as is (last bit is not tagged).
-  // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3)
-  // - Object that has already been written: (negative id in stream | 0x3)
-
-  NoSafepointScope no_safepoint;
-
-  // First check if it is a Smi (i.e not a heap object).
-  if (!rawobj->IsHeapObject()) {
-#if !defined(DART_COMPRESSED_POINTERS)
-    Write<int64_t>(static_cast<intptr_t>(rawobj));
-#else
-    // One might expect this to be unnecessary because the reader will just
-    // ignore the upper bits, but the upper bits affect the variable-length
-    // encoding and can change lower bits in the variable-length reader.
-    Write<int64_t>(static_cast<intptr_t>(rawobj) << 32 >> 32);
-#endif
-    return true;
-  }
-
-  intptr_t cid = rawobj->GetClassId();
-
-  if ((kind_ == Snapshot::kMessage) && (cid == kDoubleCid)) {
-    WriteVMIsolateObject(kDoubleObject);
-    DoublePtr rd = static_cast<DoublePtr>(rawobj);
-    WriteDouble(rd->untag()->value_);
-    return true;
-  }
-
-  // Check if object has already been serialized, in that case just write
-  // the object id out.
-  intptr_t object_id = forward_list_->FindObject(rawobj);
-  if (object_id != kInvalidIndex) {
-    WriteIndexedObject(object_id);
-    return true;
-  }
-
-  // Check if it is a code object in that case just write a Null object
-  // as we do not want code objects in the snapshot.
-  if (cid == kCodeCid) {
-    WriteVMIsolateObject(kNullObject);
-    return true;
-  }
-
-  // Now check if it is an object from the VM isolate. These objects are shared
-  // by all isolates.
-  if (HandleVMIsolateObject(rawobj)) {
-    return true;
-  }
-
-  // Check if classes are not being serialized and it is preinitialized type
-  // or a predefined internal VM class in the object store.
-  // Check if it is an internal VM class which is in the object store.
-  if (cid == kClassCid) {
-    ClassPtr raw_class = static_cast<ClassPtr>(rawobj);
-    intptr_t class_id = raw_class->untag()->id_;
-    if (IsBootstrapedClassId(class_id)) {
-      intptr_t object_id = ObjectIdFromClassId(class_id);
-      WriteIndexedObject(object_id);
-      return true;
-    }
-  }
-
-  // Now check it is a preinitialized type object.
-  intptr_t index = GetTypeIndex(object_store(), rawobj);
-  if (index != kInvalidIndex) {
-    WriteIndexedObject(index);
-    return true;
-  }
-
-  return false;
-}
-
-void SnapshotWriter::WriteObjectImpl(ObjectPtr raw, bool as_reference) {
-  // First check if object can be written as a simple predefined type.
-  if (CheckAndWritePredefinedObject(raw)) {
-    return;
-  }
-
-  // When we know that we are dealing with leaf or shallow objects we write
-  // these objects inline even when 'as_reference' is true.
-  const bool write_as_reference = as_reference && !raw->untag()->IsCanonical();
-  uintptr_t tags = GetObjectTagsAndHash(raw);
-
-  // Add object to the forward ref list and mark it so that future references
-  // to this object in the snapshot will use this object id. Mark the
-  // serialization state so that we do the right thing when we go through
-  // the forward list.
-  intptr_t class_id = raw->GetClassId();
-  intptr_t object_id;
-  if (write_as_reference && IsSplitClassId(class_id)) {
-    object_id = forward_list_->AddObject(zone(), raw, kIsNotSerialized);
-  } else {
-    object_id = forward_list_->AddObject(zone(), raw, kIsSerialized);
-  }
-  if (write_as_reference || !IsSplitClassId(class_id)) {
-    object_id = kOmittedObjectId;
-  }
-  WriteMarkedObjectImpl(raw, tags, object_id, write_as_reference);
-}
-
-void SnapshotWriter::WriteMarkedObjectImpl(ObjectPtr raw,
-                                           intptr_t tags,
-                                           intptr_t object_id,
-                                           bool as_reference) {
-  NoSafepointScope no_safepoint;
-  ClassPtr cls = class_table_->At(UntaggedObject::ClassIdTag::decode(tags));
-  intptr_t class_id = cls->untag()->id_;
-  ASSERT(class_id == UntaggedObject::ClassIdTag::decode(tags));
-  if (class_id >= kNumPredefinedCids || IsImplicitFieldClassId(class_id)) {
-    WriteInstance(raw, cls, tags, object_id, as_reference);
-    return;
-  }
-  switch (class_id) {
-#define SNAPSHOT_WRITE(clazz)                                                  \
-  case clazz::kClassId: {                                                      \
-    clazz##Ptr raw_obj = static_cast<clazz##Ptr>(raw);                         \
-    raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);           \
-    return;                                                                    \
-  }
-
-    CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz) case kTypedData##clazz##Cid:
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
-      TypedDataPtr raw_obj = static_cast<TypedDataPtr>(raw);
-      raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
-      return;
-    }
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz) case kExternalTypedData##clazz##Cid:
-
-    CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
-      ExternalTypedDataPtr raw_obj = static_cast<ExternalTypedDataPtr>(raw);
-      raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
-      return;
-    }
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz) case kTypedData##clazz##ViewCid:
-
-    case kByteDataViewCid:
-      CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
-        auto raw_obj = static_cast<TypedDataViewPtr>(raw);
-        raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
-        return;
-      }
-#undef SNAPSHOT_WRITE
-
-#define SNAPSHOT_WRITE(clazz) case kFfi##clazz##Cid:
-
-      CLASS_LIST_FFI(SNAPSHOT_WRITE) {
-        SetWriteException(Exceptions::kArgument,
-                          "Native objects (from dart:ffi) such as Pointers and "
-                          "Structs cannot be passed between isolates.");
-        UNREACHABLE();
-      }
-#undef SNAPSHOT_WRITE
-    default:
-      break;
-  }
-
-  const Object& obj = Object::Handle(raw);
-  FATAL1("Unexpected object: %s\n", obj.ToCString());
-}
-
-class WriteInlinedObjectVisitor : public ObjectVisitor {
- public:
-  explicit WriteInlinedObjectVisitor(SnapshotWriter* writer)
-      : writer_(writer) {}
-
-  virtual void VisitObject(ObjectPtr obj) {
-    intptr_t object_id = writer_->forward_list_->FindObject(obj);
-    ASSERT(object_id != kInvalidIndex);
-    intptr_t tags = MessageWriter::GetObjectTagsAndHash(ObjectPtr(obj));
-    writer_->WriteMarkedObjectImpl(obj, tags, object_id, kAsInlinedObject);
-  }
-
- private:
-  SnapshotWriter* writer_;
-};
-
-void SnapshotWriter::WriteForwardedObjects() {
-  WriteInlinedObjectVisitor visitor(this);
-  forward_list_->SerializeAll(&visitor);
-}
-
-void ForwardList::SerializeAll(ObjectVisitor* writer) {
-// Write out all objects that were added to the forward list and have
-// not been serialized yet. These would typically be fields of instance
-// objects, arrays or immutable arrays (this is done in order to avoid
-// deep recursive calls to WriteObjectImpl).
-// NOTE: The forward list might grow as we process the list.
-#ifdef DEBUG
-  for (intptr_t i = first_object_id(); i < first_unprocessed_object_id_; ++i) {
-    ASSERT(NodeForObjectId(i)->is_serialized());
-  }
-#endif  // DEBUG
-  for (intptr_t id = first_unprocessed_object_id_; id < next_object_id();
-       ++id) {
-    if (!NodeForObjectId(id)->is_serialized()) {
-      // Write the object out in the stream.
-      ObjectPtr raw = NodeForObjectId(id)->obj()->ptr();
-      writer->VisitObject(raw);
-
-      // Mark object as serialized.
-      NodeForObjectId(id)->set_state(kIsSerialized);
-    }
-  }
-  first_unprocessed_object_id_ = next_object_id();
-}
-
-void SnapshotWriter::WriteClassId(UntaggedClass* cls) {
-  ASSERT(!Snapshot::IsFull(kind_));
-  int class_id = cls->id_;
-  ASSERT(!IsSingletonClassId(class_id) && !IsBootstrapedClassId(class_id));
-
-  // Write out the library url and class name.
-  LibraryPtr library = cls->library();
-  ASSERT(library != Library::null());
-  WriteObjectImpl(library->untag()->url(), kAsInlinedObject);
-  WriteObjectImpl(cls->name(), kAsInlinedObject);
-}
-
-void SnapshotWriter::WriteStaticImplicitClosure(
-    intptr_t object_id,
-    FunctionPtr func,
-    intptr_t tags,
-    TypeArgumentsPtr delayed_type_arguments) {
-  // Write out the serialization header value for this object.
-  WriteInlinedObjectHeader(object_id);
-
-  // Indicate this is a static implicit closure object.
-  Write<int32_t>(SerializedHeaderData::encode(kStaticImplicitClosureObjectId));
-
-  // Write out the tags.
-  WriteTags(tags);
-
-  // Write out the library url, class name and signature function name.
-  ClassPtr cls = GetFunctionOwner(func);
-  ASSERT(cls != Class::null());
-  LibraryPtr library = cls->untag()->library();
-  ASSERT(library != Library::null());
-  WriteObjectImpl(library->untag()->url(), kAsInlinedObject);
-  WriteObjectImpl(cls->untag()->name(), kAsInlinedObject);
-  WriteObjectImpl(func->untag()->name(), kAsInlinedObject);
-  WriteObjectImpl(delayed_type_arguments, kAsInlinedObject);
-}
-
-void SnapshotWriter::ArrayWriteTo(intptr_t object_id,
-                                  intptr_t array_kind,
-                                  intptr_t tags,
-                                  SmiPtr length,
-                                  TypeArgumentsPtr type_arguments,
-                                  CompressedObjectPtr data[],
-                                  bool as_reference) {
-  if (as_reference) {
-    // Write out the serialization header value for this object.
-    WriteInlinedObjectHeader(kOmittedObjectId);
-
-    // Write out the class information.
-    WriteIndexedObject(array_kind);
-    WriteTags(tags);
-
-    // Write out the length field.
-    Write<ObjectPtr>(length);
-  } else {
-    intptr_t len = Smi::Value(length);
-
-    // Write out the serialization header value for this object.
-    WriteInlinedObjectHeader(object_id);
-
-    // Write out the class and tags information.
-    WriteIndexedObject(array_kind);
-    WriteTags(tags);
-
-    // Write out the length field.
-    Write<ObjectPtr>(length);
-
-    // Write out the type arguments.
-    WriteObjectImpl(type_arguments, kAsInlinedObject);
-
-    // Write out the individual object ids.
-    bool write_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-    uword heap_base = type_arguments.heap_base();
-    for (intptr_t i = 0; i < len; i++) {
-      WriteObjectImpl(data[i].Decompress(heap_base), write_as_reference);
-    }
-  }
-}
-
-void SnapshotWriter::MapWriteTo(intptr_t object_id,
-                                intptr_t class_id,
-                                intptr_t tags,
-                                TypeArgumentsPtr type_arguments,
-                                SmiPtr used_data_smi,
-                                SmiPtr deleted_keys_smi,
-                                ArrayPtr data,
-                                bool as_reference) {
-  // Write out the serialization header value for this object.
-  WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  WriteIndexedObject(class_id);
-  WriteTags(tags);
-
-  // Write out the type arguments.
-  WriteObjectImpl(type_arguments, kAsInlinedObject);
-
-  const intptr_t num_used_data = Smi::Value(used_data_smi);
-  ASSERT((num_used_data & 1) == 0);  // Keys + values, so must be even.
-  const intptr_t num_deleted_keys = Smi::Value(deleted_keys_smi);
-
-  // Write out the number of (not deleted) key/value pairs that will follow.
-  Write<ObjectPtr>(Smi::New((num_used_data >> 1) - num_deleted_keys));
-
-  // Write out the keys and values.
-  const bool write_as_reference =
-      UntaggedObject::IsCanonical(tags) ? false : true;
-  ASSERT(num_used_data <= Smi::Value(data->untag()->length()));
-#if defined(DEBUG)
-  intptr_t deleted_keys_found = 0;
-#endif  // DEBUG
-  for (intptr_t i = 0; i < num_used_data; i += 2) {
-    ObjectPtr key = data->untag()->element(i);
-    if (key == data) {
-#if defined(DEBUG)
-      ++deleted_keys_found;
-#endif  // DEBUG
-      continue;
-    }
-    ObjectPtr value = data->untag()->element(i + 1);
-    WriteObjectImpl(key, write_as_reference);
-    WriteObjectImpl(value, write_as_reference);
-  }
-  DEBUG_ASSERT(deleted_keys_found == num_deleted_keys);
-}
-
-void SnapshotWriter::SetWriteTo(intptr_t object_id,
-                                intptr_t class_id,
-                                intptr_t tags,
-                                TypeArgumentsPtr type_arguments,
-                                SmiPtr used_data_smi,
-                                SmiPtr deleted_keys_smi,
-                                ArrayPtr data,
-                                bool as_reference) {
-  // Write out the serialization header value for this object.
-  WriteInlinedObjectHeader(object_id);
-
-  // Write out the class and tags information.
-  WriteIndexedObject(class_id);
-  WriteTags(tags);
-
-  // Write out the type arguments.
-  WriteObjectImpl(type_arguments, kAsInlinedObject);
-
-  const intptr_t num_used_data = Smi::Value(used_data_smi);
-  const intptr_t num_deleted_keys = Smi::Value(deleted_keys_smi);
-
-  // Write out the number of (not deleted) key/value pairs that will follow.
-  Write<ObjectPtr>(Smi::New(num_used_data - num_deleted_keys));
-
-  // Write out the keys and values.
-  const bool write_as_reference =
-      UntaggedObject::IsCanonical(tags) ? false : true;
-  ASSERT(num_used_data <= Smi::Value(data->untag()->length()));
-#if defined(DEBUG)
-  intptr_t deleted_keys_found = 0;
-#endif  // DEBUG
-  for (intptr_t i = 0; i < num_used_data; i++) {
-    ObjectPtr key = data->untag()->element(i);
-    if (key == data) {
-#if defined(DEBUG)
-      ++deleted_keys_found;
-#endif  // DEBUG
-      continue;
-    }
-    ObjectPtr value = data->untag()->element(i + 1);
-    WriteObjectImpl(key, write_as_reference);
-    WriteObjectImpl(value, write_as_reference);
-  }
-  DEBUG_ASSERT(deleted_keys_found == num_deleted_keys);
-}
-
-FunctionPtr SnapshotWriter::IsSerializableClosure(ClosurePtr closure) {
-  // Extract the function object to check if this closure
-  // can be sent in an isolate message.
-  FunctionPtr func = closure->untag()->function();
-  // We only allow closure of top level methods or static functions in a
-  // class to be sent in isolate messages.
-  if (can_send_any_object() &&
-      Function::IsImplicitStaticClosureFunction(func)) {
-    return func;
-  }
-  // Not a closure of a top level method or static function, throw an
-  // exception as we do not allow these objects to be serialized.
-  HANDLESCOPE(thread());
-
-  const Function& errorFunc = Function::Handle(zone(), func);
-  ASSERT(!errorFunc.IsNull());
-
-  // All other closures are errors.
-  char* chars = OS::SCreate(
-      thread()->zone(),
-      "Illegal argument in isolate message : (object is a closure - %s)",
-      errorFunc.ToCString());
-  SetWriteException(Exceptions::kArgument, chars);
-  return Function::null();
-}
-
-ClassPtr SnapshotWriter::GetFunctionOwner(FunctionPtr func) {
-  ObjectPtr owner = func->untag()->owner();
-  uword tags = GetObjectTags(owner);
-  intptr_t class_id = UntaggedObject::ClassIdTag::decode(tags);
-  if (class_id == kClassCid) {
-    return static_cast<ClassPtr>(owner);
-  }
-  ASSERT(class_id == kPatchClassCid);
-  return static_cast<PatchClassPtr>(owner)->untag()->patched_class();
-}
-
-void SnapshotWriter::CheckForNativeFields(ClassPtr cls) {
-  if (cls->untag()->num_native_fields_ != 0) {
-    // We do not allow objects with native fields in an isolate message.
-    HANDLESCOPE(thread());
-    const Class& clazz = Class::Handle(zone(), cls);
-    char* chars = OS::SCreate(thread()->zone(),
-                              "Illegal argument in isolate message"
-                              " : (object extends NativeWrapper - %s)",
-                              clazz.ToCString());
-    SetWriteException(Exceptions::kArgument, chars);
-  }
-}
-
-void SnapshotWriter::SetWriteException(Exceptions::ExceptionType type,
-                                       const char* msg) {
-  set_exception_type(type);
-  set_exception_msg(msg);
-  // The more specific error is set up in SnapshotWriter::ThrowException().
-  thread()->long_jump_base()->Jump(1, Object::snapshot_writer_error());
-}
-
-void SnapshotWriter::WriteInstance(ObjectPtr raw,
-                                   ClassPtr cls,
-                                   intptr_t tags,
-                                   intptr_t object_id,
-                                   bool as_reference) {
-  // Closure instances are handled by UntaggedClosure::WriteTo().
-  ASSERT(!Class::IsClosureClass(cls));
-
-  // Check if the instance has native fields and throw an exception if it does.
-  CheckForNativeFields(cls);
-
-  // Object is regular dart instance.
-  if (as_reference) {
-    // Write out the serialization header value for this object.
-    WriteInlinedObjectHeader(kOmittedObjectId);
-
-    // Indicate this is an instance object.
-    Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId));
-    WriteTags(tags);
-
-    // Write out the class information for this object.
-    WriteObjectImpl(cls, kAsInlinedObject);
-  } else {
-    intptr_t next_field_offset = Class::host_next_field_offset_in_words(cls)
-                                 << kCompressedWordSizeLog2;
-    ASSERT(next_field_offset > 0);
-
-    // Write out the serialization header value for this object.
-    WriteInlinedObjectHeader(object_id);
-
-    // Indicate this is an instance object.
-    Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId));
-
-    // Write out the tags.
-    WriteTags(tags);
-
-    // Write out the class information for this object.
-    WriteObjectImpl(cls, kAsInlinedObject);
-
-    const auto unboxed_fields =
-        isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            cls->untag()->id_);
-
-    // Write out all the fields for the object.
-    // Instance::NextFieldOffset() returns the offset of the first field in
-    // a Dart object.
-    bool write_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-
-    intptr_t offset = Instance::NextFieldOffset();
-    uword heap_base = raw->heap_base();
-    while (offset < next_field_offset) {
-      if (unboxed_fields.Get(offset / kCompressedWordSize)) {
-        // Writes 32 bits of the unboxed value at a time
-        const uword value = *reinterpret_cast<compressed_uword*>(
-            reinterpret_cast<uword>(raw->untag()) + offset);
-        WriteWordWith32BitWrites(value);
-      } else {
-        ObjectPtr raw_obj = reinterpret_cast<CompressedObjectPtr*>(
-                                reinterpret_cast<uword>(raw->untag()) + offset)
-                                ->Decompress(heap_base);
-        WriteObjectImpl(raw_obj, write_as_reference);
-      }
-      offset += kCompressedWordSize;
-    }
-  }
-  return;
-}
-
-bool SnapshotWriter::AllowObjectsInDartLibrary(LibraryPtr library) {
-  return (library == object_store()->collection_library() ||
-          library == object_store()->core_library() ||
-          library == object_store()->typed_data_library());
-}
-
-intptr_t SnapshotWriter::FindVmSnapshotObject(ObjectPtr rawobj) {
-  intptr_t length = Object::vm_isolate_snapshot_object_table().Length();
-  for (intptr_t i = 0; i < length; i++) {
-    if (Object::vm_isolate_snapshot_object_table().At(i) == rawobj) {
-      return (i + kMaxPredefinedObjectIds);
-    }
-  }
-  return kInvalidIndex;
-}
-
-void SnapshotWriter::ThrowException(Exceptions::ExceptionType type,
-                                    const char* msg) {
-  {
-    NoSafepointScope no_safepoint;
-    ErrorPtr error = thread()->StealStickyError();
-    ASSERT(error == Object::snapshot_writer_error().ptr());
-  }
-
-  if (msg != NULL) {
-    const String& msg_obj = String::Handle(String::New(msg));
-    const Array& args = Array::Handle(Array::New(1));
-    args.SetAt(0, msg_obj);
-    Exceptions::ThrowByType(type, args);
-  } else {
-    Exceptions::ThrowByType(type, Object::empty_array());
-  }
-  UNREACHABLE();
-}
-
-void SnapshotWriter::WriteVersionAndFeatures() {
-  const char* expected_version = Version::SnapshotString();
-  ASSERT(expected_version != NULL);
-  const intptr_t version_len = strlen(expected_version);
-  WriteBytes(reinterpret_cast<const uint8_t*>(expected_version), version_len);
-
-  const char* expected_features =
-      Dart::FeaturesString(IsolateGroup::Current(), false, kind_);
-  ASSERT(expected_features != NULL);
-  const intptr_t features_len = strlen(expected_features);
-  WriteBytes(reinterpret_cast<const uint8_t*>(expected_features),
-             features_len + 1);
-  free(const_cast<char*>(expected_features));
-}
-
-void SnapshotWriterVisitor::VisitPointers(ObjectPtr* first, ObjectPtr* last) {
-  ASSERT(Utils::IsAligned(first, sizeof(*first)));
-  ASSERT(Utils::IsAligned(last, sizeof(*last)));
-  for (ObjectPtr* current = first; current <= last; current++) {
-    ObjectPtr raw_obj = *current;
-    writer_->WriteObjectImpl(raw_obj, as_references_);
-  }
-}
-
-void SnapshotWriterVisitor::VisitCompressedPointers(uword heap_base,
-                                                    CompressedObjectPtr* first,
-                                                    CompressedObjectPtr* last) {
-  ASSERT(Utils::IsAligned(first, sizeof(*first)));
-  ASSERT(Utils::IsAligned(last, sizeof(*last)));
-  for (CompressedObjectPtr* current = first; current <= last; current++) {
-    ObjectPtr raw_obj = current->Decompress(heap_base);
-    writer_->WriteObjectImpl(raw_obj, as_references_);
-  }
-}
-
-MessageWriter::MessageWriter(bool can_send_any_object)
-    : SnapshotWriter(Thread::Current(),
-                     Snapshot::kMessage,
-                     kInitialSize,
-                     &forward_list_,
-                     can_send_any_object),
-      forward_list_(thread(), kMaxPredefinedObjectIds),
-      finalizable_data_(new MessageFinalizableData()) {}
-
-MessageWriter::~MessageWriter() {
-  delete finalizable_data_;
-}
-
-std::unique_ptr<Message> MessageWriter::WriteMessage(
-    const Object& obj,
-    Dart_Port dest_port,
-    Message::Priority priority) {
-  ASSERT(kind() == Snapshot::kMessage);
-  ASSERT(isolate() != NULL);
-
-  // Setup for long jump in case there is an exception while writing
-  // the message.
-  volatile bool has_exception = false;
-  {
-    LongJumpScope jump;
-    if (setjmp(*jump.Set()) == 0) {
-      NoSafepointScope no_safepoint;
-      WriteObject(obj.ptr());
-    } else {
-      FreeBuffer();
-      has_exception = true;
-    }
-  }
-  if (has_exception) {
-    ThrowException(exception_type(), exception_msg());
-  } else {
-    finalizable_data_->SerializationSucceeded();
-  }
-
-  MessageFinalizableData* finalizable_data = finalizable_data_;
-  finalizable_data_ = nullptr;
-  intptr_t size;
-  uint8_t* buffer = Steal(&size);
-  return Message::New(dest_port, buffer, size, finalizable_data, priority);
-}
 
 }  // namespace dart
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 8123e46..63d61a8 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -9,83 +9,14 @@
 #include <utility>
 
 #include "platform/assert.h"
+#include "platform/unaligned.h"
 #include "vm/allocation.h"
-#include "vm/bitfield.h"
-#include "vm/datastream.h"
-#include "vm/finalizable_data.h"
 #include "vm/globals.h"
-#include "vm/growable_array.h"
-#include "vm/isolate.h"
 #include "vm/message.h"
-#include "vm/visitor.h"
+#include "vm/thread.h"
 
 namespace dart {
 
-// Forward declarations.
-class AbstractType;
-class Array;
-class Class;
-class ClassTable;
-class Closure;
-class Code;
-class ExternalTypedData;
-class TypedDataBase;
-class GrowableObjectArray;
-class Heap;
-class Instance;
-class Instructions;
-class LanguageError;
-class Library;
-class LinkedHashMap;
-class Object;
-class PassiveObject;
-class ObjectStore;
-class MegamorphicCache;
-class PageSpace;
-class TypedDataView;
-class String;
-class TypeArguments;
-class TypedData;
-class UnhandledException;
-
-// Serialized object header encoding is as follows:
-// - Smi: the Smi value is written as is (last bit is not tagged).
-// - VM object (from VM isolate): (object id in vm isolate | 0x3)
-//   This value is serialized as a negative number.
-//   (note VM objects are never serialized, they are expected to be found
-//    using ths unique ID assigned to them).
-// - Reference to object that has already been written: (object id | 0x3)
-//   This valus is serialized as a positive number.
-// - Object that is seen for the first time (inlined in the stream):
-//   (a unique id for this object | 0x1)
-enum SerializedHeaderType {
-  kInlined = 0x1,
-  kObjectId = 0x3,
-};
-static const int8_t kHeaderTagBits = 2;
-static const int8_t kObjectIdBits = (kBitsPerInt32 - (kHeaderTagBits + 1));
-static const intptr_t kMaxObjectId = (kMaxUint32 >> (kHeaderTagBits + 1));
-static const bool kAsReference = true;
-static const bool kAsInlinedObject = false;
-static const intptr_t kInvalidPatchIndex = -1;
-
-class SerializedHeaderTag
-    : public BitField<intptr_t, enum SerializedHeaderType, 0, kHeaderTagBits> {
-};
-
-class SerializedHeaderData
-    : public BitField<intptr_t, intptr_t, kHeaderTagBits, kObjectIdBits> {};
-
-enum DeserializeState {
-  kIsDeserialized = 0,
-  kIsNotDeserialized = 1,
-};
-
-enum SerializeState {
-  kIsSerialized = 0,
-  kIsNotSerialized = 1,
-};
-
 // Structure capturing the raw snapshot.
 //
 class Snapshot {
@@ -95,7 +26,6 @@
     kFullCore,  // Full snapshot of core libraries. Agnostic to null safety.
     kFullJIT,   // Full + JIT code
     kFullAOT,   // Full + AOT code
-    kMessage,   // A partial snapshot used only for isolate messaging.
     kNone,      // gen_snapshot
     kInvalid
   };
@@ -185,555 +115,6 @@
   return Snapshot::IsFull(isolate_kind);
 }
 
-class BaseReader {
- public:
-  BaseReader(const uint8_t* buffer, intptr_t size) : stream_(buffer, size) {}
-  // Reads raw data (for basic types).
-  // sizeof(T) must be in {1,2,4,8}.
-  template <typename T>
-  T Read() {
-    return ReadStream::Raw<sizeof(T), T>::Read(&stream_);
-  }
-
-  classid_t ReadClassIDValue() {
-    uint32_t value = Read<uint32_t>();
-    return static_cast<classid_t>(value);
-  }
-  COMPILE_ASSERT(sizeof(uint32_t) >= sizeof(classid_t));
-
-  void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); }
-
-  double ReadDouble() {
-    double result;
-    stream_.ReadBytes(reinterpret_cast<uint8_t*>(&result), sizeof(result));
-    return result;
-  }
-
-  intptr_t ReadTags() {
-    const intptr_t tags = static_cast<intptr_t>(Read<int8_t>()) & 0xff;
-    return tags;
-  }
-
-  const uint8_t* CurrentBufferAddress() const {
-    return stream_.AddressOfCurrentPosition();
-  }
-
-  void Align(intptr_t value) { stream_.Align(value); }
-  void Advance(intptr_t value) { stream_.Advance(value); }
-
-  intptr_t PendingBytes() const { return stream_.PendingBytes(); }
-
-  SmiPtr ReadAsSmi();
-  intptr_t ReadSmiValue();
-
-  // Negative header value indicates VM isolate object id.
-  bool IsVMIsolateObject(intptr_t header_value) { return (header_value < 0); }
-  intptr_t GetVMIsolateObjectId(intptr_t header_val) {
-    ASSERT(IsVMIsolateObject(header_val));
-    intptr_t value = -header_val;  // Header is negative for VM isolate objects.
-    ASSERT(SerializedHeaderTag::decode(value) == kObjectId);
-    return SerializedHeaderData::decode(value);
-  }
-
-  uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); }
-
- private:
-  ReadStream stream_;  // input stream.
-};
-
-class BackRefNode : public ValueObject {
- public:
-  BackRefNode(Object* reference, DeserializeState state)
-      : reference_(reference), state_(state) {}
-  Object* reference() const { return reference_; }
-  bool is_deserialized() const { return state_ == kIsDeserialized; }
-  void set_state(DeserializeState state) { state_ = state; }
-
-  BackRefNode& operator=(const BackRefNode& other) {
-    reference_ = other.reference_;
-    state_ = other.state_;
-    return *this;
-  }
-
- private:
-  Object* reference_;
-  DeserializeState state_;
-};
-
-// Reads a snapshot into objects.
-class SnapshotReader : public BaseReader {
- public:
-  Thread* thread() const { return thread_; }
-  Zone* zone() const { return zone_; }
-  Isolate* isolate() const { return thread_->isolate(); }
-  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
-  Heap* heap() const { return heap_; }
-  ObjectStore* object_store() const { return isolate_group()->object_store(); }
-  ClassTable* class_table() const { return isolate_group()->class_table(); }
-  PassiveObject* PassiveObjectHandle() { return &pobj_; }
-  Array* ArrayHandle() { return &array_; }
-  Class* ClassHandle() { return &cls_; }
-  Code* CodeHandle() { return &code_; }
-  Instance* InstanceHandle() { return &instance_; }
-  Instructions* InstructionsHandle() { return &instructions_; }
-  String* StringHandle() { return &str_; }
-  AbstractType* TypeHandle() { return &type_; }
-  TypeArguments* TypeArgumentsHandle() { return &type_arguments_; }
-  GrowableObjectArray* TokensHandle() { return &tokens_; }
-  ExternalTypedData* DataHandle() { return &data_; }
-  TypedDataBase* TypedDataBaseHandle() { return &typed_data_base_; }
-  TypedData* TypedDataHandle() { return &typed_data_; }
-  TypedDataView* TypedDataViewHandle() { return &typed_data_view_; }
-  Function* FunctionHandle() { return &function_; }
-  Smi* SmiHandle() { return &smi_; }
-  Snapshot::Kind kind() const { return kind_; }
-
-  // Reads an object.
-  ObjectPtr ReadObject();
-
-  // Add object to backward references.
-  void AddBackRef(intptr_t id, Object* obj, DeserializeState state);
-
-  // Get an object from the backward references list.
-  Object* GetBackRef(intptr_t id);
-
-  // Read version number of snapshot and verify.
-  ApiErrorPtr VerifyVersionAndFeatures(IsolateGroup* isolate_group);
-
-  ObjectPtr NewInteger(int64_t value);
-
- protected:
-  SnapshotReader(const uint8_t* buffer,
-                 intptr_t size,
-                 Snapshot::Kind kind,
-                 ZoneGrowableArray<BackRefNode>* backward_references,
-                 Thread* thread);
-  ~SnapshotReader() {}
-
-  ZoneGrowableArray<BackRefNode>* GetBackwardReferenceTable() const {
-    return backward_references_;
-  }
-  void ResetBackwardReferenceTable() { backward_references_ = NULL; }
-  PageSpace* old_space() const { return old_space_; }
-
- private:
-  void EnqueueTypePostprocessing(const AbstractType& type);
-  void RunDelayedTypePostprocessing();
-
-  void EnqueueRehashingOfMap(const LinkedHashMap& map);
-  void EnqueueRehashingOfSet(const LinkedHashSet& set);
-  ObjectPtr RunDelayedRehashingOfMapsAndSets();
-
-  ClassPtr ReadClassId(intptr_t object_id);
-  ObjectPtr ReadStaticImplicitClosure(intptr_t object_id, intptr_t cls_header);
-
-  // Implementation to read an object.
-  ObjectPtr ReadObjectImpl(bool as_reference);
-  ObjectPtr ReadObjectImpl(intptr_t header, bool as_reference);
-
-  // Read a Dart Instance object.
-  ObjectPtr ReadInstance(intptr_t object_id, intptr_t tags, bool as_reference);
-
-  // Read a VM isolate object that was serialized as an Id.
-  ObjectPtr ReadVMIsolateObject(intptr_t object_id);
-
-  // Read an object that was serialized as an Id (singleton in object store,
-  // or an object that was already serialized before).
-  ObjectPtr ReadIndexedObject(intptr_t object_id);
-
-  // Decode class id from the header field.
-  intptr_t LookupInternalClass(intptr_t class_header);
-
-  void ArrayReadFrom(intptr_t object_id,
-                     const Array& result,
-                     intptr_t len,
-                     intptr_t tags);
-
-  void MapReadFrom(intptr_t object_id,
-                   const LinkedHashMap& result,
-                   intptr_t tags);
-
-  void SetReadFrom(intptr_t object_id,
-                   const LinkedHashSet& result,
-                   intptr_t tags);
-
-  intptr_t NextAvailableObjectId() const;
-
-  void SetReadException(const char* msg);
-
-  ObjectPtr VmIsolateSnapshotObject(intptr_t index) const;
-
-  bool is_vm_isolate() const;
-
-  Snapshot::Kind kind_;             // Indicates type of the snapshot.
-  Thread* thread_;                  // Current thread.
-  Zone* zone_;                      // Zone for allocations while reading.
-  Heap* heap_;                      // Heap of the current isolate.
-  PageSpace* old_space_;            // Old space of the current isolate.
-  Class& cls_;                      // Temporary Class handle.
-  Code& code_;                      // Temporary Code handle.
-  Instance& instance_;              // Temporary Instance handle
-  Instructions& instructions_;      // Temporary Instructions handle
-  Object& obj_;                     // Temporary Object handle.
-  PassiveObject& pobj_;             // Temporary PassiveObject handle.
-  Array& array_;                    // Temporary Array handle.
-  Field& field_;                    // Temporary Field handle.
-  String& str_;                     // Temporary String handle.
-  Library& library_;                // Temporary library handle.
-  AbstractType& type_;              // Temporary type handle.
-  TypeArguments& type_arguments_;   // Temporary type argument handle.
-  GrowableObjectArray& tokens_;     // Temporary tokens handle.
-  ExternalTypedData& data_;         // Temporary stream data handle.
-  TypedDataBase& typed_data_base_;  // Temporary typed data base handle.
-  TypedData& typed_data_;           // Temporary typed data handle.
-  TypedDataView& typed_data_view_;  // Temporary typed data view handle.
-  Function& function_;              // Temporary function handle.
-  Smi& smi_;                        // Temporary Smi handle.
-  UnhandledException& error_;       // Error handle.
-  const Class& set_class_;          // The LinkedHashSet class.
-  intptr_t max_vm_isolate_object_id_;
-  ZoneGrowableArray<BackRefNode>* backward_references_;
-  GrowableObjectArray& types_to_postprocess_;
-  GrowableObjectArray& objects_to_rehash_;
-
-  friend class ApiError;
-  friend class Array;
-  friend class Class;
-  friend class Closure;
-  friend class ClosureData;
-  friend class Context;
-  friend class ContextScope;
-  friend class ExceptionHandlers;
-  friend class Field;
-  friend class Function;
-  friend class GrowableObjectArray;
-  friend class ICData;
-  friend class ImmutableArray;
-  friend class KernelProgramInfo;
-  friend class LanguageError;
-  friend class Library;
-  friend class LibraryPrefix;
-  friend class LinkedHashMap;
-  friend class LinkedHashSet;
-  friend class MirrorReference;
-  friend class Namespace;
-  friend class PatchClass;
-  friend class RegExp;
-  friend class Script;
-  friend class SubtypeTestCache;
-  friend class TransferableTypedData;
-  friend class Type;
-  friend class FunctionType;
-  friend class TypedDataView;
-  friend class TypeParameters;
-  friend class TypeArguments;
-  friend class TypeParameter;
-  friend class TypeRef;
-  friend class UnhandledException;
-  friend class WeakProperty;
-  friend class WeakSerializationReference;
-  DISALLOW_COPY_AND_ASSIGN(SnapshotReader);
-};
-
-class MessageSnapshotReader : public SnapshotReader {
- public:
-  MessageSnapshotReader(Message* message, Thread* thread);
-  ~MessageSnapshotReader();
-
-  MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
-
- private:
-  MessageFinalizableData* finalizable_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageSnapshotReader);
-};
-
-class BaseWriter : public StackResource {
- public:
-  uint8_t* Steal(intptr_t* length) { return stream_.Steal(length); }
-  intptr_t BytesWritten() const { return stream_.bytes_written(); }
-
-  // Writes raw data to the stream (basic type).
-  // sizeof(T) must be in {1,2,4,8}.
-  template <typename T>
-  void Write(T value) {
-    MallocWriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
-  }
-
-  void WriteClassIDValue(classid_t value) { Write<uint32_t>(value); }
-  COMPILE_ASSERT(sizeof(uint32_t) >= sizeof(classid_t));
-
-  // Write an object that is serialized as an Id (singleton in object store,
-  // or an object that was already serialized before).
-  void WriteIndexedObject(intptr_t object_id) {
-    ASSERT(object_id <= kMaxObjectId);
-    intptr_t value = 0;
-    value = SerializedHeaderTag::update(kObjectId, value);
-    value = SerializedHeaderData::update(object_id, value);
-    Write<int32_t>(value);
-  }
-
-  // Write a VM Isolateobject that is serialized as an Id.
-  void WriteVMIsolateObject(intptr_t object_id) {
-    ASSERT(object_id <= kMaxObjectId);
-    intptr_t value = 0;
-    value = SerializedHeaderTag::update(kObjectId, value);
-    value = SerializedHeaderData::update(object_id, value);
-    Write<int32_t>(-value);  // Write as a negative value.
-  }
-
-  // Write serialization header information for an object.
-  void WriteInlinedObjectHeader(intptr_t id) {
-    ASSERT(id <= kMaxObjectId);
-    intptr_t value = 0;
-    value = SerializedHeaderTag::update(kInlined, value);
-    value = SerializedHeaderData::update(id, value);
-    Write<int32_t>(value);
-  }
-
-  void WriteTags(intptr_t tags) {
-    const intptr_t flags = tags & 0xff;
-    Write<int8_t>(static_cast<int8_t>(flags));
-  }
-
-  void Align(intptr_t value) { stream_.Align(value); }
-
-  // Write out a buffer of bytes.
-  void WriteBytes(const uint8_t* addr, intptr_t len) {
-    stream_.WriteBytes(addr, len);
-  }
-
-  void WriteDouble(double value) {
-    stream_.WriteBytes(reinterpret_cast<const uint8_t*>(&value), sizeof(value));
-  }
-
-  void WriteWordWith32BitWrites(uword value) {
-    stream_.WriteWordWith32BitWrites(value);
-  }
-
- protected:
-  explicit BaseWriter(intptr_t initial_size)
-      : StackResource(Thread::Current()), stream_(initial_size) {}
-  ~BaseWriter() {}
-
-  void ReserveHeader() {
-    // Make room for recording snapshot buffer size.
-    stream_.SetPosition(Snapshot::kHeaderSize);
-  }
-
-  void FillHeader(Snapshot::Kind kind) {
-    intptr_t length;
-    Snapshot* header = reinterpret_cast<Snapshot*>(Steal(&length));
-    header->set_magic();
-    header->set_length(length);
-    header->set_kind(kind);
-  }
-
-  void FreeBuffer() {
-    intptr_t unused;
-    free(Steal(&unused));
-  }
-
- private:
-  MallocWriteStream stream_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(BaseWriter);
-};
-
-class ForwardList {
- public:
-  explicit ForwardList(Thread* thread, intptr_t first_object_id);
-  ~ForwardList();
-
-  class Node : public ZoneAllocated {
-   public:
-    Node(const Object* obj, SerializeState state) : obj_(obj), state_(state) {}
-    const Object* obj() const { return obj_; }
-    bool is_serialized() const { return state_ == kIsSerialized; }
-
-   private:
-    // Private to ensure the invariant of first_unprocessed_object_id_.
-    void set_state(SerializeState value) { state_ = value; }
-
-    const Object* obj_;
-    SerializeState state_;
-
-    friend class ForwardList;
-    DISALLOW_COPY_AND_ASSIGN(Node);
-  };
-
-  Node* NodeForObjectId(intptr_t object_id) const {
-    return nodes_[object_id - first_object_id_];
-  }
-
-  // Returns the id for the added object.
-  intptr_t AddObject(Zone* zone, ObjectPtr raw, SerializeState state);
-
-  // Returns the id for the object it it exists in the list.
-  intptr_t FindObject(ObjectPtr raw);
-
-  // Exhaustively processes all unserialized objects in this list. 'writer' may
-  // concurrently add more objects.
-  void SerializeAll(ObjectVisitor* writer);
-
-  // Set state of object in forward list.
-  void SetState(intptr_t object_id, SerializeState state) {
-    NodeForObjectId(object_id)->set_state(state);
-  }
-
- private:
-  intptr_t first_object_id() const { return first_object_id_; }
-  intptr_t next_object_id() const { return nodes_.length() + first_object_id_; }
-  Isolate* isolate() const { return thread_->isolate(); }
-
-  Thread* thread_;
-  const intptr_t first_object_id_;
-  GrowableArray<Node*> nodes_;
-  intptr_t first_unprocessed_object_id_;
-
-  void SetObjectId(ObjectPtr object, intptr_t id);
-  intptr_t GetObjectId(ObjectPtr object);
-
-  DISALLOW_COPY_AND_ASSIGN(ForwardList);
-};
-
-class SnapshotWriter : public BaseWriter {
- protected:
-  SnapshotWriter(Thread* thread,
-                 Snapshot::Kind kind,
-                 intptr_t initial_size,
-                 ForwardList* forward_list,
-                 bool can_send_any_object);
-
- public:
-  // Snapshot kind.
-  Snapshot::Kind kind() const { return kind_; }
-  Thread* thread() const { return thread_; }
-  Zone* zone() const { return thread_->zone(); }
-  Isolate* isolate() const { return thread_->isolate(); }
-  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
-  Heap* heap() const { return isolate_group()->heap(); }
-
-  // Serialize an object into the buffer.
-  void WriteObject(ObjectPtr raw);
-
-  static uint32_t GetObjectTags(ObjectPtr raw);
-  static uint32_t GetObjectTags(UntaggedObject* raw);
-  static uword GetObjectTagsAndHash(ObjectPtr raw);
-
-  Exceptions::ExceptionType exception_type() const { return exception_type_; }
-  void set_exception_type(Exceptions::ExceptionType type) {
-    exception_type_ = type;
-  }
-  const char* exception_msg() const { return exception_msg_; }
-  void set_exception_msg(const char* msg) { exception_msg_ = msg; }
-  bool can_send_any_object() const { return can_send_any_object_; }
-  void ThrowException(Exceptions::ExceptionType type, const char* msg);
-
-  // Write a version string for the snapshot.
-  void WriteVersionAndFeatures();
-
-  FunctionPtr IsSerializableClosure(ClosurePtr closure);
-
-  void WriteStaticImplicitClosure(intptr_t object_id,
-                                  FunctionPtr func,
-                                  intptr_t tags,
-                                  TypeArgumentsPtr delayed_type_arguments);
-
- protected:
-  bool CheckAndWritePredefinedObject(ObjectPtr raw);
-  bool HandleVMIsolateObject(ObjectPtr raw);
-
-  void WriteClassId(UntaggedClass* cls);
-  void WriteObjectImpl(ObjectPtr raw, bool as_reference);
-  void WriteMarkedObjectImpl(ObjectPtr raw,
-                             intptr_t tags,
-                             intptr_t object_id,
-                             bool as_reference);
-  void WriteForwardedObjects();
-  void ArrayWriteTo(intptr_t object_id,
-                    intptr_t array_kind,
-                    intptr_t tags,
-                    SmiPtr length,
-                    TypeArgumentsPtr type_arguments,
-                    CompressedObjectPtr data[],
-                    bool as_reference);
-  void MapWriteTo(intptr_t object_id,
-                  intptr_t class_id,
-                  intptr_t tags,
-                  TypeArgumentsPtr type_arguments,
-                  SmiPtr used_data_smi,
-                  SmiPtr deleted_keys_smi,
-                  ArrayPtr data,
-                  bool as_reference);
-  void SetWriteTo(intptr_t object_id,
-                  intptr_t class_id,
-                  intptr_t tags,
-                  TypeArgumentsPtr type_arguments,
-                  SmiPtr used_data_smi,
-                  SmiPtr deleted_keys_smi,
-                  ArrayPtr data,
-                  bool as_reference);
-  ClassPtr GetFunctionOwner(FunctionPtr func);
-  void CheckForNativeFields(ClassPtr cls);
-  void SetWriteException(Exceptions::ExceptionType type, const char* msg);
-  void WriteInstance(ObjectPtr raw,
-                     ClassPtr cls,
-                     intptr_t tags,
-                     intptr_t object_id,
-                     bool as_reference);
-  bool AllowObjectsInDartLibrary(LibraryPtr library);
-  intptr_t FindVmSnapshotObject(ObjectPtr rawobj);
-
-  ObjectStore* object_store() const { return object_store_; }
-
- private:
-  Thread* thread_;
-  Snapshot::Kind kind_;
-  ObjectStore* object_store_;  // Object store for common classes.
-  ClassTable* class_table_;  // Class table for the class index to class lookup.
-  ForwardList* forward_list_;
-  Exceptions::ExceptionType exception_type_;  // Exception type.
-  const char* exception_msg_;  // Message associated with exception.
-  bool can_send_any_object_;   // True if any Dart instance can be sent.
-
-  friend class UntaggedArray;
-  friend class UntaggedClass;
-  friend class UntaggedCode;
-  friend class UntaggedContextScope;
-  friend class UntaggedDynamicLibrary;
-  friend class UntaggedExceptionHandlers;
-  friend class UntaggedField;
-  friend class UntaggedFunction;
-  friend class UntaggedFunctionType;
-  friend class UntaggedGrowableObjectArray;
-  friend class UntaggedImmutableArray;
-  friend class UntaggedInstructions;
-  friend class UntaggedLibrary;
-  friend class UntaggedLinkedHashMap;
-  friend class UntaggedLinkedHashSet;
-  friend class UntaggedLocalVarDescriptors;
-  friend class UntaggedMirrorReference;
-  friend class UntaggedObjectPool;
-  friend class UntaggedPointer;
-  friend class UntaggedReceivePort;
-  friend class UntaggedRegExp;
-  friend class UntaggedScript;
-  friend class UntaggedStackTrace;
-  friend class UntaggedSubtypeTestCache;
-  friend class UntaggedTransferableTypedData;
-  friend class UntaggedType;
-  friend class UntaggedTypeArguments;
-  friend class UntaggedTypeParameter;
-  friend class UntaggedTypeRef;
-  friend class UntaggedTypedDataView;
-  friend class UntaggedUserTag;
-  friend class UntaggedWeakSerializationReference;
-  friend class SnapshotWriterVisitor;
-  friend class WriteInlinedObjectVisitor;
-  DISALLOW_COPY_AND_ASSIGN(SnapshotWriter);
-};
-
 class SerializedObjectBuffer : public StackResource {
  public:
   SerializedObjectBuffer()
@@ -749,46 +130,6 @@
   std::unique_ptr<Message> message_;
 };
 
-class MessageWriter : public SnapshotWriter {
- public:
-  static const intptr_t kInitialSize = 512;
-  explicit MessageWriter(bool can_send_any_object);
-  ~MessageWriter();
-
-  std::unique_ptr<Message> WriteMessage(const Object& obj,
-                                        Dart_Port dest_port,
-                                        Message::Priority priority);
-
-  MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
-
- private:
-  ForwardList forward_list_;
-  MessageFinalizableData* finalizable_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageWriter);
-};
-
-// An object pointer visitor implementation which writes out
-// objects to a snapshot.
-class SnapshotWriterVisitor : public ObjectPointerVisitor {
- public:
-  SnapshotWriterVisitor(SnapshotWriter* writer, bool as_references)
-      : ObjectPointerVisitor(Isolate::Current()->group()),
-        writer_(writer),
-        as_references_(as_references) {}
-
-  void VisitPointers(ObjectPtr* first, ObjectPtr* last);
-  void VisitCompressedPointers(uword heap_base,
-                               CompressedObjectPtr* first,
-                               CompressedObjectPtr* last);
-
- private:
-  SnapshotWriter* writer_;
-  bool as_references_;
-
-  DISALLOW_COPY_AND_ASSIGN(SnapshotWriterVisitor);
-};
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_SNAPSHOT_H_
diff --git a/runtime/vm/snapshot_ids.h b/runtime/vm/snapshot_ids.h
deleted file mode 100644
index b38bf1b..0000000
--- a/runtime/vm/snapshot_ids.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2012, 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.
-
-#ifndef RUNTIME_VM_SNAPSHOT_IDS_H_
-#define RUNTIME_VM_SNAPSHOT_IDS_H_
-
-#include "vm/dart_entry.h"
-#include "vm/raw_object.h"
-
-namespace dart {
-
-// Index for predefined singleton objects used in a snapshot.
-enum {
-  kNullObject = 0,
-  kSentinelObject,
-  kTransitionSentinelObject,
-  kEmptyArrayObject,
-  kZeroArrayObject,
-  kTrueValue,
-  kFalseValue,
-  // Marker for special encoding of double objects in message snapshots.
-  kDoubleObject,
-  // Object id has been optimized away; reader should use next available id.
-  kOmittedObjectId,
-
-  kClassIdsOffset = kOmittedObjectId,
-
-  // The class ids of predefined classes are included in this list
-  // at an offset of kClassIdsOffset.
-
-  kFirstTypeSnapshotId = (kNumPredefinedCids + kClassIdsOffset),
-  kLegacyObjectType = kFirstTypeSnapshotId,
-  kNullableObjectType,
-  kNullType,
-  kDynamicType,
-  kVoidType,
-  kNeverType,
-  kLegacyFunctionType,
-  kLegacyNumberType,
-  kLegacySmiType,
-  kLegacyMintType,
-  kLegacyDoubleType,
-  kLegacyIntType,
-  kLegacyBoolType,
-  kLegacyStringType,
-  kLegacyArrayType,
-  kNonNullableObjectType,
-  kNonNullableFunctionType,
-  kNonNullableNumberType,
-  kNonNullableSmiType,
-  kNonNullableMintType,
-  kNonNullableDoubleType,
-  kNonNullableIntType,
-  kNonNullableBoolType,
-  kNonNullableStringType,
-  kNonNullableArrayType,
-  kLastTypeSnapshotId = kNonNullableArrayType,
-
-  kFirstTypeArgumentsSnapshotId = kLastTypeSnapshotId + 1,
-  kLegacyIntTypeArguments = kFirstTypeArgumentsSnapshotId,
-  kLegacyDoubleTypeArguments,
-  kLegacyStringTypeArguments,
-  kLegacyStringDynamicTypeArguments,
-  kLegacyStringLegacyStringTypeArguments,
-  kNonNullableIntTypeArguments,
-  kNonNullableDoubleTypeArguments,
-  kNonNullableStringTypeArguments,
-  kNonNullableStringDynamicTypeArguments,
-  kNonNullableStringNonNullableStringTypeArguments,
-  kEmptyTypeArguments,
-  kLastTypeArgumentsSnapshotId = kEmptyTypeArguments,
-
-  kExtractorParameterTypes,
-  kExtractorParameterNames,
-  kEmptyContextScopeObject,
-  kImplicitClosureScopeObject,
-  kEmptyObjectPool,
-  kEmptyDescriptors,
-  kEmptyVarDescriptors,
-  kEmptyExceptionHandlers,
-  kCachedArgumentsDescriptor0,
-  kCachedArgumentsDescriptorN =
-      (kCachedArgumentsDescriptor0 +
-       ArgumentsDescriptor::kCachedDescriptorCount - 1),
-  kCachedICDataArray0,
-  kCachedICDataArrayN =
-      (kCachedICDataArray0 + ICData::kCachedICDataArrayCount - 1),
-
-  kInstanceObjectId,
-  kStaticImplicitClosureObjectId,
-  kMaxPredefinedObjectIds,
-  kInvalidIndex = -1,
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_SNAPSHOT_IDS_H_
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 944124f..8affadb 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -15,6 +15,7 @@
 #include "vm/debugger_api_impl_test.h"
 #include "vm/flags.h"
 #include "vm/malloc_hooks.h"
+#include "vm/message_snapshot.h"
 #include "vm/snapshot.h"
 #include "vm/symbols.h"
 #include "vm/timer.h"
@@ -59,7 +60,6 @@
   // Return immediately if entering a cycle.
   if (second->type == Dart_CObject_kNumberOfTypes) return;
 
-  EXPECT_NE(first, second);
   EXPECT_EQ(first->type, second->type);
   switch (first->type) {
     case Dart_CObject_kNull:
@@ -106,23 +106,20 @@
   }
 }
 
-static void CheckEncodeDecodeMessage(Dart_CObject* root) {
+static void CheckEncodeDecodeMessage(Zone* zone, Dart_CObject* root) {
   // Encode and decode the message.
-  ApiMessageWriter writer;
   std::unique_ptr<Message> message =
-      writer.WriteCMessage(root, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteApiMessage(zone, root, ILLEGAL_PORT, Message::kNormalPriority);
 
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* new_root = api_reader.ReadMessage();
+  Dart_CObject* new_root = ReadApiMessage(zone, message.get());
 
   // Check that the two messages are the same.
   CompareDartCObjects(root, new_root);
 }
 
-static void ExpectEncodeFail(Dart_CObject* root) {
-  ApiMessageWriter writer;
+static void ExpectEncodeFail(Zone* zone, Dart_CObject* root) {
   std::unique_ptr<Message> message =
-      writer.WriteCMessage(root, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteApiMessage(zone, root, ILLEGAL_PORT, Message::kNormalPriority);
   EXPECT(message == nullptr);
 }
 
@@ -131,22 +128,21 @@
 
   // Write snapshot with object content.
   const Object& null_object = Object::Handle();
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(null_object, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, null_object, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   EXPECT(Equals(null_object, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kNull, root->type);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeSmi1) {
@@ -154,23 +150,22 @@
 
   // Write snapshot with object content.
   const Smi& smi = Smi::Handle(Smi::New(124));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, smi, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   EXPECT(Equals(smi, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kInt32, root->type);
   EXPECT_EQ(smi.Value(), root->value.as_int32);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeSmi2) {
@@ -178,46 +173,44 @@
 
   // Write snapshot with object content.
   const Smi& smi = Smi::Handle(Smi::New(-1));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, smi, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   EXPECT(Equals(smi, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kInt32, root->type);
   EXPECT_EQ(smi.Value(), root->value.as_int32);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
-Dart_CObject* SerializeAndDeserializeMint(const Mint& mint) {
+Dart_CObject* SerializeAndDeserializeMint(Zone* zone, const Mint& mint) {
   // Write snapshot with object content.
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(mint, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, mint, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   {
     // Switch to a regular zone, where VM handle allocation is allowed.
     Thread* thread = Thread::Current();
     StackZone zone(thread);
     // Read object back from the snapshot.
-    MessageSnapshotReader reader(message.get(), thread);
-    const Object& serialized_object = Object::Handle(reader.ReadObject());
+    const Object& serialized_object =
+        Object::Handle(ReadMessage(thread, message.get()));
     EXPECT(serialized_object.IsMint());
   }
 
   // Read object back from the snapshot into a C structure.
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(zone, message.get());
   EXPECT_NOTNULL(root);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(zone, root);
   return root;
 }
 
@@ -227,7 +220,8 @@
 
   Mint& mint = Mint::Handle();
   mint ^= Integer::New(value);
-  Dart_CObject* mint_cobject = SerializeAndDeserializeMint(mint);
+  Dart_CObject* mint_cobject =
+      SerializeAndDeserializeMint(zone.GetZone(), mint);
 // On 64-bit platforms mints always require 64-bits as the smi range
 // here covers most of the 64-bit range. On 32-bit platforms the smi
 // range covers most of the 32-bit range and values outside that
@@ -270,23 +264,22 @@
 
   // Write snapshot with object content.
   const Double& dbl = Double::Handle(Double::New(101.29));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(dbl, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, dbl, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   EXPECT(Equals(dbl, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kDouble, root->type);
   EXPECT_EQ(dbl.value(), root->value.as_double);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeTrue) {
@@ -294,25 +287,24 @@
 
   // Write snapshot with true object.
   const Bool& bl = Bool::True();
-  MessageWriter writer(true);
-  std::unique_ptr<Message> message =
-      writer.WriteMessage(bl, ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* can_send_any_object */ true, bl, ILLEGAL_PORT,
+      Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   fprintf(stderr, "%s / %s\n", bl.ToCString(), serialized_object.ToCString());
 
   EXPECT(Equals(bl, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kBool, root->type);
   EXPECT_EQ(true, root->value.as_bool);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeFalse) {
@@ -320,57 +312,55 @@
 
   // Write snapshot with false object.
   const Bool& bl = Bool::False();
-  MessageWriter writer(true);
-  std::unique_ptr<Message> message =
-      writer.WriteMessage(bl, ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* can_send_any_object */ true, bl, ILLEGAL_PORT,
+      Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
-  const Object& serialized_object = Object::Handle(reader.ReadObject());
+  const Object& serialized_object =
+      Object::Handle(ReadMessage(thread, message.get()));
   EXPECT(Equals(bl, serialized_object));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kBool, root->type);
   EXPECT_EQ(false, root->value.as_bool);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeCapability) {
   // Write snapshot with object content.
   const Capability& capability = Capability::Handle(Capability::New(12345));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(capability, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, capability, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   Capability& obj = Capability::Handle();
-  obj ^= reader.ReadObject();
+  obj ^= ReadMessage(thread, message.get());
 
   EXPECT_EQ(static_cast<uint64_t>(12345), obj.Id());
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kCapability, root->type);
   int64_t id = root->value.as_capability.id;
   EXPECT_EQ(12345, id);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 #define TEST_ROUND_TRIP_IDENTICAL(object)                                      \
   {                                                                            \
-    MessageWriter writer(true);                                                \
-    std::unique_ptr<Message> message = writer.WriteMessage(                    \
-        Object::Handle(object), ILLEGAL_PORT, Message::kNormalPriority);       \
-    MessageSnapshotReader reader(message.get(), thread);                       \
-    EXPECT(reader.ReadObject() == object);                                     \
+    const Object& before = Object::Handle(object);                             \
+    std::unique_ptr<Message> message =                                         \
+        WriteMessage(/* can_send_any_object */ true, before, ILLEGAL_PORT,     \
+                     Message::kNormalPriority);                                \
+    const Object& after = Object::Handle(ReadMessage(thread, message.get()));  \
+    EXPECT(before.ptr() == after.ptr());                                       \
   }
 
 ISOLATE_UNIT_TEST_CASE(SerializeSingletons) {
@@ -393,23 +383,21 @@
   EXPECT(Utf8::IsValid(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr)));
   // Write snapshot with object content.
   String& str = String::Handle(String::New(cstr));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, str, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   String& serialized_str = String::Handle();
-  serialized_str ^= reader.ReadObject();
+  serialized_str ^= ReadMessage(thread, message.get());
   EXPECT(str.Equals(serialized_str));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kString, root->type);
   EXPECT_STREQ(cstr, root->value.as_string);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeString) {
@@ -436,20 +424,18 @@
     smi ^= Smi::New(i);
     array.SetAt(i, smi);
   }
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   Array& serialized_array = Array::Handle();
-  serialized_array ^= reader.ReadObject();
+  serialized_array ^= ReadMessage(thread, message.get());
   EXPECT(array.CanonicalizeEquals(serialized_array));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kArray, root->type);
   EXPECT_EQ(kArrayLength, root->value.as_array.length);
   for (int i = 0; i < kArrayLength; i++) {
@@ -457,7 +443,7 @@
     EXPECT_EQ(Dart_CObject_kInt32, element->type);
     EXPECT_EQ(i, element->value.as_int32);
   }
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeArrayWithTypeArgument) {
@@ -471,20 +457,18 @@
     smi ^= Smi::New(i);
     array.SetAt(i, smi);
   }
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   Array& serialized_array = Array::Handle();
-  serialized_array ^= reader.ReadObject();
+  serialized_array ^= ReadMessage(thread, message.get());
   EXPECT(array.CanonicalizeEquals(serialized_array));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kArray, root->type);
   EXPECT_EQ(kArrayLength, root->value.as_array.length);
   for (int i = 0; i < kArrayLength; i++) {
@@ -492,7 +476,7 @@
     EXPECT_EQ(Dart_CObject_kInt32, element->type);
     EXPECT_EQ(i, element->value.as_int32);
   }
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 TEST_CASE(FailSerializeLargeArray) {
@@ -500,7 +484,8 @@
   root.type = Dart_CObject_kArray;
   root.value.as_array.length = Array::kMaxElements + 1;
   root.value.as_array.values = NULL;
-  ExpectEncodeFail(&root);
+  ApiNativeScope scope;
+  ExpectEncodeFail(scope.zone(), &root);
 }
 
 TEST_CASE(FailSerializeLargeNestedArray) {
@@ -513,7 +498,8 @@
   parent.value.as_array.values = values;
   child.type = Dart_CObject_kArray;
   child.value.as_array.length = Array::kMaxElements + 1;
-  ExpectEncodeFail(&parent);
+  ApiNativeScope scope;
+  ExpectEncodeFail(scope.zone(), &parent);
 }
 
 TEST_CASE(FailSerializeLargeTypedDataInt8) {
@@ -522,7 +508,8 @@
   root.value.as_typed_data.type = Dart_TypedData_kInt8;
   root.value.as_typed_data.length =
       TypedData::MaxElements(kTypedDataInt8ArrayCid) + 1;
-  ExpectEncodeFail(&root);
+  ApiNativeScope scope;
+  ExpectEncodeFail(scope.zone(), &root);
 }
 
 TEST_CASE(FailSerializeLargeTypedDataUint8) {
@@ -531,39 +518,40 @@
   root.value.as_typed_data.type = Dart_TypedData_kUint8;
   root.value.as_typed_data.length =
       TypedData::MaxElements(kTypedDataUint8ArrayCid) + 1;
-  ExpectEncodeFail(&root);
+  ApiNativeScope scope;
+  ExpectEncodeFail(scope.zone(), &root);
 }
 
 TEST_CASE(FailSerializeLargeExternalTypedData) {
   Dart_CObject root;
   root.type = Dart_CObject_kExternalTypedData;
-  root.value.as_typed_data.length =
+  root.value.as_external_typed_data.type = Dart_TypedData_kUint8;
+  root.value.as_external_typed_data.length =
       ExternalTypedData::MaxElements(kExternalTypedDataUint8ArrayCid) + 1;
-  ExpectEncodeFail(&root);
+  ApiNativeScope scope;
+  ExpectEncodeFail(scope.zone(), &root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeEmptyArray) {
   // Write snapshot with object content.
   const int kArrayLength = 0;
   Array& array = Array::Handle(Array::New(kArrayLength));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   Array& serialized_array = Array::Handle();
-  serialized_array ^= reader.ReadObject();
+  serialized_array ^= ReadMessage(thread, message.get());
   EXPECT(array.CanonicalizeEquals(serialized_array));
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kArray, root->type);
   EXPECT_EQ(kArrayLength, root->value.as_array.length);
   EXPECT(root->value.as_array.values == NULL);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 ISOLATE_UNIT_TEST_CASE(SerializeByteArray) {
@@ -574,26 +562,24 @@
   for (int i = 0; i < kTypedDataLength; i++) {
     typed_data.SetUint8(i, i);
   }
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(typed_data, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, typed_data, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   TypedData& serialized_typed_data = TypedData::Handle();
-  serialized_typed_data ^= reader.ReadObject();
+  serialized_typed_data ^= ReadMessage(thread, message.get());
   EXPECT(serialized_typed_data.IsTypedData());
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kTypedData, root->type);
   EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
   for (int i = 0; i < kTypedDataLength; i++) {
     EXPECT(root->value.as_typed_data.values[i] == i);
   }
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 #define TEST_TYPED_ARRAY(darttype, ctype)                                      \
@@ -606,12 +592,11 @@
     for (int i = 0; i < kArrayLength; i++) {                                   \
       array.Set##darttype((i * scale), i);                                     \
     }                                                                          \
-    MessageWriter writer(true);                                                \
     std::unique_ptr<Message> message =                                         \
-        writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);    \
-    MessageSnapshotReader reader(message.get(), thread);                       \
+        WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,      \
+                     Message::kNormalPriority);                                \
     TypedData& serialized_array = TypedData::Handle();                         \
-    serialized_array ^= reader.ReadObject();                                   \
+    serialized_array ^= ReadMessage(thread, message.get());                    \
     for (int i = 0; i < kArrayLength; i++) {                                   \
       EXPECT_EQ(static_cast<ctype>(i),                                         \
                 serialized_array.Get##darttype(i* scale));                     \
@@ -627,12 +612,11 @@
         ExternalTypedData::New(kExternalTypedData##darttype##ArrayCid,         \
                                reinterpret_cast<uint8_t*>(data), length));     \
     intptr_t scale = array.ElementSizeInBytes();                               \
-    MessageWriter writer(true);                                                \
     std::unique_ptr<Message> message =                                         \
-        writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);    \
-    MessageSnapshotReader reader(message.get(), thread);                       \
+        WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,      \
+                     Message::kNormalPriority);                                \
     ExternalTypedData& serialized_array = ExternalTypedData::Handle();         \
-    serialized_array ^= reader.ReadObject();                                   \
+    serialized_array ^= ReadMessage(thread, message.get());                    \
     for (int i = 0; i < length; i++) {                                         \
       EXPECT_EQ(static_cast<ctype>(data[i]),                                   \
                 serialized_array.Get##darttype(i* scale));                     \
@@ -670,25 +654,23 @@
   const int kTypedDataLength = 0;
   TypedData& typed_data = TypedData::Handle(
       TypedData::New(kTypedDataUint8ArrayCid, kTypedDataLength));
-  MessageWriter writer(true);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(typed_data, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ true, typed_data, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
-  MessageSnapshotReader reader(message.get(), thread);
   TypedData& serialized_typed_data = TypedData::Handle();
-  serialized_typed_data ^= reader.ReadObject();
+  serialized_typed_data ^= ReadMessage(thread, message.get());
   EXPECT(serialized_typed_data.IsTypedData());
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
   EXPECT_EQ(Dart_CObject_kTypedData, root->type);
   EXPECT_EQ(Dart_TypedData_kUint8, root->value.as_typed_data.type);
   EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
   EXPECT(root->value.as_typed_data.values == NULL);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(scope.zone(), root);
 }
 
 VM_UNIT_TEST_CASE(FullSnapshot) {
@@ -790,47 +772,38 @@
   Object& obj = Object::Handle(Api::UnwrapHandle(result));
 
   // Serialize the object into a message.
-  MessageWriter writer(false);
-  return writer.WriteMessage(obj, ILLEGAL_PORT, Message::kNormalPriority);
-}
-
-// Helper function to deserialize the result into a Dart_CObject structure.
-static Dart_CObject* GetDeserialized(Message* message) {
-  // Read object back from the snapshot into a C structure.
-  ApiMessageReader api_reader(message);
-  return api_reader.ReadMessage();
+  return WriteMessage(/* can_send_any_object */ false, obj, ILLEGAL_PORT,
+                      Message::kNormalPriority);
 }
 
 static void CheckString(Dart_Handle dart_string, const char* expected) {
   StackZone zone(Thread::Current());
   String& str = String::Handle();
   str ^= Api::UnwrapHandle(dart_string);
-  MessageWriter writer(false);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ false, str, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(zone.GetZone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kString, root->type);
   EXPECT_STREQ(expected, root->value.as_string);
-  CheckEncodeDecodeMessage(root);
+  CheckEncodeDecodeMessage(zone.GetZone(), root);
 }
 
 static void CheckStringInvalid(Dart_Handle dart_string) {
   StackZone zone(Thread::Current());
   String& str = String::Handle();
   str ^= Api::UnwrapHandle(dart_string);
-  MessageWriter writer(false);
   std::unique_ptr<Message> message =
-      writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* can_send_any_object */ false, str, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
-  ApiMessageReader api_reader(message.get());
-  Dart_CObject* root = api_reader.ReadMessage();
+  Dart_CObject* root = ReadApiMessage(zone.GetZone(), message.get());
   EXPECT_NOTNULL(root);
   EXPECT_EQ(Dart_CObject_kUnsupported, root->type);
 }
@@ -928,18 +901,17 @@
       StackZone zone(thread);
       Smi& smi = Smi::Handle();
       smi ^= Api::UnwrapHandle(smi_result);
-      MessageWriter writer(false);
       std::unique_ptr<Message> message =
-          writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
+          WriteMessage(/* can_send_any_object */ false, smi, ILLEGAL_PORT,
+                       Message::kNormalPriority);
 
       // Read object back from the snapshot into a C structure.
       ApiNativeScope scope;
-      ApiMessageReader api_reader(message.get());
-      Dart_CObject* root = api_reader.ReadMessage();
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kInt32, root->type);
       EXPECT_EQ(42, root->value.as_int32);
-      CheckEncodeDecodeMessage(root);
+      CheckEncodeDecodeMessage(scope.zone(), root);
     }
     CheckString(ascii_string_result, "Hello, world!");
     CheckString(non_ascii_string_result, "Blåbærgrød");
@@ -1000,20 +972,20 @@
       // Generate a list of nulls from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
       for (int i = 0; i < kArrayLength; i++) {
         EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
       }
-      CheckEncodeDecodeMessage(root);
+      CheckEncodeDecodeMessage(scope.zone(), root);
     }
     {
       // Generate a list of ints from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1021,13 +993,13 @@
         EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[i]->type);
         EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
       }
-      CheckEncodeDecodeMessage(root);
+      CheckEncodeDecodeMessage(scope.zone(), root);
     }
     {
       // Generate a list of strings from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1042,7 +1014,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1124,20 +1096,20 @@
       // Generate a list of nulls from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
       for (int i = 0; i < kArrayLength; i++) {
         EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
       }
-      CheckEncodeDecodeMessage(root);
+      CheckEncodeDecodeMessage(scope.zone(), root);
     }
     {
       // Generate a list of ints from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1145,13 +1117,13 @@
         EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[i]->type);
         EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
       }
-      CheckEncodeDecodeMessage(root);
+      CheckEncodeDecodeMessage(scope.zone(), root);
     }
     {
       // Generate a list of strings from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1166,7 +1138,7 @@
       // Generate a list of lists from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getListList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1185,7 +1157,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1357,7 +1329,7 @@
       // Generate a list of strings from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1372,7 +1344,7 @@
       // Generate a list of medium ints from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1387,7 +1359,7 @@
       // Generate a list of doubles from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1396,8 +1368,6 @@
       EXPECT_EQ(3.14, element->value.as_double);
       for (int i = 1; i < kArrayLength; i++) {
         element = root->value.as_array.values[i];
-        // Double values are expected to not be canonicalized in messages.
-        EXPECT_NE(root->value.as_array.values[0], element);
         EXPECT_EQ(Dart_CObject_kDouble, element->type);
         EXPECT_EQ(3.14, element->value.as_double);
       }
@@ -1406,7 +1376,7 @@
       // Generate a list of Uint8Lists from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1423,7 +1393,7 @@
       std::unique_ptr<Message> message =
           GetSerialized(lib, "getTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1441,7 +1411,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1458,8 +1428,6 @@
           EXPECT_EQ(Dart_CObject_kString, element->type);
           EXPECT_STREQ("A", element->value.as_string);
         } else {
-          // Double values are expected to not be canonicalized in messages.
-          EXPECT_NE(root->value.as_array.values[1], element);
           EXPECT_EQ(Dart_CObject_kDouble, element->type);
           EXPECT_EQ(2.72, element->value.as_double);
         }
@@ -1469,7 +1437,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1560,7 +1528,7 @@
       // Generate a list of strings from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1575,7 +1543,7 @@
       // Generate a list of medium ints from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1590,18 +1558,15 @@
       // Generate a list of doubles from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
       Dart_CObject* element = root->value.as_array.values[0];
-      // Double values are expected to not be canonicalized in messages.
       EXPECT_EQ(Dart_CObject_kDouble, element->type);
       EXPECT_EQ(3.14, element->value.as_double);
       for (int i = 1; i < kArrayLength; i++) {
         element = root->value.as_array.values[i];
-        // Double values are expected to not be canonicalized in messages.
-        EXPECT_NE(root->value.as_array.values[0], element);
         EXPECT_EQ(Dart_CObject_kDouble, element->type);
         EXPECT_EQ(3.14, element->value.as_double);
       }
@@ -1610,7 +1575,7 @@
       // Generate a list of Uint8Lists from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1627,7 +1592,7 @@
       std::unique_ptr<Message> message =
           GetSerialized(lib, "getTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1645,7 +1610,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1662,8 +1627,6 @@
           EXPECT_EQ(Dart_CObject_kString, element->type);
           EXPECT_STREQ(".", element->value.as_string);
         } else {
-          // Double values are expected to not be canonicalized in messages.
-          EXPECT_NE(root->value.as_array.values[1], element);
           EXPECT_EQ(Dart_CObject_kDouble, element->type);
           EXPECT_EQ(2.72, element->value.as_double);
         }
@@ -1673,7 +1636,7 @@
       // Generate a list of objects of different types from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1806,7 +1769,7 @@
       // Generate a list of Uint8Lists from Dart code.
       std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -1834,7 +1797,7 @@
       std::unique_ptr<Message> message =
           GetSerialized(lib, "getTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -1882,7 +1845,7 @@
       std::unique_ptr<Message> message =
           GetSerialized(lib, "getMultipleTypedDataViewList");
       ApiNativeScope scope;
-      Dart_CObject* root = GetDeserialized(message.get());
+      Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
       EXPECT_NOTNULL(root);
       EXPECT_EQ(Dart_CObject_kArray, root->type);
       struct {
@@ -2009,15 +1972,6 @@
   Dart_ExitScope();
 }
 
-ISOLATE_UNIT_TEST_CASE(OmittedObjectEncodingLength) {
-  StackZone zone(Thread::Current());
-  MessageWriter writer(true);
-  writer.WriteInlinedObjectHeader(kOmittedObjectId);
-  // For performance, we'd like single-byte headers when ids are omitted.
-  // If this starts failing, consider renumbering the snapshot ids.
-  EXPECT_EQ(1, writer.BytesWritten());
-}
-
 TEST_CASE(IsKernelNegative) {
   EXPECT(!Dart_IsKernel(NULL, 0));
 
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index bed573a..3eac0b6 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -21,8 +21,6 @@
 class Code;
 class Isolate;
 class ObjectPointerVisitor;
-class SnapshotReader;
-class SnapshotWriter;
 
 DECLARE_FLAG(bool, disassemble_stubs);
 
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index ae7d824..673f26e 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -14,7 +14,6 @@
 #include "vm/object_store.h"
 #include "vm/raw_object.h"
 #include "vm/reusable_handles.h"
-#include "vm/snapshot_ids.h"
 #include "vm/visitor.h"
 
 namespace dart {
@@ -514,22 +513,4 @@
   table.Release();
 }
 
-intptr_t Symbols::LookupPredefinedSymbol(ObjectPtr obj) {
-  for (intptr_t i = 1; i < Symbols::kMaxPredefinedId; i++) {
-    if (symbol_handles_[i]->ptr() == obj) {
-      return (i + kMaxPredefinedObjectIds);
-    }
-  }
-  return kInvalidIndex;
-}
-
-ObjectPtr Symbols::GetPredefinedSymbol(intptr_t object_id) {
-  ASSERT(IsPredefinedSymbolId(object_id));
-  intptr_t i = (object_id - kMaxPredefinedObjectIds);
-  if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) {
-    return symbol_handles_[i]->ptr();
-  }
-  return Object::null();
-}
-
 }  // namespace dart
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 533119d..76d0070 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -7,7 +7,6 @@
 
 #include "vm/growable_array.h"
 #include "vm/object.h"
-#include "vm/snapshot_ids.h"
 
 namespace dart {
 
@@ -105,6 +104,7 @@
   V(ExceptionHandlers, "ExceptionHandlers")                                    \
   V(ExceptionParameter, ":exception")                                          \
   V(ExceptionVar, ":exception_var")                                            \
+  V(Expando, "Expando")                                                        \
   V(ExprTemp, ":expr_temp")                                                    \
   V(ExternalName, "ExternalName")                                              \
   V(ExternalOneByteString, "_ExternalOneByteString")                           \
@@ -415,6 +415,7 @@
   V(_objectNoSuchMethod, "_objectNoSuchMethod")                                \
   V(_objectToString, "_objectToString")                                        \
   V(_onData, "_onData")                                                        \
+  V(_rehash, "_rehash")                                                        \
   V(_rehashObjects, "_rehashObjects")                                          \
   V(_resultOrListeners, "_resultOrListeners")                                  \
   V(_runExtension, "_runExtension")                                            \
@@ -698,13 +699,6 @@
   template <typename StringType>
   static StringPtr NewSymbol(Thread* thread, const StringType& str);
 
-  static intptr_t LookupPredefinedSymbol(ObjectPtr obj);
-  static ObjectPtr GetPredefinedSymbol(intptr_t object_id);
-  static bool IsPredefinedSymbolId(intptr_t object_id) {
-    return (object_id >= kMaxPredefinedObjectIds &&
-            object_id < (kMaxPredefinedObjectIds + kMaxPredefinedId));
-  }
-
   // List of Latin1 characters stored in the vm isolate as symbols
   // in order to make Symbols::FromCharCode fast. This structure is
   // used in generated dart code for direct access to these objects.
@@ -715,11 +709,8 @@
 
   friend class Dart;
   friend class String;
-  friend class SnapshotReader;
-  friend class SnapshotWriter;
   friend class Serializer;
   friend class Deserializer;
-  friend class ApiMessageReader;
 
   DISALLOW_COPY_AND_ASSIGN(Symbols);
 };
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 12f776e..2f21ac1 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -70,7 +70,6 @@
   "dart.cc",
   "dart.h",
   "dart_api_impl.h",
-  "dart_api_message.cc",
   "dart_api_message.h",
   "dart_api_state.cc",
   "dart_api_state.h",
@@ -169,6 +168,8 @@
   "message.h",
   "message_handler.cc",
   "message_handler.h",
+  "message_snapshot.cc",
+  "message_snapshot.h",
   "metrics.cc",
   "metrics.h",
   "native_arguments.h",
@@ -235,7 +236,6 @@
   "raw_object.h",
   "raw_object_fields.cc",
   "raw_object_fields.h",
-  "raw_object_snapshot.cc",
   "regexp.cc",
   "regexp.h",
   "regexp_assembler.cc",
@@ -289,7 +289,6 @@
   "simulator_arm64.h",
   "snapshot.cc",
   "snapshot.h",
-  "snapshot_ids.h",
   "source_report.cc",
   "source_report.h",
   "stack_frame.cc",
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index 2022c9d..cb45741 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -177,6 +177,7 @@
 
   friend class StackZone;
   friend class ApiZone;
+  friend class AllocOnlyStackZone;
   template <typename T, typename B, typename Allocator>
   friend class BaseGrowableArray;
   template <typename T, typename B, typename Allocator>
@@ -212,6 +213,23 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(StackZone);
 };
 
+class AllocOnlyStackZone : public ValueObject {
+ public:
+  AllocOnlyStackZone() : zone_() {}
+  ~AllocOnlyStackZone() {
+    // This zone is not linked into the thread, so any handles would not be
+    // visited.
+    ASSERT(zone_.handles()->IsEmpty());
+  }
+
+  Zone* GetZone() { return &zone_; }
+
+ private:
+  Zone zone_;
+
+  DISALLOW_COPY_AND_ASSIGN(AllocOnlyStackZone);
+};
+
 inline uword Zone::AllocUnsafe(intptr_t size) {
   ASSERT(size >= 0);
   // Round up the requested size to fit the alignment.
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
index 2cd212a..6ff9de7 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
@@ -181,8 +181,8 @@
 /// A list of functions to reset static fields back to their uninitialized
 /// state.
 ///
-/// This is populated by [defineLazyField] and [LazyJSType] and only contains
-/// fields that have been initialized.
+/// This is populated by [defineLazyField] and only contains fields that have
+/// been initialized.
 @notNull
 final List<void Function()> _resetFields = JS('', '[]');
 
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index e48e530..3c0267d 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -81,6 +81,15 @@
 
 final metadata = JS('', 'Symbol("metadata")');
 
+/// A javascript Symbol used to store a canonical version of T? on T.
+final _cachedNullable = JS('', 'Symbol("cachedNullable")');
+
+/// A javascript Symbol used to store a canonical version of T* on T.
+final _cachedLegacy = JS('', 'Symbol("cachedLegacy")');
+
+/// A javascript Symbol used to store prior subtype checks and their results.
+final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
+
 /// Types in dart are represented internally at runtime as follows.
 ///
 ///   - Normal nominal types, produced from classes, are represented
@@ -197,67 +206,17 @@
   return JS('', '#', ret);
 }
 
-/// The Dart type that represents a JavaScript class(/constructor) type.
-///
-/// The JavaScript type may not exist, either because it's not loaded yet, or
-/// because it's not available (such as with mocks). To handle this gracefully,
-/// we disable type checks for in these cases, and allow any JS object to work
-/// as if it were an instance of this JS type.
-class LazyJSType extends DartType {
-  Function() _getRawJSTypeFn;
-  @notNull
-  final String _dartName;
-  Object? _rawJSType;
-
-  LazyJSType(this._getRawJSTypeFn, this._dartName);
-
-  toString() {
-    var raw = _getRawJSType();
-    return raw != null ? typeName(raw) : "JSObject<$_dartName>";
-  }
-
-  Object? _getRawJSType() {
-    var raw = _rawJSType;
-    if (raw != null) return raw;
-
-    // Try to evaluate the JS type. If this fails for any reason, we'll try
-    // again next time.
-    // TODO(jmesserly): is it worth trying again? It may create unnecessary
-    // overhead, especially if exceptions are being thrown. Also it means the
-    // behavior of a given type check can change later on.
-    try {
-      raw = _getRawJSTypeFn();
-    } catch (e) {}
-
-    if (raw == null) {
-      _warn('Cannot find native JavaScript type ($_dartName) for type check');
-    } else {
-      _rawJSType = raw;
-      JS('', '#.push(() => # = null)', _resetFields, _rawJSType);
-    }
-    return raw;
-  }
-
-  Object rawJSTypeForCheck() => _getRawJSType() ?? typeRep<JavaScriptObject>();
-
-  @notNull
-  @JSExportName('is')
-  bool is_T(obj) =>
-      obj != null &&
-      (_isJsObject(obj) || isSubtypeOf(getReifiedType(obj), this));
-
-  @JSExportName('as')
-  as_T(obj) => is_T(obj) ? obj : castError(obj, this);
-}
-
-/// An anonymous JS type
+/// Dart type that represents a package:js class type (either anonymous or not).
 ///
 /// For the purposes of subtype checks, these match any JS type.
-class AnonymousJSType extends DartType {
+class PackageJSType extends DartType {
   final String _dartName;
-  AnonymousJSType(this._dartName);
-  toString() => _dartName;
+  PackageJSType(this._dartName);
 
+  @override
+  String toString() => _dartName;
+
+  @notNull
   @JSExportName('is')
   bool is_T(obj) =>
       obj != null &&
@@ -299,35 +258,25 @@
   }
 }
 
-var _lazyJSTypes = JS<Object>('', 'new Map()');
-var _anonymousJSTypes = JS<Object>('', 'new Map()');
+var _packageJSTypes = JS<Object>('', 'new Map()');
 
-lazyJSType(Function() getJSTypeCallback, String name) {
-  var ret = JS('', '#.get(#)', _lazyJSTypes, name);
+packageJSType(String name) {
+  var ret = JS('', '#.get(#)', _packageJSTypes, name);
   if (ret == null) {
-    ret = LazyJSType(getJSTypeCallback, name);
-    JS('', '#.set(#, #)', _lazyJSTypes, name, ret);
+    ret = PackageJSType(name);
+    JS('', '#.set(#, #)', _packageJSTypes, name, ret);
   }
   return ret;
 }
 
-anonymousJSType(String name) {
-  var ret = JS('', '#.get(#)', _anonymousJSTypes, name);
-  if (ret == null) {
-    ret = AnonymousJSType(name);
-    JS('', '#.set(#, #)', _anonymousJSTypes, name, ret);
-  }
-  return ret;
-}
-
-/// A javascript Symbol used to store a canonical version of T? on T.
-final _cachedNullable = JS('', 'Symbol("cachedNullable")');
-
-/// A javascript Symbol used to store a canonical version of T* on T.
-final _cachedLegacy = JS('', 'Symbol("cachedLegacy")');
-
-/// A javascript Symbol used to store prior subtype checks and their results.
-final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
+/// Since package:js types are all subtypes of each other, we use this var to
+/// denote *some* package:js type in our subtyping logic.
+///
+/// Used only when a concrete PackageJSType is not available i.e. when neither
+/// the object nor the target type is a PackageJSType. Avoids initializating a
+/// new PackageJSType every time. Note that we don't add it to the set of JS
+/// types, since it's not an actual JS class.
+final _pkgJSTypeForSubtyping = PackageJSType('');
 
 /// Returns a nullable (question, ?) version of [type].
 ///
@@ -1522,34 +1471,20 @@
     //
     // JavaScriptObject <: package:js types
     // package:js types <: JavaScriptObject
-    //
-    // TODO: This doesn't allow package:js type <: another package:js type yet.
 
     if (${_isInterfaceSubtype(t1, JavaScriptObject, strictMode)}
-        && (${_jsInstanceOf(t2, LazyJSType)}
-            || ${_jsInstanceOf(t2, AnonymousJSType)}
-            // TODO: Since package:js types are instances of LazyJSType and
-            // AnonymousJSType, we don't have a mechanism to determine if *some*
-            // package:js type implements t2. This will possibly require keeping
-            // a map of these relationships for this subtyping check. For now,
-            // don't execute the following checks.
-            // || _isInterfaceSubtype(LazyJSType, t2, strictMode)
-            // || _isInterfaceSubtype(AnonymousJSType, t2, strictMode)
-            )) {
+        &&
+            // TODO: Since package:js types are instances of PackageJSType and
+            // we don't have a mechanism to determine if *some* package:js type
+            // implements t2. This will possibly require keeping a map of these
+            // relationships for this subtyping check. For now, this will only
+            // work if t2 is also a PackageJSType.
+            ${_isInterfaceSubtype(_pkgJSTypeForSubtyping, t2, strictMode)}) {
       return true;
     }
 
     if (${_isInterfaceSubtype(JavaScriptObject, t2, strictMode)}
-        && (${_jsInstanceOf(t1, LazyJSType)}
-            || ${_jsInstanceOf(t1, AnonymousJSType)}
-            // TODO: We don't have a check in `isInterfaceSubtype` to check that
-            // a class is a subtype of *some* package:js class. This will likely
-            // require modifying `_isInterfaceSubtype` to check if the
-            // interfaces of t1 include a package:js type. For now, don't
-            // execute the following checks.
-            // || _isInterfaceSubtype(t1, LazyJSType, strictMode)
-            // || _isInterfaceSubtype(t1, AnonymousJSType, strictMode)
-            )) {
+        && ${_isInterfaceSubtype(t1, _pkgJSTypeForSubtyping, strictMode)}) {
       return true;
     }
 
@@ -1617,10 +1552,11 @@
 })()''');
 
 bool _isInterfaceSubtype(t1, t2, @notNull bool strictMode) => JS('', '''(() => {
-  // If we have lazy JS types, unwrap them.  This will effectively
-  // reduce to a prototype check below.
-  if (${_jsInstanceOf(t1, LazyJSType)}) $t1 = $t1.rawJSTypeForCheck();
-  if (${_jsInstanceOf(t2, LazyJSType)}) $t2 = $t2.rawJSTypeForCheck();
+  // Instances of PackageJSType are all subtypes of each other.
+  if (${_jsInstanceOf(t1, PackageJSType)}
+      && ${_jsInstanceOf(t2, PackageJSType)}) {
+    return true;
+  }
 
   if ($t1 === $t2) {
     return true;
diff --git a/sdk/lib/_internal/vm/lib/expando_patch.dart b/sdk/lib/_internal/vm/lib/expando_patch.dart
index cacbc02..36c65df 100644
--- a/sdk/lib/_internal/vm/lib/expando_patch.dart
+++ b/sdk/lib/_internal/vm/lib/expando_patch.dart
@@ -5,11 +5,12 @@
 // part of "core_patch.dart";
 
 @patch
+@pragma("vm:entry-point")
 class Expando<T> {
   @patch
   Expando([String? name])
       : name = name,
-        _data = new List.filled(_minSize, null),
+        _data = new List<_WeakProperty?>.filled(_minSize, null),
         _used = 0;
 
   static const _minSize = 8;
@@ -95,6 +96,7 @@
     this[object] = value; // Recursively add the value.
   }
 
+  @pragma("vm:entry-point", "call")
   _rehash() {
     // Determine the population count of the map to allocate an appropriately
     // sized map below.
@@ -119,7 +121,7 @@
 
     // Reset the mappings to empty so that we can just add the existing
     // valid entries.
-    _data = new List.filled(new_size, null);
+    _data = new List<_WeakProperty?>.filled(new_size, null);
     _used = 0;
 
     for (var i = 0; i < old_data.length; i++) {
@@ -149,9 +151,9 @@
     }
   }
 
-  get _size => _data.length;
-  get _limit => (3 * (_size ~/ 4));
+  int get _size => _data.length;
+  int get _limit => (3 * (_size ~/ 4));
 
-  List _data;
+  List<_WeakProperty?> _data;
   int _used; // Number of used (active and deleted) slots.
 }
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 3e7a592..8a68d10 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -567,10 +567,16 @@
   /// Sends an asynchronous [message] through this send port, to its
   /// corresponding `ReceivePort`.
   ///
-  /// The content of [message] can be: primitive values
-  /// (null, num, bool, double, String), instances of [SendPort],
-  /// and lists and maps whose elements are any of these.
-  /// List and maps are also allowed to contain cyclic references.
+  /// The content of [message] can be:
+  ///   - [Null]
+  ///   - [bool]
+  ///   - [int]
+  ///   - [double]
+  ///   - [String]
+  ///   - [List] or [Map] (whose elements are any of these)
+  ///   - [TransferableTypedData]
+  ///   - [SendPort]
+  ///   - [Capability]
   ///
   /// In the special circumstances when two isolates share the same code and are
   /// running in the same process (e.g. isolates created via [Isolate.spawn]),
diff --git a/tests/dartdevc/debugger/debugger_test_golden.txt b/tests/dartdevc/debugger/debugger_test_golden.txt
index 76772be..a879c6e 100644
--- a/tests/dartdevc/debugger/debugger_test_golden.txt
+++ b/tests/dartdevc/debugger/debugger_test_golden.txt
@@ -6519,7 +6519,7 @@
     {
         "style": "background-color: #d9edf7;color: black"
     },
-    "Instance of 'TestGenericClass<JSObject<ExampleJSClass>, int>'"
+    "Instance of 'TestGenericClass<ExampleJSClass, int>'"
 ]
 -----------------------------------
 Test: TestGenericClassJSInterop instance body
@@ -6616,7 +6616,7 @@
     {
         "style": "background-color: #d9edf7;color: black"
     },
-    "TestGenericClass<JSObject<ExampleJSClass>, int>"
+    "TestGenericClass<ExampleJSClass, int>"
 ]
 -----------------------------------
 Test: TestGenericClassJSInterop definition formatting body
diff --git a/tests/dartdevc_2/debugger/debugger_test_golden.txt b/tests/dartdevc_2/debugger/debugger_test_golden.txt
index 76772be..a879c6e 100644
--- a/tests/dartdevc_2/debugger/debugger_test_golden.txt
+++ b/tests/dartdevc_2/debugger/debugger_test_golden.txt
@@ -6519,7 +6519,7 @@
     {
         "style": "background-color: #d9edf7;color: black"
     },
-    "Instance of 'TestGenericClass<JSObject<ExampleJSClass>, int>'"
+    "Instance of 'TestGenericClass<ExampleJSClass, int>'"
 ]
 -----------------------------------
 Test: TestGenericClassJSInterop instance body
@@ -6616,7 +6616,7 @@
     {
         "style": "background-color: #d9edf7;color: black"
     },
-    "TestGenericClass<JSObject<ExampleJSClass>, int>"
+    "TestGenericClass<ExampleJSClass, int>"
 ]
 -----------------------------------
 Test: TestGenericClassJSInterop definition formatting body
diff --git a/tests/lib/html/js_typed_interop_lazy_test.dart b/tests/lib/html/js_typed_interop_lazy_test.dart
index 63c578d..1825174 100644
--- a/tests/lib/html/js_typed_interop_lazy_test.dart
+++ b/tests/lib/html/js_typed_interop_lazy_test.dart
@@ -142,10 +142,9 @@
       expect(new Object() is! AnonClass2, isTrue);
 
       expect(<AnonClass>[] is List<AnonClass>, isTrue);
-      // TODO(jacobr): why doesn't this test pass?
-      // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+      expect(<AnonClass>[] is List<AnonClass2>, isTrue);
       expect(<int>[] is! List<AnonClass>, isTrue);
-      expect(<AnonClass>[] is! List<LazyClass>, isTrue); //# 01: ok
+      expect(<AnonClass>[] is List<LazyClass>, isTrue);
       expect(<int>[] is! List<LazyClass>, isTrue);
       expect(<LazyClass>[] is List<LazyClass>, isTrue);
 
@@ -234,10 +233,9 @@
       expect(new Object() is! AnonClass2, isTrue);
 
       expect(<AnonClass>[] is List<AnonClass>, isTrue);
-      // TODO(jacobr): why doesn't this test pass?
-      // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+      expect(<AnonClass>[] is List<AnonClass2>, isTrue);
       expect(<int>[] is! List<AnonClass>, isTrue);
-      expect(<AnonClass>[] is! List<NestedLazyClass>, isTrue); //# 01: ok
+      expect(<AnonClass>[] is List<NestedLazyClass>, isTrue);
       expect(<int>[] is! List<NestedLazyClass>, isTrue);
       expect(<NestedLazyClass>[] is List<NestedLazyClass>, isTrue);
 
diff --git a/tests/lib/isolate/type_ref_message_test.dart b/tests/lib/isolate/type_ref_message_test.dart
new file mode 100644
index 0000000..1c47e35
--- /dev/null
+++ b/tests/lib/isolate/type_ref_message_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// See https://github.com/flutter/flutter/issues/84691
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+
+class B<T> {}
+class D<S> extends B<D> {}
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var list = message as List<D<String>>;
+    var element = list[0] as D<String>;
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var list = <D<String>>[ new D() ];
+  port.sendPort.send(list);
+}
diff --git a/tests/lib/isolate/weak_property_message_1_test.dart b/tests/lib/isolate/weak_property_message_1_test.dart
new file mode 100644
index 0000000..2f4d344
--- /dev/null
+++ b/tests/lib/isolate/weak_property_message_1_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var expando1 = message[0] as Expando;
+    var expando2 = message[1] as Expando;
+    var expando3 = message[2] as Expando;
+    var key1 = message[3];
+
+    var key2 = expando1[key1!];
+    Expect.isNotNull(key2);
+    var key3 = expando2[key2!];
+    Expect.isNotNull(key3);
+    var value = expando3[key3!];
+    Expect.equals(value, "value");
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var key1 = new Object();
+  var key2 = new Object();
+  var key3 = new Object();
+  var expando1 = new Expando();
+  var expando2 = new Expando();
+  var expando3 = new Expando();
+  expando1[key1] = key2;
+  expando2[key2] = key3;
+  expando3[key3] = "value";
+
+  // key1 is placed after expando1 so that its reachability is uncertain when
+  // expando1 is first encountered.
+  var message = <dynamic>[expando1, expando2, expando3, key1];
+  port.sendPort.send(message);
+}
diff --git a/tests/lib/isolate/weak_property_message_2_test.dart b/tests/lib/isolate/weak_property_message_2_test.dart
new file mode 100644
index 0000000..236bcfe3
--- /dev/null
+++ b/tests/lib/isolate/weak_property_message_2_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+import "dart:async";
+import "dart:developer";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var expando = message as Expando;
+
+    // Sent and received without error.
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var unwrittenKey = new Object();
+  var expando = new Expando();
+  expando[unwrittenKey] = new UserTag("cant send this");
+
+  port.sendPort.send(expando);
+
+  print(unwrittenKey);  // Ensure [unwrittenKey] is live during [send].
+}
diff --git a/tests/lib_2/html/js_typed_interop_lazy_test.dart b/tests/lib_2/html/js_typed_interop_lazy_test.dart
index a7b49a9..918193d 100644
--- a/tests/lib_2/html/js_typed_interop_lazy_test.dart
+++ b/tests/lib_2/html/js_typed_interop_lazy_test.dart
@@ -144,10 +144,9 @@
       expect(new Object() is! AnonClass2, isTrue);
 
       expect(<AnonClass>[] is List<AnonClass>, isTrue);
-      // TODO(jacobr): why doesn't this test pass?
-      // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+      expect(<AnonClass>[] is List<AnonClass2>, isTrue);
       expect(<int>[] is! List<AnonClass>, isTrue);
-      expect(<AnonClass>[] is! List<LazyClass>, isTrue); //# 01: ok
+      expect(<AnonClass>[] is List<LazyClass>, isTrue);
       expect(<int>[] is! List<LazyClass>, isTrue);
       expect(<LazyClass>[] is List<LazyClass>, isTrue);
 
@@ -236,10 +235,9 @@
       expect(new Object() is! AnonClass2, isTrue);
 
       expect(<AnonClass>[] is List<AnonClass>, isTrue);
-      // TODO(jacobr): why doesn't this test pass?
-      // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+      expect(<AnonClass>[] is List<AnonClass2>, isTrue);
       expect(<int>[] is! List<AnonClass>, isTrue);
-      expect(<AnonClass>[] is! List<NestedLazyClass>, isTrue); //# 01: ok
+      expect(<AnonClass>[] is List<NestedLazyClass>, isTrue);
       expect(<int>[] is! List<NestedLazyClass>, isTrue);
       expect(<NestedLazyClass>[] is List<NestedLazyClass>, isTrue);
 
diff --git a/tests/lib_2/isolate/type_ref_message_test.dart b/tests/lib_2/isolate/type_ref_message_test.dart
new file mode 100644
index 0000000..8dd2a79
--- /dev/null
+++ b/tests/lib_2/isolate/type_ref_message_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// See https://github.com/flutter/flutter/issues/84691
+
+// @dart = 2.9
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+
+class B<T> {}
+class D<S> extends B<D> {}
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var list = message as List<D<String>>;
+    var element = list[0] as D<String>;
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var list = <D<String>>[ new D() ];
+  port.sendPort.send(list);
+}
diff --git a/tests/lib_2/isolate/weak_property_message_1_test.dart b/tests/lib_2/isolate/weak_property_message_1_test.dart
new file mode 100644
index 0000000..fa8a6d1
--- /dev/null
+++ b/tests/lib_2/isolate/weak_property_message_1_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+// @dart = 2.9
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var expando1 = message[0] as Expando;
+    var expando2 = message[1] as Expando;
+    var expando3 = message[2] as Expando;
+    var key1 = message[3];
+
+    var key2 = expando1[key1];
+    Expect.isNotNull(key2);
+    var key3 = expando2[key2];
+    Expect.isNotNull(key3);
+    var value = expando3[key3];
+    Expect.equals(value, "value");
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var key1 = new Object();
+  var key2 = new Object();
+  var key3 = new Object();
+  var expando1 = new Expando();
+  var expando2 = new Expando();
+  var expando3 = new Expando();
+  expando1[key1] = key2;
+  expando2[key2] = key3;
+  expando3[key3] = "value";
+
+  // key1 is placed after expando1 so that its reachability is uncertain when
+  // expando1 is first encountered.
+  var message = <dynamic>[expando1, expando2, expando3, key1];
+  port.sendPort.send(message);
+}
diff --git a/tests/lib_2/isolate/weak_property_message_2_test.dart b/tests/lib_2/isolate/weak_property_message_2_test.dart
new file mode 100644
index 0000000..7b5ad95
--- /dev/null
+++ b/tests/lib_2/isolate/weak_property_message_2_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+// @dart = 2.9
+
+import "dart:async";
+import "dart:developer";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+  var port;
+  port = new RawReceivePort((message) {
+    var expando = message as Expando;
+
+    // Sent and received without error.
+
+    port.close();
+    asyncEnd();
+  });
+
+
+  var unwrittenKey = new Object();
+  var expando = new Expando();
+  expando[unwrittenKey] = new UserTag("cant send this");
+
+  port.sendPort.send(expando);
+
+  print(unwrittenKey);  // Ensure [unwrittenKey] is live during [send].
+}
diff --git a/tools/VERSION b/tools/VERSION
index e61aabf..7e3201e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 366
+PRERELEASE 367
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/make_version.py b/tools/make_version.py
index c99511b..bf2c9c5 100755
--- a/tools/make_version.py
+++ b/tools/make_version.py
@@ -23,7 +23,6 @@
     'object.h',
     'raw_object.h',
     'snapshot.h',
-    'snapshot_ids.h',
     'symbols.h',
     # Source files.
     'clustered_snapshot.cc',
@@ -32,7 +31,6 @@
     'image_snapshot.cc',
     'object.cc',
     'raw_object.cc',
-    'raw_object_snapshot.cc',
     'snapshot.cc',
     'symbols.cc',
 ]