Version 2.14.0-111.0.dev

Merge commit 'c0f6b37d1732e8e468899200caf3ec68886c7bfd' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index a1ecf39..768691b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -2009,9 +2009,14 @@
 
     var fileContentMap = <String, String>{};
     var libraryFile = _fsState.getFileForPath(path);
-    for (var file in libraryFile.libraryFiles) {
-      var path = file.path;
-      fileContentMap[path] = file.content;
+    try {
+      for (var file in libraryFile.libraryFiles) {
+        var path = file.path;
+        fileContentMap[path] = file.content;
+      }
+    } catch (_) {
+      // We might get an exception while parsing to access parts.
+      // Ignore, continue with the exception that we are reporting now.
     }
 
     _exceptionController.add(
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 8a9e850..5f2b5b9 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -22,7 +22,6 @@
 import 'package:analyzer/src/dart/analysis/referenced_names.dart';
 import 'package:analyzer/src/dart/analysis/unlinked_api_signature.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -403,15 +402,9 @@
   }
 
   /// Return a new parsed unresolved [CompilationUnit].
-  ///
-  /// If an exception happens during parsing, an empty unit is returned.
   CompilationUnitImpl parse([AnalysisErrorListener? errorListener]) {
     errorListener ??= AnalysisErrorListener.NULL_LISTENER;
-    try {
-      return _parse(errorListener);
-    } catch (_) {
-      return _createEmptyCompilationUnit();
-    }
+    return _parse(errorListener);
   }
 
   /// Read the file content and ensure that all of the file properties are
@@ -525,24 +518,6 @@
     return '[id: $id][rid: $refreshId]$uri = $path';
   }
 
