Version 2.13.0-45.0.dev

Merge commit '5bcb19125ce52308c565bbe320ae5db4235c182a' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index c8e1eff..bfcdff4 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -2393,32 +2393,6 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(String name, Uri uri_, Uri uri2_)>
-    templateDuplicatedImport =
-    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
-        messageTemplate:
-            r"""'#name' is imported from both '#uri' and '#uri2'.""",
-        withArguments: _withArgumentsDuplicatedImport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_, Uri uri2_)>
-    codeDuplicatedImport =
-    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "DuplicatedImport",
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedImport(String name, Uri uri_, Uri uri2_) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  String? uri = relativizeUri(uri_);
-  String? uri2 = relativizeUri(uri2_);
-  return new Message(codeDuplicatedImport,
-      message: """'${name}' is imported from both '${uri}' and '${uri2}'.""",
-      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_, Uri uri2_)>
     templateDuplicatedImportInType =
     const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
         messageTemplate:
@@ -3244,33 +3218,6 @@
     tip: r"""Try moving the export directives before the part directives.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_, Uri uri2_)>
-    templateExportHidesExport =
-    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
-        messageTemplate:
-            r"""Export of '#name' (from '#uri') hides export from '#uri2'.""",
-        withArguments: _withArgumentsExportHidesExport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_, Uri uri2_)>
-    codeExportHidesExport =
-    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "ExportHidesExport",
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExportHidesExport(String name, Uri uri_, Uri uri2_) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  String? uri = relativizeUri(uri_);
-  String? uri2 = relativizeUri(uri2_);
-  return new Message(codeExportHidesExport,
-      message:
-          """Export of '${name}' (from '${uri}') hides export from '${uri2}'.""",
-      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeExportOptOutFromOptIn = messageExportOptOutFromOptIn;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4626,33 +4573,6 @@
     tip: r"""Try moving the import directives before the part directives.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_, Uri uri2_)>
-    templateImportHidesImport =
-    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
-        messageTemplate:
-            r"""Import of '#name' (from '#uri') hides import from '#uri2'.""",
-        withArguments: _withArgumentsImportHidesImport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_, Uri uri2_)>
-    codeImportHidesImport =
-    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "ImportHidesImport",
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsImportHidesImport(String name, Uri uri_, Uri uri2_) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  String? uri = relativizeUri(uri_);
-  String? uri2 = relativizeUri(uri2_);
-  return new Message(codeImportHidesImport,
-      message:
-          """Import of '${name}' (from '${uri}') hides import from '${uri2}'.""",
-      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeIncorrectTypeArgumentVariable =
     messageIncorrectTypeArgumentVariable;
 
@@ -6255,30 +6175,6 @@
     message: r"""List literal requires exactly one type argument.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(Uri uri_)> templateLoadLibraryHidesMember = const Template<
-        Message Function(Uri uri_)>(
-    messageTemplate:
-        r"""The library '#uri' defines a top-level member named 'loadLibrary'. This member is hidden by the special member 'loadLibrary' that the language adds to support deferred loading.""",
-    tipTemplate: r"""Try to rename or hide the member.""",
-    withArguments: _withArgumentsLoadLibraryHidesMember);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Uri uri_)> codeLoadLibraryHidesMember =
-    const Code<Message Function(Uri uri_)>("LoadLibraryHidesMember",
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsLoadLibraryHidesMember(Uri uri_) {
-  String? uri = relativizeUri(uri_);
-  return new Message(codeLoadLibraryHidesMember,
-      message:
-          """The library '${uri}' defines a top-level member named 'loadLibrary'. This member is hidden by the special member 'loadLibrary' that the language adds to support deferred loading.""",
-      tip: """Try to rename or hide the member.""",
-      arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeLoadLibraryTakesNoArguments =
     messageLoadLibraryTakesNoArguments;
 
@@ -6289,56 +6185,6 @@
     message: r"""'loadLibrary' takes no arguments.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_)>
-    templateLocalDefinitionHidesExport =
-    const Template<Message Function(String name, Uri uri_)>(
-        messageTemplate:
-            r"""Local definition of '#name' hides export from '#uri'.""",
-        withArguments: _withArgumentsLocalDefinitionHidesExport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_)>
-    codeLocalDefinitionHidesExport =
-    const Code<Message Function(String name, Uri uri_)>(
-        "LocalDefinitionHidesExport",
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsLocalDefinitionHidesExport(String name, Uri uri_) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  String? uri = relativizeUri(uri_);
-  return new Message(codeLocalDefinitionHidesExport,
-      message: """Local definition of '${name}' hides export from '${uri}'.""",
-      arguments: {'name': name, 'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_)>
-    templateLocalDefinitionHidesImport =
-    const Template<Message Function(String name, Uri uri_)>(
-        messageTemplate:
-            r"""Local definition of '#name' hides import from '#uri'.""",
-        withArguments: _withArgumentsLocalDefinitionHidesImport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_)>
-    codeLocalDefinitionHidesImport =
-    const Code<Message Function(String name, Uri uri_)>(
-        "LocalDefinitionHidesImport",
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsLocalDefinitionHidesImport(String name, Uri uri_) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  String? uri = relativizeUri(uri_);
-  return new Message(codeLocalDefinitionHidesImport,
-      message: """Local definition of '${name}' hides import from '${uri}'.""",
-      arguments: {'name': name, 'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeMainNotFunctionDeclaration =
     messageMainNotFunctionDeclaration;
 
@@ -6510,27 +6356,6 @@
     tip: r"""Try inserting 'const'.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(int count)>
-    templateMissingExplicitTypeArguments =
-    const Template<Message Function(int count)>(
-        messageTemplate: r"""No type arguments provided, #count possible.""",
-        withArguments: _withArgumentsMissingExplicitTypeArguments);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(int count)> codeMissingExplicitTypeArguments =
-    const Code<Message Function(int count)>("MissingExplicitTypeArguments",
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsMissingExplicitTypeArguments(int count) {
-  // ignore: unnecessary_null_comparison
-  if (count == null) throw 'No count provided';
-  return new Message(codeMissingExplicitTypeArguments,
-      message: """No type arguments provided, ${count} possible.""",
-      arguments: {'count': count});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeMissingExponent = messageMissingExponent;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 54cd975..95ce3fd 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -474,7 +474,6 @@
   FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE,
   FfiCode.MUST_BE_A_SUBTYPE,
   FfiCode.NON_CONSTANT_TYPE_ARGUMENT,
-  FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING,
   FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER,
   FfiCode.NON_SIZED_TYPE_ARGUMENT,
   FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS,
diff --git a/pkg/analyzer/lib/src/dart/error/ffi_code.dart b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
index 1e71193..bfbb9bd 100644
--- a/pkg/analyzer/lib/src/dart/error/ffi_code.dart
+++ b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
@@ -185,20 +185,6 @@
 
   /**
    * Parameters:
-   * 0: the name of the function, method, or constructor having type arguments
-   */
-  static const FfiCode NON_CONSTANT_TYPE_ARGUMENT_WARNING = FfiCode(
-      name: 'NON_CONSTANT_TYPE_ARGUMENT_WARNING',
-      message:
-          "Support for using non-constant type arguments '{0}' in this FFI API"
-          " is deprecated and will be removed in the next stable version of "
-          "Dart. Rewrite the code to ensure that type arguments are compile "
-          "time constants referring to a valid native type.",
-      correction: "Try changing the type argument to be a constant type.",
-      type: ErrorType.HINT);
-
-  /**
-   * Parameters:
    * 0: the type that should be a valid dart:ffi native type.
    */
   static const FfiCode NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER = FfiCode(
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index bf59990..5f6241e 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -525,9 +525,7 @@
       if (!_isValidFfiNativeType(T, allowVoid: true, allowEmptyStruct: true)) {
         final AstNode errorNode = node;
         _errorReporter.reportErrorForNode(
-            FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING,
-            errorNode,
-            ['elementAt']);
+            FfiCode.NON_CONSTANT_TYPE_ARGUMENT, errorNode, ['elementAt']);
       }
     }
   }
@@ -703,7 +701,7 @@
     if (!_isValidFfiNativeType(T, allowVoid: true, allowEmptyStruct: true)) {
       final AstNode errorNode = node;
       _errorReporter.reportErrorForNode(
-          FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING, errorNode, ['sizeOf']);
+          FfiCode.NON_CONSTANT_TYPE_ARGUMENT, errorNode, ['sizeOf']);
     }
   }
 
diff --git a/pkg/build_integration/lib/file_system/multi_root.dart b/pkg/build_integration/lib/file_system/multi_root.dart
index b5edb1b..bfaead5 100644
--- a/pkg/build_integration/lib/file_system/multi_root.dart
+++ b/pkg/build_integration/lib/file_system/multi_root.dart
@@ -75,9 +75,17 @@
   Future<bool> exists() async => (await delegate).exists();
 
   @override
+  Future<bool> existsAsyncIfPossible() async =>
+      (await delegate).existsAsyncIfPossible();
+
+  @override
   Future<List<int>> readAsBytes() async => (await delegate).readAsBytes();
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() async =>
+      (await delegate).readAsBytes();
+
+  @override
   Future<String> readAsString() async => (await delegate).readAsString();
 }
 
@@ -91,10 +99,16 @@
   Future<bool> exists() => Future.value(false);
 
   @override
+  Future<bool> existsAsyncIfPossible() => exists();
+
+  @override
   Future<List<int>> readAsBytes() =>
       Future.error(FileSystemException(uri, 'File not found'));
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() => readAsBytes();
+
+  @override
   Future<String> readAsString() =>
       Future.error(FileSystemException(uri, 'File not found'));
 }
diff --git a/pkg/build_integration/lib/file_system/single_root.dart b/pkg/build_integration/lib/file_system/single_root.dart
index 03c73df..30cbc66 100644
--- a/pkg/build_integration/lib/file_system/single_root.dart
+++ b/pkg/build_integration/lib/file_system/single_root.dart
@@ -62,9 +62,17 @@
   Future<bool> exists() async => delegate.exists();
 
   @override
+  Future<bool> existsAsyncIfPossible() async =>
+      delegate.existsAsyncIfPossible();
+
+  @override
   Future<List<int>> readAsBytes() async => delegate.readAsBytes();
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() async =>
+      delegate.readAsBytesAsyncIfPossible();
+
+  @override
   Future<String> readAsString() async => delegate.readAsString();
 }
 
