Version 2.15.0-118.0.dev

Merge commit '78b9f5495796463bd09e01ab7f90477840d8f0e4' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index fe38ee1..722a3f4 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -21,10 +21,11 @@
         Element,
         ElementKind,
         FieldElement,
+        FunctionElement,
         LibraryElement,
+        LocalVariableElement,
         PropertyAccessorElement,
-        TopLevelVariableElement,
-        LocalVariableElement;
+        TopLevelVariableElement;
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/dart/element/type_system.dart';
@@ -322,7 +323,9 @@
       // override of `noSuchMethod`.
       return 0.0;
     }
-    return proposedMemberName == 'noSuchMethod' ? -1.0 : 0.0;
+    return proposedMemberName == FunctionElement.NO_SUCH_METHOD_METHOD_NAME
+        ? -1.0
+        : 0.0;
   }
 
   /// Return the value of the _keyword_ feature for the [keyword] when
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 9bcd314..71cc613 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -457,9 +457,8 @@
 
   /// Add a suggestion for the `call` method defined on functions.
   void suggestFunctionCall() {
-    const callString = 'call';
-    final element = protocol.Element(
-        protocol.ElementKind.METHOD, callString, protocol.Element.makeFlags(),
+    final element = protocol.Element(protocol.ElementKind.METHOD,
+        FunctionElement.CALL_METHOD_NAME, protocol.Element.makeFlags(),
         location: null,
         typeParameters: null,
         parameters: '()',
@@ -467,8 +466,8 @@
     _add(CompletionSuggestion(
       CompletionSuggestionKind.INVOCATION,
       Relevance.callFunction,
-      callString,
-      callString.length,
+      FunctionElement.CALL_METHOD_NAME,
+      FunctionElement.CALL_METHOD_NAME.length,
       0,
       false,
       false,
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 8387f8a..26da055 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -140,7 +140,8 @@
       if (elementKind == ElementKind.CONSTRUCTOR) {
         kind = IndexSyntheticElementKind.constructor;
         element = element.enclosingElement!;
-      } else if (element is FunctionElement && element.name == 'loadLibrary') {
+      } else if (element is FunctionElement &&
+          element.name == FunctionElement.LOAD_LIBRARY_NAME) {
         kind = IndexSyntheticElementKind.loadLibrary;
         element = element.library;
       } else if (elementKind == ElementKind.FIELD) {
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index 4f0e447..86ad536 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -43,7 +43,8 @@
 
 /// Manages knowledge about interface types and their members.
 class InheritanceManager3 {
-  static final _noSuchMethodName = Name(null, 'noSuchMethod');
+  static final _noSuchMethodName =
+      Name(null, FunctionElement.NO_SUCH_METHOD_METHOD_NAME);
 
   /// Cached instance interfaces for [ClassElement].
   final Map<ClassElement, Interface> _interfaces = {};
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index 4e01067..ce90a43 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -316,7 +316,9 @@
   /// return the function type for the call method, otherwise return null.
   FunctionType? getCallMethodType(DartType t) {
     if (t is InterfaceType) {
-      return t.lookUpMethod2('call', t.element.library)?.type;
+      return t
+          .lookUpMethod2(FunctionElement.CALL_METHOD_NAME, t.element.library)
+          ?.type;
     }
     return null;
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 790cd79..0427d04 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -77,6 +77,31 @@
     }
   }
 
+  /// Checks for a type instantiation of a `dynamic`-typed expression.
+  ///
+  /// Returns `true` if an error was reported, and resolution can stop.
+  bool _checkDynamicTypeInstantiation(FunctionReferenceImpl node,
+      PrefixedIdentifierImpl function, Element prefixElement) {
+    DartType? prefixType;
+    if (prefixElement is VariableElement) {
+      prefixType = prefixElement.type;
+    } else if (prefixElement is PropertyAccessorElement) {
+      prefixType = prefixElement.returnType;
+    }
+
+    function.prefix.staticType = prefixType;
+    if (prefixType != null && prefixType.isDynamic) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.GENERIC_METHOD_TYPE_INSTANTIATION_ON_DYNAMIC,
+        function,
+        [],
+      );
+      node.staticType = DynamicTypeImpl.instance;
+      return true;
+    }
+    return false;
+  }
+
   List<DartType> _checkTypeArguments(
     TypeArgumentList typeArgumentList,
     String? name,
@@ -271,6 +296,36 @@
     _resolve(node: node, rawType: member.type, name: propertyName.name);
   }
 
+  /// Resolve a possible function tearoff of a [FunctionElement] receiver.
+  ///
+  /// There are three possible valid cases: tearing off the `call` method of a
+  /// function element, tearing off an extension element declared on [Function],
+  /// and tearing off an extension element declared on a function type.
+  ExecutableElement? _resolveFunctionElementFunction(
+    Expression receiver,
+    SimpleIdentifier methodName,
+    FunctionElement receiverElement,
+  ) {
+    if (methodName.name == FunctionElement.CALL_METHOD_NAME) {
+      return receiverElement;
+    }
+
+    var methodElement = _resolver.typePropertyResolver
+        .resolve(
+          receiver: receiver,
+          receiverType: receiverElement.type,
+          name: methodName.name,
+          propertyErrorEntity: methodName,
+          nameErrorEntity: methodName,
+        )
+        .getter;
+    if (methodElement != null && methodElement.isStatic) {
+      _reportInvalidAccessToStaticMember(methodName, methodElement,
+          implicitReceiver: false);
+    }
+    return methodElement;
+  }
+
   void _resolvePrefixedIdentifierFunction(
       FunctionReferenceImpl node, PrefixedIdentifierImpl function) {
     var prefixElement = function.prefix.scopeLookupResult!.getter;
@@ -287,14 +342,15 @@
     }
 
     function.prefix.staticElement = prefixElement;
+    var functionName = function.identifier.name;
+
     if (prefixElement is PrefixElement) {
-      var functionName = function.identifier.name;
       var functionElement = prefixElement.scope.lookup(functionName).getter;
       if (functionElement == null) {
         _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
           function.identifier,
-          [function.identifier.name, function.prefix.name],
+          [functionName, function.prefix.name],
         );
         function.staticType = DynamicTypeImpl.instance;
         node.staticType = DynamicTypeImpl.instance;
@@ -306,21 +362,17 @@
       }
     }
 
-    DartType? prefixType;
-    if (prefixElement is VariableElement) {
-      prefixType = prefixElement.type;
-    } else if (prefixElement is PropertyAccessorElement) {
-      prefixType = prefixElement.returnType;
+    if (_checkDynamicTypeInstantiation(node, function, prefixElement)) {
+      return;
     }
 
-    function.prefix.staticType = prefixType;
-    if (prefixType != null && prefixType.isDynamic) {
-      _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.GENERIC_METHOD_TYPE_INSTANTIATION_ON_DYNAMIC,
-        function,
-        [],
+    if (prefixElement is FunctionElement &&
+        functionName == FunctionElement.CALL_METHOD_NAME) {
+      _resolve(
+        node: node,
+        rawType: prefixElement.type,
+        name: functionName,
       );
-      node.staticType = DynamicTypeImpl.instance;
       return;
     }
 
@@ -337,7 +389,7 @@
       _resolve(
         node: node,
         rawType: methodElement.type,
-        name: function.identifier.name,
+        name: functionName,
       );
       return;
     }
@@ -686,6 +738,8 @@
     }
     if (receiverElement is ClassElement) {
       return _resolveStaticElement(receiverElement, name);
+    } else if (receiverElement is FunctionElement) {
+      return _resolveFunctionElementFunction(receiver, name, receiverElement);
     } else if (receiverElement is TypeAliasElement) {
       var aliasedType = receiverElement.aliasedType;
       if (aliasedType is InterfaceType) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
index 86f1008..307a656 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -350,7 +350,8 @@
 
     var targetType = target.typeOrThrow;
 
-    if (targetType is FunctionType && propertyName.name == 'call') {
+    if (targetType is FunctionType &&
+        propertyName.name == FunctionElement.CALL_METHOD_NAME) {
       return PropertyElementResolverResult(
         functionTypeCallType: targetType,
       );
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
index 1f2aaf5..2a71f1d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
@@ -170,14 +170,16 @@
         if (_hasGetterOrSetter) {
           return _toResult();
         }
-        if (receiverTypeResolved.isDartCoreFunction && _name == 'call') {
+        if (receiverTypeResolved.isDartCoreFunction &&
+            _name == FunctionElement.CALL_METHOD_NAME) {
           _needsGetterError = false;
           _needsSetterError = false;
           return _toResult();
         }
       }
 
-      if (receiverTypeResolved is FunctionType && _name == 'call') {
+      if (receiverTypeResolved is FunctionType &&
+          _name == FunctionElement.CALL_METHOD_NAME) {
         return _toResult();
       }
 
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 9415a30..ca0efc9 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -14,7 +14,7 @@
   static final Set<String> _enumInstanceMembers = {
     'hashCode',
     'index',
-    'noSuchMethod',
+    FunctionElement.NO_SUCH_METHOD_METHOD_NAME,
     'runtimeType',
     'toString',
   };
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 31e2553..bf8620e 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2396,7 +2396,7 @@
         name == 'hashCode' ||
         name == 'toString' ||
         name == 'runtimeType' ||
-        name == 'noSuchMethod') {
+        name == FunctionElement.NO_SUCH_METHOD_METHOD_NAME) {
       errorReporter.reportErrorForNode(
         CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT,
         node.name,
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index 37dddf5..9585048 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -334,6 +334,102 @@
         reference, findElement.method('foo'), 'void Function(int)');
   }
 
+  test_function_call() async {
+    await assertNoErrorsInCode('''
+void foo<T>(T a) {}
+
+void bar() {
+  foo.call<int>;
+}
+''');
+
+    assertFunctionReference(findNode.functionReference('foo.call<int>;'), null,
+        'void Function(int)');
+  }
+
+  test_function_call_tooFewTypeArgs() async {
+    await assertErrorsInCode('''
+void foo<T, U>(T a, U b) {}
+
+void bar() {
+  foo.call<int>;
+}
+''', [
+      error(
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 52, 5),
+    ]);
+
+    assertFunctionReference(findNode.functionReference('foo.call<int>;'), null,
+        'void Function(dynamic, dynamic)');
+  }
+
+  test_function_call_tooManyTypeArgs() async {
+    await assertErrorsInCode('''
+void foo(String a) {}
+
+void bar() {
+  foo.call<int>;
+}
+''', [
+      error(
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 46, 5),
+    ]);
+
+    assertFunctionReference(findNode.functionReference('foo.call<int>;'), null,
+        'void Function(String)');
+  }
+
+  test_function_call_typeArgNotMatchingBound() async {
+    await assertNoErrorsInCode('''
+void foo<T extends num>(T a) {}
+
+void bar() {
+  foo.call<String>;
+}
+''');
+
+    assertFunctionReference(findNode.functionReference('foo.call<String>;'),
+        null, 'void Function(String)');
+  }
+
+  test_function_extensionOnFunction() async {
+    // TODO(srawlins): Test extension on function type, like
+    // `extension on void Function<T>(T)`.
+    await assertNoErrorsInCode('''
+void foo<T>(T a) {}
+
+void bar() {
+  foo.m<int>;
+}
+
+extension on Function {
+  void m<T>(T t) {}
+}
+''');
+
+    assertFunctionReference(findNode.functionReference('foo.m<int>;'),
+        findElement.method('m'), 'void Function(int)');
+  }
+
+  test_function_extensionOnFunction_static() async {
+    await assertErrorsInCode('''
+void foo<T>(T a) {}
+
+void bar() {
+  foo.m<int>;
+}
+
+extension on Function {
+  static void m<T>(T t) {}
+}
+''', [
+      error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 40, 1),
+    ]);
+
+    assertFunctionReference(findNode.functionReference('foo.m<int>;'),
+        findElement.method('m'), 'void Function(int)');
+  }
+
   test_instanceGetter_explicitReceiver() async {
     await assertErrorsInCode('''
 class A {
@@ -1040,6 +1136,21 @@
         findNode.functionReference('foo<int>;'), null, 'dynamic');
   }
 
+  test_topLevelFunction_targetOfCall() async {
+    await assertNoErrorsInCode('''
+void foo<T>(T a) {}
+
+void bar() {
+  foo<int>.call;
+}
+''');
+
+    assertFunctionReference(findNode.functionReference('foo<int>.call;'),
+        findElement.topFunction('foo'), 'void Function(int)');
+    assertSimpleIdentifier(findNode.simple('call;'),
+        element: null, type: 'void Function(int)');
+  }
+
   test_topLevelFunction_targetOfFunctionCall() async {
     await assertNoErrorsInCode('''
 void foo<T>(T arg) {}
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 8f0efb1..0884b17 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -49,6 +49,7 @@
 import 'null_compiler_output.dart' show NullCompilerOutput;
 import 'options.dart' show CompilerOptions;
 import 'serialization/task.dart';
+import 'serialization/serialization.dart';
 import 'serialization/strategies.dart';
 import 'ssa/nodes.dart' show HInstruction;
 import 'universe/selector.dart' show Selector;
@@ -90,6 +91,7 @@
   List<CodeLocation> _userCodeLocations = <CodeLocation>[];
 
   JClosedWorld backendClosedWorldForTesting;
+  DataSourceIndices closedWorldIndicesForTesting;
 
   DiagnosticReporter get reporter => _reporter;
   Map<Entity, WorldImpact> get impactCache => _impactCache;
@@ -257,15 +259,18 @@
     if (onlyPerformGlobalTypeInference) {
       ir.Component component =
           await serializationTask.deserializeComponentAndUpdateOptions();
-      JsClosedWorld closedWorld =
+      var closedWorldAndIndices =
           await serializationTask.deserializeClosedWorld(
               environment, abstractValueStrategy, component);
+      if (retainDataForTesting) {
+        closedWorldIndicesForTesting = closedWorldAndIndices.indices;
+      }
       GlobalTypeInferenceResults globalTypeInferenceResults =
-          performGlobalTypeInference(closedWorld);
+          performGlobalTypeInference(closedWorldAndIndices.closedWorld);
       if (options.writeDataUri != null) {
         if (options.noClosedWorldInData) {
-          serializationTask
-              .serializeGlobalTypeInference(globalTypeInferenceResults);
+          serializationTask.serializeGlobalTypeInference(
+              globalTypeInferenceResults, closedWorldAndIndices.indices);
         } else {
           serializationTask
               .serializeGlobalTypeInferenceLegacy(globalTypeInferenceResults);
@@ -277,12 +282,15 @@
       GlobalTypeInferenceResults globalTypeInferenceResults;
       ir.Component component =
           await serializationTask.deserializeComponentAndUpdateOptions();
-      JsClosedWorld closedWorld =
+      var closedWorldAndIndices =
           await serializationTask.deserializeClosedWorld(
               environment, abstractValueStrategy, component);
       globalTypeInferenceResults =
           await serializationTask.deserializeGlobalTypeInferenceResults(
-              environment, abstractValueStrategy, component, closedWorld);
+              environment,
+              abstractValueStrategy,
+              component,
+              closedWorldAndIndices);
       await generateJavaScriptCode(globalTypeInferenceResults);
     } else if (options.readDataUri != null) {
       // TODO(joshualitt) delete and clean up after google3 roll
@@ -480,15 +488,25 @@
     List<int> irData = strategy.unpackAndSerializeComponent(results);
     List<int> closedWorldData =
         strategy.serializeClosedWorld(results.closedWorld);
+    var component = strategy.deserializeComponent(irData);
+    var closedWorldAndIndices = strategy.deserializeClosedWorld(
+        options,
+        reporter,
+        environment,
+        abstractValueStrategy,
+        component,
+        closedWorldData);
     List<int> globalTypeInferenceResultsData =
-        strategy.serializeGlobalTypeInferenceResults(results);
+        strategy.serializeGlobalTypeInferenceResults(
+            closedWorldAndIndices.indices, results);
     return strategy.deserializeGlobalTypeInferenceResults(
         options,
         reporter,
         environment,
         abstractValueStrategy,
-        strategy.deserializeComponent(irData),
-        closedWorldData,
+        component,
+        closedWorldAndIndices.closedWorld,
+        closedWorldAndIndices.indices,
         globalTypeInferenceResultsData);
   }
 
@@ -515,8 +533,7 @@
       if (options.writeDataUri != null) {
         // TODO(joshualitt) delete after google3 roll.
         if (options.noClosedWorldInData) {
-          serializationTask
-              .serializeGlobalTypeInference(globalInferenceResults);
+          throw '"no-closed-world-in-data" requires serializing closed world.';
         } else {
           serializationTask
               .serializeGlobalTypeInferenceLegacy(globalInferenceResults);
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index d4a4746..8cf7074 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -13,6 +13,7 @@
   /// This is used for debugging data inconsistencies between serialization
   /// and deserialization.
   final bool useDataKinds;
+  DataSourceIndices importedIndices;
 
   /// Visitor used for serializing [ir.DartType]s.
   DartTypeNodeWriter _dartTypeNodeWriter;
@@ -40,13 +41,23 @@
   ir.Member _currentMemberContext;
   _MemberData _currentMemberData;
 
-  AbstractDataSink({this.useDataKinds: false, this.tagFrequencyMap}) {
-    _dartTypeNodeWriter = new DartTypeNodeWriter(this);
-    _stringIndex = new IndexedSink<String>(this);
-    _uriIndex = new IndexedSink<Uri>(this);
-    _memberNodeIndex = new IndexedSink<ir.Member>(this);
-    _importIndex = new IndexedSink<ImportEntity>(this);
-    _constantIndex = new IndexedSink<ConstantValue>(this);
+  IndexedSink<T> _createSink<T>() {
+    if (importedIndices == null || !importedIndices.caches.containsKey(T)) {
+      return IndexedSink<T>(this);
+    } else {
+      Map<T, int> cacheCopy = Map.from(importedIndices.caches[T].cache);
+      return IndexedSink<T>(this, cache: cacheCopy);
+    }
+  }
+
+  AbstractDataSink(
+      {this.useDataKinds: false, this.tagFrequencyMap, this.importedIndices}) {
+    _dartTypeNodeWriter = DartTypeNodeWriter(this);
+    _stringIndex = _createSink<String>();
+    _uriIndex = _createSink<Uri>();
+    _memberNodeIndex = _createSink<ir.Member>();
+    _importIndex = _createSink<ImportEntity>();
+    _constantIndex = _createSink<ConstantValue>();
   }
 
   @override
@@ -93,7 +104,7 @@
 
   @override
   void writeCached<E>(E value, void f(E value)) {
-    IndexedSink sink = _generalCaches[E] ??= new IndexedSink<E>(this);
+    IndexedSink sink = _generalCaches[E] ??= _createSink<E>();
     sink.write(value, (v) => f(v));
   }
 
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index ed14321..bda940e 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -12,6 +12,7 @@
       List<ir.DartType>.filled(0, null, growable: false);
 
   final bool useDataKinds;
+  DataSourceIndices importedIndices;
   EntityReader _entityReader = const EntityReader();
   ComponentLookup _componentLookup;
   EntityLookup _entityLookup;
@@ -29,12 +30,39 @@
   ir.Member _currentMemberContext;
   _MemberData _currentMemberData;
 
-  AbstractDataSource({this.useDataKinds: false}) {
-    _stringIndex = new IndexedSource<String>(this);
-    _uriIndex = new IndexedSource<Uri>(this);
-    _memberNodeIndex = new IndexedSource<_MemberData>(this);
-    _importIndex = new IndexedSource<ImportEntity>(this);
-    _constantIndex = new IndexedSource<ConstantValue>(this);
+  IndexedSource<T> _createSource<T>() {
+    if (importedIndices == null || !importedIndices.caches.containsKey(T)) {
+      return IndexedSource<T>(this);
+    } else {
+      List<T> cacheCopy = importedIndices.caches[T].cacheAsList.toList();
+      return IndexedSource<T>(this, cache: cacheCopy);
+    }
+  }
+
+  AbstractDataSource({this.useDataKinds: false, this.importedIndices}) {
+    _stringIndex = _createSource<String>();
+    _uriIndex = _createSource<Uri>();
+    _memberNodeIndex = _createSource<_MemberData>();
+    _importIndex = _createSource<ImportEntity>();
+    _constantIndex = _createSource<ConstantValue>();
+  }
+
+  @override
+  DataSourceIndices exportIndices() {
+    var indices = DataSourceIndices();
+    indices.caches[String] = DataSourceTypeIndices(_stringIndex.cache);
+    indices.caches[Uri] = DataSourceTypeIndices(_uriIndex.cache);
+    indices.caches[ImportEntity] = DataSourceTypeIndices(_importIndex.cache);
+    // _memberNodeIndex needs two entries depending on if the indices will be
+    // consumed by a [DataSource] or [DataSink].
+    indices.caches[_MemberData] = DataSourceTypeIndices(_memberNodeIndex.cache);
+    indices.caches[ir.Member] = DataSourceTypeIndices<ir.Member, _MemberData>(
+        _memberNodeIndex.cache, (_MemberData data) => data?.node);
+    indices.caches[ConstantValue] = DataSourceTypeIndices(_constantIndex.cache);
+    _generalCaches.forEach((type, indexedSource) {
+      indices.caches[type] = DataSourceTypeIndices(indexedSource.cache);
+    });
+    return indices;
   }
 
   @override
@@ -119,7 +147,7 @@
 
   @override
   E readCached<E>(E f()) {
-    IndexedSource source = _generalCaches[E] ??= new IndexedSource<E>(this);
+    IndexedSource source = _generalCaches[E] ??= _createSource<E>();
     return source.read(f);
   }
 
diff --git a/pkg/compiler/lib/src/serialization/binary_sink.dart b/pkg/compiler/lib/src/serialization/binary_sink.dart
index 6d46fb4..7394824 100644
--- a/pkg/compiler/lib/src/serialization/binary_sink.dart
+++ b/pkg/compiler/lib/src/serialization/binary_sink.dart
@@ -13,9 +13,14 @@
   int _length = 0;
 
   BinarySink(this.sink,
-      {bool useDataKinds: false, Map<String, int> tagFrequencyMap})
+      {bool useDataKinds: false,
+      Map<String, int> tagFrequencyMap,
+      DataSourceIndices importedIndices})
       : _bufferedSink = new BufferedSink(sink),
-        super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
+        super(
+            useDataKinds: useDataKinds,
+            tagFrequencyMap: tagFrequencyMap,
+            importedIndices: importedIndices);
 
   @override
   void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/binary_source.dart b/pkg/compiler/lib/src/serialization/binary_source.dart
index 92888ad..0bbe4d0 100644
--- a/pkg/compiler/lib/src/serialization/binary_source.dart
+++ b/pkg/compiler/lib/src/serialization/binary_source.dart
@@ -13,9 +13,11 @@
   final StringInterner _stringInterner;
 
   BinarySourceImpl(this._bytes,
-      {bool useDataKinds: false, StringInterner stringInterner})
+      {bool useDataKinds: false,
+      StringInterner stringInterner,
+      DataSourceIndices importedIndices})
       : _stringInterner = stringInterner,
-        super(useDataKinds: useDataKinds);
+        super(useDataKinds: useDataKinds, importedIndices: importedIndices);
 
   @override
   void _begin(String tag) {}
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 70a8662..17a3eda 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -264,9 +264,12 @@
 /// Data sink helper that canonicalizes [E] values using indices.
 class IndexedSink<E> {
   final AbstractDataSink _sink;
-  final Map<E, int> _cache = {null: 0}; // slot 0 is pre-allocated to `null`.
+  Map<E, int> cache;
 
-  IndexedSink(this._sink);
+  IndexedSink(this._sink, {this.cache}) {
+    // [cache] slot 0 is pre-allocated to `null`.
+    this.cache ??= {null: 0};
+  }
 
   /// Write a reference to [value] to the data sink.
   ///
@@ -274,13 +277,13 @@
   /// serialize the [value] itself.
   void write(E value, void writeValue(E value)) {
     const int pending = -1;
-    int index = _cache[value];
+    int index = cache[value];
     if (index == null) {
-      index = _cache.length;
+      index = cache.length;
       _sink._writeIntInternal(index);
-      _cache[value] = pending; // Increments length to allocate slot.
+      cache[value] = pending; // Increments length to allocate slot.
       writeValue(value);
-      _cache[value] = index;
+      cache[value] = index;
     } else if (index == pending) {
       throw ArgumentError("Cyclic dependency on cached value: $value");
     } else {
@@ -292,9 +295,12 @@
 /// Data source helper reads canonicalized [E] values through indices.
 class IndexedSource<E> {
   final AbstractDataSource _source;
-  final List<E> _cache = [null]; // slot 0 is pre-allocated to `null`.
+  List<E> cache;
 
-  IndexedSource(this._source);
+  IndexedSource(this._source, {this.cache}) {
+    // [cache] slot 0 is pre-allocated to `null`.
+    this.cache ??= [null];
+  }
 
   /// Reads a reference to an [E] value from the data source.
   ///
@@ -302,14 +308,14 @@
   /// the value itself.
   E read(E readValue()) {
     int index = _source._readIntInternal();
-    if (index >= _cache.length) {
-      assert(index == _cache.length);
-      _cache.add(null); // placeholder.
+    if (index >= cache.length) {
+      assert(index == cache.length);
+      cache.add(null); // placeholder.
       E value = readValue();
-      _cache[index] = value;
+      cache[index] = value;
       return value;
     } else {
-      E value = _cache[index];
+      E value = cache[index];
       if (value == null && index != 0) {
         throw StateError('Unfilled index $index of $E');
       }
diff --git a/pkg/compiler/lib/src/serialization/object_sink.dart b/pkg/compiler/lib/src/serialization/object_sink.dart
index 82c8885..623e104 100644
--- a/pkg/compiler/lib/src/serialization/object_sink.dart
+++ b/pkg/compiler/lib/src/serialization/object_sink.dart
@@ -11,8 +11,14 @@
 class ObjectSink extends AbstractDataSink {
   List<dynamic> _data;
 
-  ObjectSink(this._data, {bool useDataKinds, Map<String, int> tagFrequencyMap})
-      : super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
+  ObjectSink(this._data,
+      {bool useDataKinds,
+      Map<String, int> tagFrequencyMap,
+      DataSourceIndices importedIndices})
+      : super(
+            useDataKinds: useDataKinds,
+            tagFrequencyMap: tagFrequencyMap,
+            importedIndices: importedIndices);
 
   @override
   void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/object_source.dart b/pkg/compiler/lib/src/serialization/object_source.dart
index 54207a2..2d61f96 100644
--- a/pkg/compiler/lib/src/serialization/object_source.dart
+++ b/pkg/compiler/lib/src/serialization/object_source.dart
@@ -12,8 +12,9 @@
   int _index = 0;
   final List<dynamic> _data;
 
-  ObjectSource(this._data, {bool useDataKinds})
-      : super(useDataKinds: useDataKinds);
+  ObjectSource(this._data,
+      {bool useDataKinds, DataSourceIndices importedIndices})
+      : super(useDataKinds: useDataKinds, importedIndices: importedIndices);
 
   T _read<T>() {
     dynamic value = _data[_index++];
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 8e2cf4d..051be85 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -460,8 +460,50 @@
   void inMemberContext(ir.Member member, void f());
 }
 
+/// Data class representing cache information for a given [T] which can be
+/// passed from a [DataSource] to other [DataSource]s and [DataSink]s.
+class DataSourceTypeIndices<E, T> {
+  /// Reshapes a [List<T>] to a [Map<E, int>] using [_getValue].
+  Map<E, int> _reshape() {
+    var cache = <E, int>{};
+    for (int i = 0; i < cacheAsList.length; i++) {
+      cache[_getValue(cacheAsList[i])] = i;
+    }
+    return cache;
+  }
+
+  Map<E, int> get cache {
+    return _cache ??= _reshape();
+  }
+
+  final List<T> cacheAsList;
+  E Function(T value) _getValue;
+  Map<E, int> _cache;
+
+  /// Though [DataSourceTypeIndices] supports two types of caches. If the
+  /// exported indices are imported into a [DataSource] then the [cacheAsList]
+  /// will be used as is. If, however, the exported indices are imported into a
+  /// [DataSink] then we need to reshape the [List<T>] into a [Map<E, int>]
+  /// where [E] is either [T] or some value which can be derived from [T] by
+  /// [_getValue].
+  DataSourceTypeIndices(this.cacheAsList, [this._getValue]) {
+    assert(_getValue != null || T == E);
+    _getValue ??= (T t) => t as E;
+  }
+}
+
+/// Data class representing the sum of all cache information for a given
+/// [DataSource].
+class DataSourceIndices {
+  final Map<Type, DataSourceTypeIndices> caches = {};
+}
+
 /// Interface for deserialization.
 abstract class DataSource {
+  /// Exports [DataSourceIndices] for use in other [DataSource]s and
+  /// [DataSink]s.
+  DataSourceIndices exportIndices();
+
   /// Registers that the section [tag] starts.
   ///
   /// This is used for debugging to verify that sections are correctly aligned
diff --git a/pkg/compiler/lib/src/serialization/strategies.dart b/pkg/compiler/lib/src/serialization/strategies.dart
index 9269eed..909e909 100644
--- a/pkg/compiler/lib/src/serialization/strategies.dart
+++ b/pkg/compiler/lib/src/serialization/strategies.dart
@@ -31,7 +31,7 @@
   }
 
   List<T> serializeGlobalTypeInferenceResults(
-      GlobalTypeInferenceResults results);
+      DataSourceIndices indices, GlobalTypeInferenceResults results);
 
   List<int> serializeComponent(ir.Component component) {
     return ir.serializeComponent(component);
@@ -49,12 +49,13 @@
       Environment environment,
       AbstractValueStrategy abstractValueStrategy,
       ir.Component component,
-      List<T> closedWorldData,
+      JsClosedWorld closedWorld,
+      DataSourceIndices indices,
       List<T> globalTypeInferenceResultsData);
 
   List<T> serializeClosedWorld(JsClosedWorld closedWorld);
 
-  JsClosedWorld deserializeClosedWorld(
+  ClosedWorldAndIndices deserializeClosedWorld(
       CompilerOptions options,
       DiagnosticReporter reporter,
       Environment environment,
@@ -70,9 +71,10 @@
 
   @override
   List<int> serializeGlobalTypeInferenceResults(
-      GlobalTypeInferenceResults results) {
+      DataSourceIndices indices, GlobalTypeInferenceResults results) {
     ByteSink byteSink = new ByteSink();
-    DataSink sink = new BinarySink(byteSink, useDataKinds: useDataKinds);
+    DataSink sink = new BinarySink(byteSink,
+        useDataKinds: useDataKinds, importedIndices: indices);
     serializeGlobalTypeInferenceResultsToSink(results, sink);
     return byteSink.builder.takeBytes();
   }
@@ -84,20 +86,13 @@
       Environment environment,
       AbstractValueStrategy abstractValueStrategy,
       ir.Component component,
-      List<int> closedWorldData,
+      JsClosedWorld closedWorld,
+      DataSourceIndices indices,
       List<int> globalTypeInferenceResultsData) {
-    DataSource closedWorldSource =
-        BinarySourceImpl(closedWorldData, useDataKinds: useDataKinds);
     DataSource globalTypeInferenceResultsSource = BinarySourceImpl(
         globalTypeInferenceResultsData,
-        useDataKinds: useDataKinds);
-    JsClosedWorld closedWorld = deserializeClosedWorldFromSource(
-        options,
-        reporter,
-        environment,
-        abstractValueStrategy,
-        component,
-        closedWorldSource);
+        useDataKinds: useDataKinds,
+        importedIndices: indices);
     return deserializeGlobalTypeInferenceResultsFromSource(
         options,
         reporter,
@@ -117,7 +112,7 @@
   }
 
   @override
-  JsClosedWorld deserializeClosedWorld(
+  ClosedWorldAndIndices deserializeClosedWorld(
       CompilerOptions options,
       DiagnosticReporter reporter,
       Environment environment,
@@ -125,8 +120,9 @@
       ir.Component component,
       List<int> data) {
     DataSource source = new BinarySourceImpl(data, useDataKinds: useDataKinds);
-    return deserializeClosedWorldFromSource(options, reporter, environment,
-        abstractValueStrategy, component, source);
+    var closedWorld = deserializeClosedWorldFromSource(options, reporter,
+        environment, abstractValueStrategy, component, source);
+    return ClosedWorldAndIndices(closedWorld, source.exportIndices());
   }
 }
 
@@ -137,11 +133,12 @@
 
   @override
   List<int> serializeGlobalTypeInferenceResults(
-      GlobalTypeInferenceResults results) {
+      DataSourceIndices indices, GlobalTypeInferenceResults results) {
     Uri uri = Uri.base.resolve('world.data');
     DataSink sink = new BinarySink(
         new BinaryOutputSinkAdapter(new RandomAccessBinaryOutputSink(uri)),
-        useDataKinds: useDataKinds);
+        useDataKinds: useDataKinds,
+        importedIndices: indices);
     serializeGlobalTypeInferenceResultsToSink(results, sink);
     return new File.fromUri(uri).readAsBytesSync();
   }
@@ -153,20 +150,13 @@
       Environment environment,
       AbstractValueStrategy abstractValueStrategy,
       ir.Component component,
-      List<int> closedWorldData,
+      JsClosedWorld closedWorld,
+      DataSourceIndices indices,
       List<int> globalTypeInferenceResultsData) {
-    DataSource closedWorldSource =
-        BinarySourceImpl(closedWorldData, useDataKinds: useDataKinds);
     DataSource globalTypeInferenceResultsSource = BinarySourceImpl(
         globalTypeInferenceResultsData,
-        useDataKinds: useDataKinds);
-    JsClosedWorld closedWorld = deserializeClosedWorldFromSource(
-        options,
-        reporter,
-        environment,
-        abstractValueStrategy,
-        component,
-        closedWorldSource);
+        useDataKinds: useDataKinds,
+        importedIndices: indices);
     return deserializeGlobalTypeInferenceResultsFromSource(
         options,
         reporter,
@@ -188,7 +178,7 @@
   }
 
   @override
-  JsClosedWorld deserializeClosedWorld(
+  ClosedWorldAndIndices deserializeClosedWorld(
       CompilerOptions options,
       DiagnosticReporter reporter,
       Environment environment,
@@ -196,8 +186,9 @@
       ir.Component component,
       List<int> data) {
     DataSource source = new BinarySourceImpl(data, useDataKinds: useDataKinds);
-    return deserializeClosedWorldFromSource(options, reporter, environment,
-        abstractValueStrategy, component, source);
+    var closedWorld = deserializeClosedWorldFromSource(options, reporter,
+        environment, abstractValueStrategy, component, source);
+    return ClosedWorldAndIndices(closedWorld, source.exportIndices());
   }
 }
 
@@ -209,9 +200,10 @@
 
   @override
   List<Object> serializeGlobalTypeInferenceResults(
-      GlobalTypeInferenceResults results) {
+      DataSourceIndices indices, GlobalTypeInferenceResults results) {
     List<Object> data = [];
-    DataSink sink = new ObjectSink(data, useDataKinds: useDataKinds);
+    DataSink sink = new ObjectSink(data,
+        useDataKinds: useDataKinds, importedIndices: indices);
     serializeGlobalTypeInferenceResultsToSink(results, sink);
     return data;
   }
@@ -223,20 +215,13 @@
       Environment environment,
       AbstractValueStrategy abstractValueStrategy,
       ir.Component component,
-      List<Object> closedWorldData,
+      JsClosedWorld closedWorld,
+      DataSourceIndices indices,
       List<Object> globalTypeInferenceResultsData) {
-    DataSource closedWorldSource =
-        ObjectSource(closedWorldData, useDataKinds: useDataKinds);
     DataSource globalTypeInferenceResultsSource = ObjectSource(
         globalTypeInferenceResultsData,
-        useDataKinds: useDataKinds);
-    JsClosedWorld closedWorld = deserializeClosedWorldFromSource(
-        options,
-        reporter,
-        environment,
-        abstractValueStrategy,
-        component,
-        closedWorldSource);
+        useDataKinds: useDataKinds,
+        importedIndices: indices);
     return deserializeGlobalTypeInferenceResultsFromSource(
         options,
         reporter,
@@ -256,7 +241,7 @@
   }
 
   @override
-  JsClosedWorld deserializeClosedWorld(
+  ClosedWorldAndIndices deserializeClosedWorld(
       CompilerOptions options,
       DiagnosticReporter reporter,
       Environment environment,
@@ -264,7 +249,8 @@
       ir.Component component,
       List<Object> data) {
     DataSource source = new ObjectSource(data, useDataKinds: useDataKinds);
-    return deserializeClosedWorldFromSource(options, reporter, environment,
-        abstractValueStrategy, component, source);
+    var closedWorld = deserializeClosedWorldFromSource(options, reporter,
+        environment, abstractValueStrategy, component, source);
+    return ClosedWorldAndIndices(closedWorld, source.exportIndices());
   }
 }
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 72bd9b1..479a2aa 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -28,6 +28,15 @@
 import '../world.dart';
 import 'serialization.dart';
 
+/// A data class holding a [JsClosedWorld] and the associated
+/// [DataSourceIndices].
+class ClosedWorldAndIndices {
+  final JsClosedWorld closedWorld;
+  final DataSourceIndices indices;
+
+  ClosedWorldAndIndices(this.closedWorld, this.indices);
+}
+
 void serializeGlobalTypeInferenceResultsToSink(
     GlobalTypeInferenceResults results, DataSink sink) {
   JsClosedWorld closedWorld = results.closedWorld;
@@ -255,7 +264,7 @@
     });
   }
 
-  Future<JsClosedWorld> deserializeClosedWorld(
+  Future<ClosedWorldAndIndices> deserializeClosedWorld(
       Environment environment,
       AbstractValueStrategy abstractValueStrategy,
       ir.Component component) async {
@@ -266,12 +275,14 @@
           inputKind: api.InputKind.binary);
       DataSource source =
           BinarySourceImpl(dataInput.data, stringInterner: _stringInterner);
-      return deserializeClosedWorldFromSource(_options, _reporter, environment,
-          abstractValueStrategy, component, source);
+      var closedWorld = deserializeClosedWorldFromSource(_options, _reporter,
+          environment, abstractValueStrategy, component, source);
+      return ClosedWorldAndIndices(closedWorld, source.exportIndices());
     });
   }
 
-  void serializeGlobalTypeInference(GlobalTypeInferenceResults results) {
+  void serializeGlobalTypeInference(
+      GlobalTypeInferenceResults results, DataSourceIndices indices) {
     JsClosedWorld closedWorld = results.closedWorld;
     ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
     serializeComponent(component);
@@ -280,7 +291,8 @@
       _reporter.log('Writing data to ${_options.writeDataUri}');
       api.BinaryOutputSink dataOutput =
           _outputProvider.createBinarySink(_options.writeDataUri);
-      DataSink sink = new BinarySink(new BinaryOutputSinkAdapter(dataOutput));
+      DataSink sink = BinarySink(BinaryOutputSinkAdapter(dataOutput),
+          importedIndices: indices);
       serializeGlobalTypeInferenceResultsToSink(results, sink);
     });
   }
@@ -289,20 +301,21 @@
       Environment environment,
       AbstractValueStrategy abstractValueStrategy,
       ir.Component component,
-      JsClosedWorld closedWorld) async {
+      ClosedWorldAndIndices closedWorldAndIndices) async {
     return await measureIoSubtask('deserialize data', () async {
       _reporter.log('Reading data from ${_options.readDataUri}');
       api.Input<List<int>> dataInput = await _provider
           .readFromUri(_options.readDataUri, inputKind: api.InputKind.binary);
-      DataSource source =
-          BinarySourceImpl(dataInput.data, stringInterner: _stringInterner);
+      DataSource source = BinarySourceImpl(dataInput.data,
+          stringInterner: _stringInterner,
+          importedIndices: closedWorldAndIndices.indices);
       return deserializeGlobalTypeInferenceResultsFromSource(
           _options,
           _reporter,
           environment,
           abstractValueStrategy,
           component,
-          closedWorld,
+          closedWorldAndIndices.closedWorld,
           source);
     });
   }
@@ -338,6 +351,8 @@
     });
   }
 
+  // TODO(joshualitt): Investigate whether closed world indices can be shared
+  // with codegen.
   void serializeCodegen(
       BackendStrategy backendStrategy, CodegenResults codegenResults) {
     GlobalTypeInferenceResults globalTypeInferenceResults =
diff --git a/pkg/compiler/test/serialization/serialization_test.dart b/pkg/compiler/test/serialization/serialization_test.dart
index 139dde5..3b052f5 100644
--- a/pkg/compiler/test/serialization/serialization_test.dart
+++ b/pkg/compiler/test/serialization/serialization_test.dart
@@ -52,7 +52,6 @@
     testCount++;
     List<String> testOptions = options.toList();
     testOptions.add(Flags.dumpInfo);
-    testOptions.add('--out=out.js');
     if (onTest != null) {
       onTest(entity.uri);
     }
diff --git a/pkg/compiler/test/serialization/serialization_test_helper.dart b/pkg/compiler/test/serialization/serialization_test_helper.dart
index b7b771c..2507434 100644
--- a/pkg/compiler/test/serialization/serialization_test_helper.dart
+++ b/pkg/compiler/test/serialization/serialization_test_helper.dart
@@ -4,11 +4,16 @@
 
 // @dart = 2.7
 
+import 'dart:io';
+
 import 'package:compiler/compiler_new.dart';
+import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/inferrer/types.dart';
+import 'package:compiler/src/serialization/serialization.dart';
 import 'package:compiler/src/serialization/strategies.dart';
+import 'package:compiler/src/serialization/task.dart';
 import 'package:expect/expect.dart';
 import 'package:kernel/ast.dart' as ir;
 import '../helpers/memory_compiler.dart';
@@ -30,16 +35,18 @@
     bool stoppedAfterTypeInference = false}) {
   if (stoppedAfterClosedWorld) {
     JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
-    JsClosedWorld newClosedWorld =
+    var newClosedWorldAndIndices =
         cloneClosedWorld(compiler, closedWorld, strategy);
-    compiler.performGlobalTypeInference(newClosedWorld);
+    compiler.performGlobalTypeInference(newClosedWorldAndIndices.closedWorld);
   }
 
   if (stoppedAfterClosedWorld || stoppedAfterTypeInference) {
     GlobalTypeInferenceResults globalInferenceResults =
         compiler.globalInference.resultsForTesting;
+    var indices = compiler.closedWorldIndicesForTesting;
     GlobalTypeInferenceResults newGlobalInferenceResults =
-        cloneInferenceResults(compiler, globalInferenceResults, strategy);
+        cloneInferenceResults(
+            indices, compiler, globalInferenceResults, strategy);
     compiler.generateJavaScriptCode(newGlobalInferenceResults);
   }
   var actualOutput = actualOutputCollector.clear();
@@ -88,13 +95,14 @@
     List<String> options,
     SerializationStrategy strategy: const BytesInMemorySerializationStrategy(),
     bool useDataKinds: false}) async {
+  var commonOptions = options + ['--out=out.js'];
   OutputCollector collector = new OutputCollector();
   CompilationResult result = await runCompiler(
       entryPoint: entryPoint,
       memorySourceFiles: memorySourceFiles,
       packageConfig: packageConfig,
       librariesSpecificationUri: librariesSpecificationUri,
-      options: options,
+      options: commonOptions,
       outputProvider: collector,
       beforeRun: (Compiler compiler) {
         compiler.kernelLoader.forceSerialization = true;
@@ -108,7 +116,7 @@
       memorySourceFiles: memorySourceFiles,
       packageConfig: packageConfig,
       librariesSpecificationUri: librariesSpecificationUri,
-      options: options,
+      options: commonOptions,
       outputProvider: collector2,
       beforeRun: (Compiler compiler) {
         compiler.kernelLoader.forceSerialization = true;
@@ -116,26 +124,57 @@
       });
   Expect.isTrue(result2.isSuccess);
 
-  OutputCollector collector3 = new OutputCollector();
-  CompilationResult result3 = await runCompiler(
+  var dillUri = Uri.parse('out.dill');
+  var closedWorldUri = Uri.parse('world.data');
+  OutputCollector collector3a = new OutputCollector();
+  CompilationResult result3a = await runCompiler(
       entryPoint: entryPoint,
       memorySourceFiles: memorySourceFiles,
       packageConfig: packageConfig,
       librariesSpecificationUri: librariesSpecificationUri,
-      options: options,
-      outputProvider: collector3,
+      options: options +
+          ['--out=$dillUri', '${Flags.writeClosedWorld}=$closedWorldUri'],
+      outputProvider: collector3a,
+      beforeRun: (Compiler compiler) {
+        compiler.kernelLoader.forceSerialization = true;
+      });
+  Expect.isTrue(result3a.isSuccess);
+  Expect.isTrue(collector3a.binaryOutputMap.containsKey(dillUri));
+  Expect.isTrue(collector3a.binaryOutputMap.containsKey(closedWorldUri));
+
+  Directory dir =
+      await Directory.systemTemp.createTemp('serialization_test_helper');
+  var dillFileUri = dir.uri.resolve('out.dill');
+  var closedWorldFileUri = dir.uri.resolve('world.data');
+  var dillBytes = collector3a.binaryOutputMap[dillUri].list;
+  var closedWorldBytes = collector3a.binaryOutputMap[closedWorldUri].list;
+  File(dillFileUri.path).writeAsBytesSync(dillBytes);
+  File(closedWorldFileUri.path).writeAsBytesSync(closedWorldBytes);
+  OutputCollector collector3b = new OutputCollector();
+  CompilationResult result3b = await runCompiler(
+      entryPoint: dillFileUri,
+      memorySourceFiles: memorySourceFiles,
+      packageConfig: packageConfig,
+      librariesSpecificationUri: librariesSpecificationUri,
+      options: commonOptions +
+          [
+            '${Flags.readClosedWorld}=$closedWorldFileUri',
+            '${Flags.writeData}=global.data'
+          ],
+      outputProvider: collector3b,
       beforeRun: (Compiler compiler) {
         compiler.kernelLoader.forceSerialization = true;
         compiler.stopAfterTypeInference = true;
       });
-  Expect.isTrue(result3.isSuccess);
+  Expect.isTrue(result3b.isSuccess);
 
   finishCompileAndCompare(
       expectedOutput, collector2, result2.compiler, strategy,
       stoppedAfterClosedWorld: true);
   finishCompileAndCompare(
-      expectedOutput, collector3, result3.compiler, strategy,
+      expectedOutput, collector3b, result3b.compiler, strategy,
       stoppedAfterTypeInference: true);
+  await dir.delete(recursive: true);
 }
 
 void checkData(List<int> data, List<int> newData) {
@@ -161,35 +200,48 @@
   Expect.listEquals(data, newData);
 }
 
-JsClosedWorld cloneClosedWorld(Compiler compiler, JsClosedWorld closedWorld,
-    SerializationStrategy strategy) {
+ClosedWorldAndIndices cloneClosedWorld(Compiler compiler,
+    JsClosedWorld closedWorld, SerializationStrategy strategy) {
   ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
   List<int> irData = strategy.serializeComponent(component);
   List<int> closedWorldData = strategy.serializeClosedWorld(closedWorld);
   print('data size: ${closedWorldData.length}');
 
   ir.Component newComponent = strategy.deserializeComponent(irData);
-  JsClosedWorld newClosedWorld = strategy.deserializeClosedWorld(
+  var newClosedWorldAndIndices = strategy.deserializeClosedWorld(
       compiler.options,
       compiler.reporter,
       compiler.environment,
       compiler.abstractValueStrategy,
       newComponent,
       closedWorldData);
-  List<int> newClosedWorldData = strategy.serializeClosedWorld(newClosedWorld);
+  List<int> newClosedWorldData =
+      strategy.serializeClosedWorld(newClosedWorldAndIndices.closedWorld);
   checkData(closedWorldData, newClosedWorldData);
-  return newClosedWorld;
+  return newClosedWorldAndIndices;
 }
 
-GlobalTypeInferenceResults cloneInferenceResults(Compiler compiler,
-    GlobalTypeInferenceResults results, SerializationStrategy strategy) {
+GlobalTypeInferenceResults cloneInferenceResults(
+    DataSourceIndices indices,
+    Compiler compiler,
+    GlobalTypeInferenceResults results,
+    SerializationStrategy strategy) {
   List<int> irData = strategy.unpackAndSerializeComponent(results);
   List<int> closedWorldData =
       strategy.serializeClosedWorld(results.closedWorld);
-  List<int> worldData = strategy.serializeGlobalTypeInferenceResults(results);
+  List<int> worldData =
+      strategy.serializeGlobalTypeInferenceResults(indices, results);
   print('data size: ${worldData.length}');
 
   ir.Component newComponent = strategy.deserializeComponent(irData);
+  var newClosedWorldAndIndices = strategy.deserializeClosedWorld(
+      compiler.options,
+      compiler.reporter,
+      compiler.environment,
+      compiler.abstractValueStrategy,
+      newComponent,
+      closedWorldData);
+  var newIndices = indices == null ? null : newClosedWorldAndIndices.indices;
   GlobalTypeInferenceResults newResults =
       strategy.deserializeGlobalTypeInferenceResults(
           compiler.options,
@@ -197,10 +249,11 @@
           compiler.environment,
           compiler.abstractValueStrategy,
           newComponent,
-          closedWorldData,
+          newClosedWorldAndIndices.closedWorld,
+          newIndices,
           worldData);
   List<int> newWorldData =
-      strategy.serializeGlobalTypeInferenceResults(newResults);
+      strategy.serializeGlobalTypeInferenceResults(newIndices, newResults);
   checkData(worldData, newWorldData);
   return newResults;
 }
diff --git a/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart b/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart
index 13cc373..79b8b41 100644
--- a/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart
+++ b/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart
@@ -4,7 +4,6 @@
 import "dart:convert";
 import "dart:io";
 import "package:kernel/kernel.dart";
-import "package:kernel/ast.dart";
 
 main(List<String> args) async {
   // Ensure right args are passed.
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index 22e9e1a..ace7285 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -165,6 +165,12 @@
         negatable: false,
         help: 'Enables tracing of library and script loading.',
       )
+      ..addFlag('dds',
+          hide: !verbose,
+          help: 'Use the Dart Development Service (DDS) for enhanced debugging '
+              'functionality. Note: Disabling DDS may break some functionality '
+              'in IDEs and other tooling.',
+          defaultsTo: true)
       ..addFlag(
         'debug-dds',
         hide: true,
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index 45eb00c..613a508 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -12,6 +12,9 @@
 import '../utils.dart';
 
 const String soundNullSafetyMessage = 'Info: Compiling with sound null safety';
+const devToolsMessagePrefix =
+    'The Dart DevTools debugger and profiler is available at: http://127.0.0.1:';
+const observatoryMessagePrefix = 'Observatory listening on http://127.0.0.1:';
 
 void main() {
   group('run', run, timeout: longTimeout);
@@ -347,10 +350,59 @@
     expect(result.exitCode, 0);
   });
 
-  group('DevTools', () {
-    const devToolsMessagePrefix =
-        'The Dart DevTools debugger and profiler is available at: http://127.0.0.1:';
+  group('DDS', () {
+    group('disable', () {
+      test('dart run simple', () {
+        p = project(mainSrc: "void main() { print('Hello World'); }");
+        ProcessResult result = p.runSync([
+          'run',
+          '--no-dds',
+          '--enable-vm-service',
+          p.relativeFilePath,
+        ]);
+        expect(result.stdout, isNot(contains(devToolsMessagePrefix)));
+        expect(result.stdout, contains(observatoryMessagePrefix));
+      });
 
+      test('dart simple', () {
+        p = project(mainSrc: "void main() { print('Hello World'); }");
+        ProcessResult result = p.runSync([
+          '--no-dds',
+          '--enable-vm-service',
+          p.relativeFilePath,
+        ]);
+        expect(result.stdout, isNot(contains(devToolsMessagePrefix)));
+        expect(result.stdout, contains(observatoryMessagePrefix));
+      });
+    });
+
+    group('explicit enable', () {
+      test('dart run simple', () {
+        p = project(mainSrc: "void main() { print('Hello World'); }");
+        ProcessResult result = p.runSync([
+          'run',
+          '--dds',
+          '--enable-vm-service',
+          p.relativeFilePath,
+        ]);
+        expect(result.stdout, contains(devToolsMessagePrefix));
+        expect(result.stdout, contains(observatoryMessagePrefix));
+      });
+
+      test('dart simple', () {
+        p = project(mainSrc: "void main() { print('Hello World'); }");
+        ProcessResult result = p.runSync([
+          '--dds',
+          '--enable-vm-service',
+          p.relativeFilePath,
+        ]);
+        expect(result.stdout, contains(devToolsMessagePrefix));
+        expect(result.stdout, contains(observatoryMessagePrefix));
+      });
+    });
+  });
+
+  group('DevTools', () {
     test('dart run simple', () async {
       p = project(mainSrc: "void main() { print('Hello World'); }");
       ProcessResult result = p.runSync([
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index d3ca835..64f1715 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -538,7 +538,7 @@
   CHECK_RESULT(result);
 
   int vm_service_server_port = INVALID_VM_SERVICE_SERVER_PORT;
-  if (Options::disable_dart_dev()) {
+  if (Options::disable_dart_dev() || Options::disable_dds()) {
     vm_service_server_port = Options::vm_service_server_port();
   } else if (Options::vm_service_server_port() !=
              INVALID_VM_SERVICE_SERVER_PORT) {
@@ -549,12 +549,14 @@
   // the following scenarios:
   // - The DartDev CLI is disabled (CLI isolate starts DDS) and VM service is
   //   enabled.
+  // - DDS is disabled.
   // TODO(bkonyi): do we want to tie DevTools / DDS to the CLI in the long run?
-  bool wait_for_dds_to_advertise_service = !Options::disable_dart_dev();
+  bool wait_for_dds_to_advertise_service =
+      !(Options::disable_dart_dev() || Options::disable_dds());
   // Load embedder specific bits and return.
   if (!VmService::Setup(
-          Options::disable_dart_dev() ? Options::vm_service_server_ip()
-                                      : DEFAULT_VM_SERVICE_SERVER_IP,
+          !wait_for_dds_to_advertise_service ? Options::vm_service_server_ip()
+                                             : DEFAULT_VM_SERVICE_SERVER_IP,
           vm_service_server_port, Options::vm_service_dev_mode(),
           Options::vm_service_auth_disabled(),
           Options::vm_write_service_info_filename(), Options::trace_loading(),
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 44386ec..e213e70 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -454,6 +454,11 @@
       } else if (IsOption(argv[i], "no-serve-devtools")) {
         serve_devtools = false;
         skipVmOption = true;
+      } else if (IsOption(argv[i], "dds")) {
+        // This flag is set by default in dartdev, so we ignore it. --no-dds is
+        // a VM flag as disabling DDS changes how we configure the VM service,
+        // so we don't need to handle that case here.
+        skipVmOption = true;
       }
       if (!skipVmOption) {
         temp_vm_options.AddArgument(argv[i]);
@@ -623,7 +628,8 @@
       if (!run_command && strcmp(argv[i - 1], "run") == 0) {
         run_command = true;
       }
-      if (!Options::disable_dart_dev() && enable_vm_service_ && run_command) {
+      if (!Options::disable_dart_dev() && !Options::disable_dds() &&
+          enable_vm_service_ && run_command) {
         const char* dds_format_str = "--launch-dds=%s\\:%d";
         size_t size =
             snprintf(nullptr, 0, dds_format_str, vm_service_server_ip(),
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 66e6fde..e1daacf 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -44,6 +44,7 @@
   V(suppress_core_dump, suppress_core_dump)                                    \
   V(enable_service_port_fallback, enable_service_port_fallback)                \
   V(disable_dart_dev, disable_dart_dev)                                        \
+  V(no_dds, disable_dds)                                                       \
   V(long_ssl_cert_evaluation, long_ssl_cert_evaluation)                        \
   V(bypass_trusting_system_roots, bypass_trusting_system_roots)                \
   V(delayed_filewatch_callback, delayed_filewatch_callback)                    \
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index f478245..38ee528 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -68,11 +68,13 @@
 dart/regress_40753_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 dart/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 dart/use_strip_flag_test: Pass, Slow # This test can take a longer time to complete.
+dart/v8_snapshot_profile_writer_test: SkipSlow
 dart_2/appjit_cha_deopt_test: SkipSlow
 dart_2/regress_40462_test: SkipSlow
 dart_2/regress_40753_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 dart_2/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 dart_2/use_strip_flag_test: Pass, Slow # This test can take a longer time to complete.
+dart_2/v8_snapshot_profile_writer_test: SkipSlow
 
 [ $compiler == app_jitk ]
 dart/snapshot_version_test: RuntimeError
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index e62c225..76a9ecd 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -136,7 +136,13 @@
     return addr;
   }
 
-  old_space_.TryReleaseReservation();
+  if (old_space_.GrowthControlState()) {
+    WaitForSweeperTasks(Thread::Current());
+    old_space_.TryReleaseReservation();
+  } else {
+    // We may or may not be a safepoint, so we don't know how to wait for the
+    // sweeper.
+  }
 
   // Give up allocating this object.
   OS::PrintErr("Exhausted heap space, trying to allocate %" Pd " bytes.\n",
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 0cda99e..0c8a740 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -1037,6 +1037,8 @@
 }
 
 void PageSpace::TryReleaseReservation() {
+  ASSERT(phase() != kSweepingLarge);
+  ASSERT(phase() != kSweepingRegular);
   if (oom_reservation_ == nullptr) return;
   uword addr = reinterpret_cast<uword>(oom_reservation_);
   intptr_t size = oom_reservation_->HeapSize();
diff --git a/runtime/vm/longjump.cc b/runtime/vm/longjump.cc
index c778dc7..e789ecf 100644
--- a/runtime/vm/longjump.cc
+++ b/runtime/vm/longjump.cc
@@ -36,13 +36,6 @@
   Thread* thread = Thread::Current();
   DEBUG_ASSERT(thread->TopErrorHandlerIsSetJump());
 
-#if defined(DEBUG)
-#define CHECK_REUSABLE_HANDLE(name)                                            \
-  ASSERT(!thread->reusable_##name##_handle_scope_active());
-  REUSABLE_HANDLE_LIST(CHECK_REUSABLE_HANDLE)
-#undef CHECK_REUSABLE_HANDLE
-#endif  // defined(DEBUG)
-
   // Destruct all the active StackResource objects.
   StackResource::UnwindAbove(thread, top_);
   longjmp(environment_, value);
diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc
index 2853b37..45642c8 100644
--- a/runtime/vm/object_graph_copy.cc
+++ b/runtime/vm/object_graph_copy.cc
@@ -1795,9 +1795,13 @@
       const intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
       // External typed data is already initialized.
       if (!IsExternalTypedDataClassId(cid) && !IsTypedDataViewClassId(cid)) {
+#if defined(DART_COMPRESSED_POINTERS)
+        const bool compressed = true;
+#else
+        const bool compressed = false;
+#endif
         Object::InitializeObject(reinterpret_cast<uword>(to.untag()), cid,
-                                 from.untag()->HeapSize(),
-                                 /*compressed=*/cid != kContextCid);
+                                 from.untag()->HeapSize(), compressed);
         UpdateLengthField(cid, from, to);
       }
     }
diff --git a/runtime/vm/reusable_handles.h b/runtime/vm/reusable_handles.h
index e2ac116..5fcb2f7 100644
--- a/runtime/vm/reusable_handles.h
+++ b/runtime/vm/reusable_handles.h
@@ -32,16 +32,13 @@
 
 #if defined(DEBUG)
 #define REUSABLE_SCOPE(name)                                                   \
-  class Reusable##name##HandleScope : public ValueObject {                     \
+  class Reusable##name##HandleScope : public StackResource {                   \
    public:                                                                     \
-    explicit Reusable##name##HandleScope(Thread* thread) : thread_(thread) {   \
+    explicit Reusable##name##HandleScope(Thread* thread = Thread::Current())   \
+        : StackResource(thread), thread_(thread) {                             \
       ASSERT(!thread->reusable_##name##_handle_scope_active());                \
       thread->set_reusable_##name##_handle_scope_active(true);                 \
     }                                                                          \
-    Reusable##name##HandleScope() : thread_(Thread::Current()) {               \
-      ASSERT(!thread_->reusable_##name##_handle_scope_active());               \
-      thread_->set_reusable_##name##_handle_scope_active(true);                \
-    }                                                                          \
     ~Reusable##name##HandleScope() {                                           \
       ASSERT(thread_->reusable_##name##_handle_scope_active());                \
       thread_->set_reusable_##name##_handle_scope_active(false);               \
@@ -60,10 +57,8 @@
 #define REUSABLE_SCOPE(name)                                                   \
   class Reusable##name##HandleScope : public ValueObject {                     \
    public:                                                                     \
-    explicit Reusable##name##HandleScope(Thread* thread)                       \
+    explicit Reusable##name##HandleScope(Thread* thread = Thread::Current())   \
         : handle_(thread->name##_handle_) {}                                   \
-    Reusable##name##HandleScope()                                              \
-        : handle_(Thread::Current()->name##_handle_) {}                        \
     ~Reusable##name##HandleScope() { handle_->ptr_ = name::null(); }           \
     name& Handle() const {                                                     \
       ASSERT(handle_ != NULL);                                                 \
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 971e2ce..d3b0fe3 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -24,6 +24,8 @@
 LibTest/async/Stream/Stream.periodic_all_t02: Skip # Issue 42898
 
 [ $arch == simarm || $arch == simarm64 || $arch == simarm64c ]
+Language/Libraries_and_Scripts/Scripts/top_level_main_t01: SkipSlow # Very slow on sim* architectures.
+Language/Libraries_and_Scripts/Scripts/top_level_main_t06: SkipSlow # Very slow on sim* architectures.
 LibTest/collection/ListBase/ListBase_class_A01_t01: SkipSlow # Very slow on sim* architectures.
 LibTest/collection/ListBase/ListBase_class_A01_t04: SkipSlow # Very slow on sim* architectures.
 LibTest/collection/ListBase/ListBase_class_A01_t05: SkipSlow # Very slow on sim* architectures.
diff --git a/tools/VERSION b/tools/VERSION
index 90c741d..cff4e45 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 117
+PRERELEASE 118
 PRERELEASE_PATCH 0
\ No newline at end of file