-  CompilationUnitImpl _createEmptyCompilationUnit() {
-    var token = Token.eof(0);
-    var unit = astFactory.compilationUnit(
-      beginToken: token,
-      endToken: token,
-      featureSet: _contextFeatureSet,
-    );
-
-    unit.lineInfo = LineInfo(const <int>[0]);
-
-    unit.languageVersion = LibraryLanguageVersion(
-      package: packageLanguageVersion,
-      override: null,
-    );
-
-    return unit;
-  }
-
   /// Return the [FileState] for the given [relativeUri], or `null` if the
   /// URI cannot be parsed, cannot correspond any file, etc.
   Either2<FileState?, ExternalLibrary> _fileForRelativeUri(
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index cfbe557..61af881 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3741,43 +3741,15 @@
 /// A concrete implementation of an [ExportElement].
 class ExportElementImpl extends UriReferencedElementImpl
     implements ExportElement {
-  /// The library that is exported from this library by this export directive.
-  LibraryElement? _exportedLibrary;
+  @override
+  LibraryElement? exportedLibrary;
 
-  /// The combinators that were specified as part of the export directive in the
-  /// order in which they were specified.
-  List<NamespaceCombinator> _combinators = _Sentinel.namespaceCombinator;
+  @override
+  List<NamespaceCombinator> combinators = const [];
 
   /// Initialize a newly created export element at the given [offset].
   ExportElementImpl(int offset) : super(null, offset);
 
-  ExportElementImpl.forLinkedNode(
-      LibraryElementImpl enclosing, ExportDirectiveImpl linkedNode)
-      : super.forLinkedNode(enclosing, null, linkedNode) {
-    linkedNode.element = this;
-  }
-
-  @override
-  List<NamespaceCombinator> get combinators {
-    if (!identical(_combinators, _Sentinel.namespaceCombinator)) {
-      return _combinators;
-    }
-
-    if (linkedNode != null) {
-      var node = linkedNode as ExportDirective;
-      return _combinators = ImportElementImpl._buildCombinators2(
-        enclosingUnit.linkedContext!,
-        node.combinators,
-      );
-    }
-
-    return _combinators;
-  }
-
-  set combinators(List<NamespaceCombinator> combinators) {
-    _combinators = combinators;
-  }
-
   @override
   CompilationUnitElementImpl get enclosingUnit {
     var enclosingLibrary = enclosingElement as LibraryElementImpl;
@@ -3785,40 +3757,12 @@
   }
 
   @override
-  LibraryElement? get exportedLibrary {
-    return _exportedLibrary;
-  }
-
-  set exportedLibrary(LibraryElement? exportedLibrary) {
-    _exportedLibrary = exportedLibrary;
-  }
-
-  @override
   String get identifier => exportedLibrary!.name ?? 'unknown';
 
   @override
   ElementKind get kind => ElementKind.EXPORT;
 
   @override
-  int get nameOffset {
-    if (linkedNode != null) {
-      return linkedContext!.getDirectiveOffset(linkedNode as Directive);
-    }
-
-    return super.nameOffset;
-  }
-
-  @override
-  String? get uri {
-    if (linkedNode != null) {
-      var node = linkedNode as ExportDirective;
-      return node.uri.stringValue;
-    }
-
-    return super.uri;
-  }
-
-  @override
   T? accept<T>(ElementVisitor<T> visitor) => visitor.visitExportElement(this);
 
   @override
@@ -4599,35 +4543,8 @@
 
 /// A concrete implementation of a [HideElementCombinator].
 class HideElementCombinatorImpl implements HideElementCombinator {
-  final LinkedUnitContext? linkedContext;
-  final HideCombinator? linkedNode;
-
-  /// The names that are not to be made visible in the importing library even if
-  /// they are defined in the imported library.
-  List<String> _hiddenNames = _Sentinel.string;
-
-  HideElementCombinatorImpl()
-      : linkedContext = null,
-        linkedNode = null;
-
-  HideElementCombinatorImpl.forLinkedNode(this.linkedContext, this.linkedNode);
-
   @override
-  List<String> get hiddenNames {
-    if (!identical(_hiddenNames, _Sentinel.string)) {
-      return _hiddenNames;
-    }
-
-    if (linkedNode != null) {
-      return _hiddenNames = linkedNode!.hiddenNames.map((i) => i.name).toList();
-    }
-
-    return _hiddenNames;
-  }
-
-  set hiddenNames(List<String> hiddenNames) {
-    _hiddenNames = hiddenNames;
-  }
+  List<String> hiddenNames = const [];
 
   @override
   String toString() {
@@ -4647,20 +4564,17 @@
 /// A concrete implementation of an [ImportElement].
 class ImportElementImpl extends UriReferencedElementImpl
     implements ImportElement {
-  /// The offset of the prefix of this import in the file that contains the this
-  /// import directive, or `-1` if this import is synthetic.
-  int _prefixOffset = 0;
+  @override
+  LibraryElement? importedLibrary;
 
-  /// The library that is imported into this library by this import directive.
-  LibraryElement? _importedLibrary;
+  @override
+  PrefixElement? prefix;
 
-  /// The combinators that were specified as part of the import directive in the
-  /// order in which they were specified.
-  List<NamespaceCombinator> _combinators = _Sentinel.namespaceCombinator;
+  @override
+  int prefixOffset = -1;
 
-  /// The prefix that was specified as part of the import directive, or `null
-  ///` if there was no prefix specified.
-  PrefixElement? _prefix;
+  @override
+  List<NamespaceCombinator> combinators = const [];
 
   /// The cached value of [namespace].
   Namespace? _namespace;
@@ -4669,33 +4583,6 @@
   /// The offset may be `-1` if the import is synthetic.
   ImportElementImpl(int offset) : super(null, offset);
 
-  ImportElementImpl.forLinkedNode(
-      LibraryElementImpl enclosing, ImportDirectiveImpl linkedNode)
-      : super.forLinkedNode(enclosing, null, linkedNode) {
-    linkedNode.element = this;
-  }
-
-  @override
-  List<NamespaceCombinator> get combinators {
-    if (!identical(_combinators, _Sentinel.namespaceCombinator)) {
-      return _combinators;
-    }
-
-    if (linkedNode != null) {
-      var node = linkedNode as ImportDirective;
-      return _combinators = ImportElementImpl._buildCombinators2(
-        enclosingUnit.linkedContext!,
-        node.combinators,
-      );
-    }
-
-    return _combinators;
-  }
-
-  set combinators(List<NamespaceCombinator> combinators) {
-    _combinators = combinators;
-  }
-
   @override
   CompilationUnitElementImpl get enclosingUnit {
     var enclosingLibrary = enclosingElement as LibraryElementImpl;
@@ -4706,20 +4593,7 @@
   String get identifier => "${importedLibrary?.identifier}@$nameOffset";
 
   @override
-  LibraryElement? get importedLibrary {
-    return _importedLibrary;
-  }
-
-  set importedLibrary(LibraryElement? importedLibrary) {
-    _importedLibrary = importedLibrary;
-  }
-
-  @override
   bool get isDeferred {
-    if (linkedNode != null) {
-      final linkedNode = this.linkedNode as ImportDirective;
-      return linkedNode.deferredKeyword != null;
-    }
     return hasModifier(Modifier.DEFERRED);
   }
 
@@ -4732,69 +4606,12 @@
   ElementKind get kind => ElementKind.IMPORT;
 
   @override
-  int get nameOffset {
-    if (linkedNode != null) {
-      return linkedContext!.getDirectiveOffset(linkedNode as Directive);
-    }
-
-    return super.nameOffset;
-  }
-
-  @override
   Namespace get namespace {
     return _namespace ??=
         NamespaceBuilder().createImportNamespaceForDirective(this);
   }
 
   @override
-  PrefixElement? get prefix {
-    if (_prefix != null) return _prefix;
-
-    if (linkedNode != null) {
-      final linkedNode = this.linkedNode as ImportDirective;
-      var prefix = linkedNode.prefix;
-      if (prefix != null) {
-        var name = prefix.name;
-        var library = enclosingElement as LibraryElementImpl;
-        _prefix = PrefixElementImpl.forLinkedNode(
-          library,
-          library.reference!.getChild('@prefix').getChild(name),
-          prefix,
-        );
-      }
-    }
-
-    return _prefix;
-  }
-
-  set prefix(PrefixElement? prefix) {
-    _prefix = prefix;
-  }
-
-  @override
-  int get prefixOffset {
-    if (linkedNode != null) {
-      var node = linkedNode as ImportDirective;
-      return node.prefix?.offset ?? -1;
-    }
-    return _prefixOffset;
-  }
-
-  set prefixOffset(int prefixOffset) {
-    _prefixOffset = prefixOffset;
-  }
-
-  @override
-  String? get uri {
-    if (linkedNode != null) {
-      var node = linkedNode as ImportDirective;
-      return node.uri.stringValue;
-    }
-
-    return super.uri;
-  }
-
-  @override
   T? accept<T>(ElementVisitor<T> visitor) => visitor.visitImportElement(this);
 
   @override
@@ -4807,19 +4624,6 @@
     super.visitChildren(visitor);
     prefix?.accept(visitor);
   }
-
-  static List<NamespaceCombinator> _buildCombinators2(
-      LinkedUnitContext context, List<Combinator> combinators) {
-    return combinators.map((node) {
-      if (node is HideCombinator) {
-        return HideElementCombinatorImpl.forLinkedNode(context, node);
-      }
-      if (node is ShowCombinator) {
-        return ShowElementCombinatorImpl.forLinkedNode(context, node);
-      }
-      throw UnimplementedError('${node.runtimeType}');
-    }).toList();
-  }
 }
 
 /// A concrete implementation of a [LabelElement].
@@ -6899,66 +6703,14 @@
 
 /// A concrete implementation of a [ShowElementCombinator].
 class ShowElementCombinatorImpl implements ShowElementCombinator {
-  final LinkedUnitContext? linkedContext;
-  final ShowCombinator? linkedNode;
-
-  /// The names that are to be made visible in the importing library if they are
-  /// defined in the imported library.
-  List<String> _shownNames = _Sentinel.string;
-
-  /// The offset of the character immediately following the last character of
-  /// this node.
-  int _end = -1;
-
-  /// The offset of the 'show' keyword of this element.
-  int _offset = 0;
-
-  ShowElementCombinatorImpl()
-      : linkedContext = null,
-        linkedNode = null;
-
-  ShowElementCombinatorImpl.forLinkedNode(this.linkedContext, this.linkedNode);
+  @override
+  List<String> shownNames = const [];
 
   @override
-  int get end {
-    if (linkedNode != null) {
-      return linkedNode!.end;
-    }
-    return _end;
-  }
-
-  set end(int end) {
-    _end = end;
-  }
+  int offset = 0;
 
   @override
-  int get offset {
-    if (linkedNode != null) {
-      return linkedNode!.keyword.offset;
-    }
-    return _offset;
-  }
-
-  set offset(int offset) {
-    _offset = offset;
-  }
-
-  @override
-  List<String> get shownNames {
-    if (!identical(_shownNames, _Sentinel.string)) {
-      return _shownNames;
-    }
-
-    if (linkedNode != null) {
-      return _shownNames = linkedNode!.shownNames.map((i) => i.name).toList();
-    }
-
-    return _shownNames;
-  }
-
-  set shownNames(List<String> shownNames) {
-    _shownNames = shownNames;
-  }
+  int end = -1;
 
   @override
   String toString() {
@@ -7699,12 +7451,9 @@
   static final List<ImportElement> importElement = List.unmodifiable([]);
   static final List<InterfaceType> interfaceType = List.unmodifiable([]);
   static final List<MethodElement> methodElement = List.unmodifiable([]);
-  static final List<NamespaceCombinator> namespaceCombinator =
-      List.unmodifiable([]);
   static final List<ParameterElement> parameterElement = List.unmodifiable([]);
   static final List<PropertyAccessorElement> propertyAccessorElement =
       List.unmodifiable([]);
-  static final List<String> string = List.unmodifiable([]);
   static final List<TopLevelVariableElement> topLevelVariables =
       List.unmodifiable([]);
   static final List<TypeAliasElement> typeAliasElement = List.unmodifiable([]);
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index d874003..c6cb319 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart' as ast;
+import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/ast/ast.dart' as ast;
 import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
@@ -45,42 +46,36 @@
   LibraryBuilder._(this.linker, this.uri, this.reference);
 
   void addExporters() {
-    var unitContext = context.definingUnit;
-    for (var directive in unitContext.unit.directives) {
-      if (directive is ast.ExportDirective) {
-        Uri? uri;
-        try {
-          uri = _selectAbsoluteUri(directive);
-          if (uri == null) continue;
-        } on FormatException {
-          continue;
-        }
+    for (var element in element.exports) {
+      var exportedLibrary = element.exportedLibrary;
+      if (exportedLibrary == null) {
+        continue;
+      }
 
-        var combinators = directive.combinators.map((node) {
-          if (node is ast.ShowCombinator) {
-            var nameList = node.shownNames.map((i) => i.name).toList();
-            return Combinator.show(nameList);
-          } else if (node is ast.HideCombinator) {
-            var nameList = node.hiddenNames.map((i) => i.name).toList();
-            return Combinator.hide(nameList);
-          } else {
-            throw UnimplementedError();
-          }
-        }).toList();
-
-        var exported = linker.builders[uri];
-        var export = Export(this, exported, combinators);
-        if (exported != null) {
-          exported.exporters.add(export);
+      var combinators = element.combinators.map((combinator) {
+        if (combinator is ShowElementCombinator) {
+          return Combinator.show(combinator.shownNames);
+        } else if (combinator is HideElementCombinator) {
+          return Combinator.hide(combinator.hiddenNames);
         } else {
-          var references = linker.elementFactory.exportsOfLibrary('$uri');
-          for (var reference in references) {
-            var name = reference.name;
-            if (reference.isSetter) {
-              export.addToExportScope('$name=', reference);
-            } else {
-              export.addToExportScope(name, reference);
-            }
+          throw UnimplementedError();
+        }
+      }).toList();
+
+      var exportedUri = exportedLibrary.source.uri;
+      var exportedBuilder = linker.builders[exportedUri];
+
+      var export = Export(this, exportedBuilder, combinators);
+      if (exportedBuilder != null) {
+        exportedBuilder.exporters.add(export);
+      } else {
+        var references = linker.elementFactory.exportsOfLibrary('$exportedUri');
+        for (var reference in references) {
+          var name = reference.name;
+          if (reference.isSetter) {
+            export.addToExportScope('$name=', reference);
+          } else {
+            export.addToExportScope(name, reference);
           }
         }
       }
@@ -259,49 +254,13 @@
   }
 
   void buildDirectives() {
-    var exports = <ExportElement>[];
-    var imports = <ImportElement>[];
-    var hasCoreImport = false;
-
-    // Build elements directives in all units.
-    // Store elements only for the defining unit of the library.
-    var isDefiningUnit = true;
-    for (var unitContext in context.units) {
-      for (var node in unitContext.unit.directives) {
-        if (node is ast.ExportDirectiveImpl) {
-          var exportElement = ExportElementImpl.forLinkedNode(element, node);
-          if (isDefiningUnit) {
-            exports.add(exportElement);
-          }
-        } else if (node is ast.ImportDirectiveImpl) {
-          var importElement = ImportElementImpl.forLinkedNode(element, node);
-          if (isDefiningUnit) {
-            imports.add(importElement);
-            if (!hasCoreImport) {
-              if (node.uri.stringValue == 'dart:core') {
-                hasCoreImport = true;
-              }
-            }
-          }
-        } else if (isDefiningUnit && node is ast.PartOfDirective) {
-          element.hasPartOfDirective = true;
-        }
-      }
-      isDefiningUnit = false;
-    }
-
-    element.exports = exports;
-
-    if (!hasCoreImport) {
-      var dartCore = linker.elementFactory.libraryOfUri2('dart:core');
-      imports.add(
-        ImportElementImpl(-1)
-          ..importedLibrary = dartCore
-          ..isSynthetic = true
-          ..uri = 'dart:core',
-      );
-    }
-    element.imports = imports;
+    var definingUnit = context.definingUnit;
+    var elementBuilder = _ElementBuilder(
+      libraryBuilder: this,
+      unitElement: definingUnit.element,
+    );
+    definingUnit.unit.directives.accept(elementBuilder);
+    elementBuilder.setExportsImports();
   }
 
   void buildElement() {
@@ -369,29 +328,6 @@
     }
   }
 
-  void resolveUriDirectives() {
-    var unitContext = context.units[0];
-    for (var directive in unitContext.unit.directives) {
-      if (directive is ast.NamespaceDirective) {
-        try {
-          var uri = _selectAbsoluteUri(directive);
-          if (uri != null) {
-            var library = linker.elementFactory.libraryOfUri('$uri');
-            if (directive is ast.ExportDirective) {
-              var exportElement = directive.element as ExportElementImpl;
-              exportElement.exportedLibrary = library;
-            } else if (directive is ast.ImportDirective) {
-              var importElement = directive.element as ImportElementImpl;
-              importElement.importedLibrary = library;
-            }
-          }
-        } on FormatException {
-          // ignored
-        }
-      }
-    }
-  }
-
   void storeExportScope() {
     exports = exportScope.map.values.toList();
     linker.elementFactory.linkingExports['$uri'] = exports;
@@ -403,32 +339,6 @@
     // }
   }
 
-  Uri? _selectAbsoluteUri(ast.NamespaceDirective directive) {
-    var relativeUriStr = _selectRelativeUri(
-      directive.configurations,
-      directive.uri.stringValue,
-    );
-    if (relativeUriStr == null) {
-      return null;
-    }
-    var relativeUri = Uri.parse(relativeUriStr);
-    return resolveRelativeUri(uri, relativeUri);
-  }
-
-  String? _selectRelativeUri(
-    List<ast.Configuration> configurations,
-    String? defaultUri,
-  ) {
-    for (var configuration in configurations) {
-      var name = configuration.name.components.join('.');
-      var value = configuration.value?.stringValue ?? 'true';
-      if (linker.declaredVariables.get(name) == value) {
-        return configuration.uri.stringValue;
-      }
-    }
-    return defaultUri;
-  }
-
   static void build(Linker linker, LinkInputLibrary inputLibrary) {
     var uriStr = inputLibrary.uriStr;
     var reference = linker.rootReference.getChild(uriStr);
@@ -459,3 +369,171 @@
     builder.context = context;
   }
 }
+
+class _ElementBuilder extends ThrowingAstVisitor<void> {
+  final LibraryBuilder _libraryBuilder;
+  final CompilationUnitElementImpl _unitElement;
+
+  final _exports = <ExportElement>[];
+  final _imports = <ImportElement>[];
+  var _hasCoreImport = false;
+
+  _ElementBuilder({
+    required LibraryBuilder libraryBuilder,
+    required CompilationUnitElementImpl unitElement,
+  })  : _libraryBuilder = libraryBuilder,
+        _unitElement = unitElement;
+
+  LibraryElementImpl get _libraryElement => _libraryBuilder.element;
+
+  Linker get _linker => _libraryBuilder.linker;
+
+  /// This method should be invoked after visiting directive nodes, it
+  /// will set created exports and imports into [_libraryElement].
+  void setExportsImports() {
+    _libraryElement.exports = _exports;
+
+    if (!_hasCoreImport) {
+      var dartCore = _linker.elementFactory.libraryOfUri2('dart:core');
+      _imports.add(
+        ImportElementImpl(-1)
+          ..importedLibrary = dartCore
+          ..isSynthetic = true
+          ..uri = 'dart:core',
+      );
+    }
+    _libraryElement.imports = _imports;
+  }
+
+  @override
+  void visitExportDirective(ast.ExportDirective node) {
+    node as ast.ExportDirectiveImpl;
+
+    var element = ExportElementImpl(node.keyword.offset);
+    element.combinators = _buildCombinators(node.combinators);
+    element.exportedLibrary = _selectLibrary(node);
+    element.metadata = _buildAnnotations(node.metadata);
+    element.uri = node.uri.stringValue;
+
+    node.element = element;
+    _exports.add(element);
+  }
+
+  @override
+  void visitImportDirective(ast.ImportDirective node) {
+    node as ast.ImportDirectiveImpl;
+
+    var element = ImportElementImpl(node.keyword.offset);
+    element.combinators = _buildCombinators(node.combinators);
+    element.importedLibrary = _selectLibrary(node);
+    element.isDeferred = node.deferredKeyword != null;
+    element.metadata = _buildAnnotations(node.metadata);
+    element.uri = node.uri.stringValue;
+
+    var prefixNode = node.prefix;
+    if (prefixNode != null) {
+      element.prefix = PrefixElementImpl(
+        prefixNode.name,
+        prefixNode.offset,
+        reference: _libraryBuilder.reference
+            .getChild('@prefix')
+            .getChild(prefixNode.name),
+      );
+    }
+
+    node.element = element;
+
+    _imports.add(element);
+    if (!_hasCoreImport) {
+      if (node.uri.stringValue == 'dart:core') {
+        _hasCoreImport = true;
+      }
+    }
+  }
+
+  @override
+  void visitLibraryDirective(ast.LibraryDirective node) {}
+
+  @override
+  void visitPartDirective(ast.PartDirective node) {}
+
+  @override
+  void visitPartOfDirective(ast.PartOfDirective node) {
+    _libraryElement.hasPartOfDirective = true;
+  }
+
+  List<ElementAnnotation> _buildAnnotations(
+    List<ast.Annotation> nodeList,
+  ) {
+    var length = nodeList.length;
+    if (length == 0) {
+      return const <ElementAnnotation>[];
+    }
+
+    var annotations = <ElementAnnotation>[];
+    for (int i = 0; i < length; i++) {
+      var ast = nodeList[i];
+      annotations.add(ElementAnnotationImpl(_unitElement)
+        ..annotationAst = ast
+        ..element = ast.element);
+    }
+    return annotations;
+  }
+
+  Uri? _selectAbsoluteUri(ast.NamespaceDirective directive) {
+    var relativeUriStr = _selectRelativeUri(
+      directive.configurations,
+      directive.uri.stringValue,
+    );
+    if (relativeUriStr == null) {
+      return null;
+    }
+    var relativeUri = Uri.parse(relativeUriStr);
+    return resolveRelativeUri(_libraryBuilder.uri, relativeUri);
+  }
+
+  LibraryElement? _selectLibrary(ast.NamespaceDirective node) {
+    try {
+      var uri = _selectAbsoluteUri(node);
+      return _linker.elementFactory.libraryOfUri('$uri');
+    } on FormatException {
+      return null;
+    }
+  }
+
+  String? _selectRelativeUri(
+    List<ast.Configuration> configurations,
+    String? defaultUri,
+  ) {
+    for (var configuration in configurations) {
+      var name = configuration.name.components.join('.');
+      var value = configuration.value?.stringValue ?? 'true';
+      if (_linker.declaredVariables.get(name) == value) {
+        return configuration.uri.stringValue;
+      }
+    }
+    return defaultUri;
+  }
+
+  static List<NamespaceCombinator> _buildCombinators(
+    List<ast.Combinator> combinators,
+  ) {
+    return combinators.map((node) {
+      if (node is ast.HideCombinator) {
+        return HideElementCombinatorImpl()
+          ..hiddenNames = node.hiddenNames.nameList;
+      }
+      if (node is ast.ShowCombinator) {
+        return ShowElementCombinatorImpl()
+          ..shownNames = node.shownNames.nameList;
+      }
+      throw UnimplementedError('${node.runtimeType}');
+    }).toList();
+  }
+}
+
+extension on Iterable<ast.SimpleIdentifier> {
+  List<String> get nameList {
+    return map((e) => e.name).toList();
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index e47b901..51c7ff0 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -107,10 +107,6 @@
     }
 
     for (var library in builders.values) {
-      library.resolveUriDirectives();
-    }
-
-    for (var library in builders.values) {
       library.buildInitialExportScope();
     }
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 62fbaa6..7842aa3 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -532,7 +532,7 @@
     null_ = static_cast<InstancePtr>(address + kHeapObjectTag);
     // The call below is using 'null_' to initialize itself.
     InitializeObject(address, kNullCid, Instance::InstanceSize(),
-                     /*compressed*/ false);
+                     Instance::ContainsCompressedPointers());
     null_->untag()->SetCanonical();
   }
 
@@ -544,7 +544,7 @@
     // Allocate a dummy bool object to give true the desired alignment.
     uword address = heap->Allocate(Bool::InstanceSize(), Heap::kOld);
     InitializeObject(address, kBoolCid, Bool::InstanceSize(),
-                     /*compressed*/ false);
+                     Bool::ContainsCompressedPointers());
     static_cast<BoolPtr>(address + kHeapObjectTag)->untag()->value_ = false;
   }
   {
@@ -552,7 +552,7 @@
     uword address = heap->Allocate(Bool::InstanceSize(), Heap::kOld);
     true_ = static_cast<BoolPtr>(address + kHeapObjectTag);
     InitializeObject(address, kBoolCid, Bool::InstanceSize(),
-                     /*compressed*/ false);
+                     Bool::ContainsCompressedPointers());
     true_->untag()->value_ = true;
     true_->untag()->SetCanonical();
   }
@@ -561,7 +561,7 @@
     uword address = heap->Allocate(Bool::InstanceSize(), Heap::kOld);
     false_ = static_cast<BoolPtr>(address + kHeapObjectTag);
     InitializeObject(address, kBoolCid, Bool::InstanceSize(),
-                     /*compressed*/ false);
+                     Bool::ContainsCompressedPointers());
     false_->untag()->value_ = false;
     false_->untag()->SetCanonical();
   }
@@ -710,7 +710,8 @@
     intptr_t size = Class::InstanceSize();
     uword address = heap->Allocate(size, Heap::kOld);
     class_class_ = static_cast<ClassPtr>(address + kHeapObjectTag);
-    InitializeObject(address, Class::kClassId, size, /*compressed*/ true);
+    InitializeObject(address, Class::kClassId, size,
+                     Class::ContainsCompressedPointers());
 
     Class fake;
     // Initialization from Class::New<Class>.
@@ -770,19 +771,23 @@
 
   // Allocate and initialize the sentinel values.
   {
-    *sentinel_ ^= Object::Allocate(kNeverCid, Instance::InstanceSize(),
-                                   Heap::kOld, /*compressed*/ false);
+    *sentinel_ ^=
+        Object::Allocate(kNeverCid, Instance::InstanceSize(), Heap::kOld,
+                         Instance::ContainsCompressedPointers());
 
-    *transition_sentinel_ ^= Object::Allocate(
-        kNeverCid, Instance::InstanceSize(), Heap::kOld, /*compressed*/ false);
+    *transition_sentinel_ ^=
+        Object::Allocate(kNeverCid, Instance::InstanceSize(), Heap::kOld,
+                         Instance::ContainsCompressedPointers());
   }
 
   // Allocate and initialize optimizing compiler constants.
   {
-    *unknown_constant_ ^= Object::Allocate(kNeverCid, Instance::InstanceSize(),
-                                           Heap::kOld, /*compressed*/ false);
-    *non_constant_ ^= Object::Allocate(kNeverCid, Instance::InstanceSize(),
-                                       Heap::kOld, /*compressed*/ false);
+    *unknown_constant_ ^=
+        Object::Allocate(kNeverCid, Instance::InstanceSize(), Heap::kOld,
+                         Instance::ContainsCompressedPointers());
+    *non_constant_ ^=
+        Object::Allocate(kNeverCid, Instance::InstanceSize(), Heap::kOld,
+                         Instance::ContainsCompressedPointers());
   }
 
   // Allocate the remaining VM internal classes.
@@ -945,7 +950,7 @@
   {
     uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld);
     InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(0),
-                     /*compressed*/ false);
+                     Array::ContainsCompressedPointers());
     Array::initializeHandle(empty_array_,
                             static_cast<ArrayPtr>(address + kHeapObjectTag));
     empty_array_->untag()->set_length(Smi::New(0));
@@ -957,7 +962,7 @@
   {
     uword address = heap->Allocate(Array::InstanceSize(1), Heap::kOld);
     InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1),
-                     /*compressed*/ false);
+                     Array::ContainsCompressedPointers());
     Array::initializeHandle(zero_array_,
                             static_cast<ArrayPtr>(address + kHeapObjectTag));
     zero_array_->untag()->set_length(Smi::New(1));