diff --git a/pkg/compiler/lib/src/kernel/front_end_adapter.dart b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
index 25796fa..5076088 100644
--- a/pkg/compiler/lib/src/kernel/front_end_adapter.dart
+++ b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
@@ -69,6 +69,9 @@
   }
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() => readAsBytes();
+
+  @override
   Future<bool> exists() async {
     try {
       api.Input input = await fs.inputProvider
@@ -78,6 +81,9 @@
       return false;
     }
   }
+
+  @override
+  Future<bool> existsAsyncIfPossible() => exists();
 }
 
 /// Report a [message] received from the front-end, using dart2js's
diff --git a/pkg/front_end/lib/src/api_prototype/file_system.dart b/pkg/front_end/lib/src/api_prototype/file_system.dart
index 82b511a..e4195c5 100644
--- a/pkg/front_end/lib/src/api_prototype/file_system.dart
+++ b/pkg/front_end/lib/src/api_prototype/file_system.dart
@@ -38,17 +38,50 @@
   Uri get uri;
 
   /// Whether this file system entity exists.
+  ///
+  /// This method cannot be assumed to do any async work, in fact, if possible
+  /// it should perform the check sync as that might be faster depending on the
+  /// caller. If wanting to check async - for instance if trying to physically
+  /// check for existence and read in parallel - use [existsAsyncIfPossible]
+  /// instead.
   Future<bool> exists();
 
+  /// Whether this file system entity exists.
+  ///
+  /// This method cannot be assumed to do any async work, but should - if
+  /// possible - in fact do async work as that might be faster depending on the
+  /// caller - for instance if trying to physically check for existence (and
+  /// read) in parallel.
+  /// For sequential checks one should use [exists] instead.
+  Future<bool> existsAsyncIfPossible();
+
   /// Attempts to access this file system entity as a file and read its contents
   /// as raw bytes.
   ///
+  /// This method cannot be assumed to do any async work, in fact, if possible
+  /// it should the read sync as that might be faster depending on the caller.
+  /// If wanting to read async - for instance if trying to physically read in
+  /// parallel - use [readAsBytesAsyncIfPossible] instead.
+  ///
   /// If an error occurs while attempting to read the file (e.g. because no such
   /// file exists, or the entity is a directory), the future is completed with
   /// [FileSystemException].
   Future<List<int>> readAsBytes();
 
   /// Attempts to access this file system entity as a file and read its contents
+  /// as raw bytes.
+  ///
+  /// This method cannot be assumed to do any async work, but should - if
+  /// possible - in fact do async work as that might be faster depending on the
+  /// caller - for instance if trying to physically read in parallel.
+  /// For sequential reads one should use [readAsBytes] instead.
+  ///
+  /// If an error occurs while attempting to read the file (e.g. because no such
+  /// file exists, or the entity is a directory), the future is completed with
+  /// [FileSystemException].
+  Future<List<int>> readAsBytesAsyncIfPossible();
+
+  /// Attempts to access this file system entity as a file and read its contents
   /// as a string.
   ///
   /// The file is assumed to be UTF-8 encoded.
diff --git a/pkg/front_end/lib/src/api_prototype/memory_file_system.dart b/pkg/front_end/lib/src/api_prototype/memory_file_system.dart
index 194393b..01aa2e6 100644
--- a/pkg/front_end/lib/src/api_prototype/memory_file_system.dart
+++ b/pkg/front_end/lib/src/api_prototype/memory_file_system.dart
@@ -86,6 +86,9 @@
   }
 
   @override
+  Future<bool> existsAsyncIfPossible() => exists();
+
+  @override
   Future<List<int>> readAsBytes() async {
     Uint8List? contents = _fileSystem._files[uri];
     if (contents == null) {
@@ -95,6 +98,9 @@
   }
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() => readAsBytes();
+
+  @override
   Future<String> readAsString() async {
     List<int> bytes = await readAsBytes();
     try {
diff --git a/pkg/front_end/lib/src/api_prototype/standard_file_system.dart b/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
index bc1a4bc..35d34d5 100644
--- a/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
+++ b/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
@@ -25,7 +25,9 @@
 
   @override
   FileSystemEntity entityForUri(Uri uri) {
-    if (uri.scheme == 'file' || uri.scheme == '') {
+    if (uri.scheme == 'file') {
+      return new _IoFileSystemEntity(uri);
+    } else if (uri.scheme == '') {
       // TODO(askesc): Empty schemes should have been handled elsewhere.
       return new _IoFileSystemEntity(Uri.base.resolveUri(uri));
     } else if (uri.scheme == 'data') {
@@ -53,11 +55,26 @@
 
   @override
   Future<bool> exists() async {
+    if (new io.File.fromUri(uri).existsSync()) {
+      return true;
+    }
+    if (io.FileSystemEntity.isDirectorySync(uri.toFilePath())) {
+      return true;
+    }
+    // TODO(CFE-team): What about [Link]s?
+    return false;
+  }
+
+  @override
+  Future<bool> existsAsyncIfPossible() async {
+    if (await new io.File.fromUri(uri).exists()) {
+      return true;
+    }
     if (await io.FileSystemEntity.isDirectory(uri.toFilePath())) {
       return true;
-    } else {
-      return new io.File.fromUri(uri).exists();
     }
+    // TODO(CFE-team): What about [Link]s?
+    return false;
   }
 
   @override
@@ -71,6 +88,16 @@
   }
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() async {
+    try {
+      CompilerContext.recordDependency(uri);
+      return await new io.File.fromUri(uri).readAsBytes();
+    } on io.FileSystemException catch (exception) {
+      throw _toFileSystemException(exception);
+    }
+  }
+
+  @override
   Future<String> readAsString() async {
     try {
       CompilerContext.recordDependency(uri);
@@ -118,6 +145,12 @@
   }
 
   @override
+  Future<bool> existsAsyncIfPossible() => exists();
+
+  @override
+  Future<List<int>> readAsBytesAsyncIfPossible() => readAsBytes();
+
+  @override
   Future<String> readAsString() async {
     return uri.data.contentAsString();
   }
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index 78acbcf..33b9faa 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -62,7 +62,6 @@
         templateFfiFieldCyclic,
         templateFfiFieldInitializer,
         templateFfiFieldNoAnnotation,
-        templateFfiNonConstantTypeArgumentWarning,
         templateFfiNotStatic,
         templateFfiStructGeneric,
         templateFfiTypeInvalid,
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 1618af1..0678910 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -21,7 +21,6 @@
         messageTypedefCause,
         noLength,
         templateExtendingRestricted,
-        templateMissingExplicitTypeArguments,
         templateNotAType,
         templateSupertypeIsIllegal,
         templateSupertypeIsTypeVariable,
@@ -142,23 +141,6 @@
     } else if (member is TypeDeclarationBuilder) {
       declaration = member.origin;
       if (!declaration.isExtension) {
-        if (arguments == null && declaration.typeVariablesCount != 0) {
-          String typeName;
-          int typeNameOffset;
-          if (name is Identifier) {
-            typeName = name.name;
-            typeNameOffset = name.charOffset;
-          } else {
-            typeName = name;
-            typeNameOffset = charOffset;
-          }
-          library.addProblem(
-              templateMissingExplicitTypeArguments
-                  .withArguments(declaration.typeVariablesCount),
-              typeNameOffset,
-              typeName.length,
-              fileUri);
-        }
         return;
       }
     }
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
index 0d94cfb..a145ee7 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
@@ -916,35 +916,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
-    templateFfiNonConstantTypeArgumentWarning = const Template<
-            Message Function(DartType _type, bool isNonNullableByDefault)>(
-        messageTemplate:
-            r"""Support for using non-constant type arguments '#type' in this FFI API is deprecated and will be removed in the next stable version of Dart. Rewrite the code to ensure that type arguments are compile time constants referring to a valid native type.""",
-        withArguments: _withArgumentsFfiNonConstantTypeArgumentWarning);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, bool isNonNullableByDefault)>
-    codeFfiNonConstantTypeArgumentWarning =
-    const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
-        "FfiNonConstantTypeArgumentWarning",
-        analyzerCodes: <String>["NON_CONSTANT_TYPE_ARGUMENT_WARNING"],
-        severity: Severity.info);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFfiNonConstantTypeArgumentWarning(
-    DartType _type, bool isNonNullableByDefault) {
-  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeFfiNonConstantTypeArgumentWarning,
-      message:
-          """Support for using non-constant type arguments '${type}' in this FFI API is deprecated and will be removed in the next stable version of Dart. Rewrite the code to ensure that type arguments are compile time constants referring to a valid native type.""" +
-              labeler.originMessages,
-      arguments: {'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         DartType _type,
diff --git a/pkg/front_end/lib/src/fasta/hybrid_file_system.dart b/pkg/front_end/lib/src/fasta/hybrid_file_system.dart
index 9f1a08b..10b1a47 100644
--- a/pkg/front_end/lib/src/fasta/hybrid_file_system.dart
+++ b/pkg/front_end/lib/src/fasta/hybrid_file_system.dart
@@ -51,8 +51,16 @@
   Future<bool> exists() async => (await delegate).exists();
 
   @override
+  Future<bool> existsAsyncIfPossible() async =>
+      (await delegate).existsAsyncIfPossible();
+
+  @override
   Future<List<int>> readAsBytes() async => (await delegate).readAsBytes();
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() async =>
+      (await delegate).readAsBytesAsyncIfPossible();
+
+  @override
   Future<String> readAsString() async => (await delegate).readAsString();
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 353fd1db..c407429 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -2995,12 +2995,6 @@
         // as a recovery node once the IR can represent it (Issue #29840).
         arguments = null;
       }
-    } else if (declaration.typeVariablesCount != 0) {
-      _helper.addProblem(
-          templateMissingExplicitTypeArguments
-              .withArguments(declaration.typeVariablesCount),
-          fileOffset,
-          lengthForToken(token));
     }
 
     List<TypeBuilder> argumentBuilders;
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index a68f32c..b973591 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -2707,54 +2707,25 @@
       AccessErrorBuilder error = other;
       other = error.builder;
     }
-    bool isLocal = false;
-    bool isLoadLibrary = false;
     Builder preferred;
     Uri uri;
     Uri otherUri;
-    Uri preferredUri;
-    Uri hiddenUri;
     if (scope.lookupLocalMember(name, setter: false) == declaration) {
-      isLocal = true;
       preferred = declaration;
-      hiddenUri = computeLibraryUri(other);
     } else {
       uri = computeLibraryUri(declaration);
       otherUri = computeLibraryUri(other);
       if (declaration is LoadLibraryBuilder) {
-        isLoadLibrary = true;
         preferred = declaration;
-        preferredUri = otherUri;
       } else if (other is LoadLibraryBuilder) {
-        isLoadLibrary = true;
         preferred = other;
-        preferredUri = uri;
       } else if (otherUri?.scheme == "dart" && uri?.scheme != "dart") {
         preferred = declaration;
-        preferredUri = uri;
-        hiddenUri = otherUri;
       } else if (uri?.scheme == "dart" && otherUri?.scheme != "dart") {
         preferred = other;
-        preferredUri = otherUri;
-        hiddenUri = uri;
       }
     }
     if (preferred != null) {
-      if (isLocal) {
-        Template<Message Function(String name, Uri uri)> template = isExport
-            ? templateLocalDefinitionHidesExport
-            : templateLocalDefinitionHidesImport;
-        addProblem(template.withArguments(name, hiddenUri), charOffset,
-            noLength, fileUri);
-      } else if (isLoadLibrary) {
-        addProblem(templateLoadLibraryHidesMember.withArguments(preferredUri),
-            charOffset, noLength, fileUri);
-      } else {
-        Template<Message Function(String name, Uri uri, Uri uri2)> template =
-            isExport ? templateExportHidesExport : templateImportHidesImport;
-        addProblem(template.withArguments(name, preferredUri, hiddenUri),
-            charOffset, noLength, fileUri);
-      }
       return preferred;
     }
     if (declaration.next == null && other.next == null) {
@@ -2770,15 +2741,17 @@
           });
       }
     }
-    Template<Message Function(String name, Uri uri, Uri uri2)> template =
-        isExport ? templateDuplicatedExport : templateDuplicatedImport;
-    Message message = template.withArguments(name, uri, otherUri);
-    addProblem(message, charOffset, noLength, fileUri);
+    if (isExport) {
+      Template<Message Function(String name, Uri uri, Uri uri2)> template =
+          templateDuplicatedExport;
+      Message message = template.withArguments(name, uri, otherUri);
+      addProblem(message, charOffset, noLength, fileUri);
+    }
     Template<Message Function(String name, Uri uri, Uri uri2)> builderTemplate =
         isExport
             ? templateDuplicatedExportInType
             : templateDuplicatedImportInType;