@@ -970,7 +975,7 @@
   {
     uword address = heap->Allocate(ContextScope::InstanceSize(0), Heap::kOld);
     InitializeObject(address, kContextScopeCid, ContextScope::InstanceSize(0),
-                     /*compressed*/ true);
+                     ContextScope::ContainsCompressedPointers());
     ContextScope::initializeHandle(
         empty_context_scope_,
         static_cast<ContextScopePtr>(address + kHeapObjectTag));
@@ -985,7 +990,7 @@
   {
     uword address = heap->Allocate(ObjectPool::InstanceSize(0), Heap::kOld);
     InitializeObject(address, kObjectPoolCid, ObjectPool::InstanceSize(0),
-                     /*compressed*/ false);
+                     ObjectPool::ContainsCompressedPointers());
     ObjectPool::initializeHandle(
         empty_object_pool_,
         static_cast<ObjectPoolPtr>(address + kHeapObjectTag));
@@ -999,7 +1004,7 @@
     const intptr_t instance_size = CompressedStackMaps::InstanceSize(0);
     uword address = heap->Allocate(instance_size, Heap::kOld);
     InitializeObject(address, kCompressedStackMapsCid, instance_size,
-                     /*compressed*/ true);
+                     CompressedStackMaps::ContainsCompressedPointers());
     CompressedStackMaps::initializeHandle(
         empty_compressed_stackmaps_,
         static_cast<CompressedStackMapsPtr>(address + kHeapObjectTag));
@@ -1012,7 +1017,7 @@
   {
     uword address = heap->Allocate(PcDescriptors::InstanceSize(0), Heap::kOld);
     InitializeObject(address, kPcDescriptorsCid, PcDescriptors::InstanceSize(0),
-                     /*compressed*/ true);
+                     PcDescriptors::ContainsCompressedPointers());
     PcDescriptors::initializeHandle(
         empty_descriptors_,
         static_cast<PcDescriptorsPtr>(address + kHeapObjectTag));
@@ -1026,7 +1031,8 @@
     uword address =
         heap->Allocate(LocalVarDescriptors::InstanceSize(0), Heap::kOld);
     InitializeObject(address, kLocalVarDescriptorsCid,
-                     LocalVarDescriptors::InstanceSize(0), /*compressed*/ true);
+                     LocalVarDescriptors::InstanceSize(0),
+                     LocalVarDescriptors::ContainsCompressedPointers());
     LocalVarDescriptors::initializeHandle(
         empty_var_descriptors_,
         static_cast<LocalVarDescriptorsPtr>(address + kHeapObjectTag));
@@ -1042,7 +1048,8 @@
     uword address =
         heap->Allocate(ExceptionHandlers::InstanceSize(0), Heap::kOld);
     InitializeObject(address, kExceptionHandlersCid,
-                     ExceptionHandlers::InstanceSize(0), /*compressed*/ true);
+                     ExceptionHandlers::InstanceSize(0),
+                     ExceptionHandlers::ContainsCompressedPointers());
     ExceptionHandlers::initializeHandle(
         empty_exception_handlers_,
         static_cast<ExceptionHandlersPtr>(address + kHeapObjectTag));
@@ -1055,7 +1062,7 @@
   {
     uword address = heap->Allocate(TypeArguments::InstanceSize(0), Heap::kOld);
     InitializeObject(address, kTypeArgumentsCid, TypeArguments::InstanceSize(0),
-                     /*compressed*/ true);
+                     TypeArguments::ContainsCompressedPointers());
     TypeArguments::initializeHandle(
         empty_type_arguments_,
         static_cast<TypeArgumentsPtr>(address + kHeapObjectTag));
@@ -2736,7 +2743,7 @@
   const Class& cls = Class::Handle(orig.clazz());
   intptr_t size = orig.ptr()->untag()->HeapSize();
   ObjectPtr raw_clone =
-      Object::Allocate(cls.id(), size, space, /*compressed*/ false);
+      Object::Allocate(cls.id(), size, space, cls.HasCompressedPointers());
   NoSafepointScope no_safepoint;
   // Copy the body of the original into the clone.
   uword orig_addr = UntaggedObject::ToAddr(orig.ptr());
@@ -2756,6 +2763,42 @@
   return raw_clone;
 }
 
+bool Class::HasCompressedPointers() const {
+  const intptr_t cid = id();
+  switch (cid) {
+    // Only a couple of FFI cids correspond to actual Dart classes. so they're
+    // explicitly listed here.
+    case kFfiPointerCid:
+      return Pointer::ContainsCompressedPointers();
+    case kFfiDynamicLibraryCid:
+      return DynamicLibrary::ContainsCompressedPointers();
+    case kByteBufferCid:
+      return ByteBuffer::ContainsCompressedPointers();
+#define HANDLE_CASE(clazz)                                                     \
+  case k##clazz##Cid:                                                          \
+    return dart::clazz::ContainsCompressedPointers();
+      CLASS_LIST(HANDLE_CASE)
+#undef HANDLE_CASE
+#define HANDLE_CASE(clazz)                                                     \
+  case kTypedData##clazz##Cid:                                                 \
+    return dart::TypedData::ContainsCompressedPointers();                      \
+  case kTypedData##clazz##ViewCid:                                             \
+    return dart::TypedDataView::ContainsCompressedPointers();                  \
+  case kExternalTypedData##clazz##Cid:                                         \
+    return dart::ExternalTypedData::ContainsCompressedPointers();
+      CLASS_LIST_TYPED_DATA(HANDLE_CASE)
+#undef HANDLE_CASE
+    default:
+      if (cid >= kNumPredefinedCids) {
+        return dart::Instance::ContainsCompressedPointers();
+      }
+  }
+  FATAL("Unsupported class for compressed pointers translation: %s (id=%" Pd
+        ", kNumPredefinedCids=%" Pd ")\n",
+        ToCString(), cid, kNumPredefinedCids);
+  return false;
+}
+
 StringPtr Class::Name() const {
   return untag()->name();
 }
@@ -2834,8 +2877,9 @@
   ASSERT(Object::class_class() != Class::null());
   Class& result = Class::Handle();
   {
-    ObjectPtr raw = Object::Allocate(Class::kClassId, Class::InstanceSize(),
-                                     Heap::kOld, /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(Class::kClassId, Class::InstanceSize(), Heap::kOld,
+                         Class::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -4534,8 +4578,9 @@
   ASSERT(Object::class_class() != Class::null());
   Class& result = Class::Handle();
   {
-    ObjectPtr raw = Object::Allocate(Class::kClassId, Class::InstanceSize(),
-                                     Heap::kOld, /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(Class::kClassId, Class::InstanceSize(), Heap::kOld,
+                         Class::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -6176,9 +6221,9 @@
 
 TypeParametersPtr TypeParameters::New(Heap::Space space) {
   ASSERT(Object::type_parameters_class() != Class::null());
-  ObjectPtr ptr = Object::Allocate(TypeParameters::kClassId,
-                                   TypeParameters::InstanceSize(), space,
-                                   /*compressed*/ false);
+  ObjectPtr ptr =
+      Object::Allocate(TypeParameters::kClassId, TypeParameters::InstanceSize(),
+                       space, TypeParameters::ContainsCompressedPointers());
   return static_cast<TypeParametersPtr>(ptr);
 }
 
@@ -6873,9 +6918,9 @@
   }
   TypeArguments& result = TypeArguments::Handle();
   {
-    ObjectPtr raw = Object::Allocate(TypeArguments::kClassId,
-                                     TypeArguments::InstanceSize(len), space,
-                                     /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        TypeArguments::kClassId, TypeArguments::InstanceSize(len), space,
+        TypeArguments::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     // Length must be set before we start storing into the array.
@@ -7021,7 +7066,7 @@
   ASSERT(Object::patch_class_class() != Class::null());
   ObjectPtr raw =
       Object::Allocate(PatchClass::kClassId, PatchClass::InstanceSize(),
-                       Heap::kOld, /*compressed*/ true);
+                       Heap::kOld, PatchClass::ContainsCompressedPointers());
   return static_cast<PatchClassPtr>(raw);
 }
 
@@ -8890,8 +8935,9 @@
 
 FunctionPtr Function::New(Heap::Space space) {
   ASSERT(Object::function_class() != Class::null());
-  ObjectPtr raw = Object::Allocate(Function::kClassId, Function::InstanceSize(),
-                                   space, /*compressed*/ true);
+  ObjectPtr raw =
+      Object::Allocate(Function::kClassId, Function::InstanceSize(), space,
+                       Function::ContainsCompressedPointers());
   return static_cast<FunctionPtr>(raw);
 }
 
@@ -10079,7 +10125,7 @@
   ASSERT(Object::closure_data_class() != Class::null());
   ObjectPtr raw =
       Object::Allocate(ClosureData::kClassId, ClosureData::InstanceSize(),
-                       Heap::kOld, /*compressed*/ true);
+                       Heap::kOld, ClosureData::ContainsCompressedPointers());
   return static_cast<ClosureDataPtr>(raw);
 }
 
@@ -10156,7 +10202,7 @@
 FunctionTypePtr FunctionType::New(Heap::Space space) {
   ObjectPtr raw =
       Object::Allocate(FunctionType::kClassId, FunctionType::InstanceSize(),
-                       space, /*compressed*/ true);
+                       space, FunctionType::ContainsCompressedPointers());
   return static_cast<FunctionTypePtr>(raw);
 }
 
@@ -10252,9 +10298,9 @@
 
 FfiTrampolineDataPtr FfiTrampolineData::New() {
   ASSERT(Object::ffi_trampoline_data_class() != Class::null());
-  ObjectPtr raw = Object::Allocate(FfiTrampolineData::kClassId,
-                                   FfiTrampolineData::InstanceSize(),
-                                   Heap::kOld, /*compressed*/ true);
+  ObjectPtr raw = Object::Allocate(
+      FfiTrampolineData::kClassId, FfiTrampolineData::InstanceSize(),
+      Heap::kOld, FfiTrampolineData::ContainsCompressedPointers());
   FfiTrampolineDataPtr data = static_cast<FfiTrampolineDataPtr>(raw);
   data->untag()->callback_id_ = 0;
   return data;
@@ -10515,8 +10561,9 @@
 
 FieldPtr Field::New() {
   ASSERT(Object::field_class() != Class::null());
-  ObjectPtr raw = Object::Allocate(Field::kClassId, Field::InstanceSize(),
-                                   Heap::kOld, /*compressed*/ true);
+  ObjectPtr raw =
+      Object::Allocate(Field::kClassId, Field::InstanceSize(), Heap::kOld,
+                       Field::ContainsCompressedPointers());
   return static_cast<FieldPtr>(raw);
 }
 
@@ -11943,8 +11990,9 @@
 
 ScriptPtr Script::New() {
   ASSERT(Object::script_class() != Class::null());
-  ObjectPtr raw = Object::Allocate(Script::kClassId, Script::InstanceSize(),
-                                   Heap::kOld, /*compressed*/ true);
+  ObjectPtr raw =
+      Object::Allocate(Script::kClassId, Script::InstanceSize(), Heap::kOld,
+                       Script::ContainsCompressedPointers());
   return static_cast<ScriptPtr>(raw);
 }
 
@@ -13003,8 +13051,9 @@
 
 LibraryPtr Library::New() {
   ASSERT(Object::library_class() != Class::null());
-  ObjectPtr raw = Object::Allocate(Library::kClassId, Library::InstanceSize(),
-                                   Heap::kOld, /*compressed*/ true);
+  ObjectPtr raw =
+      Object::Allocate(Library::kClassId, Library::InstanceSize(), Heap::kOld,
+                       Library ::ContainsCompressedPointers());
   return static_cast<LibraryPtr>(raw);
 }
 
@@ -13711,7 +13760,7 @@
 LibraryPrefixPtr LibraryPrefix::New() {
   ObjectPtr raw =
       Object::Allocate(LibraryPrefix::kClassId, LibraryPrefix::InstanceSize(),
-                       Heap::kOld, /*compressed*/ false);
+                       Heap::kOld, LibraryPrefix::ContainsCompressedPointers());
   return static_cast<LibraryPrefixPtr>(raw);
 }
 
@@ -13867,7 +13916,7 @@
   ASSERT(Object::namespace_class() != Class::null());
   ObjectPtr raw =
       Object::Allocate(Namespace::kClassId, Namespace::InstanceSize(),
-                       Heap::kOld, /*compressed*/ true);
+                       Heap::kOld, Namespace::ContainsCompressedPointers());
   return static_cast<NamespacePtr>(raw);
 }
 
@@ -13886,9 +13935,9 @@
 }
 
 KernelProgramInfoPtr KernelProgramInfo::New() {
-  ObjectPtr raw = Object::Allocate(KernelProgramInfo::kClassId,
-                                   KernelProgramInfo::InstanceSize(),
-                                   Heap::kOld, /*compressed*/ true);
+  ObjectPtr raw = Object::Allocate(
+      KernelProgramInfo::kClassId, KernelProgramInfo::InstanceSize(),
+      Heap::kOld, KernelProgramInfo::ContainsCompressedPointers());
   return static_cast<KernelProgramInfoPtr>(raw);
 }
 