-    message = builderTemplate.withArguments(
+    Message message = builderTemplate.withArguments(
         name,
         // TODO(ahe): We should probably use a context object here
         // instead of including URIs in this message.
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 2ec9981..5a98676 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1677,11 +1677,6 @@
   template: "'loadLibrary' takes no arguments."
   analyzerCode: LOAD_LIBRARY_TAKES_NO_ARGUMENTS
 
-LoadLibraryHidesMember:
-  template: "The library '#uri' defines a top-level member named 'loadLibrary'. This member is hidden by the special member 'loadLibrary' that the language adds to support deferred loading."
-  tip: "Try to rename or hide the member."
-  severity: IGNORED
-
 TypeArgumentMismatch:
   template: "Expected #count type arguments."
   analyzerCode: WRONG_NUMBER_OF_TYPE_ARGUMENTS
@@ -1925,26 +1920,10 @@
 IncrementalCompilerIllegalTypeParameter:
   template: "Illegal type parameter name '#string' found during expression compilation."
 
-LocalDefinitionHidesExport:
-  template: "Local definition of '#name' hides export from '#uri'."
-  severity: IGNORED
-
-LocalDefinitionHidesImport:
-  template: "Local definition of '#name' hides import from '#uri'."
-  severity: IGNORED
-
 DebugTrace:
   template: "Fatal '#name' at:\n#string"
   severity: IGNORED
 
-ExportHidesExport:
-  template: "Export of '#name' (from '#uri') hides export from '#uri2'."
-  severity: IGNORED
-
-ImportHidesImport:
-  template: "Import of '#name' (from '#uri') hides import from '#uri2'."
-  severity: IGNORED
-
 MissingPrefixInDeferredImport:
   index: 30
   template: "Deferred imports should have a prefix."
@@ -1991,10 +1970,6 @@
 DuplicatedExportInType:
   template: "'#name' is exported from both '#uri' and '#uri2'."
 
-DuplicatedImport:
-  template: "'#name' is imported from both '#uri' and '#uri2'."
-  severity: IGNORED
-
 DuplicatedImportInType:
   template: "'#name' is imported from both '#uri' and '#uri2'."
   analyzerCode: AMBIGUOUS_IMPORT
@@ -3777,10 +3752,6 @@
   frontendInternal: true
   external: test/incremental_load_from_invalid_dill_test.dart
 
-MissingExplicitTypeArguments:
-  template: "No type arguments provided, #count possible."
-  severity: IGNORED
-
 WebLiteralCannotBeRepresentedExactly:
   template: "The integer literal #string can't be represented exactly in JavaScript."
   tip: "Try changing the literal to something that can be represented in Javascript. In Javascript #string2 is the nearest value that can be represented exactly."
@@ -4271,13 +4242,6 @@
     #names
   external: test/ffi_test.dart
 
-FfiNonConstantTypeArgumentWarning:
-  # Used by dart:ffi
-  template: "Support for using non-constant type arguments '#type' in this FFI API is deprecated and will be removed in the next stable version of Dart. Rewrite the code to ensure that type arguments are compile time constants referring to a valid native type."
-  analyzerCode: NON_CONSTANT_TYPE_ARGUMENT_WARNING
-  severity: INFO
-  external: test/ffi_test.dart
-
 FfiNotStatic:
   # Used by dart:ffi
   template: "#name expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code."
diff --git a/pkg/front_end/test/crashing_test_case_minimizer_impl.dart b/pkg/front_end/test/crashing_test_case_minimizer_impl.dart
index be6565f..1d3264e 100644
--- a/pkg/front_end/test/crashing_test_case_minimizer_impl.dart
+++ b/pkg/front_end/test/crashing_test_case_minimizer_impl.dart
@@ -2159,6 +2159,9 @@
   }
 
   @override
+  Future<bool> existsAsyncIfPossible() => exists();
+
+  @override
   Future<List<int>> readAsBytes() {
     _ensureCachedIfOk();
     Uint8List data = fs.data[uri];
@@ -2167,6 +2170,9 @@
   }
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() => readAsBytes();
+
+  @override
   Future<String> readAsString() {
     _ensureCachedIfOk();
     Uint8List data = fs.data[uri];
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 6743621..9a03fcc 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -1611,6 +1611,9 @@
   }
 
   @override
+  Future<bool> existsAsyncIfPossible() => exists();
+
+  @override
   Future<List<int>> readAsBytes() async {
     await _ensureCachedIfOk();
     Uint8List data = fs.data[uri];
@@ -1619,6 +1622,9 @@
   }
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() => readAsBytes();
+
+  @override
   Future<String> readAsString() async {
     await _ensureCachedIfOk();
     Uint8List data = fs.data[uri];
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index d977b3a..3858ee0 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -388,6 +388,7 @@
 estimate
 eval
 exhausted
+existence
 existentially
 exp
 expando
@@ -845,6 +846,7 @@
 perf
 permanently
 permit
+physically
 pi
 picking
 pkg
@@ -1033,6 +1035,7 @@
 semver
 separators
 sequencing
+sequential
 serializables
 serializer
 serializers
@@ -1340,6 +1343,7 @@
 vtab
 w
 waiting
+wanting
 waste
 wasted
 watch
diff --git a/pkg/front_end/tool/incremental_perf.dart b/pkg/front_end/tool/incremental_perf.dart
index 50c922c..cb00f51 100644
--- a/pkg/front_end/tool/incremental_perf.dart
+++ b/pkg/front_end/tool/incremental_perf.dart
@@ -249,9 +249,17 @@
   Future<bool> exists() async => (await delegate).exists();
 
   @override
+  Future<bool> existsAsyncIfPossible() async =>
+      (await delegate).existsAsyncIfPossible();
+
+  @override
   Future<List<int>> readAsBytes() async => (await delegate).readAsBytes();
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() async =>
+      (await delegate).readAsBytesAsyncIfPossible();
+
+  @override
   Future<String> readAsString() async => (await delegate).readAsString();
 
   void writeAsStringSync(String contents) =>
diff --git a/pkg/vm/lib/http_filesystem.dart b/pkg/vm/lib/http_filesystem.dart
index bae57bf..6d249e3 100644
--- a/pkg/vm/lib/http_filesystem.dart
+++ b/pkg/vm/lib/http_filesystem.dart
@@ -34,6 +34,9 @@
   }
 
   @override
+  Future<bool> existsAsyncIfPossible() => exists();
+
+  @override
   Future<List<int>> readAsBytes() async {
     return connectAndRun((io.HttpClient httpClient) async {
       io.HttpClientRequest request = await httpClient.getUrl(uri);
@@ -47,6 +50,9 @@
   }
 
   @override
+  Future<List<int>> readAsBytesAsyncIfPossible() => readAsBytes();
+
+  @override
   Future<String> readAsString() async {
     return String.fromCharCodes(await readAsBytes());
   }
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index c03f4b4..154a575 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -13,7 +13,6 @@
         templateFfiExpectedExceptionalReturn,
         templateFfiExpectedNoExceptionalReturn,
         templateFfiExtendsOrImplementsSealedClass,
-        templateFfiNonConstantTypeArgumentWarning,
         templateFfiNotStatic,
         templateFfiTypeInvalid,
         templateFfiTypeMismatch;
@@ -189,7 +188,7 @@
         // TODO(http://dartbug.com/38721): Change this to an error after
         // package:ffi is no longer using sizeOf generically.
         if (!isFfiLibrary) {
-          _warningNativeTypeValid(nativeType, node);
+          _ensureNativeTypeValid(nativeType, node);
         }
 
         if (nativeType is InterfaceType) {
@@ -467,13 +466,7 @@
             node.receiver.getStaticType(_staticTypeContext);
         final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
 
-        _warningNativeTypeValid(nativeType, node);
-
-        // TODO(http://dartbug.com/38721): Change this to an error.
-        if (nativeType is TypeParameterType) {
-          // Do not rewire generic invocations.
-          return node;
-        }
+        _ensureNativeTypeValid(nativeType, node);
 
         Expression inlineSizeOf = _inlineSizeOf(nativeType);
         if (inlineSizeOf != null) {
@@ -541,22 +534,6 @@
     }
   }
 
-  void _warningNativeTypeValid(DartType nativeType, Expression node,
-      {bool allowHandle: false, bool allowStructItself = true}) {
-    if (!_nativeTypeValid(nativeType,
-        allowStructs: true,
-        allowStructItself: allowStructItself,
-        allowHandle: allowHandle)) {
-      diagnosticReporter.report(
-          templateFfiNonConstantTypeArgumentWarning.withArguments(
-              nativeType, currentLibrary.isNonNullableByDefault),
-          node.fileOffset,
-          1,
-          node.location.file);
-      throw _FfiStaticTypeError();
-    }
-  }
-
   void _ensureNoEmptyStructs(DartType nativeType, Expression node) {
     // Error on structs with no fields.
     if (nativeType is InterfaceType) {
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 0724681..7b1ad66 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -11,7 +11,6 @@
 #include "vm/bootstrap_natives.h"
 #include "vm/class_finalizer.h"
 #include "vm/class_id.h"
-#include "vm/compiler/ffi/native_type.h"
 #include "vm/exceptions.h"
 #include "vm/flags.h"
 #include "vm/log.h"
@@ -30,45 +29,6 @@
 
 namespace dart {
 
-// The following functions are runtime checks on type arguments.
-// Some checks are also performed in kernel transformation, these are asserts.
-// Some checks are only performed at runtime to allow for generic code, these
-// throw ArgumentExceptions.
-
-static void CheckSized(const AbstractType& type_arg) {
-  const classid_t type_cid = type_arg.type_class_id();
-  if (IsFfiNativeTypeTypeClassId(type_cid) || IsFfiTypeVoidClassId(type_cid) ||
-      IsFfiTypeNativeFunctionClassId(type_cid)) {
-    const String& error = String::Handle(String::NewFormatted(
-        "%s does not have a predefined size (@unsized). "
-        "Unsized NativeTypes do not support [sizeOf] because their size "
-        "is unknown. "
-        "Consequently, [allocate], [Pointer.load], [Pointer.store], and "
-        "[Pointer.elementAt] are not available.",
-        String::Handle(type_arg.UserVisibleName()).ToCString()));
-    Exceptions::ThrowArgumentError(error);
-  }
-}
-
-// Calculate the size of a native type.
-//
-// You must check [IsConcreteNativeType] and [CheckSized] first to verify that
-// this type has a defined size.
-static size_t SizeOf(Zone* zone, const AbstractType& type) {
-  if (IsFfiTypeClassId(type.type_class_id())) {
-    return compiler::ffi::NativeType::FromAbstractType(zone, type)
-        .SizeInBytes();
-  } else {
-    Class& struct_class = Class::Handle(type.type_class());
-    Object& result = Object::Handle(
-        struct_class.InvokeGetter(Symbols::SizeOfStructField(),
-                                  /*throw_nsm_if_absent=*/false,
-                                  /*respect_reflectable=*/false));
-    ASSERT(!result.IsNull() && result.IsInteger());
-    return Integer::Cast(result).AsInt64Value();
-  }
-}
-
 // The remainder of this file implements the dart:ffi native methods.
 
 DEFINE_NATIVE_ENTRY(Ffi_fromAddress, 1, 1) {
@@ -101,13 +61,6 @@
   UNREACHABLE();
 }
 
-DEFINE_NATIVE_ENTRY(Ffi_sizeOf, 1, 0) {
-  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
-  CheckSized(type_arg);
-
-  return Integer::New(SizeOf(zone, type_arg));
-}
-
 // Static invocations to this method are translated directly in streaming FGB.
 DEFINE_NATIVE_ENTRY(Ffi_asFunctionInternal, 2, 1) {
   UNREACHABLE();
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 000452a..db34630 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -405,7 +405,6 @@
   V(Ffi_storePointer, 3)                                                       \
   V(Ffi_address, 1)                                                            \
   V(Ffi_fromAddress, 1)                                                        \
-  V(Ffi_sizeOf, 0)                                                             \
   V(Ffi_asFunctionInternal, 1)                                                 \
   V(Ffi_nativeCallbackFunction, 2)                                             \
   V(Ffi_pointerFromFunction, 1)                                                \
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index 1496c09..edfa863 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -107,6 +107,8 @@
   "ffi/native_calling_convention.h",
   "ffi/native_location.cc",
   "ffi/native_location.h",
+  "ffi/native_type.cc",
+  "ffi/native_type.h",
   "ffi/recognized_method.cc",
   "ffi/recognized_method.h",
   "frontend/base_flow_graph_builder.cc",
@@ -189,8 +191,6 @@
   "api/print_filter.cc",
   "api/print_filter.h",
   "api/type_check_mode.h",
-  "ffi/native_type.cc",
-  "ffi/native_type.h",
   "jit/compiler.cc",
   "jit/compiler.h",
   "runtime_api.cc",
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 734e76e..f730542 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -222,7 +222,7 @@
       heap_(isolate_group()->heap()),
       old_space_(heap_->old_space()),
       writable_(writable) {
-  isolate()->safepoint_handler()->SafepointThreads(thread);
+  isolate_group()->safepoint_handler()->SafepointThreads(thread);
 
   {
     // It's not safe to iterate over old space when concurrent marking or
@@ -273,7 +273,7 @@
     ml.NotifyAll();
   }
 
-  isolate()->safepoint_handler()->ResumeThreads(thread());
+  isolate_group()->safepoint_handler()->ResumeThreads(thread());
 }
 
 void HeapIterationScope::IterateObjects(ObjectVisitor* visitor) const {
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index d5603cc..97dab6c 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2866,19 +2866,19 @@
                  /*at_safepoint=*/true);
 }
 
-ClassPtr Isolate::GetClassForHeapWalkAt(intptr_t cid) {
+ClassPtr IsolateGroup::GetClassForHeapWalkAt(intptr_t cid) {
   ClassPtr raw_class = nullptr;
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
-  if (group()->IsReloading()) {
-    raw_class = group()->program_reload_context()->GetClassForHeapWalkAt(cid);
+  if (IsReloading()) {
+    raw_class = program_reload_context()->GetClassForHeapWalkAt(cid);
   } else {
-    raw_class = group()->class_table()->At(cid);
+    raw_class = class_table()->At(cid);
   }
 #else
-  raw_class = group()->class_table()->At(cid);
+  raw_class = class_table()->At(cid);
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   ASSERT(raw_class != nullptr);
-  ASSERT(group()->remapping_cids() || raw_class->untag()->id_ == cid);
+  ASSERT(remapping_cids() || raw_class->untag()->id_ == cid);
   return raw_class;
 }
 
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 65c9a17..aa8575f 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -713,6 +713,9 @@
   bool CanReload() { return false; }
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
+  // Prefers old classes when we are in the middle of a reload.
+  ClassPtr GetClassForHeapWalkAt(intptr_t cid);
+
   bool IsReloading() const {
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
     return group_reload_context_ != nullptr;
@@ -1026,9 +1029,6 @@
     return isolate_object_store_.get();
   }
 
-  // Prefers old classes when we are in the middle of a reload.
-  ClassPtr GetClassForHeapWalkAt(intptr_t cid);
-
   static intptr_t ic_miss_code_offset() {
     return OFFSET_OF(Isolate, ic_miss_code_);
   }
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index c117abf..dcc42cc 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -59,7 +59,6 @@
 
 DECLARE_FLAG(bool, trace_deoptimization);
 
-#define I (isolate())
 #define IG (isolate_group())
 #define Z zone_
 
@@ -485,26 +484,22 @@
 }
 
 void IsolateGroupReloadContext::ReportError(const Error& error) {
-  // TODO(dartbug.com/36097): We need to change the "reloadSources" service-api
-  // call to accept an isolate group instead of an isolate.
-  Isolate* isolate = Isolate::Current();
-  if (Isolate::IsSystemIsolate(isolate)) {
+  IsolateGroup* isolate_group = IsolateGroup::Current();
+  if (IsolateGroup::IsSystemIsolateGroup(isolate_group)) {
     return;
   }
   TIR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString());
-  ServiceEvent service_event(isolate, ServiceEvent::kIsolateReload);
+  ServiceEvent service_event(isolate_group, ServiceEvent::kIsolateReload);
   service_event.set_reload_error(&error);
   Service::HandleEvent(&service_event);
 }
 
 void IsolateGroupReloadContext::ReportSuccess() {
-  // TODO(dartbug.com/36097): We need to change the "reloadSources" service-api
-  // call to accept an isolate group instead of an isolate.
-  Isolate* isolate = Isolate::Current();
-  if (Isolate::IsSystemIsolate(isolate)) {
+  IsolateGroup* isolate_group = IsolateGroup::Current();
+  if (IsolateGroup::IsSystemIsolateGroup(isolate_group)) {
     return;
   }
-  ServiceEvent service_event(isolate, ServiceEvent::kIsolateReload);
+  ServiceEvent service_event(isolate_group, ServiceEvent::kIsolateReload);
   Service::HandleEvent(&service_event);
 }
 
@@ -616,9 +611,11 @@
       kernel_program = kernel::Program::ReadFromTypedData(typed_data);
     }
 
+    NoActiveIsolateScope no_active_isolate_scope;
+
     ExternalTypedData& external_typed_data =
         ExternalTypedData::Handle(Z, kernel_program.get()->typed_data()->ptr());
-    IsolateGroupSource* source = Isolate::Current()->source();
+    IsolateGroupSource* source = IsolateGroup::Current()->source();
     source->add_loaded_blob(Z, external_typed_data);
 
     modified_libs_ = new (Z) BitVector(Z, num_old_libs_);
@@ -2124,10 +2121,13 @@
       if (field.needs_load_guard()) {
         continue;  // Already guarding.
       }
-      value_ = field.StaticValue();
-      if (value_.ptr() != Object::sentinel().ptr()) {
-        CheckValueType(null_safety, value_, field);
-      }
+      const intptr_t field_id = field.field_id();
+      thread->isolate_group()->ForEachIsolate([&](Isolate* isolate) {
+        value_ = isolate->field_table()->At(field_id);
+        if (value_.ptr() != Object::sentinel().ptr()) {
+          CheckValueType(null_safety, value_, field);
+        }
+      });
     }
   }
 
diff --git a/runtime/vm/lockers.cc b/runtime/vm/lockers.cc
index cb04006..30e6ef8 100644
--- a/runtime/vm/lockers.cc
+++ b/runtime/vm/lockers.cc
@@ -86,4 +86,120 @@
   }
 }
 
+#if defined(DEBUG)
+bool SafepointRwLock::IsCurrentThreadReader() {
+  ThreadId id = OSThread::GetCurrentThreadId();
+  if (IsCurrentThreadWriter()) {
+    return true;
+  }
+  MonitorLocker ml(&monitor_);
+  for (intptr_t i = readers_ids_.length() - 1; i >= 0; i--) {
+    if (readers_ids_.At(i) == id) {
+      return true;
+    }
+  }
+  return false;
+}
+#endif  // defined(DEBUG)
+
+bool SafepointRwLock::EnterRead() {
+  // No need to safepoint if the current thread is not attached.
+  auto thread = Thread::Current();
+  const bool can_block_without_safepoint = thread == nullptr;
+
+  bool acquired_read_lock = false;
+  if (!TryEnterRead(can_block_without_safepoint, &acquired_read_lock)) {
+    // Important: must never hold monitor_ when blocking for safepoint.
+    TransitionVMToBlocked transition(thread);
+    const bool ok = TryEnterRead(/*can_block=*/true, &acquired_read_lock);
+    RELEASE_ASSERT(ok);
+    RELEASE_ASSERT(acquired_read_lock);
+  }
+  return acquired_read_lock;
+}
+
+bool SafepointRwLock::TryEnterRead(bool can_block, bool* acquired_read_lock) {
+  MonitorLocker ml(&monitor_);
+  if (IsCurrentThreadWriter()) {
+    *acquired_read_lock = false;
+    return true;
+  }
+  if (can_block) {
+    while (state_ < 0) {
+      ml.Wait();
+    }
+  }
+  if (state_ >= 0) {
+    ++state_;
+    DEBUG_ONLY(readers_ids_.Add(OSThread::GetCurrentThreadId()));
+    *acquired_read_lock = true;
+    return true;
+  }
+  return false;
+}
+
+void SafepointRwLock::LeaveRead() {
+  MonitorLocker ml(&monitor_);
+  ASSERT(state_ > 0);
+#if defined(DEBUG)
+  {
+    intptr_t i = readers_ids_.length() - 1;
+    ThreadId id = OSThread::GetCurrentThreadId();
+    while (i >= 0) {
+      if (readers_ids_.At(i) == id) {
+        readers_ids_.RemoveAt(i);
+        break;
+      }
+      i--;
+    }
+    ASSERT(i >= 0);
+  }
+#endif
+  if (--state_ == 0) {
+    ml.NotifyAll();
+  }
+}
+
+void SafepointRwLock::EnterWrite() {
+  // No need to safepoint if the current thread is not attached.
+  auto thread = Thread::Current();
+  const bool can_block_without_safepoint = thread == nullptr;
+
+  if (!TryEnterWrite(can_block_without_safepoint)) {
+    // Important: must never hold monitor_ when blocking for safepoint.
+    TransitionVMToBlocked transition(thread);
+    const bool ok = TryEnterWrite(/*can_block=*/true);
+    RELEASE_ASSERT(ok);
+  }
+}
+
+bool SafepointRwLock::TryEnterWrite(bool can_block) {
+  MonitorLocker ml(&monitor_);
+  if (IsCurrentThreadWriter()) {
+    state_--;
+    return true;
+  }
+  if (can_block) {
+    while (state_ != 0) {
+      ml.Wait();
+    }
+  }
+  if (state_ == 0) {
+    writer_id_ = OSThread::GetCurrentThreadId();
+    state_ = -1;
+    return true;
+  }
+  return false;
+}
+
+void SafepointRwLock::LeaveWrite() {
+  MonitorLocker ml(&monitor_);
+  ASSERT(state_ < 0);
+  if (++state_ < 0) {
+    return;
+  }
+  writer_id_ = OSThread::kInvalidThreadId;
+  ml.NotifyAll();
+}
+
 }  // namespace dart
diff --git a/runtime/vm/lockers.h b/runtime/vm/lockers.h
index d5b2576..7213808 100644
--- a/runtime/vm/lockers.h
+++ b/runtime/vm/lockers.h
@@ -322,21 +322,7 @@
   SafepointRwLock() {}
   ~SafepointRwLock() {}
 
-#if defined(DEBUG)
-  bool IsCurrentThreadReader() {
-    ThreadId id = OSThread::GetCurrentThreadId();
-    if (IsCurrentThreadWriter()) {
-      return true;
-    }
-    MutexLocker ml(&reader_ids_mutex_);
-    for (intptr_t i = readers_ids_.length() - 1; i >= 0; i--) {
-      if (readers_ids_.At(i) == id) {
-        return true;
-      }
-    }
-    return false;
-  }
-#endif  // defined(DEBUG)
+  DEBUG_ONLY(bool IsCurrentThreadReader());
 
   bool IsCurrentThreadWriter() {
     return writer_id_ == OSThread::GetCurrentThreadId();
@@ -346,82 +332,33 @@
   friend class SafepointReadRwLocker;
   friend class SafepointWriteRwLocker;
 
-  // returns [true] if read lock was acuired,
+  // returns [true] if read lock was acquired,
   // returns [false] if the thread didn't have to acquire read lock due
   // to the thread already holding write lock
-  bool EnterRead() {
-    SafepointMonitorLocker ml(&monitor_);
-    if (IsCurrentThreadWriter()) {
-      return false;
-    }
-    while (state_ < 0) {
-      ml.Wait();
-    }
-#if defined(DEBUG)
-    {
-      MutexLocker ml(&reader_ids_mutex_);
-      readers_ids_.Add(OSThread::GetCurrentThreadId());
-    }
-#endif
-    ++state_;
-    return true;
-  }
-  void LeaveRead() {
-    SafepointMonitorLocker ml(&monitor_);
-    ASSERT(state_ > 0);
-#if defined(DEBUG)
-    {
-      MutexLocker ml(&reader_ids_mutex_);
-      intptr_t i = readers_ids_.length() - 1;
-      ThreadId id = OSThread::GetCurrentThreadId();
-      while (i >= 0) {
-        if (readers_ids_.At(i) == id) {
-          readers_ids_.RemoveAt(i);
-          break;
-        }
-        i--;
-      }
-      ASSERT(i >= 0);
-    }
-#endif
-    if (--state_ == 0) {
-      ml.NotifyAll();
-    }
-  }
+  bool EnterRead();
+  bool TryEnterRead(bool can_block, bool* acquired_read_lock);
+  void LeaveRead();
 
-  void EnterWrite() {
-    SafepointMonitorLocker ml(&monitor_);
-    if (IsCurrentThreadWriter()) {
-      state_--;
-      return;
-    }
-    while (state_ != 0) {
-      ml.Wait();
-    }
-    writer_id_ = OSThread::GetCurrentThreadId();
-    state_ = -1;
-  }
-  void LeaveWrite() {
-    SafepointMonitorLocker ml(&monitor_);
-    ASSERT(state_ < 0);
-    state_++;
-    if (state_ < 0) {
-      return;
-    }
-    writer_id_ = OSThread::kInvalidThreadId;
-    ml.NotifyAll();
-  }
+  void EnterWrite();
+  bool TryEnterWrite(bool can_block);
+  void LeaveWrite();
 
+  // We maintain an invariant that this monitor is never locked for long periods
+  // of time: Any thread that acquired this monitor must always be able to do
+  // it's work and release it (or wait on the monitor which will also release
+  // it).
+  //
+  // In particular we must ensure the monitor is never held and then a potential
+  // safepoint operation is triggered, since another thread could try to acquire
+  // the lock and it would deadlock.
   Monitor monitor_;
+
   // [state_] > 0  : The lock is held by multiple readers.
   // [state_] == 0 : The lock is free (no readers/writers).
   // [state_] < 0  : The lock is held by a single writer (possibly nested).
   intptr_t state_ = 0;
 
-#if defined(DEBUG)
-  Mutex reader_ids_mutex_;
-  MallocGrowableArray<ThreadId> readers_ids_;
-#endif
+  DEBUG_ONLY(MallocGrowableArray<ThreadId> readers_ids_);
   ThreadId writer_id_ = OSThread::kInvalidThreadId;
 };
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ef11697..1186974 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3254,7 +3254,6 @@
 ClassPtr Class::SuperClass(bool original_classes) const {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  auto isolate = thread->isolate();
   auto isolate_group = thread->isolate_group();
   if (super_type() == AbstractType::null()) {
     if (id() == kTypeArgumentsCid) {
@@ -3266,7 +3265,7 @@
   const AbstractType& sup_type = AbstractType::Handle(zone, super_type());
   const intptr_t type_class_id = sup_type.type_class_id();
   if (original_classes) {
-    return isolate->GetClassForHeapWalkAt(type_class_id);
+    return isolate_group->GetClassForHeapWalkAt(type_class_id);
   } else {
     return isolate_group->class_table()->At(type_class_id);
   }
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index aae4940..8fc322a 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -876,7 +876,7 @@
       : ObjectVisitor(),
         ObjectPointerVisitor(IsolateGroup::Current()),
         HandleVisitor(Thread::Current()),
-        isolate_(thread()->isolate()),
+        isolate_group_(thread()->isolate_group()),
         writer_(writer) {}
 
   virtual bool trace_values_through_fields() const { return true; }
@@ -989,9 +989,9 @@
     }
 
     DoCount();
-    obj->untag()->VisitPointersPrecise(isolate_, this);
+    obj->untag()->VisitPointersPrecise(isolate_group_, this);
     DoWrite();
-    obj->untag()->VisitPointersPrecise(isolate_, this);
+    obj->untag()->VisitPointersPrecise(isolate_group_, this);
   }
 
   void ScrubAndWriteUtf8(StringPtr str) {
@@ -1069,10 +1069,7 @@
   }
 
  private:
-  // TODO(dartbug.com/36097): Once the shared class table contains more
-  // information than just the size (i.e. includes an immutable class
-  // descriptor), we can remove this dependency on the current isolate.
-  Isolate* isolate_;
+  IsolateGroup* isolate_group_;
   HeapSnapshotWriter* const writer_;
   bool writing_ = false;
   intptr_t counted_ = 0;
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index 675836c1..edd66f5 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -377,6 +377,7 @@
 
   friend class MonitorLocker;
   friend class SafepointMonitorLocker;
+  friend class SafepointRwLock;
   friend void Dart_TestMonitor();
   DISALLOW_COPY_AND_ASSIGN(Monitor);
 };
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 6bd76cd..cfe671e 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -377,7 +377,7 @@
 #endif
 }
 
-void UntaggedObject::VisitPointersPrecise(Isolate* isolate,
+void UntaggedObject::VisitPointersPrecise(IsolateGroup* isolate_group,
                                           ObjectPointerVisitor* visitor) {
   intptr_t class_id = GetClassId();
   if (class_id < kNumPredefinedCids) {
@@ -386,7 +386,7 @@
   }
 
   // N.B.: Not using the heap size!
-  uword next_field_offset = isolate->GetClassForHeapWalkAt(class_id)
+  uword next_field_offset = isolate_group->GetClassForHeapWalkAt(class_id)
                                 ->untag()
                                 ->host_next_field_offset_in_words_
                             << kWordSizeLog2;
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 6b6cf9a..1ac32d0 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -498,7 +498,8 @@
 
   // This variant ensures that we do not visit the extra slot created from
   // rounding up instance sizes up to the allocation unit.
-  void VisitPointersPrecise(Isolate* isolate, ObjectPointerVisitor* visitor);
+  void VisitPointersPrecise(IsolateGroup* isolate_group,
+                            ObjectPointerVisitor* visitor);
 
   static ObjectPtr FromAddr(uword addr) {
     // We expect the untagged address here.
@@ -900,7 +901,7 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
   friend class Instance;
-  friend class Isolate;
+  friend class IsolateGroup;
   friend class Object;
   friend class UntaggedInstance;
   friend class UntaggedInstructions;
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 7d41f1a..b026035 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -3757,7 +3757,7 @@
 
   // Notify clients that the set of subscribed streams has been updated.
   if (Service::timeline_stream.enabled()) {
-    ServiceEvent event(NULL, ServiceEvent::kTimelineStreamSubscriptionsUpdate);
+    ServiceEvent event(ServiceEvent::kTimelineStreamSubscriptionsUpdate);
     Service::HandleEvent(&event);
   }
 
@@ -4885,7 +4885,7 @@
       Profiler::UpdateRunningState();
     }
     if (Service::vm_stream.enabled()) {
-      ServiceEvent event(NULL, ServiceEvent::kVMFlagUpdate);
+      ServiceEvent event(ServiceEvent::kVMFlagUpdate);
       event.set_flag_name(flag_name);
       event.set_flag_new_value(flag_value);
       Service::HandleEvent(&event);
@@ -4951,7 +4951,7 @@
   free(vm_name);
   vm_name = Utils::StrDup(name_param);
   if (Service::vm_stream.enabled()) {
-    ServiceEvent event(NULL, ServiceEvent::kVMUpdate);
+    ServiceEvent event(ServiceEvent::kVMUpdate);
     Service::HandleEvent(&event);
   }
   PrintSuccess(js);
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 7f86141..aed7093 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -13,8 +13,20 @@
 
 #ifndef PRODUCT
 
+ServiceEvent::ServiceEvent(EventKind event_kind)
+    : ServiceEvent(nullptr, nullptr, event_kind) {}
+
+ServiceEvent::ServiceEvent(IsolateGroup* isolate_group, EventKind event_kind)
+    : ServiceEvent(isolate_group, nullptr, event_kind) {}
+
 ServiceEvent::ServiceEvent(Isolate* isolate, EventKind event_kind)
+    : ServiceEvent(isolate->group(), isolate, event_kind) {}
+
+ServiceEvent::ServiceEvent(IsolateGroup* isolate_group,
+                           Isolate* isolate,
+                           EventKind event_kind)
     : isolate_(isolate),
+      isolate_group_(isolate_group),
       kind_(event_kind),
       flag_name_(NULL),
       flag_new_value_(NULL),
diff --git a/runtime/vm/service_event.h b/runtime/vm/service_event.h
index 735ab0f..08979ac 100644
--- a/runtime/vm/service_event.h
+++ b/runtime/vm/service_event.h
@@ -78,10 +78,12 @@
     const String* event_data;
   };
 
+  explicit ServiceEvent(EventKind event_kind);
+  ServiceEvent(IsolateGroup* isolate_group, EventKind event_kind);
   ServiceEvent(Isolate* isolate, EventKind event_kind);
 
   Isolate* isolate() const { return isolate_; }
-  IsolateGroup* isolate_group() const { return isolate_->group(); }
+  IsolateGroup* isolate_group() const { return isolate_group_; }
 
   // Used by the C embedding api.
   Dart_Port isolate_id() const { return isolate_->main_port(); }
@@ -204,7 +206,12 @@
   void PrintJSONHeader(JSONObject* jsobj) const;
 
  private:
+  ServiceEvent(IsolateGroup* isolate_group,
+               Isolate* isolate,
+               EventKind event_kind);
+
   Isolate* isolate_;
+  IsolateGroup* isolate_group_;
   EventKind kind_;
   const char* flag_name_;
   const char* flag_new_value_;
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 5253189..609f66e 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -1524,7 +1524,7 @@
   in_use_ = false;
 #ifndef PRODUCT
   if (Service::timeline_stream.enabled()) {
-    ServiceEvent service_event(NULL, ServiceEvent::kTimelineEvents);
+    ServiceEvent service_event(ServiceEvent::kTimelineEvents);
     service_event.set_timeline_event_block(this);
     Service::HandleEvent(&service_event);
   }
diff --git a/sdk/lib/_internal/vm/lib/ffi_allocation_patch.dart b/sdk/lib/_internal/vm/lib/ffi_allocation_patch.dart
index daa428e..0edd45c 100644
--- a/sdk/lib/_internal/vm/lib/ffi_allocation_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_allocation_patch.dart
@@ -12,6 +12,7 @@
   // TODO(http://dartbug.com/39964): Add `alignmentOf<T>()` call.
   @patch
   Pointer<T> call<T extends NativeType>([int count = 1]) {
-    return this.allocate(sizeOf<T>() * count);
+    // This case should have been rewritten in pre-processing.
+    throw UnimplementedError("Pointer<$T>");
   }
 }
diff --git a/sdk/lib/_internal/vm/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart
index 4c69e41..7b55e4a 100644
--- a/sdk/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_patch.dart
@@ -26,19 +26,10 @@
 
 @patch
 int sizeOf<T extends NativeType>() {
-  // This is not super fast, but it is faster than a runtime entry.
-  // Hot loops with elementAt().load() do not use this sizeOf, elementAt is
-  // optimized per NativeType statically to prevent use of sizeOf at runtime.
-  final int? knownSize = _knownSizes[T];
-  if (knownSize != null) return knownSize;
-  if (T == IntPtr) return _intPtrSize;
-  if (T == Pointer) return _intPtrSize;
-  // For structs we fall back to a runtime entry.
-  return _sizeOf<T>();
+  // This case should have been rewritten in pre-processing.
+  throw UnimplementedError("$T");
 }
 
-int _sizeOf<T extends NativeType>() native "Ffi_sizeOf";
-
 @pragma("vm:recognized", "other")
 Pointer<T> _fromAddress<T extends NativeType>(int ptr) native "Ffi_fromAddress";
 
@@ -98,11 +89,13 @@
   @pragma("vm:recognized", "other")
   int get address native "Ffi_address";
 
-  // For statically known types, this is rewired.
-  // (Method sizeOf is slow, see notes above.)
+  // For statically known types, this is rewritten.
   @patch
-  Pointer<T> elementAt(int index) =>
-      Pointer.fromAddress(address + sizeOf<T>() * index);
+  Pointer<T> elementAt(int index) {
+    // This case should have been rewritten in pre-processing.
+    // Only dynamic invocations are not rewritten in pre-processing.
+    throw UnsupportedError("Pointer.elementAt cannot be called dynamically.");
+  }
 
   @patch
   Pointer<T> _offsetBy(int offsetInBytes) =>
diff --git a/sdk/lib/core/bigint.dart b/sdk/lib/core/bigint.dart
index 25c0476..e3f7090 100644
--- a/sdk/lib/core/bigint.dart
+++ b/sdk/lib/core/bigint.dart
@@ -141,7 +141,7 @@
   /// of `this` and [other]
   ///
   /// If both operands are non-negative, the result is non-negative,
-  /// otherwise the result us negative.
+  /// otherwise the result is negative.
   BigInt operator |(BigInt other);
 
   /// Bit-wise exclusive-or operator.
diff --git a/sdk/lib/core/bool.dart b/sdk/lib/core/bool.dart
index f365d79..5f4d6d1 100644
--- a/sdk/lib/core/bool.dart
+++ b/sdk/lib/core/bool.dart
@@ -36,6 +36,11 @@
   /// ```dart
   /// const isLoggingOn = (const String.fromEnvironment("logging") == "on");
   /// ```
+  ///
+  /// The string value, or lack of a value, associated with a [name]
+  /// must be consistent across all calls to [String.fromEnvironment],
+  /// [int.fromEnvironment], `bool.fromEnvironment` and [bool.hasEnvironment]
+  /// in a single program.
   // The .fromEnvironment() constructors are special in that we do not want
   // users to call them using "new". We prohibit that by giving them bodies
   // that throw, even though const constructors are not allowed to have bodies.
@@ -66,6 +71,11 @@
   ///     ? String.fromEnvironment("logging")
   ///     : null;
   /// ```
+  ///
+  /// The string value, or lack of a value, associated with a [name]
+  /// must be consistent across all calls to [String.fromEnvironment],
+  /// [int.fromEnvironment], [bool.fromEnvironment] and `bool.hasEnvironment`
+  /// in a single program.
   // The .hasEnvironment() constructor is special in that we do not want
   // users to call them using "new". We prohibit that by giving them bodies
   // that throw, even though const constructors are not allowed to have bodies.
diff --git a/sdk/lib/core/int.dart b/sdk/lib/core/int.dart
index 5d8f5d3..1578770 100644
--- a/sdk/lib/core/int.dart
+++ b/sdk/lib/core/int.dart
@@ -32,6 +32,11 @@
   /// ```
   /// const int.fromEnvironment("defaultPort", defaultValue: 80)
   /// ```
+  ///
+  /// The string value, or lack of a value, associated with a [name]
+  /// must be consistent across all calls to [String.fromEnvironment],
+  /// `int.fromEnvironment`, [bool.fromEnvironment] and [bool.hasEnvironment]
+  /// in a single program.
   // The .fromEnvironment() constructors are special in that we do not want
   // users to call them using "new". We prohibit that by giving them bodies
   // that throw, even though const constructors are not allowed to have bodies.
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index 27aba63..fbeae71 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -146,6 +146,11 @@
   ///     ? String.fromEnvironment("maybeDeclared")
   ///     : null;
   /// ```
+  ///
+  /// The string value, or lack of a value, associated with a [name]
+  /// must be consistent across all calls to `String.fromEnvironment`,
+  /// [int.fromEnvironment], [bool.fromEnvironment] and [bool.hasEnvironment]
+  /// in a single program.
   // The .fromEnvironment() constructors are special in that we do not want
   // users to call them using "new". We prohibit that by giving them bodies
   // that throw, even though const constructors are not allowed to have bodies.
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index aef06c1..6beed01 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -24,9 +24,7 @@
 ///
 /// Includes padding and alignment of structs.
 ///
-/// Support for invoking this function with non-constant [T] will be removed in
-/// the next stable version of Dart and it will become mandatory to invoke it
-/// with a compile-time constant [T].
+/// This function must be invoked with a compile-time constant [T].
 external int sizeOf<T extends NativeType>();
 
 /// Represents a pointer into the native C memory corresponding to "NULL", e.g.
@@ -65,9 +63,10 @@
 
   /// Pointer arithmetic (takes element size into account).
   ///
-  /// Support for invoking this method with non-constant [T] will be removed in
-  /// the next stable version of Dart and it will become mandatory to invoke it
-  /// with a compile-time constant [T].
+  /// This method must be invoked with a compile-time constant [T].
+  ///
+  /// Does not accept dynamic invocations -- where the type of the receiver is
+  /// [dynamic].
   external Pointer<T> elementAt(int index);
 
   /// Cast Pointer<T> to a Pointer<V>.
diff --git a/tests/ffi/data_test.dart b/tests/ffi/data_test.dart
index 1a10124..4b619dd 100644
--- a/tests/ffi/data_test.dart
+++ b/tests/ffi/data_test.dart
@@ -449,7 +449,7 @@
     final int i = p.value;
   });
   Expect.throws(() => p.value = 1);
-  p.elementAt(5); // Works, but is slow.
+  Expect.throws(() => p.elementAt(5));
   final int addr = p.address;
   final Pointer<Int16> p2 = p.cast<Int16>();
   calloc.free(p);
diff --git a/tests/ffi/vmspecific_static_checks_test.dart b/tests/ffi/vmspecific_static_checks_test.dart
index 832d1ad..b88ef03 100644
--- a/tests/ffi/vmspecific_static_checks_test.dart
+++ b/tests/ffi/vmspecific_static_checks_test.dart
@@ -625,7 +625,7 @@
 void testSizeOfGeneric() {
   int generic<T extends Pointer>() {
     int size = sizeOf<IntPtr>();
-    size = sizeOf<T>(); //# 1300: ok
+    size = sizeOf<T>(); //# 1300: compile-time error
     return size;
   }
 
@@ -634,7 +634,7 @@
 
 void testSizeOfNativeType() {
   try {
-    sizeOf(); //# 1301: ok
+    sizeOf(); //# 1301: compile-time error
   } catch (e) {
     print(e);
   }
@@ -643,7 +643,7 @@
 void testElementAtGeneric() {
   Pointer<T> generic<T extends NativeType>(Pointer<T> pointer) {
     Pointer<T> returnValue = pointer;
-    returnValue = returnValue.elementAt(1); //# 1310: ok
+    returnValue = returnValue.elementAt(1); //# 1310: compile-time error
     return returnValue;
   }
 
@@ -657,6 +657,6 @@
   Pointer<Int8> p = calloc();
   p.elementAt(1);
   Pointer<NativeType> p2 = p;
-  p2.elementAt(1); //# 1311: ok
+  p2.elementAt(1); //# 1311: compile-time error
   calloc.free(p);
 }
diff --git a/tests/ffi_2/data_test.dart b/tests/ffi_2/data_test.dart
index f8ac487e..448b465 100644
--- a/tests/ffi_2/data_test.dart
+++ b/tests/ffi_2/data_test.dart
@@ -449,7 +449,7 @@
     final int i = p.value;
   });
   Expect.throws(() => p.value = 1);