@@ -14289,8 +14338,9 @@
   Instructions& result = Instructions::Handle();
   {
     uword aligned_size = Instructions::InstanceSize(size);
-    ObjectPtr raw = Object::Allocate(Instructions::kClassId, aligned_size,
-                                     Heap::kCode, /*compressed*/ false);
+    ObjectPtr raw =
+        Object::Allocate(Instructions::kClassId, aligned_size, Heap::kCode,
+                         Instructions::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetSize(size);
@@ -14350,8 +14400,9 @@
   InstructionsTable& result = InstructionsTable::Handle(thread->zone());
   {
     uword size = InstructionsTable::InstanceSize(length);
-    ObjectPtr raw = Object::Allocate(InstructionsTable::kClassId, size,
-                                     Heap::kOld, /*compressed*/ false);
+    ObjectPtr raw =
+        Object::Allocate(InstructionsTable::kClassId, size, Heap::kOld,
+                         InstructionsTable::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.set_length(length);
@@ -14452,7 +14503,7 @@
   {
     uword size = ObjectPool::InstanceSize(len);
     ObjectPtr raw = Object::Allocate(ObjectPool::kClassId, size, Heap::kOld,
-                                     /*compressed*/ false);
+                                     ObjectPool::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(len);
@@ -14567,9 +14618,9 @@
   Thread* thread = Thread::Current();
   PcDescriptors& result = PcDescriptors::Handle(thread->zone());
   {
-    ObjectPtr raw = Object::Allocate(PcDescriptors::kClassId,
-                                     PcDescriptors::InstanceSize(size),
-                                     Heap::kOld, /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        PcDescriptors::kClassId, PcDescriptors::InstanceSize(size), Heap::kOld,
+        PcDescriptors::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(size);
@@ -14584,8 +14635,9 @@
   PcDescriptors& result = PcDescriptors::Handle(thread->zone());
   {
     uword size = PcDescriptors::InstanceSize(length);
-    ObjectPtr raw = Object::Allocate(PcDescriptors::kClassId, size, Heap::kOld,
-                                     /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(PcDescriptors::kClassId, size, Heap::kOld,
+                         PcDescriptors::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(length);
@@ -14717,8 +14769,9 @@
   CodeSourceMap& result = CodeSourceMap::Handle(thread->zone());
   {
     uword size = CodeSourceMap::InstanceSize(length);
-    ObjectPtr raw = Object::Allocate(CodeSourceMap::kClassId, size, Heap::kOld,
-                                     /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(CodeSourceMap::kClassId, size, Heap::kOld,
+                         CodeSourceMap::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(length);
@@ -14907,9 +14960,9 @@
   {
     // CompressedStackMaps data objects are associated with a code object,
     // allocate them in old generation.
-    ObjectPtr raw = Object::Allocate(CompressedStackMaps::kClassId,
-                                     CompressedStackMaps::InstanceSize(size),
-                                     Heap::kOld, /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        CompressedStackMaps::kClassId, CompressedStackMaps::InstanceSize(size),
+        Heap::kOld, CompressedStackMaps::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.StoreNonPointer(
@@ -15057,8 +15110,9 @@
   LocalVarDescriptors& result = LocalVarDescriptors::Handle();
   {
     uword size = LocalVarDescriptors::InstanceSize(num_variables);
-    ObjectPtr raw = Object::Allocate(LocalVarDescriptors::kClassId, size,
-                                     Heap::kOld, /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(LocalVarDescriptors::kClassId, size, Heap::kOld,
+                         LocalVarDescriptors::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.StoreNonPointer(&result.untag()->num_entries_, num_variables);
@@ -15158,8 +15212,9 @@
   ExceptionHandlers& result = ExceptionHandlers::Handle();
   {
     uword size = ExceptionHandlers::InstanceSize(num_handlers);
-    ObjectPtr raw = Object::Allocate(ExceptionHandlers::kClassId, size,
-                                     Heap::kOld, /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(ExceptionHandlers::kClassId, size, Heap::kOld,
+                         ExceptionHandlers::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.StoreNonPointer(&result.untag()->num_entries_, num_handlers);
@@ -15183,8 +15238,9 @@
   ExceptionHandlers& result = ExceptionHandlers::Handle();
   {
     uword size = ExceptionHandlers::InstanceSize(num_handlers);
-    ObjectPtr raw = Object::Allocate(ExceptionHandlers::kClassId, size,
-                                     Heap::kOld, /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(ExceptionHandlers::kClassId, size, Heap::kOld,
+                         ExceptionHandlers::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.StoreNonPointer(&result.untag()->num_entries_, num_handlers);
@@ -15257,9 +15313,9 @@
   SingleTargetCache& result = SingleTargetCache::Handle();
   {
     // IC data objects are long living objects, allocate them in old generation.
-    ObjectPtr raw = Object::Allocate(SingleTargetCache::kClassId,
-                                     SingleTargetCache::InstanceSize(),
-                                     Heap::kOld, /*compressed*/ false);
+    ObjectPtr raw = Object::Allocate(
+        SingleTargetCache::kClassId, SingleTargetCache::InstanceSize(),
+        Heap::kOld, SingleTargetCache::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -15292,7 +15348,7 @@
   UnlinkedCall& result = UnlinkedCall::Handle();
   result ^=
       Object::Allocate(UnlinkedCall::kClassId, UnlinkedCall::InstanceSize(),
-                       Heap::kOld, /*compressed*/ false);
+                       Heap::kOld, UnlinkedCall::ContainsCompressedPointers());
   result.set_can_patch_to_monomorphic(!FLAG_precompiled_mode);
   return result.ptr();
 }
@@ -15300,9 +15356,9 @@
 MonomorphicSmiableCallPtr MonomorphicSmiableCall::New(classid_t expected_cid,
                                                       const Code& target) {
   auto& result = MonomorphicSmiableCall::Handle();
-  result ^= Object::Allocate(MonomorphicSmiableCall::kClassId,
-                             MonomorphicSmiableCall::InstanceSize(), Heap::kOld,
-                             /*compressed*/ false);
+  result ^= Object::Allocate(
+      MonomorphicSmiableCall::kClassId, MonomorphicSmiableCall::InstanceSize(),
+      Heap::kOld, MonomorphicSmiableCall::ContainsCompressedPointers());
   result.untag()->set_target(target.ptr());
   result.StoreNonPointer(&result.untag()->expected_cid_, expected_cid);
   result.StoreNonPointer(&result.untag()->entrypoint_, target.EntryPoint());
@@ -16257,8 +16313,9 @@
   ICData& result = ICData::Handle(zone);
   {
     // IC data objects are long living objects, allocate them in old generation.
-    ObjectPtr raw = Object::Allocate(ICData::kClassId, ICData::InstanceSize(),
-                                     Heap::kOld, /*compressed*/ false);
+    ObjectPtr raw =
+        Object::Allocate(ICData::kClassId, ICData::InstanceSize(), Heap::kOld,
+                         ICData::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -16281,8 +16338,9 @@
   ICData& result = ICData::Handle();
   {
     // IC data objects are long living objects, allocate them in old generation.
-    ObjectPtr raw = Object::Allocate(ICData::kClassId, ICData::InstanceSize(),
-                                     Heap::kOld, /*compressed*/ false);
+    ObjectPtr raw =
+        Object::Allocate(ICData::kClassId, ICData::InstanceSize(), Heap::kOld,
+                         ICData::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -16437,9 +16495,10 @@
   ASSERT(Object::weak_serialization_reference_class() != Class::null());
   WeakSerializationReference& result = WeakSerializationReference::Handle();
   {
-    ObjectPtr raw = Object::Allocate(WeakSerializationReference::kClassId,
-                                     WeakSerializationReference::InstanceSize(),
-                                     Heap::kOld, /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        WeakSerializationReference::kClassId,
+        WeakSerializationReference::InstanceSize(), Heap::kOld,
+        WeakSerializationReference::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
 
     result ^= raw;
@@ -16874,7 +16933,7 @@
   {
     uword size = Code::InstanceSize(pointer_offsets_length);
     ObjectPtr raw = Object::Allocate(Code::kClassId, size, Heap::kOld,
-                                     /*compressed*/ false);
+                                     Code::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.set_pointer_offsets_length(pointer_offsets_length);
@@ -17413,9 +17472,9 @@
   }
   Context& result = Context::Handle();
   {
-    ObjectPtr raw = Object::Allocate(Context::kClassId,
-                                     Context::InstanceSize(num_variables),
-                                     space, /*compressed*/ false);
+    ObjectPtr raw = Object::Allocate(
+        Context::kClassId, Context::InstanceSize(num_variables), space,
+        Context::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.set_num_variables(num_variables);
@@ -17484,8 +17543,9 @@
   intptr_t size = ContextScope::InstanceSize(num_variables);
   ContextScope& result = ContextScope::Handle();
   {
-    ObjectPtr raw = Object::Allocate(ContextScope::kClassId, size, Heap::kOld,
-                                     /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(ContextScope::kClassId, size, Heap::kOld,
+                         ContextScope::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.set_num_variables(num_variables);
@@ -17663,9 +17723,9 @@
 MegamorphicCachePtr MegamorphicCache::New() {
   MegamorphicCache& result = MegamorphicCache::Handle();
   {
-    ObjectPtr raw = Object::Allocate(MegamorphicCache::kClassId,
-                                     MegamorphicCache::InstanceSize(),
-                                     Heap::kOld, /*compressed*/ false);
+    ObjectPtr raw = Object::Allocate(
+        MegamorphicCache::kClassId, MegamorphicCache::InstanceSize(),
+        Heap::kOld, MegamorphicCache::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -17677,9 +17737,9 @@
                                           const Array& arguments_descriptor) {
   MegamorphicCache& result = MegamorphicCache::Handle();
   {
-    ObjectPtr raw = Object::Allocate(MegamorphicCache::kClassId,
-                                     MegamorphicCache::InstanceSize(),
-                                     Heap::kOld, /*compressed*/ false);
+    ObjectPtr raw = Object::Allocate(
+        MegamorphicCache::kClassId, MegamorphicCache::InstanceSize(),
+        Heap::kOld, MegamorphicCache::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -17863,9 +17923,9 @@
   {
     // SubtypeTestCache objects are long living objects, allocate them in the
     // old generation.
-    ObjectPtr raw = Object::Allocate(SubtypeTestCache::kClassId,
-                                     SubtypeTestCache::InstanceSize(),
-                                     Heap::kOld, /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        SubtypeTestCache::kClassId, SubtypeTestCache::InstanceSize(),
+        Heap::kOld, SubtypeTestCache::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -18146,7 +18206,7 @@
     // old generation.
     ObjectPtr raw =
         Object::Allocate(LoadingUnit::kClassId, LoadingUnit::InstanceSize(),
-                         Heap::kOld, /*compressed*/ true);
+                         Heap::kOld, LoadingUnit::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -18218,8 +18278,9 @@
 
 ApiErrorPtr ApiError::New() {
   ASSERT(Object::api_error_class() != Class::null());
-  ObjectPtr raw = Object::Allocate(ApiError::kClassId, ApiError::InstanceSize(),
-                                   Heap::kOld, /*compressed*/ true);
+  ObjectPtr raw =
+      Object::Allocate(ApiError::kClassId, ApiError::InstanceSize(), Heap::kOld,
+                       ApiError::ContainsCompressedPointers());
   return static_cast<ApiErrorPtr>(raw);
 }
 
@@ -18236,7 +18297,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(ApiError::kClassId, ApiError::InstanceSize(), space,
-                         /*compressed*/ true);
+                         ApiError::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -18261,7 +18322,7 @@
   ASSERT(Object::language_error_class() != Class::null());
   ObjectPtr raw =
       Object::Allocate(LanguageError::kClassId, LanguageError::InstanceSize(),
-                       Heap::kOld, /*compressed*/ true);
+                       Heap::kOld, LanguageError::ContainsCompressedPointers());
   return static_cast<LanguageErrorPtr>(raw);
 }
 
@@ -18278,7 +18339,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(LanguageError::kClassId, LanguageError::InstanceSize(),
-                         space, /*compressed*/ true);
+                         space, LanguageError::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -18318,7 +18379,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(LanguageError::kClassId, LanguageError::InstanceSize(),
-                         space, /*compressed*/ true);
+                         space, LanguageError::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -18388,9 +18449,9 @@
   ASSERT(Object::unhandled_exception_class() != Class::null());
   UnhandledException& result = UnhandledException::Handle();
   {
-    ObjectPtr raw = Object::Allocate(UnhandledException::kClassId,
-                                     UnhandledException::InstanceSize(), space,
-                                     /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        UnhandledException::kClassId, UnhandledException::InstanceSize(), space,
+        UnhandledException::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -18403,9 +18464,9 @@
   ASSERT(Object::unhandled_exception_class() != Class::null());
   UnhandledException& result = UnhandledException::Handle();
   {
-    ObjectPtr raw = Object::Allocate(UnhandledException::kClassId,
-                                     UnhandledException::InstanceSize(), space,
-                                     /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        UnhandledException::kClassId, UnhandledException::InstanceSize(), space,
+        UnhandledException::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -18463,7 +18524,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(UnwindError::kClassId, UnwindError::InstanceSize(),
-                         space, /*compressed*/ true);
+                         space, UnwindError::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -19325,8 +19386,8 @@
   }
   intptr_t instance_size = cls.host_instance_size();
   ASSERT(instance_size > 0);
-  ObjectPtr raw =
-      Object::Allocate(cls.id(), instance_size, space, /*compressed*/ false);
+  ObjectPtr raw = Object::Allocate(cls.id(), instance_size, space,
+                                   Instance::ContainsCompressedPointers());
   return static_cast<InstancePtr>(raw);
 }
 
@@ -19335,8 +19396,8 @@
                                         Heap::Space heap) {
   const intptr_t instance_size = shared_class_table->SizeAt(cid);
   ASSERT(instance_size > 0);
-  ObjectPtr raw =
-      Object::Allocate(cid, instance_size, heap, /*compressed*/ false);
+  ObjectPtr raw = Object::Allocate(cid, instance_size, heap,
+                                   Instance::ContainsCompressedPointers());
   return static_cast<InstancePtr>(raw);
 }
 
@@ -20900,7 +20961,7 @@
 
 TypePtr Type::New(Heap::Space space) {
   ObjectPtr raw = Object::Allocate(Type::kClassId, Type::InstanceSize(), space,
-                                   /*compressed*/ true);
+                                   Type::ContainsCompressedPointers());
   return static_cast<TypePtr>(raw);
 }
 
@@ -21308,8 +21369,9 @@
 }
 
 TypeRefPtr TypeRef::New() {
-  ObjectPtr raw = Object::Allocate(TypeRef::kClassId, TypeRef::InstanceSize(),
-                                   Heap::kOld, /*compressed*/ true);
+  ObjectPtr raw =
+      Object::Allocate(TypeRef::kClassId, TypeRef::InstanceSize(), Heap::kOld,
+                       TypeRef::ContainsCompressedPointers());
   return static_cast<TypeRefPtr>(raw);
 }
 
@@ -21719,7 +21781,7 @@
 TypeParameterPtr TypeParameter::New() {
   ObjectPtr raw =
       Object::Allocate(TypeParameter::kClassId, TypeParameter::InstanceSize(),
-                       Heap::kOld, /*compressed*/ true);
+                       Heap::kOld, TypeParameter::ContainsCompressedPointers());
   return static_cast<TypeParameterPtr>(raw);
 }
 
@@ -22156,7 +22218,7 @@
   Mint& result = Mint::Handle();
   {
     ObjectPtr raw = Object::Allocate(Mint::kClassId, Mint::InstanceSize(),
-                                     space, /*compressed*/ false);
+                                     space, Mint::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -22277,8 +22339,9 @@
          Class::null());
   Double& result = Double::Handle();
   {
-    ObjectPtr raw = Object::Allocate(Double::kClassId, Double::InstanceSize(),
-                                     space, /*compressed*/ false);
+    ObjectPtr raw =
+        Object::Allocate(Double::kClassId, Double::InstanceSize(), space,
+                         Double::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -23399,9 +23462,9 @@
     FATAL1("Fatal error in OneByteString::New: invalid len %" Pd "\n", len);
   }
   {
-    ObjectPtr raw = Object::Allocate(OneByteString::kClassId,
-                                     OneByteString::InstanceSize(len), space,
-                                     /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        OneByteString::kClassId, OneByteString::InstanceSize(len), space,
+        OneByteString::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     OneByteStringPtr result = static_cast<OneByteStringPtr>(raw);
     result->untag()->set_length(Smi::New(len));
@@ -23607,9 +23670,9 @@
   }
   String& result = String::Handle();
   {
-    ObjectPtr raw = Object::Allocate(TwoByteString::kClassId,
-                                     TwoByteString::InstanceSize(len), space,
-                                     /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        TwoByteString::kClassId, TwoByteString::InstanceSize(len), space,
+        TwoByteString::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(len);
@@ -23764,9 +23827,9 @@
   }
   String& result = String::Handle();
   {
-    ObjectPtr raw = Object::Allocate(ExternalOneByteString::kClassId,
-                                     ExternalOneByteString::InstanceSize(),
-                                     space, /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        ExternalOneByteString::kClassId, ExternalOneByteString::InstanceSize(),
+        space, ExternalOneByteString::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(len);
@@ -23794,9 +23857,9 @@
   }
   String& result = String::Handle();
   {
-    ObjectPtr raw = Object::Allocate(ExternalTwoByteString::kClassId,
-                                     ExternalTwoByteString::InstanceSize(),
-                                     space, /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        ExternalTwoByteString::kClassId, ExternalTwoByteString::InstanceSize(),
+        space, ExternalTwoByteString::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(len);
@@ -23901,8 +23964,9 @@
     FATAL1("Fatal error in Array::New: invalid len %" Pd "\n", len);
   }
   {
-    ArrayPtr raw = static_cast<ArrayPtr>(Object::Allocate(
-        class_id, Array::InstanceSize(len), space, /*compressed*/ false));
+    ArrayPtr raw = static_cast<ArrayPtr>(
+        Object::Allocate(class_id, Array::InstanceSize(len), space,
+                         Array::ContainsCompressedPointers()));
     NoSafepointScope no_safepoint;
     raw->untag()->set_length(Smi::New(len));
     return raw;
@@ -24109,9 +24173,9 @@
       Class::null());
   GrowableObjectArray& result = GrowableObjectArray::Handle();
   {
-    ObjectPtr raw = Object::Allocate(GrowableObjectArray::kClassId,
-                                     GrowableObjectArray::InstanceSize(), space,
-                                     /*compressed*/ false);
+    ObjectPtr raw = Object::Allocate(
+        GrowableObjectArray::kClassId, GrowableObjectArray::InstanceSize(),
+        space, GrowableObjectArray::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(0);
@@ -24199,7 +24263,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(LinkedHashMap::kClassId, LinkedHashMap::InstanceSize(),
-                         space, /*compressed*/ false);
+                         space, LinkedHashMap::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -24227,7 +24291,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(Float32x4::kClassId, Float32x4::InstanceSize(), space,
-                         /*compressed*/ false);
+                         Float32x4::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -24245,7 +24309,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(Float32x4::kClassId, Float32x4::InstanceSize(), space,
-                         /*compressed*/ false);
+                         Float32x4::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -24313,8 +24377,9 @@
          Class::null());
   Int32x4& result = Int32x4::Handle();
   {
-    ObjectPtr raw = Object::Allocate(Int32x4::kClassId, Int32x4::InstanceSize(),
-                                     space, /*compressed*/ false);
+    ObjectPtr raw =
+        Object::Allocate(Int32x4::kClassId, Int32x4::InstanceSize(), space,
+                         Int32x4::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -24330,8 +24395,9 @@
          Class::null());
   Int32x4& result = Int32x4::Handle();
   {
-    ObjectPtr raw = Object::Allocate(Int32x4::kClassId, Int32x4::InstanceSize(),
-                                     space, /*compressed*/ false);
+    ObjectPtr raw =
+        Object::Allocate(Int32x4::kClassId, Int32x4::InstanceSize(), space,
+                         Int32x4::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -24397,7 +24463,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(Float64x2::kClassId, Float64x2::InstanceSize(), space,
-                         /*compressed*/ false);
+                         Float64x2::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -24413,7 +24479,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(Float64x2::kClassId, Float64x2::InstanceSize(), space,
-                         /*compressed*/ false);
+                         Float64x2::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -24517,7 +24583,7 @@
     const intptr_t length_in_bytes = len * ElementSizeInBytes(class_id);
     ObjectPtr raw =
         Object::Allocate(class_id, TypedData::InstanceSize(length_in_bytes),
-                         space, /*compressed*/ true);
+                         space, TypedData::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(len);
@@ -24564,7 +24630,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(class_id, ExternalTypedData::InstanceSize(), space,
-                         /*compressed*/ true);
+                         ExternalTypedData::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.SetLength(len);
@@ -24585,8 +24651,9 @@
 TypedDataViewPtr TypedDataView::New(intptr_t class_id, Heap::Space space) {
   auto& result = TypedDataView::Handle();
   {
-    ObjectPtr raw = Object::Allocate(class_id, TypedDataView::InstanceSize(),
-                                     space, /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(class_id, TypedDataView::InstanceSize(), space,
+                         TypedDataView::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.Clear();
@@ -24636,7 +24703,7 @@
 
   Pointer& result = Pointer::Handle(zone);
   result ^= Object::Allocate(kFfiPointerCid, Pointer::InstanceSize(), space,
-                             /*compressed*/ false);
+                             Pointer::ContainsCompressedPointers());
   result.SetTypeArguments(type_args);
   result.SetNativeAddress(native_address);
 
@@ -24654,7 +24721,7 @@
   DynamicLibrary& result = DynamicLibrary::Handle();
   result ^=
       Object::Allocate(kFfiDynamicLibraryCid, DynamicLibrary::InstanceSize(),
-                       space, /*compressed*/ false);
+                       space, DynamicLibrary::ContainsCompressedPointers());
   NoSafepointScope no_safepoint;
   result.SetHandle(handle);
   return result.ptr();
@@ -24678,7 +24745,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(Capability::kClassId, Capability::InstanceSize(),
-                         space, /*compressed*/ false);
+                         space, Capability::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.StoreNonPointer(&result.untag()->id_, id);
@@ -24708,7 +24775,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(ReceivePort::kClassId, ReceivePort::InstanceSize(),
-                         space, /*compressed*/ true);
+                         space, ReceivePort::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.untag()->set_send_port(send_port.ptr());
@@ -24741,7 +24808,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(SendPort::kClassId, SendPort::InstanceSize(), space,
-                         /*compressed*/ false);
+                         SendPort::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.StoreNonPointer(&result.untag()->id_, id);
@@ -24767,9 +24834,9 @@
   Thread* thread = Thread::Current();
   TransferableTypedData& result = TransferableTypedData::Handle();
   {
-    ObjectPtr raw = Object::Allocate(TransferableTypedData::kClassId,
-                                     TransferableTypedData::InstanceSize(),
-                                     space, /*compressed*/ false);
+    ObjectPtr raw = Object::Allocate(
+        TransferableTypedData::kClassId, TransferableTypedData::InstanceSize(),
+        space, TransferableTypedData::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     thread->heap()->SetPeer(raw, peer);
     result ^= raw;
@@ -24906,8 +24973,9 @@
                         Heap::Space space) {
   Closure& result = Closure::Handle();
   {
-    ObjectPtr raw = Object::Allocate(Closure::kClassId, Closure::InstanceSize(),
-                                     space, /*compressed*/ false);
+    ObjectPtr raw =
+        Object::Allocate(Closure::kClassId, Closure::InstanceSize(), space,
+                         Closure::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.untag()->set_instantiator_type_arguments(
@@ -24921,8 +24989,9 @@
 }
 
 ClosurePtr Closure::New() {
-  ObjectPtr raw = Object::Allocate(Closure::kClassId, Closure::InstanceSize(),
-                                   Heap::kOld, /*compressed*/ false);
+  ObjectPtr raw =
+      Object::Allocate(Closure::kClassId, Closure::InstanceSize(), Heap::kOld,
+                       Closure::ContainsCompressedPointers());
   return static_cast<ClosurePtr>(raw);
 }
 
@@ -25019,7 +25088,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(StackTrace::kClassId, StackTrace::InstanceSize(),
-                         space, /*compressed*/ true);
+                         space, StackTrace::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -25039,7 +25108,7 @@
   {
     ObjectPtr raw =
         Object::Allocate(StackTrace::kClassId, StackTrace::InstanceSize(),
-                         space, /*compressed*/ true);
+                         space, StackTrace::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -25399,8 +25468,9 @@
 RegExpPtr RegExp::New(Heap::Space space) {
   RegExp& result = RegExp::Handle();
   {
-    ObjectPtr raw = Object::Allocate(RegExp::kClassId, RegExp::InstanceSize(),
-                                     space, /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(RegExp::kClassId, RegExp::InstanceSize(), space,
+                         RegExp::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.set_type(kUninitialized);
@@ -25482,7 +25552,7 @@
          Class::null());
   ObjectPtr raw =
       Object::Allocate(WeakProperty::kClassId, WeakProperty::InstanceSize(),
-                       space, /*compressed*/ false);
+                       space, WeakProperty::ContainsCompressedPointers());
   return static_cast<WeakPropertyPtr>(raw);
 }
 
@@ -25529,9 +25599,9 @@
                                         Heap::Space space) {
   MirrorReference& result = MirrorReference::Handle();
   {
-    ObjectPtr raw = Object::Allocate(MirrorReference::kClassId,
-                                     MirrorReference::InstanceSize(), space,
-                                     /*compressed*/ true);
+    ObjectPtr raw = Object::Allocate(
+        MirrorReference::kClassId, MirrorReference::InstanceSize(), space,
+        MirrorReference::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
@@ -25568,8 +25638,9 @@
   }
   // No tag with label exists, create and register with isolate tag table.
   {
-    ObjectPtr raw = Object::Allocate(UserTag::kClassId, UserTag::InstanceSize(),
-                                     space, /*compressed*/ true);
+    ObjectPtr raw =
+        Object::Allocate(UserTag::kClassId, UserTag::InstanceSize(), space,
+                         UserTag::ContainsCompressedPointers());
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 29ed4b3..e3189da 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -81,10 +81,32 @@
 #define CHECK_HANDLE()
 #endif
 
+// For AllStatic classes like OneByteString. Checks that
+// ContainsCompressedPointers() returns the same value for AllStatic class and
+// class used for handles.
+#define ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(object, handle)           \
+  static_assert(std::is_base_of<dart::handle##Ptr, dart::object##Ptr>::value,  \
+                #object "Ptr must be a subtype of " #handle "Ptr");            \
+  static_assert(dart::handle::ContainsCompressedPointers() ==                  \
+                    dart::Untagged##object::kContainsCompressedPointers,       \
+                "Pointer compression in Untagged" #object                      \
+                " must match pointer compression in Untagged" #handle);        \
+  static constexpr bool ContainsCompressedPointers() {                         \
+    return dart::Untagged##object::kContainsCompressedPointers;                \
+  }
+
 #define BASE_OBJECT_IMPLEMENTATION(object, super)                              \
  public: /* NOLINT */                                                          \
   using UntaggedObjectType = dart::Untagged##object;                           \
   using ObjectPtrType = dart::object##Ptr;                                     \
+  static_assert(!dart::super::ContainsCompressedPointers() ||                  \
+                    UntaggedObjectType::kContainsCompressedPointers,           \
+                "Untagged" #object                                             \
+                " must have compressed pointers, as supertype Untagged" #super \
+                " has compressed pointers");                                   \
+  static constexpr bool ContainsCompressedPointers() {                         \
+    return UntaggedObjectType::kContainsCompressedPointers;                    \
+  }                                                                            \
   object##Ptr ptr() const { return static_cast<object##Ptr>(ptr_); }           \
   bool Is##object() const { return true; }                                     \
   DART_NOINLINE static object& Handle() {                                      \
@@ -287,6 +309,9 @@
 
   virtual ~Object() {}
 
+  static constexpr bool ContainsCompressedPointers() {
+    return UntaggedObject::kContainsCompressedPointers;
+  }
   ObjectPtr ptr() const { return ptr_; }
   void operator=(ObjectPtr value) { initializeHandle(this, value); }
 
@@ -937,6 +962,7 @@
     kInvocationDispatcherEntrySize,
   };
 
+  bool HasCompressedPointers() const;
   intptr_t host_instance_size() const {
     ASSERT(is_finalized() || is_prefinalized());
     return (untag()->host_instance_size_in_words_ * kWordSize);
@@ -9367,6 +9393,8 @@
 
 class OneByteString : public AllStatic {
  public:
+  ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(OneByteString, String);
+
   static uint16_t CharAt(const String& str, intptr_t index) {
     ASSERT(str.IsOneByteString());
     NoSafepointScope no_safepoint;
@@ -9512,6 +9540,8 @@
 
 class TwoByteString : public AllStatic {
  public:
+  ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(TwoByteString, String);
+
   static uint16_t CharAt(const String& str, intptr_t index) {
     ASSERT(str.IsTwoByteString());
     NoSafepointScope no_safepoint;
@@ -9639,6 +9669,8 @@
 
 class ExternalOneByteString : public AllStatic {
  public:
+  ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(ExternalOneByteString, String);
+
   static uint16_t CharAt(const String& str, intptr_t index) {
     ASSERT(str.IsExternalOneByteString());
     NoSafepointScope no_safepoint;
@@ -9737,6 +9769,8 @@
 
 class ExternalTwoByteString : public AllStatic {
  public:
+  ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(ExternalTwoByteString, String);
+
   static uint16_t CharAt(const String& str, intptr_t index) {
     ASSERT(str.IsExternalTwoByteString());
     NoSafepointScope no_safepoint;
@@ -10056,6 +10090,10 @@
 
 class ImmutableArray : public AllStatic {
  public:
+  static constexpr bool ContainsCompressedPointers() {
+    return Array::ContainsCompressedPointers();
+  }
+
   static ImmutableArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew);
 
   static ImmutableArrayPtr ReadFrom(SnapshotReader* reader,
@@ -10671,6 +10709,10 @@
 
 class ByteBuffer : public AllStatic {
  public:
+  static constexpr bool ContainsCompressedPointers() {
+    return Instance::ContainsCompressedPointers();
+  }
+
   static InstancePtr Data(const Instance& view_obj) {
     ASSERT(!view_obj.IsNull());
     return *reinterpret_cast<InstancePtr const*>(view_obj.untag() +
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 7c62065..ac28bb9 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -45,24 +45,71 @@
 class CodeStatistics;
 class StackFrame;
 
-#define VISIT_FROM(type, first)                                                \
-  type* from() { return reinterpret_cast<type*>(&first##_); }
+#define DEFINE_CONTAINS_COMPRESSED(type)                                       \
+  static constexpr bool kContainsCompressedPointers =                          \
+      is_compressed_ptr<type>::value;
 
-#define VISIT_TO(type, last)                                                   \
-  type* to() { return reinterpret_cast<type*>(&last##_); }
+#define CHECK_CONTAIN_COMPRESSED(type)                                         \
+  static_assert(                                                               \
+      kContainsCompressedPointers || is_uncompressed_ptr<type>::value,         \
+      "From declaration uses ObjectPtr");                                      \
+  static_assert(                                                               \
+      !kContainsCompressedPointers || is_compressed_ptr<type>::value,          \
+      "From declaration uses CompressedObjectPtr");
 
-#define VISIT_TO_LENGTH(type, last)                                            \
-  type* to(intptr_t length) { return reinterpret_cast<type*>(last); }
+#define VISIT_FROM(first)                                                      \
+  DEFINE_CONTAINS_COMPRESSED(decltype(first##_))                               \
+  base_ptr_type<decltype(first##_)>::type* from() {                            \
+    return reinterpret_cast<base_ptr_type<decltype(first##_)>::type*>(         \
+        &first##_);                                                            \
+  }
+
+#define VISIT_FROM_PAYLOAD_START(elem_type)                                    \
+  static_assert(is_uncompressed_ptr<elem_type>::value ||                       \
+                    is_compressed_ptr<elem_type>::value,                       \
+                "Payload elements must be object pointers");                   \
+  DEFINE_CONTAINS_COMPRESSED(elem_type)                                        \
+  base_ptr_type<elem_type>::type* from() {                                     \
+    const uword payload_start = reinterpret_cast<uword>(this) + sizeof(*this); \
+    ASSERT(Utils::IsAligned(payload_start, sizeof(elem_type)));                \
+    return reinterpret_cast<base_ptr_type<elem_type>::type*>(payload_start);   \
+  }
+
+#define VISIT_TO(last)                                                         \
+  CHECK_CONTAIN_COMPRESSED(decltype(last##_));                                 \
+  base_ptr_type<decltype(last##_)>::type* to(intptr_t length = 0) {            \
+    return reinterpret_cast<base_ptr_type<decltype(last##_)>::type*>(          \
+        &last##_);                                                             \
+  }
+
+#define VISIT_TO_PAYLOAD_END(elem_type)                                        \
+  static_assert(is_uncompressed_ptr<elem_type>::value ||                       \
+                    is_compressed_ptr<elem_type>::value,                       \
+                "Payload elements must be object pointers");                   \
+  CHECK_CONTAIN_COMPRESSED(elem_type);                                         \
+  base_ptr_type<elem_type>::type* to(intptr_t length) {                        \
+    const uword payload_start = reinterpret_cast<uword>(this) + sizeof(*this); \
+    ASSERT(Utils::IsAligned(payload_start, sizeof(elem_type)));                \
+    const uword payload_last =                                                 \
+        payload_start + sizeof(elem_type) * (length - 1);                      \
+    return reinterpret_cast<base_ptr_type<elem_type>::type*>(payload_last);    \
+  }
 
 #define VISIT_NOTHING() int NothingToVisit();
 
+#if defined(DART_COMPRESSED_POINTERS)
 #define ASSERT_UNCOMPRESSED(Type)                                              \
-  ASSERT(SIZE_OF_DEREFERENCED_RETURNED_VALUE(Untagged##Type, from) ==          \
-         sizeof(ObjectPtr))
+  static_assert(!Untagged##Type::kContainsCompressedPointers,                  \
+                "Should contain compressed pointers");
 
 #define ASSERT_COMPRESSED(Type)                                                \
-  ASSERT(SIZE_OF_DEREFERENCED_RETURNED_VALUE(Untagged##Type, from) ==          \
-         sizeof(CompressedObjectPtr))
+  static_assert(Untagged##Type::kContainsCompressedPointers,                   \
+                "Should not contain compressed pointers");
+#else
+// Do no checks if there are no compressed pointers.
+#define ASSERT_UNCOMPRESSED(Type)
+#define ASSERT_COMPRESSED(Type)
+#endif
 
 #define ASSERT_NOTHING_TO_VISIT(Type)                                          \
   ASSERT(SIZE_OF_RETURNED_VALUE(Untagged##Type, NothingToVisit) == sizeof(int))
@@ -539,10 +586,13 @@
     tags_.UpdateUnsynchronized<ClassIdTag>(new_cid);
   }
 
+ protected:
+  // Automatically inherited by subclasses unless overridden.
+  static constexpr bool kContainsCompressedPointers = false;
+
   // All writes to heap objects should ultimately pass through one of the
   // methods below or their counterparts in Object, to ensure that the
   // write barrier is correctly applied.
- protected:
   template <typename type, std::memory_order order = std::memory_order_relaxed>
   type LoadPointer(type const* addr) const {
     return reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
@@ -862,7 +912,8 @@
                                                                                \
  protected:                                                                    \
   type* array_name() { OPEN_ARRAY_START(type, type); }                         \
-  type const* array_name() const { OPEN_ARRAY_START(type, type); }
+  type const* array_name() const { OPEN_ARRAY_START(type, type); }             \
+  VISIT_TO_PAYLOAD_END(type)
 
 #define COMPRESSED_VARIABLE_POINTER_FIELDS(type, accessor_name, array_name)    \
  public:                                                                       \
@@ -883,7 +934,8 @@
   }                                                                            \
   Compressed##type const* array_name() const {                                 \
     OPEN_ARRAY_START(Compressed##type, Compressed##type);                      \
-  }
+  }                                                                            \
+  VISIT_TO_PAYLOAD_END(Compressed##type)
 
 #define SMI_FIELD(type, name)                                                  \
  public:                                                                       \
@@ -944,8 +996,8 @@
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(Class);
 
-  VISIT_FROM(CompressedObjectPtr, name)
   COMPRESSED_POINTER_FIELD(StringPtr, name)
+  VISIT_FROM(name)
   NOT_IN_PRODUCT(COMPRESSED_POINTER_FIELD(StringPtr, user_name))
   COMPRESSED_POINTER_FIELD(ArrayPtr, functions)
   COMPRESSED_POINTER_FIELD(ArrayPtr, functions_hash_table)
@@ -979,12 +1031,12 @@
 
 #if defined(DART_PRECOMPILED_RUNTIME)
 #if defined(PRODUCT)
-  VISIT_TO(CompressedObjectPtr, invocation_dispatcher_cache)
+  VISIT_TO(invocation_dispatcher_cache)
 #else
-  VISIT_TO(CompressedObjectPtr, direct_subclasses)
+  VISIT_TO(direct_subclasses)
 #endif  // defined(PRODUCT)
 #else
-  VISIT_TO(CompressedObjectPtr, dependent_code)
+  VISIT_TO(dependent_code)
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) {
@@ -1063,12 +1115,12 @@
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(PatchClass);
 
-  VISIT_FROM(CompressedObjectPtr, patched_class)
   COMPRESSED_POINTER_FIELD(ClassPtr, patched_class)
+  VISIT_FROM(patched_class)
   COMPRESSED_POINTER_FIELD(ClassPtr, origin_class)
   COMPRESSED_POINTER_FIELD(ScriptPtr, script)
   COMPRESSED_POINTER_FIELD(ExternalTypedDataPtr, library_kernel_data)
-  VISIT_TO(CompressedObjectPtr, library_kernel_data)
+  VISIT_TO(library_kernel_data)
 
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
@@ -1247,8 +1299,8 @@
   uword entry_point_;            // Accessed from generated code.
   uword unchecked_entry_point_;  // Accessed from generated code.
 
-  VISIT_FROM(CompressedObjectPtr, name)
   COMPRESSED_POINTER_FIELD(StringPtr, name)
+  VISIT_FROM(name)
   // Class or patch class or mixin class where this function is defined.
   COMPRESSED_POINTER_FIELD(ObjectPtr, owner)
   COMPRESSED_POINTER_FIELD(ArrayPtr, parameter_names)
@@ -1278,9 +1330,9 @@
   // Unoptimized code, keep it after optimization.
   NOT_IN_PRECOMPILED(COMPRESSED_POINTER_FIELD(CodePtr, unoptimized_code));
 #if defined(DART_PRECOMPILED_RUNTIME)
-  VISIT_TO(CompressedObjectPtr, code);
+  VISIT_TO(code);
 #else
-  VISIT_TO(CompressedObjectPtr, unoptimized_code);
+  VISIT_TO(unoptimized_code);
 #endif
 
   NOT_IN_PRECOMPILED(UnboxedParameterBitmap unboxed_parameters_info_);
@@ -1346,8 +1398,8 @@
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(ClosureData);
 
-  VISIT_FROM(CompressedObjectPtr, context_scope)
   COMPRESSED_POINTER_FIELD(ContextScopePtr, context_scope)
+  VISIT_FROM(context_scope)
   // Enclosing function of this local function.
 #if defined(DART_PRECOMPILER)
   // Can be wrapped by a WSR in the precompiler.
@@ -1357,7 +1409,7 @@
 #endif
   // Closure object for static implicit closures.
   COMPRESSED_POINTER_FIELD(InstancePtr, closure)
-  VISIT_TO(CompressedObjectPtr, closure)
+  VISIT_TO(closure)
 
   enum class DefaultTypeArgumentsKind : uint8_t {
     // Only here to make sure it's explicitly set appropriately.
@@ -1388,8 +1440,8 @@
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData);
 
-  VISIT_FROM(CompressedObjectPtr, signature_type)
   COMPRESSED_POINTER_FIELD(TypePtr, signature_type)
+  VISIT_FROM(signature_type)
   COMPRESSED_POINTER_FIELD(FunctionTypePtr, c_signature)
 
   // Target Dart method for callbacks, otherwise null.
@@ -1397,8 +1449,7 @@
 
   // For callbacks, value to return if Dart target throws an exception.
   COMPRESSED_POINTER_FIELD(InstancePtr, callback_exceptional_return)
-
-  VISIT_TO(CompressedObjectPtr, callback_exceptional_return)
+  VISIT_TO(callback_exceptional_return)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   // Callback id for callbacks.
@@ -1416,8 +1467,8 @@
 class UntaggedField : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Field);
 
-  VISIT_FROM(CompressedObjectPtr, name)
   COMPRESSED_POINTER_FIELD(StringPtr, name)
+  VISIT_FROM(name)
   // Class or patch class or mixin class where this field is defined or original
   // field.
   COMPRESSED_POINTER_FIELD(ObjectPtr, owner)
@@ -1445,11 +1496,11 @@
     return NULL;
   }
 #if defined(DART_PRECOMPILED_RUNTIME)
-  VISIT_TO(CompressedObjectPtr, dependent_code);
+  VISIT_TO(dependent_code);
 #else
   // For type test in implicit setter.
   COMPRESSED_POINTER_FIELD(SubtypeTestCachePtr, type_test_cache);
-  VISIT_TO(CompressedObjectPtr, type_test_cache);
+  VISIT_TO(type_test_cache);
 #endif
   TokenPosition token_pos_;
   TokenPosition end_token_pos_;
@@ -1487,8 +1538,8 @@
 class alignas(8) UntaggedScript : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Script);
 
-  VISIT_FROM(CompressedObjectPtr, url)
   COMPRESSED_POINTER_FIELD(StringPtr, url)
+  VISIT_FROM(url)
   COMPRESSED_POINTER_FIELD(StringPtr, resolved_url)
   COMPRESSED_POINTER_FIELD(ArrayPtr, compile_time_constants)
   COMPRESSED_POINTER_FIELD(TypedDataPtr, line_starts)
@@ -1498,7 +1549,7 @@
   COMPRESSED_POINTER_FIELD(ArrayPtr, debug_positions)
   COMPRESSED_POINTER_FIELD(KernelProgramInfoPtr, kernel_program_info)
   COMPRESSED_POINTER_FIELD(StringPtr, source)
-  VISIT_TO(CompressedObjectPtr, source)
+  VISIT_TO(source)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kFullAOT:
@@ -1579,8 +1630,8 @@
 
   RAW_HEAP_OBJECT_IMPLEMENTATION(Library);
 
-  VISIT_FROM(CompressedObjectPtr, name)
   COMPRESSED_POINTER_FIELD(StringPtr, name)
+  VISIT_FROM(name)
   COMPRESSED_POINTER_FIELD(StringPtr, url)
   COMPRESSED_POINTER_FIELD(StringPtr, private_key)
   // Top-level names in this library.
@@ -1619,7 +1670,7 @@
   COMPRESSED_POINTER_FIELD(ArrayPtr, exported_names);
   // Array of scripts loaded in this library.
   COMPRESSED_POINTER_FIELD(ArrayPtr, loaded_scripts);
-  VISIT_TO(CompressedObjectPtr, loaded_scripts);
+  VISIT_TO(loaded_scripts);
 
   Dart_NativeEntryResolver native_entry_resolver_;  // Resolves natives.
   Dart_NativeEntrySymbol native_entry_symbol_resolver_;
@@ -1639,15 +1690,15 @@
 class UntaggedNamespace : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Namespace);
 
-  VISIT_FROM(CompressedObjectPtr, target)
   // library with name dictionary.
   COMPRESSED_POINTER_FIELD(LibraryPtr, target)
+  VISIT_FROM(target)
   // list of names that are exported.
   COMPRESSED_POINTER_FIELD(ArrayPtr, show_names)
   // list of names that are hidden.
   COMPRESSED_POINTER_FIELD(ArrayPtr, hide_names)
   COMPRESSED_POINTER_FIELD(LibraryPtr, owner)
-  VISIT_TO(CompressedObjectPtr, owner)
+  VISIT_TO(owner)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kFullAOT:
@@ -1669,8 +1720,8 @@
 class UntaggedKernelProgramInfo : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(KernelProgramInfo);
 
-  VISIT_FROM(CompressedObjectPtr, string_offsets)
   COMPRESSED_POINTER_FIELD(TypedDataPtr, string_offsets)
+  VISIT_FROM(string_offsets)
   COMPRESSED_POINTER_FIELD(ExternalTypedDataPtr, string_data)
   COMPRESSED_POINTER_FIELD(TypedDataPtr, canonical_names)
   COMPRESSED_POINTER_FIELD(ExternalTypedDataPtr, metadata_payloads)
@@ -1683,7 +1734,7 @@
   COMPRESSED_POINTER_FIELD(ArrayPtr, libraries_cache)
   COMPRESSED_POINTER_FIELD(ArrayPtr, classes_cache)
   COMPRESSED_POINTER_FIELD(ObjectPtr, retained_kernel_blob)
-  VISIT_TO(CompressedObjectPtr, retained_kernel_blob)
+  VISIT_TO(retained_kernel_blob)
 
   uint32_t kernel_binary_version_;
 
@@ -1695,10 +1746,10 @@
 class UntaggedWeakSerializationReference : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(WeakSerializationReference);
 
-  VISIT_FROM(CompressedObjectPtr, target)
   COMPRESSED_POINTER_FIELD(ObjectPtr, target)
+  VISIT_FROM(target)
   COMPRESSED_POINTER_FIELD(ObjectPtr, replacement)
-  VISIT_TO(CompressedObjectPtr, replacement)
+  VISIT_TO(replacement)
 };
 
 class UntaggedCode : public UntaggedObject {
@@ -1750,8 +1801,8 @@
   uword unchecked_entry_point_;              // Accessed from generated code.
   uword monomorphic_unchecked_entry_point_;  // Accessed from generated code.
 
-  VISIT_FROM(ObjectPtr, object_pool)
   POINTER_FIELD(ObjectPoolPtr, object_pool)  // Accessed from generated code.
+  VISIT_FROM(object_pool)
   POINTER_FIELD(InstructionsPtr,
                 instructions)  // Accessed from generated code.
   // If owner_ is Function::null() the owner is a regular stub.
@@ -1779,11 +1830,11 @@
   NOT_IN_PRODUCT(POINTER_FIELD(ArrayPtr, comments))
 
 #if !defined(PRODUCT)
-  VISIT_TO(ObjectPtr, comments);
+  VISIT_TO(comments);
 #elif defined(DART_PRECOMPILED_RUNTIME)
-  VISIT_TO(ObjectPtr, code_source_map);
+  VISIT_TO(code_source_map);
 #else
-  VISIT_TO(ObjectPtr, static_calls_target_table);
+  VISIT_TO(static_calls_target_table);
 #endif
 
   // Compilation timestamp.
@@ -1830,6 +1881,7 @@
   };
   Entry* data() { OPEN_ARRAY_START(Entry, Entry); }
   Entry const* data() const { OPEN_ARRAY_START(Entry, Entry); }
+  DEFINE_CONTAINS_COMPRESSED(decltype(Entry::raw_obj_));
 
   // The entry bits are located after the last entry. They are encoded versions
   // of `ObjectPool::TypeBits() | ObjectPool::PatchabililtyBit()`.
@@ -1901,9 +1953,9 @@
 class UntaggedInstructionsTable : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(InstructionsTable);
 
-  VISIT_FROM(ObjectPtr, descriptors)
   POINTER_FIELD(ArrayPtr, descriptors)
-  VISIT_TO_LENGTH(ObjectPtr, &descriptors_)
+  VISIT_FROM(descriptors)
+  VISIT_TO(descriptors)
 
   intptr_t length_;
   uword start_pc_;
@@ -2159,21 +2211,13 @@
   // platforms.
   uword num_entries_;
 
-  CompressedObjectPtr* from() {
-    return reinterpret_cast<CompressedObjectPtr*>(&names()[0]);
-  }
-  CompressedStringPtr* names() {
-    // Array of [num_entries_] variable names.
-    OPEN_ARRAY_START(CompressedStringPtr, CompressedStringPtr);
-  }
+  VISIT_FROM_PAYLOAD_START(CompressedStringPtr)
+  COMPRESSED_VARIABLE_POINTER_FIELDS(StringPtr, name, names)
+
   CompressedStringPtr* nameAddrAt(intptr_t i) { return &(names()[i]); }
-  StringPtr name(intptr_t i) {
-    return LoadCompressedPointer<StringPtr>(nameAddrAt(i));
-  }
   void set_name(intptr_t i, StringPtr value) {
     StoreCompressedPointer(nameAddrAt(i), value);
   }
-  VISIT_TO_LENGTH(CompressedObjectPtr, nameAddrAt(length - 1));
 
   // Variable info with [num_entries_] entries.
   VarInfo* data() {
@@ -2192,9 +2236,9 @@
 
   // Array with [num_entries_] entries. Each entry is an array of all handled
   // exception types.
-  VISIT_FROM(CompressedObjectPtr, handled_types_data)
   COMPRESSED_POINTER_FIELD(ArrayPtr, handled_types_data)
-  VISIT_TO_LENGTH(CompressedObjectPtr, &handled_types_data_)
+  VISIT_FROM(handled_types_data)
+  VISIT_TO(handled_types_data)
 
   // Exception handler info of length [num_entries_].
   const ExceptionHandlerInfo* data() const {
@@ -2212,11 +2256,10 @@
 
   int32_t num_variables_;
 
-  VISIT_FROM(ObjectPtr, parent)
   POINTER_FIELD(ContextPtr, parent)
+  VISIT_FROM(parent)
   // Variable length data follows here.
   VARIABLE_POINTER_FIELDS(ObjectPtr, element, data)
-  VISIT_TO_LENGTH(ObjectPtr, &data()[length - 1]);
 
   friend class Object;
   friend class SnapshotReader;
@@ -2247,6 +2290,10 @@
   int32_t num_variables_;
   bool is_implicit_;  // true, if this context scope is for an implicit closure.
 
+  // Just choose one of the fields in VariableDesc, since they should all be
+  // compressed or not compressed.
+  DEFINE_CONTAINS_COMPRESSED(decltype(VariableDesc::name));
+
   CompressedObjectPtr* from() {
     VariableDesc* begin = const_cast<VariableDesc*>(VariableDescAddr(0));
     return reinterpret_cast<CompressedObjectPtr*>(begin);
@@ -2296,9 +2343,9 @@
 
 class UntaggedSingleTargetCache : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(SingleTargetCache);
-  VISIT_FROM(ObjectPtr, target)
   POINTER_FIELD(CodePtr, target)
-  VISIT_TO(ObjectPtr, target)
+  VISIT_FROM(target)
+  VISIT_TO(target)
   uword entry_point_;
   ClassIdTagType lower_limit_;
   ClassIdTagType upper_limit_;
@@ -2306,10 +2353,10 @@
 
 class UntaggedMonomorphicSmiableCall : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(MonomorphicSmiableCall);
-  VISIT_FROM(ObjectPtr, target)
   POINTER_FIELD(CodePtr,
                 target);  // Entrypoint PC in bare mode, Code in non-bare mode.
-  VISIT_TO(ObjectPtr, target)
+  VISIT_FROM(target)
+  VISIT_TO(target)
   uword expected_cid_;
   uword entrypoint_;
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
@@ -2319,31 +2366,31 @@
 class UntaggedCallSiteData : public UntaggedObject {
  protected:
   POINTER_FIELD(StringPtr, target_name);  // Name of target function.
+  VISIT_FROM(target_name)
   // arg_descriptor in RawICData and in RawMegamorphicCache should be
   // in the same position so that NoSuchMethod can access it.
   POINTER_FIELD(ArrayPtr, args_descriptor);  // Arguments descriptor.
+  VISIT_TO(args_descriptor)
+  ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
+
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(CallSiteData)
 };
 
 class UntaggedUnlinkedCall : public UntaggedCallSiteData {
   RAW_HEAP_OBJECT_IMPLEMENTATION(UnlinkedCall);
-  VISIT_FROM(ObjectPtr, target_name)
-  VISIT_TO(ObjectPtr, args_descriptor)
-  ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   bool can_patch_to_monomorphic_;
 };
 
 class UntaggedICData : public UntaggedCallSiteData {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
-  VISIT_FROM(ObjectPtr, target_name)
   POINTER_FIELD(ArrayPtr, entries)  // Contains class-ids, target and count.
   // Static type of the receiver, if instance call and available.
   NOT_IN_PRECOMPILED(POINTER_FIELD(AbstractTypePtr, receivers_static_type))
   POINTER_FIELD(ObjectPtr,
                 owner)  // Parent/calling function or original IC of cloned IC.
-  VISIT_TO(ObjectPtr, owner)
+  VISIT_TO(owner)
   ObjectPtr* to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kFullAOT:
@@ -2367,10 +2414,9 @@
 class UntaggedMegamorphicCache : public UntaggedCallSiteData {
   RAW_HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache);
 
-  VISIT_FROM(ObjectPtr, target_name)
   POINTER_FIELD(ArrayPtr, buckets)
   SMI_FIELD(SmiPtr, mask)
-  VISIT_TO(ObjectPtr, mask)
+  VISIT_TO(mask)
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   int32_t filled_entry_count_;
@@ -2379,18 +2425,18 @@
 class UntaggedSubtypeTestCache : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(SubtypeTestCache);
 
-  VISIT_FROM(ObjectPtr, cache)
   POINTER_FIELD(ArrayPtr, cache)
-  VISIT_TO(ObjectPtr, cache)
+  VISIT_FROM(cache)
+  VISIT_TO(cache)
 };
 
 class UntaggedLoadingUnit : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LoadingUnit);
 
-  VISIT_FROM(CompressedObjectPtr, parent)
   COMPRESSED_POINTER_FIELD(LoadingUnitPtr, parent)
+  VISIT_FROM(parent)
   COMPRESSED_POINTER_FIELD(ArrayPtr, base_objects)
-  VISIT_TO(CompressedObjectPtr, base_objects)
+  VISIT_TO(base_objects)
   int32_t id_;
   bool load_outstanding_;
   bool loaded_;
@@ -2403,21 +2449,21 @@
 class UntaggedApiError : public UntaggedError {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ApiError);
 
-  VISIT_FROM(CompressedObjectPtr, message)
   COMPRESSED_POINTER_FIELD(StringPtr, message)
-  VISIT_TO(CompressedObjectPtr, message)
+  VISIT_FROM(message)
+  VISIT_TO(message)
 };
 
 class UntaggedLanguageError : public UntaggedError {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LanguageError);
 
-  VISIT_FROM(CompressedObjectPtr, previous_error)
   COMPRESSED_POINTER_FIELD(ErrorPtr, previous_error)  // May be null.
+  VISIT_FROM(previous_error)
   COMPRESSED_POINTER_FIELD(ScriptPtr, script)
   COMPRESSED_POINTER_FIELD(StringPtr, message)
   // Incl. previous error's formatted message.
   COMPRESSED_POINTER_FIELD(StringPtr, formatted_message)
-  VISIT_TO(CompressedObjectPtr, formatted_message)
+  VISIT_TO(formatted_message)
   TokenPosition token_pos_;  // Source position in script_.
   bool report_after_token_;  // Report message at or after the token.
   int8_t kind_;              // Of type Report::Kind.
@@ -2428,37 +2474,39 @@
 class UntaggedUnhandledException : public UntaggedError {
   RAW_HEAP_OBJECT_IMPLEMENTATION(UnhandledException);
 
-  VISIT_FROM(CompressedObjectPtr, exception)
   COMPRESSED_POINTER_FIELD(InstancePtr, exception)
+  VISIT_FROM(exception)
   COMPRESSED_POINTER_FIELD(InstancePtr, stacktrace)
-  VISIT_TO(CompressedObjectPtr, stacktrace)
+  VISIT_TO(stacktrace)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
 class UntaggedUnwindError : public UntaggedError {
   RAW_HEAP_OBJECT_IMPLEMENTATION(UnwindError);
 
-  VISIT_FROM(CompressedObjectPtr, message)
   COMPRESSED_POINTER_FIELD(StringPtr, message)
-  VISIT_TO(CompressedObjectPtr, message)
+  VISIT_FROM(message)
+  VISIT_TO(message)
   bool is_user_initiated_;
 };
 
 class UntaggedInstance : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Instance);
+  friend class Object;
+  friend class SnapshotReader;
 };
 
 class UntaggedLibraryPrefix : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix);
 
-  VISIT_FROM(CompressedObjectPtr, name)
   // Library prefix name.
   COMPRESSED_POINTER_FIELD(StringPtr, name)
+  VISIT_FROM(name)
   // Libraries imported with this prefix.
   COMPRESSED_POINTER_FIELD(ArrayPtr, imports)
   // Library which declares this prefix.
   COMPRESSED_POINTER_FIELD(LibraryPtr, importer)
-  VISIT_TO(CompressedObjectPtr, importer)
+  VISIT_TO(importer)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kFullAOT:
@@ -2483,18 +2531,15 @@
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypeArguments);
 
-  VISIT_FROM(CompressedObjectPtr, instantiations)
   // The instantiations_ array remains empty for instantiated type arguments.
   // Of 3-tuple: 2 instantiators, result.
   COMPRESSED_POINTER_FIELD(ArrayPtr, instantiations)
+  VISIT_FROM(instantiations)
   COMPRESSED_SMI_FIELD(SmiPtr, length)
   COMPRESSED_SMI_FIELD(SmiPtr, hash)
   COMPRESSED_SMI_FIELD(SmiPtr, nullability)
   // Variable length data follows here.
   COMPRESSED_VARIABLE_POINTER_FIELDS(AbstractTypePtr, element, types)
-  CompressedObjectPtr* to(intptr_t length) {
-    return reinterpret_cast<CompressedObjectPtr*>(&types()[length - 1]);
-  }
 
   friend class Object;
   friend class SnapshotReader;
@@ -2504,15 +2549,15 @@
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypeParameters);
 
-  VISIT_FROM(CompressedObjectPtr, names)
   // Length of names reflects the number of type parameters.
   COMPRESSED_POINTER_FIELD(ArrayPtr, names)
+  VISIT_FROM(names)
   // flags: isGenericCovariantImpl and (todo) variance.
   COMPRESSED_POINTER_FIELD(ArrayPtr, flags)
   COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, bounds)
   // defaults is the instantiation to bounds (calculated by CFE).
   COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, defaults)
-  VISIT_TO(CompressedObjectPtr, defaults)
+  VISIT_TO(defaults)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   friend class Object;
@@ -2534,8 +2579,8 @@
 
   // Accessed from generated code.
   uword type_test_stub_entry_point_;
-  // Must be the last field, since subclasses use it in their VISIT_FROM.
   COMPRESSED_POINTER_FIELD(CodePtr, type_test_stub)
+  VISIT_FROM(type_test_stub)
 
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(AbstractType);
@@ -2548,11 +2593,10 @@
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(Type);
 
-  VISIT_FROM(CompressedObjectPtr, type_test_stub)
   COMPRESSED_POINTER_FIELD(SmiPtr, type_class_id)
   COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, arguments)
   COMPRESSED_POINTER_FIELD(SmiPtr, hash)
-  VISIT_TO(CompressedObjectPtr, hash)
+  VISIT_TO(hash)
   uint8_t type_state_;
   uint8_t nullability_;
 
@@ -2566,13 +2610,12 @@
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(FunctionType);
 
-  VISIT_FROM(CompressedObjectPtr, type_test_stub)
   COMPRESSED_POINTER_FIELD(TypeParametersPtr, type_parameters)
   COMPRESSED_POINTER_FIELD(AbstractTypePtr, result_type)
   COMPRESSED_POINTER_FIELD(ArrayPtr, parameter_types)
   COMPRESSED_POINTER_FIELD(ArrayPtr, parameter_names);
   COMPRESSED_POINTER_FIELD(SmiPtr, hash)
-  VISIT_TO(CompressedObjectPtr, hash)
+  VISIT_TO(hash)
   uint32_t packed_fields_;  // Number of parent type args and own parameters.
   uint8_t type_state_;
   uint8_t nullability_;
@@ -2628,9 +2671,8 @@
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypeRef);
 
-  VISIT_FROM(CompressedObjectPtr, type_test_stub)
   COMPRESSED_POINTER_FIELD(AbstractTypePtr, type)  // The referenced type.
-  VISIT_TO(CompressedObjectPtr, type)
+  VISIT_TO(type)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
@@ -2638,11 +2680,10 @@
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypeParameter);
 
-  VISIT_FROM(CompressedObjectPtr, type_test_stub)
   COMPRESSED_POINTER_FIELD(SmiPtr, hash)
   // ObjectType if no explicit bound specified.
   COMPRESSED_POINTER_FIELD(AbstractTypePtr, bound)
-  VISIT_TO(CompressedObjectPtr, bound)
+  VISIT_TO(bound)
   ClassIdTagType parameterized_class_id_;  // Or kFunctionCid for function tp.
   uint8_t base_;   // Number of enclosing function type parameters.
   uint8_t index_;  // Keep size in sync with BuildTypeParameterTypeTestStub.
@@ -2670,15 +2711,14 @@
 
   // The following fields are also declared in the Dart source of class
   // _Closure.
-  VISIT_FROM(ObjectPtr, instantiator_type_arguments)
   POINTER_FIELD(TypeArgumentsPtr, instantiator_type_arguments)
+  VISIT_FROM(instantiator_type_arguments)
   POINTER_FIELD(TypeArgumentsPtr, function_type_arguments)
   POINTER_FIELD(TypeArgumentsPtr, delayed_type_arguments)
   POINTER_FIELD(FunctionPtr, function)
   POINTER_FIELD(ContextPtr, context)
   POINTER_FIELD(SmiPtr, hash)
-
-  VISIT_TO(ObjectPtr, hash)
+  VISIT_TO(hash)
 
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
@@ -2747,13 +2787,13 @@
   RAW_HEAP_OBJECT_IMPLEMENTATION(String);
 
  protected:
-  VISIT_FROM(CompressedObjectPtr, length)
   COMPRESSED_SMI_FIELD(SmiPtr, length)
-#if !defined(HASH_IN_OBJECT_HEADER)
-  COMPRESSED_SMI_FIELD(SmiPtr, hash)
-  VISIT_TO(CompressedObjectPtr, hash)
+  VISIT_FROM(length)
+#if defined(HASH_IN_OBJECT_HEADER)
+  VISIT_TO(length)
 #else
-  VISIT_TO(CompressedObjectPtr, length)
+  COMPRESSED_SMI_FIELD(SmiPtr, hash)
+  VISIT_TO(hash);
 #endif
 
  private:
@@ -2823,6 +2863,8 @@
   // The length of the view in element sizes (obtainable via
   // [TypedDataBase::ElementSizeInBytes]).
   COMPRESSED_SMI_FIELD(SmiPtr, length);
+  VISIT_FROM(length)
+  VISIT_TO(length)
 
  private:
   friend class UntaggedTypedDataView;
@@ -2841,11 +2883,7 @@
   void RecomputeDataField() { data_ = internal_data(); }
 
  protected:
-  VISIT_FROM(CompressedObjectPtr, length)
-  VISIT_TO_LENGTH(CompressedObjectPtr, &length_)
-
   // Variable length data follows here.
-
   uint8_t* internal_data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
   const uint8_t* internal_data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
 
@@ -2916,10 +2954,9 @@
   }
 
  protected:
-  VISIT_FROM(CompressedObjectPtr, length)
   COMPRESSED_POINTER_FIELD(TypedDataBasePtr, typed_data)
   COMPRESSED_SMI_FIELD(SmiPtr, offset_in_bytes)
-  VISIT_TO(CompressedObjectPtr, offset_in_bytes)
+  VISIT_TO(offset_in_bytes)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   friend class Api;
@@ -2963,12 +3000,11 @@
 class UntaggedArray : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Array);
 
-  VISIT_FROM(ObjectPtr, type_arguments)
   ARRAY_POINTER_FIELD(TypeArgumentsPtr, type_arguments)
+  VISIT_FROM(type_arguments)
   SMI_FIELD(SmiPtr, length)
   // Variable length data follows here.
   VARIABLE_POINTER_FIELDS(ObjectPtr, element, data)
-  VISIT_TO_LENGTH(ObjectPtr, &data()[length - 1])
 
   friend class LinkedHashMapSerializationCluster;
   friend class LinkedHashMapDeserializationCluster;
@@ -2999,11 +3035,11 @@
 class UntaggedGrowableObjectArray : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(GrowableObjectArray);
 
-  VISIT_FROM(ObjectPtr, type_arguments)
   POINTER_FIELD(TypeArgumentsPtr, type_arguments)
+  VISIT_FROM(type_arguments)
   SMI_FIELD(SmiPtr, length)
   POINTER_FIELD(ArrayPtr, data)
-  VISIT_TO(ObjectPtr, data)
+  VISIT_TO(data)
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   friend class SnapshotReader;
@@ -3013,14 +3049,14 @@
 class UntaggedLinkedHashMap : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashMap);
 
-  VISIT_FROM(ObjectPtr, type_arguments)
   POINTER_FIELD(TypeArgumentsPtr, type_arguments)
+  VISIT_FROM(type_arguments)
   POINTER_FIELD(TypedDataPtr, index)
   POINTER_FIELD(SmiPtr, hash_mask)
   POINTER_FIELD(ArrayPtr, data)
   POINTER_FIELD(SmiPtr, used_data)
   POINTER_FIELD(SmiPtr, deleted_keys)
-  VISIT_TO(ObjectPtr, deleted_keys)
+  VISIT_TO(deleted_keys)
 
   friend class SnapshotReader;
 };
@@ -3094,18 +3130,14 @@
 
 class UntaggedExternalTypedData : public UntaggedTypedDataBase {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalTypedData);
-
- protected:
-  VISIT_FROM(CompressedObjectPtr, length)
-  VISIT_TO(CompressedObjectPtr, length)
 };
 
 class UntaggedPointer : public UntaggedPointerBase {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Pointer);
 
-  VISIT_FROM(CompressedObjectPtr, type_arguments)
   COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_arguments)
-  VISIT_TO(CompressedObjectPtr, type_arguments)
+  VISIT_FROM(type_arguments)
+  VISIT_TO(type_arguments)
 
   friend class Pointer;
 };
@@ -3137,15 +3169,15 @@
 class UntaggedReceivePort : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ReceivePort);
 
-  VISIT_FROM(CompressedObjectPtr, send_port)
   COMPRESSED_POINTER_FIELD(SendPortPtr, send_port)
+  VISIT_FROM(send_port)
   COMPRESSED_POINTER_FIELD(InstancePtr, handler)
-#if !defined(PRODUCT)
+#if defined(PRODUCT)
+  VISIT_TO(handler)
+#else
   COMPRESSED_POINTER_FIELD(StringPtr, debug_name)
   COMPRESSED_POINTER_FIELD(StackTracePtr, allocation_location)
-  VISIT_TO(CompressedObjectPtr, allocation_location)
-#else
-  VISIT_TO(CompressedObjectPtr, handler)
+  VISIT_TO(allocation_location)
 #endif  // !defined(PRODUCT)
 };
 
@@ -3161,15 +3193,15 @@
 class UntaggedStackTrace : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(StackTrace);
 
-  VISIT_FROM(CompressedObjectPtr, async_link)
   // Link to parent async stack trace.
   COMPRESSED_POINTER_FIELD(StackTracePtr, async_link);
+  VISIT_FROM(async_link)
   // Code object for each frame in the stack trace.
   COMPRESSED_POINTER_FIELD(ArrayPtr, code_array);
   // Offset of PC for each frame.
   COMPRESSED_POINTER_FIELD(TypedDataPtr, pc_offset_array);
 
-  VISIT_TO(CompressedObjectPtr, pc_offset_array)
+  VISIT_TO(pc_offset_array)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   // False for pre-allocated stack trace (used in OOM and Stack overflow).
@@ -3184,8 +3216,8 @@
 class UntaggedRegExp : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(RegExp);
 
-  VISIT_FROM(CompressedObjectPtr, capture_name_map)
   COMPRESSED_POINTER_FIELD(ArrayPtr, capture_name_map)
+  VISIT_FROM(capture_name_map)
   // Pattern to be used for matching.
   COMPRESSED_POINTER_FIELD(StringPtr, pattern)
   COMPRESSED_POINTER_FIELD(ObjectPtr, one_byte)  // FunctionPtr or TypedDataPtr
@@ -3196,7 +3228,7 @@
   COMPRESSED_POINTER_FIELD(ObjectPtr, two_byte_sticky)
   COMPRESSED_POINTER_FIELD(ObjectPtr, external_one_byte_sticky)
   COMPRESSED_POINTER_FIELD(ObjectPtr, external_two_byte_sticky)
-  VISIT_TO(CompressedObjectPtr, external_two_byte_sticky)
+  VISIT_TO(external_two_byte_sticky)
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   intptr_t num_bracket_expressions_;
@@ -3218,10 +3250,10 @@
 class UntaggedWeakProperty : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(WeakProperty);
 
-  VISIT_FROM(ObjectPtr, key)
   POINTER_FIELD(ObjectPtr, key)
+  VISIT_FROM(key)
   POINTER_FIELD(ObjectPtr, value)
-  VISIT_TO(ObjectPtr, value)
+  VISIT_TO(value)
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   // Linked list is chaining all pending weak properties. Not visited by
@@ -3241,18 +3273,18 @@
 class UntaggedMirrorReference : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(MirrorReference);
 
-  VISIT_FROM(CompressedObjectPtr, referent)
   COMPRESSED_POINTER_FIELD(ObjectPtr, referent)
-  VISIT_TO(CompressedObjectPtr, referent)
+  VISIT_FROM(referent)
+  VISIT_TO(referent)
 };
 
 // UserTag are used by the profiler to track Dart script state.
 class UntaggedUserTag : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(UserTag);
 
-  VISIT_FROM(CompressedObjectPtr, label)
   COMPRESSED_POINTER_FIELD(StringPtr, label)
-  VISIT_TO(CompressedObjectPtr, label)
+  VISIT_FROM(label)
+  VISIT_TO(label)
 
   // Isolate unique tag.
   uword tag_;
@@ -3267,9 +3299,9 @@
 class UntaggedFutureOr : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(FutureOr);
 
-  VISIT_FROM(ObjectPtr, type_arguments)
   POINTER_FIELD(TypeArgumentsPtr, type_arguments)
-  VISIT_TO(ObjectPtr, type_arguments)
+  VISIT_FROM(type_arguments)
+  VISIT_TO(type_arguments)
 
   friend class SnapshotReader;
 };
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 606d930..6617eec 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -745,7 +745,7 @@
   // constant.
   Instance& obj = Instance::ZoneHandle(reader->zone(), Instance::null());
   obj ^= Object::Allocate(kInstanceCid, Instance::InstanceSize(), Heap::kNew,
-                          /*compressed*/ false);
+                          Instance::ContainsCompressedPointers());
   if (UntaggedObject::IsCanonical(tags)) {
     obj = obj.Canonicalize(reader->thread());
   }
diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h
index 582e207..790050c 100644
--- a/runtime/vm/tagged_pointer.h
+++ b/runtime/vm/tagged_pointer.h
@@ -5,6 +5,7 @@
 #ifndef RUNTIME_VM_TAGGED_POINTER_H_
 #define RUNTIME_VM_TAGGED_POINTER_H_
 
+#include <type_traits>
 #include "platform/assert.h"
 #include "platform/utils.h"
 #include "vm/class_id.h"
@@ -218,6 +219,22 @@
 }
 #endif
 
+template <typename T, typename Enable = void>
+struct is_uncompressed_ptr : std::false_type {};
+template <typename T>
+struct is_uncompressed_ptr<
+    T,
+    typename std::enable_if<std::is_base_of<ObjectPtr, T>::value, void>::type>
+    : std::true_type {};
+template <typename T, typename Enable = void>
+struct is_compressed_ptr : std::false_type {};
+
+template <typename T, typename Enable = void>
+struct base_ptr_type {
+  using type =
+      typename std::enable_if<is_uncompressed_ptr<T>::value, ObjectPtr>::type;
+};
+
 #if !defined(DART_COMPRESSED_POINTERS)
 typedef ObjectPtr CompressedObjectPtr;
 #define DEFINE_COMPRESSED_POINTER(klass, base)                                 \
@@ -247,6 +264,20 @@
  protected:
   uint32_t compressed_pointer_;
 };
+
+template <typename T>
+struct is_compressed_ptr<
+    T,
+    typename std::enable_if<std::is_base_of<CompressedObjectPtr, T>::value,
+                            void>::type> : std::true_type {};
+template <typename T>
+struct base_ptr_type<
+    T,
+    typename std::enable_if<std::is_base_of<CompressedObjectPtr, T>::value,
+                            void>::type> {
+  using type = CompressedObjectPtr;
+};
+
 #define DEFINE_COMPRESSED_POINTER(klass, base)                                 \
   class Compressed##klass##Ptr : public Compressed##base##Ptr {                \
    public:                                                                     \
diff --git a/tools/VERSION b/tools/VERSION
index 195dc9c..f7875ea 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 110
+PRERELEASE 111
 PRERELEASE_PATCH 0
\ No newline at end of file