-  p.elementAt(5); // Works, but is slow.
+  Expect.throws(() => p.elementAt(5));
   final int addr = p.address;
   final Pointer<Int16> p2 = p.cast<Int16>();
   calloc.free(p);
diff --git a/tests/ffi_2/vmspecific_static_checks_test.dart b/tests/ffi_2/vmspecific_static_checks_test.dart
index b6a0451..079da6f 100644
--- a/tests/ffi_2/vmspecific_static_checks_test.dart
+++ b/tests/ffi_2/vmspecific_static_checks_test.dart
@@ -623,7 +623,7 @@
 void testSizeOfGeneric() {
   int generic<T extends Pointer>() {
     int size = sizeOf<IntPtr>();
-    size = sizeOf<T>(); //# 1300: ok
+    size = sizeOf<T>(); //# 1300: compile-time error
     return size;
   }
 
@@ -632,7 +632,7 @@
 
 void testSizeOfNativeType() {
   try {
-    sizeOf(); //# 1301: ok
+    sizeOf(); //# 1301: compile-time error
   } catch (e) {
     print(e);
   }
@@ -641,7 +641,7 @@
 void testElementAtGeneric() {
   Pointer<T> generic<T extends NativeType>(Pointer<T> pointer) {
     Pointer<T> returnValue = pointer;
-    returnValue = returnValue.elementAt(1); //# 1310: ok
+    returnValue = returnValue.elementAt(1); //# 1310: compile-time error
     return returnValue;
   }
 
@@ -655,6 +655,6 @@
   Pointer<Int8> p = calloc();
   p.elementAt(1);
   Pointer<NativeType> p2 = p;
-  p2.elementAt(1); //# 1311: ok
+  p2.elementAt(1); //# 1311: compile-time error
   calloc.free(p);
 }
diff --git a/tools/VERSION b/tools/VERSION
index 4eba935..d35a7a6 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 44
+PRERELEASE 45
 PRERELEASE_PATCH 0
\ No newline at end of file