Version 2.15.0-212.0.dev

Merge commit '14428eda6940e0edab7f3810542ddcc049a569e2' into 'dev'
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index fd178e1..939c8fc 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -10,4 +10,5 @@
   build_with_chromium = false
   use_libfuzzer = false
   is_apple = is_ios || is_mac
+  use_thin_lto = false
 }
diff --git a/pkg/analysis_server/lib/src/status/element_writer.dart b/pkg/analysis_server/lib/src/status/element_writer.dart
index dffcd49..bc09cd5 100644
--- a/pkg/analysis_server/lib/src/status/element_writer.dart
+++ b/pkg/analysis_server/lib/src/status/element_writer.dart
@@ -107,7 +107,6 @@
     if (element is LibraryElement) {
       properties['definingCompilationUnit'] = element.definingCompilationUnit;
       properties['entryPoint'] = element.entryPoint;
-      properties['hasExtUri'] = element.hasExtUri;
       properties['isBrowserApplication'] = element.isBrowserApplication;
       properties['isDartAsync'] = element.isDartAsync;
       properties['isDartCore'] = element.isDartCore;
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 4663fa5..1a8d912 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,6 +1,7 @@
 ## 2.6.0-dev
 * Deprecated `AnalysisResult.state`, check for specific valid or invalid subtypes.
 * Deprecated `ResultState`.
+* Deprecated `LibraryElement.hasExtUri`, FFI should be used instead.
 
 ## 2.5.0
 * Updated `MockSdk` to include more declarations.
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 7dc7476..362575d 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -479,6 +479,8 @@
 
   R? visitImplementsClause(ImplementsClause node);
 
+  R? visitImplicitCallReference(ImplicitCallReference node);
+
   R? visitImportDirective(ImportDirective node);
 
   R? visitIndexExpression(IndexExpression node);
@@ -2599,6 +2601,33 @@
   NodeList<NamedType> get interfaces2;
 }
 
+/// An expression representing an implicit 'call' method reference.
+///
+/// Objects of this type are not produced directly by the parser (because the
+/// parser cannot tell whether an expression refers to a callable type); they
+/// are produced at resolution time.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ImplicitCallReference implements MethodReferenceExpression {
+  /// Return the expression from which a `call` method is being referenced.
+  Expression get expression;
+
+  /// Return the element associated with the implicit 'call' reference based on
+  /// the static types.
+  @override
+  MethodElement get staticElement;
+
+  /// The type arguments being applied to the tear-off, or `null` if there are
+  /// no type arguments.
+  TypeArgumentList? get typeArguments;
+
+  /// The actual type arguments being applied to the tear-off, either explicitly
+  /// specified in [typeArguments], or inferred.
+  ///
+  /// Returns an empty list if the 'call' method does not have type parameters.
+  List<DartType> get typeArgumentTypes;
+}
+
 /// An import directive.
 ///
 ///    importDirective ::=
diff --git a/pkg/analyzer/lib/dart/ast/ast_factory.dart b/pkg/analyzer/lib/dart/ast/ast_factory.dart
index 64d8fb4..baa41a5 100644
--- a/pkg/analyzer/lib/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/dart/ast/ast_factory.dart
@@ -5,6 +5,8 @@
 import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 /// A collection of factory methods which may be used to create concrete
@@ -580,6 +582,17 @@
   ImplementsClause implementsClause(
       Token implementsKeyword, List<NamedType> interfaces);
 
+  /// Returns a newly created implicit call reference.
+  ///
+  /// The [typeArguments] can be `null` if there are no type arguments being
+  /// applied to the reference.
+  ImplicitCallReference implicitCallReference({
+    required Expression expression,
+    required MethodElement staticElement,
+    required TypeArgumentList? typeArguments,
+    required List<DartType> typeArgumentTypes,
+  });
+
   /// Returns a newly created import directive. Either or both of the
   /// [comment] and [metadata] can be `null` if the function does not have the
   /// corresponding attribute. The [deferredKeyword] can be `null` if the import
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
index 451f318..5d3dda9 100644
--- a/pkg/analyzer/lib/dart/ast/visitor.dart
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -383,6 +383,9 @@
   R? visitImplementsClause(ImplementsClause node) => visitNode(node);
 
   @override
+  R? visitImplicitCallReference(ImplicitCallReference node) => visitNode(node);
+
+  @override
   R? visitImportDirective(ImportDirective node) =>
       visitNamespaceDirective(node);
 
@@ -1035,6 +1038,12 @@
   }
 
   @override
+  R? visitImplicitCallReference(ImplicitCallReference node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
   R? visitImportDirective(ImportDirective node) {
     node.visitChildren(this);
     return null;
@@ -1624,6 +1633,9 @@
   R? visitImplementsClause(ImplementsClause node) => null;
 
   @override
+  R? visitImplicitCallReference(ImplicitCallReference node) => null;
+
+  @override
   R? visitImportDirective(ImportDirective node) => null;
 
   @override
@@ -2032,6 +2044,9 @@
   R? visitImplementsClause(ImplementsClause node) => _throw(node);
 
   @override
+  R? visitImplicitCallReference(ImplicitCallReference node) => _throw(node);
+
+  @override
   R? visitImportDirective(ImportDirective node) => _throw(node);
 
   @override
@@ -2769,6 +2784,14 @@
   }
 
   @override
+  T? visitImplicitCallReference(ImplicitCallReference node) {
+    stopwatch.start();
+    T? result = _baseVisitor.visitImplicitCallReference(node);
+    stopwatch.stop();
+    return result;
+  }
+
+  @override
   T? visitImportDirective(ImportDirective node) {
     stopwatch.start();
     T? result = _baseVisitor.visitImportDirective(node);
@@ -3498,6 +3521,9 @@
   R? visitImplementsClause(ImplementsClause node) => visitNode(node);
 
   @override
+  R? visitImplicitCallReference(ImplicitCallReference node) => visitNode(node);
+
+  @override
   R? visitImportDirective(ImportDirective node) => visitNode(node);
 
   @override
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index f34732b..43cc3b1 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1331,6 +1331,7 @@
 
   /// Return `true` if the defining compilation unit of this library contains at
   /// least one import directive whose URI uses the "dart-ext" scheme.
+  @Deprecated('Support for dart-ext is replaced with FFI')
   bool get hasExtUri;
 
   /// Return `true` if this library defines a top-level function named
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 311591d..1871a08 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -457,6 +457,7 @@
   CompileTimeErrorCode.URI_DOES_NOT_EXIST,
   CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED,
   CompileTimeErrorCode.URI_WITH_INTERPOLATION,
+  CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
   CompileTimeErrorCode.USE_OF_VOID_RESULT,
   CompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
   CompileTimeErrorCode.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
@@ -640,7 +641,6 @@
   HintCode.UNUSED_RESULT,
   HintCode.UNUSED_RESULT_WITH_MESSAGE,
   HintCode.UNUSED_SHOWN_NAME,
-  HintCode.USE_OF_NATIVE_EXTENSION,
   LanguageCode.IMPLICIT_DYNAMIC_FIELD,
   LanguageCode.IMPLICIT_DYNAMIC_FUNCTION,
   LanguageCode.IMPLICIT_DYNAMIC_INVOKE,
diff --git a/pkg/analyzer/lib/src/dart/analysis/byte_store.dart b/pkg/analyzer/lib/src/dart/analysis/byte_store.dart
index 740ddc2..7fa38f7 100644
--- a/pkg/analyzer/lib/src/dart/analysis/byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/byte_store.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:typed_data';
+
 import 'package:analyzer/src/dart/analysis/cache.dart';
 
 /// Store of bytes associated with string keys.
@@ -17,23 +19,23 @@
 abstract class ByteStore {
   /// Return the bytes associated with the given [key].
   /// Return `null` if the association does not exist.
-  List<int>? get(String key);
+  Uint8List? get(String key);
 
   /// Associate the given [bytes] with the [key].
-  void put(String key, List<int> bytes);
+  void put(String key, Uint8List bytes);
 }
 
 /// [ByteStore] which stores data only in memory.
 class MemoryByteStore implements ByteStore {
-  final Map<String, List<int>> _map = {};
+  final Map<String, Uint8List> _map = {};
 
   @override
-  List<int>? get(String key) {
+  Uint8List? get(String key) {
     return _map[key];
   }
 
   @override
-  void put(String key, List<int> bytes) {
+  void put(String key, Uint8List bytes) {
     _map[key] = bytes;
   }
 }
@@ -41,18 +43,18 @@
 /// A wrapper around [ByteStore] which adds an in-memory LRU cache to it.
 class MemoryCachingByteStore implements ByteStore {
   final ByteStore _store;
-  final Cache<String, List<int>> _cache;
+  final Cache<String, Uint8List> _cache;
 
   MemoryCachingByteStore(this._store, int maxSizeBytes)
-      : _cache = Cache<String, List<int>>(maxSizeBytes, (v) => v.length);
+      : _cache = Cache<String, Uint8List>(maxSizeBytes, (v) => v.length);
 
   @override
-  List<int>? get(String key) {
+  Uint8List? get(String key) {
     return _cache.get(key, () => _store.get(key));
   }
 
   @override
-  void put(String key, List<int> bytes) {
+  void put(String key, Uint8List bytes) {
     _store.put(key, bytes);
     _cache.put(key, bytes);
   }
@@ -61,8 +63,8 @@
 /// [ByteStore] which does not store any data.
 class NullByteStore implements ByteStore {
   @override
-  List<int>? get(String key) => null;
+  Uint8List? get(String key) => null;
 
   @override
-  void put(String key, List<int> bytes) {}
+  void put(String key, Uint8List bytes) {}
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 0d71dc5..aba8fef 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -80,7 +80,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 185;
+  static const int DATA_VERSION = 186;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
@@ -1318,7 +1318,7 @@
         late CompilationUnit resolvedUnit;
         for (FileState unitFile in results.keys) {
           UnitAnalysisResult unitResult = results[unitFile]!;
-          List<int> unitBytes =
+          var unitBytes =
               _serializeResolvedUnit(unitResult.unit, unitResult.errors);
           String unitSignature = _getResolvedUnitSignature(library, unitFile);
           String unitKey = _getResolvedUnitKey(unitSignature);
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart b/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
index d4d3e04..58f154e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
@@ -41,10 +41,10 @@
   }
 
   @override
-  List<int>? get(String key) => _fileByteStore.get(key);
+  Uint8List? get(String key) => _fileByteStore.get(key);
 
   @override
-  void put(String key, List<int> bytes) {
+  void put(String key, Uint8List bytes) {
     _fileByteStore.put(key, bytes);
     // Update the current size.
     _bytesWrittenSinceCleanup += bytes.length;
@@ -146,7 +146,7 @@
 
   final String _cachePath;
   final String _tempSuffix;
-  final Map<String, List<int>> _writeInProgress = {};
+  final Map<String, Uint8List> _writeInProgress = {};
   final FuturePool _pool = FuturePool(20);
 
   /// If the same cache path is used from more than one isolate of the same
@@ -156,7 +156,7 @@
             '-temp-$pid${tempNameSuffix.isEmpty ? '' : '-$tempNameSuffix'}';
 
   @override
-  List<int>? get(String key) {
+  Uint8List? get(String key) {
     if (!_canShard(key)) return null;
 
     var bytes = _writeInProgress[key];
@@ -176,7 +176,7 @@
   }
 
   @override
-  void put(String key, List<int> bytes) {
+  void put(String key, Uint8List bytes) {
     if (!_canShard(key)) return;
 
     _writeInProgress[key] = bytes;
@@ -225,7 +225,7 @@
 
   /// If the [rawBytes] have the valid version and checksum, extract and
   /// return the data from it. Otherwise return `null`.
-  List<int>? getData(List<int> rawBytes) {
+  Uint8List? getData(Uint8List rawBytes) {
     // There must be at least the version and the checksum in the raw bytes.
     if (rawBytes.length < 4) {
       return null;
@@ -238,7 +238,7 @@
     }
 
     // Check the checksum of the data.
-    List<int> data = rawBytes.sublist(0, len);
+    var data = rawBytes.sublist(0, len);
     int checksum = fletcher16(data);
     if (rawBytes[len + 2] != checksum & 0xFF ||
         rawBytes[len + 3] != (checksum >> 8) & 0xFF) {
@@ -251,7 +251,7 @@
 
   /// Return bytes that include the given [data] plus the current version and
   /// the checksum of the [data].
-  List<int> wrapData(List<int> data) {
+  Uint8List wrapData(Uint8List data) {
     int len = data.length;
     var bytes = Uint8List(len + 4);
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index d44f37d..239d1cb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -341,7 +341,7 @@
   }
 
   Uint8List getInformativeBytes({CompilationUnit? unit}) {
-    var bytes = _fsState._byteStore.get(_informativeKey!) as Uint8List?;
+    var bytes = _fsState._byteStore.get(_informativeKey!);
     if (bytes == null) {
       unit ??= parse();
       bytes = writeUnitInformative(unit);
@@ -404,11 +404,8 @@
       _informativeKey = '$signatureHex.ast';
     }
 
-    // Prepare bytes of the unlinked bundle - existing or new.
-    var bytes = _getUnlinkedBytes();
-
-    // Read the unlinked bundle.
-    _driverUnlinkedUnit = AnalysisDriverUnlinkedUnit.fromBytes(bytes);
+    // Prepare the unlinked unit.
+    _driverUnlinkedUnit = _getUnlinkedUnit();
     _unlinked2 = _driverUnlinkedUnit!.unit;
     _lineInfo = LineInfo(_unlinked2!.lineStarts);
 
@@ -493,11 +490,11 @@
     return _fsState.getFileForUri(absoluteUri);
   }
 
-  /// Return the bytes of the unlinked summary - existing or new.
-  Uint8List _getUnlinkedBytes() {
+  /// Return the unlinked unit, from bytes or new.
+  AnalysisDriverUnlinkedUnit _getUnlinkedUnit() {
     var bytes = _fsState._byteStore.get(_unlinkedKey!);
     if (bytes != null && bytes.isNotEmpty) {
-      return bytes as Uint8List;
+      return AnalysisDriverUnlinkedUnit.fromBytes(bytes);
     }
 
     var unit = parse();
@@ -506,17 +503,18 @@
       var definedNames = computeDefinedNames(unit);
       var referencedNames = computeReferencedNames(unit);
       var subtypedNames = computeSubtypedNames(unit);
-      var bytes = AnalysisDriverUnlinkedUnit(
+      var driverUnlinkedUnit = AnalysisDriverUnlinkedUnit(
         definedTopLevelNames: definedNames.topLevelNames,
         definedClassMemberNames: definedNames.classMemberNames,
         referencedNames: referencedNames,
         subtypedNames: subtypedNames,
         unit: unlinkedUnit,
-      ).toBytes();
+      );
+      var bytes = driverUnlinkedUnit.toBytes();
       _fsState._byteStore.put(_unlinkedKey!, bytes);
       counterUnlinkedBytes += bytes.length;
       counterUnlinkedLinkedBytes += bytes.length;
-      return bytes;
+      return driverUnlinkedUnit;
     });
   }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 04235d9..6278c6f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -532,10 +532,14 @@
             var importedLibrary = importElement.importedLibrary;
             if (importedLibrary is LibraryElementImpl) {
               if (importedLibrary.hasPartOfDirective) {
+                // It is safe to assume that `directive.uri.stringValue` is
+                // non-`null`, because the only time it is `null` is if the URI
+                // contains a string interpolation, in which case the import
+                // would never have resolved in the first place.
                 libraryErrorReporter.reportErrorForNode(
                     CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY,
                     directive.uri,
-                    [directive.uri]);
+                    [directive.uri.stringValue!]);
               }
             }
           }
@@ -547,10 +551,14 @@
             var exportedLibrary = exportElement.exportedLibrary;
             if (exportedLibrary is LibraryElementImpl) {
               if (exportedLibrary.hasPartOfDirective) {
+                // It is safe to assume that `directive.uri.stringValue` is
+                // non-`null`, because the only time it is `null` is if the URI
+                // contains a string interpolation, in which case the export
+                // would never have resolved in the first place.
                 libraryErrorReporter.reportErrorForNode(
                     CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
                     directive.uri,
-                    [directive.uri]);
+                    [directive.uri.stringValue!]);
               }
             }
           }
@@ -696,8 +704,6 @@
         return null;
       }
       return _sourceFactory.resolveUri(file.source, uriContent);
-    } else if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
-      return null;
     } else if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
       _getErrorReporter(file).reportErrorForNode(
           CompileTimeErrorCode.URI_WITH_INTERPOLATION, uriLiteral);
@@ -783,13 +789,21 @@
         return;
       }
     }
-    StringLiteral uriLiteral = directive.uri;
+
+    if (uriContent != null && uriContent.startsWith('dart-ext:')) {
+      _getErrorReporter(file).reportErrorForNode(
+        CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
+        directive.uri,
+      );
+      return;
+    }
+
     CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
     if (isGeneratedSource(source)) {
       errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
     }
     _getErrorReporter(file)
-        .reportErrorForNode(errorCode, uriLiteral, [uriContent]);
+        .reportErrorForNode(errorCode, directive.uri, [uriContent]);
   }
 
   /// Check each directive in the given [unit] to see if the referenced source
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index dbc60bd..7973df8 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -122,7 +122,7 @@
       }
 
       var resolutionKey = cycle.transitiveSignature + '.linked_bundle';
-      var resolutionBytes = byteStore.get(resolutionKey) as Uint8List?;
+      var resolutionBytes = byteStore.get(resolutionKey);
 
       if (resolutionBytes == null) {
         librariesLinkedTimer.start();
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 38a93cf..d9d000b 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -5803,6 +5803,69 @@
   }
 }
 
+class ImplicitCallReferenceImpl extends ExpressionImpl
+    implements ImplicitCallReference {
+  ExpressionImpl _expression;
+
+  TypeArgumentListImpl? _typeArguments;
+
+  @override
+  List<DartType> typeArgumentTypes;
+
+  @override
+  MethodElement staticElement;
+
+  ImplicitCallReferenceImpl(
+    this._expression, {
+    required this.staticElement,
+    required TypeArgumentListImpl? typeArguments,
+    required this.typeArgumentTypes,
+  }) : _typeArguments = typeArguments {
+    _becomeParentOf(_expression);
+    _becomeParentOf(_typeArguments);
+  }
+
+  @override
+  Token get beginToken => expression.beginToken;
+
+  @override
+  Iterable<SyntacticEntity> get childEntities => ChildEntities()
+    ..add(expression)
+    ..add(typeArguments);
+
+  @override
+  Token get endToken => typeArguments?.endToken ?? expression.endToken;
+
+  @override
+  ExpressionImpl get expression => _expression;
+
+  set expression(ExpressionImpl value) {
+    _expression = _becomeParentOf(value);
+  }
+
+  @override
+  Precedence get precedence =>
+      typeArguments == null ? expression.precedence : Precedence.postfix;
+
+  @override
+  TypeArgumentListImpl? get typeArguments => _typeArguments;
+
+  set typeArguments(TypeArgumentListImpl? value) {
+    _typeArguments = _becomeParentOf(value);
+  }
+
+  @override
+  E? accept<E>(AstVisitor<E> visitor) {
+    return visitor.visitImplicitCallReference(this);
+  }
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    expression.accept(visitor);
+    typeArguments?.accept(visitor);
+  }
+}
+
 /// An import directive.
 ///
 ///    importDirective ::=
@@ -10466,10 +10529,6 @@
 ///      | [PartDirective]
 abstract class UriBasedDirectiveImpl extends DirectiveImpl
     implements UriBasedDirective {
-  /// The prefix of a URI using the `dart-ext` scheme to reference a native code
-  /// library.
-  static const String _DART_EXT_SCHEME = "dart-ext:";
-
   /// The URI referenced by this directive.
   StringLiteralImpl _uri;
 
@@ -10518,9 +10577,6 @@
     if (uriContent.isEmpty) {
       return null;
     }
-    if (isImport && uriContent.startsWith(_DART_EXT_SCHEME)) {
-      return UriValidationCode.URI_WITH_DART_EXT_SCHEME;
-    }
     Uri uri;
     try {
       uri = Uri.parse(Uri.encodeFull(uriContent));
@@ -10541,9 +10597,6 @@
   static const UriValidationCode URI_WITH_INTERPOLATION =
       UriValidationCode('URI_WITH_INTERPOLATION');
 
-  static const UriValidationCode URI_WITH_DART_EXT_SCHEME =
-      UriValidationCode('URI_WITH_DART_EXT_SCHEME');
-
   /// The name of the validation code.
   final String name;
 
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index 0fcad99..f9e04f4 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -6,6 +6,8 @@
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/ast_factory.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
@@ -786,6 +788,18 @@
       ImplementsClauseImpl(implementsKeyword, interfaces);
 
   @override
+  ImplicitCallReferenceImpl implicitCallReference({
+    required Expression expression,
+    required MethodElement staticElement,
+    required TypeArgumentList? typeArguments,
+    required List<DartType> typeArgumentTypes,
+  }) =>
+      ImplicitCallReferenceImpl(expression as ExpressionImpl,
+          staticElement: staticElement,
+          typeArguments: typeArguments as TypeArgumentListImpl?,
+          typeArgumentTypes: typeArgumentTypes);
+
+  @override
   ImportDirectiveImpl importDirective(
           Comment? comment,
           List<Annotation>? metadata,
diff --git a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
index b912645..c32bd06 100644
--- a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
@@ -604,6 +604,12 @@
   }
 
   @override
+  void visitImplicitCallReference(ImplicitCallReference node) {
+    _visitNode(node.expression);
+    _visitNode(node.typeArguments);
+  }
+
+  @override
   void visitImportDirective(ImportDirective node) {
     _visitNodeList(node.metadata, separator: ' ', suffix: ' ');
     sink.write('import ');
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 11c386e..6e2918a 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -723,6 +723,13 @@
   }
 
   @override
+  bool visitImplicitCallReference(ImplicitCallReference node) {
+    ImplicitCallReference other = _other as ImplicitCallReference;
+    return isEqualNodes(node.expression, other.expression) &&
+        isEqualNodes(node.typeArguments, other.typeArguments);
+  }
+
+  @override
   bool visitImportDirective(ImportDirective node) {
     ImportDirective other = _other as ImportDirective;
     return isEqualNodes(
@@ -2345,6 +2352,18 @@
   }
 
   @override
+  bool visitImplicitCallReference(covariant ImplicitCallReferenceImpl node) {
+    if (identical(node.expression, _oldNode)) {
+      node.expression = _newNode as ExpressionImpl;
+      return true;
+    } else if (identical(node.typeArguments, _oldNode)) {
+      node.typeArguments = _newNode as TypeArgumentListImpl;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
   bool visitImportDirective(covariant ImportDirectiveImpl node) {
     if (identical(node.prefix, _oldNode)) {
       node.prefix = _newNode as SimpleIdentifier;
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 4a5e452..34df7af 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -171,6 +171,7 @@
         _evaluationEngine.evaluateConstructorCall(
             _currentLibrary,
             node,
+            constructor.returnType.typeArguments,
             node.argumentList.arguments,
             constructor,
             constantVisitor,
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 3c30694..54d5c5d 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -4,6 +4,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -141,6 +142,7 @@
         var result = evaluateConstructorCall(
             library,
             constNode,
+            element.returnType.typeArguments,
             constNode.arguments!.arguments,
             element,
             constantVisitor,
@@ -272,15 +274,26 @@
   DartObjectImpl? evaluateConstructorCall(
     LibraryElementImpl library,
     AstNode node,
+    List<DartType>? typeArguments,
     List<Expression> arguments,
     ConstructorElement constructor,
     ConstantVisitor constantVisitor,
     ErrorReporter errorReporter, {
     ConstructorInvocation? invocation,
   }) {
-    return _InstanceCreationEvaluator.evaluate(this, _declaredVariables,
-        errorReporter, library, node, constructor, arguments, constantVisitor,
-        isNullSafe: _isNonNullableByDefault, invocation: invocation);
+    return _InstanceCreationEvaluator.evaluate(
+      this,
+      _declaredVariables,
+      errorReporter,
+      library,
+      node,
+      constructor,
+      typeArguments,
+      arguments,
+      constantVisitor,
+      isNullSafe: _isNonNullableByDefault,
+      invocation: invocation,
+    );
   }
 
   /// Generate an error indicating that the given [constant] is not a valid
@@ -430,7 +443,12 @@
   /// The library that contains the constant expression being evaluated.
   final LibraryElementImpl _library;
 
+  /// A mapping of variable names to runtime values.
   final Map<String, DartObjectImpl>? _lexicalEnvironment;
+
+  /// A mapping of type parameter names to runtime values (types).
+  final Map<String, DartType>? _lexicalTypeEnvironment;
+
   final Substitution? _substitution;
 
   /// Error reporter that we use to report errors accumulated while computing
@@ -453,8 +471,10 @@
     this._library,
     this._errorReporter, {
     Map<String, DartObjectImpl>? lexicalEnvironment,
+    Map<String, DartType>? lexicalTypeEnvironment,
     Substitution? substitution,
   })  : _lexicalEnvironment = lexicalEnvironment,
+        _lexicalTypeEnvironment = lexicalTypeEnvironment,
         _substitution = substitution {
     _dartObjectComputer = DartObjectComputer(
       typeSystem,
@@ -705,8 +725,15 @@
       return null;
     }
 
-    return evaluationEngine.evaluateConstructorCall(_library, node,
-        node.argumentList.arguments, constructor, this, _errorReporter);
+    return evaluationEngine.evaluateConstructorCall(
+      _library,
+      node,
+      constructor.returnType.typeArguments,
+      node.argumentList.arguments,
+      constructor,
+      this,
+      _errorReporter,
+    );
   }
 
   @override
@@ -1253,7 +1280,18 @@
         TypeState(_typeProvider.neverType),
       );
     } else if (variableElement is TypeParameterElement) {
-      // Constants may not refer to type parameters.
+      // Constants may refer to type parameters only if the constructor-tearoffs
+      // feature is enabled.
+      if (_library.featureSet.isEnabled(Feature.constructor_tearoffs)) {
+        var typeArgument = _lexicalTypeEnvironment?[identifier.name];
+        if (typeArgument != null) {
+          return DartObjectImpl(
+            typeSystem,
+            _typeProvider.typeType,
+            TypeState(typeArgument),
+          );
+        }
+      }
     }
 
     // TODO(https://github.com/dart-lang/sdk/issues/47061): Use a specific
@@ -1926,13 +1964,17 @@
     _constructor.library as LibraryElementImpl,
     _externalErrorReporter,
     lexicalEnvironment: _parameterMap,
+    lexicalTypeEnvironment: _typeParameterMap,
     substitution: Substitution.fromInterfaceType(definingType),
   );
 
-  final AstNode _node;
+  /// The node used for most error reporting.
+  final AstNode _errorNode;
 
   final ConstructorElement _constructor;
 
+  final List<DartType>? _typeArguments;
+
   final ConstructorInvocation _invocation;
 
   final Map<String, NamedExpression> _namedNodes;
@@ -1941,17 +1983,25 @@
 
   final List<DartObjectImpl> _argumentValues;
 
+  final Map<String, DartType> _typeParameterMap = HashMap();
+
   final Map<String, DartObjectImpl> _parameterMap = HashMap();
 
   final Map<String, DartObjectImpl> _fieldMap = HashMap();
 
-  _InstanceCreationEvaluator.generative(
+  /// Constructor for [_InstanceCreationEvaluator].
+  ///
+  /// This constructor is private, as the entry point for using a
+  /// [_InstanceCreationEvaluator] is the static method,
+  /// [_InstanceCreationEvaluator.evaluate].
+  _InstanceCreationEvaluator._(
     this._evaluationEngine,
     this._declaredVariables,
     this._errorReporter,
     this._library,
-    this._node,
-    this._constructor, {
+    this._errorNode,
+    this._constructor,
+    this._typeArguments, {
     required Map<String, NamedExpression> namedNodes,
     required Map<String, DartObjectImpl> namedValues,
     required List<DartObjectImpl> argumentValues,
@@ -1979,7 +2029,7 @@
     if (_constructor.name == "fromEnvironment") {
       if (!_checkFromEnvironmentArguments(arguments, definingType)) {
         _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+            CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
         return null;
       }
       String? variableName =
@@ -2004,7 +2054,7 @@
         argumentCount == 1) {
       if (!_checkSymbolArguments(arguments, isNullSafe: isNullSafe)) {
         _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+            CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
         return null;
       }
       return DartObjectImpl(
@@ -2028,6 +2078,7 @@
     // Start with final fields that are initialized at their declaration site.
     _checkFields();
 
+    _checkTypeParameters();
     _checkParameters(arguments);
     var evaluationResult = _checkInitializers();
     if (evaluationResult.evaluationIsComplete) {
@@ -2038,7 +2089,7 @@
         superArguments: evaluationResult.superArguments);
     if (_externalErrorListener.errorReported) {
       _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+          CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
     }
     return DartObjectImpl(
       typeSystem,
@@ -2049,8 +2100,7 @@
 
   void _checkFields() {
     var fields = _constructor.enclosingElement.fields;
-    for (var i = 0; i < fields.length; i++) {
-      var field = fields[i];
+    for (var field in fields) {
       if ((field.isFinal || field.isConst) &&
           !field.isStatic &&
           field is ConstFieldElementImpl) {
@@ -2067,7 +2117,7 @@
         if (!typeSystem.runtimeTypeMatch(fieldValue, fieldType)) {
           _errorReporter.reportErrorForNode(
               CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
-              _node,
+              _errorNode,
               [fieldValue.type, field.name, fieldType]);
         }
         _fieldMap[field.name] = fieldValue;
@@ -2130,7 +2180,7 @@
           var fieldName = initializer.fieldName.name;
           if (_fieldMap.containsKey(fieldName)) {
             _errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
           }
           _fieldMap[fieldName] = evaluationResult;
           var getter = definingType.getGetter(fieldName);
@@ -2139,13 +2189,13 @@
             if (!typeSystem.runtimeTypeMatch(evaluationResult, field.type)) {
               _errorReporter.reportErrorForNode(
                   CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
-                  _node,
+                  _errorNode,
                   [evaluationResult.type, fieldName, field.type]);
             }
           }
         } else {
           _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
         }
       } else if (initializer is SuperConstructorInvocation) {
         var name = initializer.constructorName;
@@ -2162,7 +2212,8 @@
           constructor = ConstructorMember.from(constructor, definingType);
           var result = _evaluationEngine.evaluateConstructorCall(
               _library,
-              _node,
+              _errorNode,
+              _typeArguments,
               initializer.argumentList.arguments,
               constructor,
               _initializerVisitor,
@@ -2170,7 +2221,7 @@
               invocation: _invocation);
           if (_externalErrorListener.errorReported) {
             _errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
           }
           return _InitializersEvaluationResult(result,
               evaluationIsComplete: true);
@@ -2182,7 +2233,7 @@
             !evaluationResult.isBool ||
             evaluationResult.toBoolValue() == false) {
           _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
           return _InitializersEvaluationResult(null,
               evaluationIsComplete: true);
         }
@@ -2213,7 +2264,7 @@
       // No argument node that we can direct error messages to, because we
       // are handling an optional parameter that wasn't specified.  So just
       // direct error messages to the constructor call.
-      errorTarget ??= _node;
+      errorTarget ??= _errorNode;
       if (argumentValue == null && baseParameter is ParameterElementImpl) {
         // The parameter is an optional positional parameter for which no value
         // was provided, so use the default value.
@@ -2252,7 +2303,7 @@
             var fieldName = field.name;
             if (_fieldMap.containsKey(fieldName)) {
               _errorReporter.reportErrorForNode(
-                  CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+                  CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
             }
             _fieldMap[fieldName] = argumentValue;
           }
@@ -2288,8 +2339,9 @@
       if (superConstructor.isConst) {
         var evaluationResult = _evaluationEngine.evaluateConstructorCall(
           _library,
-          _node,
-          superArguments ?? astFactory.nodeList(_node),
+          _errorNode,
+          superclass.typeArguments,
+          superArguments ?? astFactory.nodeList(_errorNode),
           superConstructor,
           _initializerVisitor,
           _externalErrorReporter,
@@ -2328,6 +2380,20 @@
     return _isValidPublicSymbol(name);
   }
 
+  void _checkTypeParameters() {
+    var typeParameters = _constructor.enclosingElement.typeParameters;
+    var typeArguments = _typeArguments;
+    if (typeParameters.isNotEmpty &&
+        typeArguments != null &&
+        typeParameters.length == typeArguments.length) {
+      for (int i = 0; i < typeParameters.length; i++) {
+        var typeParameter = typeParameters[i];
+        var typeArgument = typeArguments[i];
+        _typeParameterMap[typeParameter.name] = typeArgument;
+      }
+    }
+  }
+
   /// Evaluates [node] as an instance creation expression using [constructor].
   static DartObjectImpl? evaluate(
     ConstantEvaluationEngine evaluationEngine,
@@ -2336,6 +2402,7 @@
     LibraryElementImpl library,
     AstNode node,
     ConstructorElement constructor,
+    List<DartType>? typeArguments,
     List<Expression> arguments,
     ConstantVisitor constantVisitor, {
     required bool isNullSafe,
@@ -2386,13 +2453,14 @@
 
     constructor = _followConstantRedirectionChain(constructor);
 
-    var evaluator = _InstanceCreationEvaluator.generative(
+    var evaluator = _InstanceCreationEvaluator._(
       evaluationEngine,
       declaredVariables,
       errorReporter,
       library,
       node,
       constructor,
+      typeArguments,
       namedNodes: namedNodes,
       namedValues: namedValues,
       argumentValues: argumentValues,
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index f1b79a3..541f9db 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3786,15 +3786,9 @@
     return _exports;
   }
 
+  @Deprecated('Support for dart-ext is replaced with FFI')
   @override
-  bool get hasExtUri {
-    return hasModifier(Modifier.HAS_EXT_URI);
-  }
-
-  /// Set whether this library has an import of a "dart-ext" URI.
-  set hasExtUri(bool hasExtUri) {
-    setModifier(Modifier.HAS_EXT_URI, hasExtUri);
-  }
+  bool get hasExtUri => false;
 
   @Deprecated('Not useful for clients')
   @override
@@ -4354,47 +4348,42 @@
   /// Indicates that the pseudo-modifier 'get' was applied to the element.
   static const Modifier GETTER = Modifier('GETTER', 11);
 
-  /// A flag used for libraries indicating that the defining compilation unit
-  /// contains at least one import directive whose URI uses the "dart-ext"
-  /// scheme.
-  static const Modifier HAS_EXT_URI = Modifier('HAS_EXT_URI', 12);
-
   /// A flag used for libraries indicating that the variable has an explicit
   /// initializer.
-  static const Modifier HAS_INITIALIZER = Modifier('HAS_INITIALIZER', 13);
+  static const Modifier HAS_INITIALIZER = Modifier('HAS_INITIALIZER', 12);
 
   /// A flag used for fields and top-level variables that have implicit type,
   /// and specify when the type has been inferred.
-  static const Modifier HAS_TYPE_INFERRED = Modifier('HAS_TYPE_INFERRED', 14);
+  static const Modifier HAS_TYPE_INFERRED = Modifier('HAS_TYPE_INFERRED', 13);
 
   /// A flag used for libraries indicating that the defining compilation unit
   /// has a `part of` directive, meaning that this unit should be a part,
   /// but is used as a library.
   static const Modifier HAS_PART_OF_DIRECTIVE =
-      Modifier('HAS_PART_OF_DIRECTIVE', 15);
+      Modifier('HAS_PART_OF_DIRECTIVE', 14);
 
   /// Indicates that the associated element did not have an explicit type
   /// associated with it. If the element is an [ExecutableElement], then the
   /// type being referred to is the return type.
-  static const Modifier IMPLICIT_TYPE = Modifier('IMPLICIT_TYPE', 16);
+  static const Modifier IMPLICIT_TYPE = Modifier('IMPLICIT_TYPE', 15);
 
   /// Indicates that modifier 'lazy' was applied to the element.
-  static const Modifier LATE = Modifier('LATE', 17);
+  static const Modifier LATE = Modifier('LATE', 16);
 
   /// Indicates that a class is a mixin application.
-  static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 18);
+  static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 17);
 
   /// Indicates that the pseudo-modifier 'set' was applied to the element.
-  static const Modifier SETTER = Modifier('SETTER', 19);
+  static const Modifier SETTER = Modifier('SETTER', 18);
 
   /// Indicates that the modifier 'static' was applied to the element.
-  static const Modifier STATIC = Modifier('STATIC', 20);
+  static const Modifier STATIC = Modifier('STATIC', 19);
 
   /// Indicates that the element does not appear in the source code but was
   /// implicitly created. For example, if a class does not define any
   /// constructors, an implicit zero-argument constructor will be created and it
   /// will be marked as being synthetic.
-  static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 21);
+  static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 20);
 
   static const List<Modifier> values = [
     ABSTRACT,
@@ -4409,7 +4398,6 @@
     FINAL,
     GENERATOR,
     GETTER,
-    HAS_EXT_URI,
     HAS_INITIALIZER,
     HAS_PART_OF_DIRECTIVE,
     IMPLICIT_TYPE,
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
index 12bbdcc..3406875 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
@@ -3866,35 +3866,6 @@
     hasPublishedDocs: true,
   );
 
-  /**
-   * No parameters.
-   */
-  // #### Description
-  //
-  // The analyzer produces this diagnostic when a library is imported using the
-  // `dart-ext` scheme.
-  //
-  // #### Example
-  //
-  // The following code produces this diagnostic because the native library `x`
-  // is being imported using a scheme of `dart-ext`:
-  //
-  // ```dart
-  // [!import 'dart-ext:x';!]
-  // int f() native 'string';
-  // ```
-  //
-  // #### Common fixes
-  //
-  // Rewrite the code to use `dart:ffi` as a way of invoking the contents of the
-  // native library.
-  static const HintCode USE_OF_NATIVE_EXTENSION = HintCode(
-    'USE_OF_NATIVE_EXTENSION',
-    "Dart native extensions are deprecated and aren’t available in Dart 2.15.",
-    correctionMessage: "Try using dart:ffi for C interop.",
-    hasPublishedDocs: true,
-  );
-
   /// Initialize a newly created error code to have the given [name].
   const HintCode(
     String name,
diff --git a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
index fc56800..dc78189 100644
--- a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
@@ -2,12 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:typed_data';
+
 import 'package:analyzer/src/dart/analysis/cache.dart';
 import 'package:collection/collection.dart';
 
 class CacheData {
   final int id;
-  final List<int> bytes;
+  final Uint8List bytes;
 
   CacheData(this.id, this.bytes);
 }
@@ -25,11 +27,11 @@
   /// [signature].
   ///
   /// Return `null` if the association does not exist.
-  CacheData? get(String key, List<int> signature);
+  CacheData? get(String key, Uint8List signature);
 
   /// Associate the given [bytes] with the [key] and [signature]. Return the
   /// [CacheData].
-  CacheData putGet(String key, List<int> signature, List<int> bytes);
+  CacheData putGet(String key, Uint8List signature, Uint8List bytes);
 
   ///  Used to decrement reference count for the given ids, if implemented.
   void release(Iterable<int> ids);
@@ -51,7 +53,7 @@
             maxCacheSize, (v) => v.data.bytes.length);
 
   @override
-  CacheData? get(String key, List<int> signature) {
+  CacheData? get(String key, Uint8List signature) {
     var entry = _cache.get(key, () => null);
 
     if (entry != null &&
@@ -62,7 +64,7 @@
   }
 
   @override
-  CacheData putGet(String key, List<int> signature, List<int> bytes) {
+  CacheData putGet(String key, Uint8List signature, Uint8List bytes) {
     idCounter++;
     var entry = CiderCacheEntry(signature, CacheData(idCounter, bytes));
     _cache.put(key, entry);
@@ -78,7 +80,7 @@
 
 class CiderCacheEntry {
   final CacheData data;
-  final List<int> signature;
+  final Uint8List signature;
 
   CiderCacheEntry(this.signature, this.data);
 }
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index 1fa7152..30be965 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -565,9 +565,13 @@
             directive.prefix?.staticElement = importElement.prefix;
             var source = importElement.importedLibrary?.source;
             if (source != null && !_isLibrarySource(source)) {
+              // It is safe to assume that `directive.uri.stringValue` is
+              // non-`null`, because the only time it is `null` is if the URI
+              // contains a string interpolation, in which case the import
+              // would never have resolved in the first place.
               ErrorCode errorCode = CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY;
               libraryErrorReporter.reportErrorForNode(
-                  errorCode, directive.uri, [directive.uri]);
+                  errorCode, directive.uri, [directive.uri.stringValue!]);
             }
           }
         }
@@ -577,10 +581,14 @@
             directive.element = exportElement;
             var source = exportElement.exportedLibrary?.source;
             if (source != null && !_isLibrarySource(source)) {
+              // It is safe to assume that `directive.uri.stringValue` is
+              // non-`null`, because the only time it is `null` is if the URI
+              // contains a string interpolation, in which case the export
+              // would never have resolved in the first place.
               libraryErrorReporter.reportErrorForNode(
                   CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
                   directive.uri,
-                  [directive.uri]);
+                  [directive.uri.stringValue!]);
             }
           }
         }
@@ -737,8 +745,6 @@
         UriBasedDirectiveImpl.validateUri(isImport, uriLiteral, uriContent);
     if (code == null) {
       return _sourceFactory.resolveUri(file.source, uriContent);
-    } else if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
-      return null;
     } else if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
       _getErrorReporter(file).reportErrorForNode(
           CompileTimeErrorCode.URI_WITH_INTERPOLATION, uriLiteral);
@@ -798,13 +804,23 @@
         return;
       }
     }
+
+    var uriContent = directive.uriContent;
+    if (uriContent != null && uriContent.startsWith('dart-ext:')) {
+      _getErrorReporter(file).reportErrorForNode(
+        CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
+        directive.uri,
+      );
+      return;
+    }
+
     StringLiteral uriLiteral = directive.uri;
     CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
     if (isGeneratedSource(source)) {
       errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
     }
     _getErrorReporter(file)
-        .reportErrorForNode(errorCode, uriLiteral, [directive.uriContent]);
+        .reportErrorForNode(errorCode, uriLiteral, [uriContent]);
   }
 
   /// Check each directive in the given [unit] to see if the referenced source
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index 4e56df0..c1b1c9f 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -83,7 +83,7 @@
   final List<FileState> libraryFiles = [];
   FileState? partOfLibrary;
 
-  late List<int> _digest;
+  late Uint8List _digest;
   late bool _exists;
   late List<int> _apiSignature;
   late UnlinkedUnit2 unlinked2;
@@ -226,7 +226,7 @@
     performance.getDataInt('count').increment();
 
     performance.run('digest', (_) {
-      _digest = utf8.encode(_fsState.getFileDigest(path));
+      _digest = utf8.encode(_fsState.getFileDigest(path)) as Uint8List;
       _exists = _digest.isNotEmpty;
     });
 
@@ -235,8 +235,8 @@
 
     // Prepare bytes of the unlinked bundle - existing or new.
     // TODO(migration): should not be nullable
-    List<int>? unlinkedBytes;
-    List<int>? informativeBytes;
+    Uint8List? unlinkedBytes;
+    Uint8List? informativeBytes;
     {
       var unlinkedData = _fsState._byteStore.get(unlinkedKey, _digest);
       var informativeData = _fsState._byteStore.get(informativeKey, _digest);
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index e28b029..f60649d 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -898,7 +898,7 @@
           BundleReader(
             elementFactory: elementFactory,
             unitsInformativeBytes: unitsInformativeBytes,
-            resolutionBytes: resolutionBytes as Uint8List,
+            resolutionBytes: resolutionBytes,
           ),
         );
       }
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 66844bc..3900f37 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -427,7 +427,6 @@
   void visitExportDirective(ExportDirective node) {
     _deprecatedVerifier.exportDirective(node);
     _checkForInternalExport(node);
-    _checkForUseOfNativeExtension(node);
     super.visitExportDirective(node);
   }
 
@@ -582,7 +581,6 @@
     }
     _invalidAccessVerifier.verifyImport(node);
     _checkForImportOfLegacyLibraryIntoNullSafe(node);
-    _checkForUseOfNativeExtension(node);
     super.visitImportDirective(node);
   }
 
@@ -1442,16 +1440,6 @@
     return false;
   }
 
-  void _checkForUseOfNativeExtension(UriBasedDirective node) {
-    var uri = node.uriContent;
-    if (uri == null) {
-      return;
-    }
-    if (uri.startsWith('dart-ext:')) {
-      _errorReporter.reportErrorForNode(HintCode.USE_OF_NATIVE_EXTENSION, node);
-    }
-  }
-
   void _checkRequiredParameter(FormalParameterList node) {
     final requiredParameters =
         node.parameters.where((p) => p.declaredElement?.hasRequired == true);
diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart
index dd11f38..22dec30 100644
--- a/pkg/analyzer/lib/src/error/codes.g.dart
+++ b/pkg/analyzer/lib/src/error/codes.g.dart
@@ -15028,6 +15028,35 @@
    */
   // #### Description
   //
+  // The analyzer produces this diagnostic when a library is imported using the
+  // `dart-ext` scheme.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the native library `x`
+  // is being imported using a scheme of `dart-ext`:
+  //
+  // ```dart
+  // import [!'dart-ext:x'!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Rewrite the code to use `dart:ffi` as a way of invoking the contents of the
+  // native library.
+  static const CompileTimeErrorCode USE_OF_NATIVE_EXTENSION =
+      CompileTimeErrorCode(
+    'USE_OF_NATIVE_EXTENSION',
+    "Dart native extensions are deprecated and aren’t available in Dart 2.15.",
+    correctionMessage: "Try using dart:ffi for C interop.",
+    hasPublishedDocs: true,
+  );
+
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
   // The analyzer produces this diagnostic when it finds an expression whose
   // type is `void`, and the expression is used in a place where a value is
   // expected, such as before a member access or on the right-hand side of an
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 647e36b..7f01644 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -208,10 +208,6 @@
   /// A flag indicating whether the visitor is currently within code in the SDK.
   bool _isInSystemLibrary = false;
 
-  /// A flag indicating whether the current library contains at least one import
-  /// directive with a URI that uses the "dart-ext" scheme.
-  bool _hasExtUri = false;
-
   /// The class containing the AST nodes being visited, or `null` if we are not
   /// in the scope of a class.
   ClassElementImpl? _enclosingClass;
@@ -265,7 +261,6 @@
         _duplicateDefinitionVerifier =
             DuplicateDefinitionVerifier(_currentLibrary, errorReporter) {
     _isInSystemLibrary = _currentLibrary.source.isInSystemLibrary;
-    _hasExtUri = _currentLibrary.hasExtUri;
     _isInCatchClause = false;
     _isInStaticVariableDeclaration = false;
     _isInConstructorInitializer = false;
@@ -2274,10 +2269,14 @@
       return;
     }
 
+    // It is safe to assume that `directive.uri.stringValue` is non-`null`,
+    // because the only time it is `null` is if the URI contains a string
+    // interpolation, in which case the export would never have resolved in the
+    // first place.
     errorReporter.reportErrorForNode(
         CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY,
         directive,
-        [directive.uri]);
+        [directive.uri.stringValue!]);
   }
 
   /// See [CompileTimeErrorCode.EXPORT_LEGACY_SYMBOL].
@@ -3247,7 +3246,7 @@
   ///
   /// See [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE].
   void _checkForNativeFunctionBodyInNonSdkCode(NativeFunctionBody body) {
-    if (!_isInSystemLibrary && !_hasExtUri) {
+    if (!_isInSystemLibrary) {
       errorReporter.reportErrorForNode(
           ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE, body);
     }
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 2203d3d..f134a33 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -48,10 +48,6 @@
   /// The name of the `dart` scheme.
   static String DART_SCHEME = "dart";
 
-  /// The prefix of a URI using the dart-ext scheme to reference a native code
-  /// library.
-  static const String _DART_EXT_SCHEME = "dart-ext:";
-
   /// The Dart SDK against which URI's are to be resolved.
   final DartSdk _sdk;
 
@@ -78,13 +74,6 @@
     return dartSource?.uri;
   }
 
-  /// Return `true` if the given URI is a `dart-ext:` URI.
-  ///
-  /// @param uriContent the textual representation of the URI being tested
-  /// @return `true` if the given URI is a `dart-ext:` URI
-  static bool isDartExtUri(String? uriContent) =>
-      uriContent != null && uriContent.startsWith(_DART_EXT_SCHEME);
-
   /// Return `true` if the given URI is a `dart:` URI.
   ///
   /// @param uri the URI being tested
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index c375b8c..5d1e535 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary2/library_builder.dart';
 import 'package:analyzer/src/summary2/link.dart';
@@ -24,7 +23,6 @@
   final _imports = <ImportElement>[];
   var _isFirstLibraryDirective = true;
   var _hasCoreImport = false;
-  var _hasExtUri = false;
   var _partDirectiveIndex = 0;
 
   _EnclosingContext _enclosingContext;
@@ -72,7 +70,6 @@
       );
     }
     _libraryElement.imports = _imports;
-    _libraryElement.hasExtUri = _hasExtUri;
 
     if (_isFirstLibraryDirective) {
       _isFirstLibraryDirective = false;
@@ -619,8 +616,6 @@
 
     if (uriStr == 'dart:core') {
       _hasCoreImport = true;
-    } else if (DartUriResolver.isDartExtUri(uriStr)) {
-      _hasExtUri = true;
     }
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/element_flags.dart b/pkg/analyzer/lib/src/summary2/element_flags.dart
index e808000..806aab7 100644
--- a/pkg/analyzer/lib/src/summary2/element_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/element_flags.dart
@@ -136,20 +136,17 @@
 }
 
 class LibraryElementFlags {
-  static const int _hasExtUri = 1 << 0;
-  static const int _hasPartOfDirective = 1 << 1;
-  static const int _isSynthetic = 1 << 2;
+  static const int _hasPartOfDirective = 1 << 0;
+  static const int _isSynthetic = 1 << 1;
 
   static void read(SummaryDataReader reader, LibraryElementImpl element) {
     var byte = reader.readByte();
-    element.hasExtUri = (byte & _hasExtUri) != 0;
     element.hasPartOfDirective = (byte & _hasPartOfDirective) != 0;
     element.isSynthetic = (byte & _isSynthetic) != 0;
   }
 
   static void write(BufferedSink sink, LibraryElementImpl element) {
     var result = 0;
-    result |= element.hasExtUri ? _hasExtUri : 0;
     result |= element.hasPartOfDirective ? _hasPartOfDirective : 0;
     result |= element.isSynthetic ? _isSynthetic : 0;
     sink.writeByte(result);
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index ebd0349..bee1e35 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -13204,6 +13204,30 @@
 
       var zero = min(0, 0);
       ```
+  USE_OF_NATIVE_EXTENSION:
+    problemMessage: Dart native extensions are deprecated and aren’t available in Dart 2.15.
+    correctionMessage: "Try using dart:ffi for C interop."
+    hasPublishedDocs: true
+    comment: No parameters.
+    documentation: |-
+      #### Description
+
+      The analyzer produces this diagnostic when a library is imported using the
+      `dart-ext` scheme.
+
+      #### Example
+
+      The following code produces this diagnostic because the native library `x`
+      is being imported using a scheme of `dart-ext`:
+
+      ```dart
+      import [!'dart-ext:x'!];
+      ```
+
+      #### Common fixes
+
+      Rewrite the code to use `dart:ffi` as a way of invoking the contents of the
+      native library.
   USE_OF_VOID_RESULT:
     problemMessage: "This expression has a type of 'void' so its value can't be used."
     correctionMessage: "Try checking to see if you're using the correct API; there might be a function or call that returns void you didn't expect. Also check type parameters and variables which might also be void."
@@ -17272,31 +17296,6 @@
 
       var x = min(0, 1);
       ```
-  USE_OF_NATIVE_EXTENSION:
-    problemMessage: Dart native extensions are deprecated and aren’t available in Dart 2.15.
-    correctionMessage: "Try using dart:ffi for C interop."
-    hasPublishedDocs: true
-    comment: No parameters.
-    documentation: |-
-      #### Description
-
-      The analyzer produces this diagnostic when a library is imported using the
-      `dart-ext` scheme.
-
-      #### Example
-
-      The following code produces this diagnostic because the native library `x`
-      is being imported using a scheme of `dart-ext`:
-
-      ```dart
-      [!import 'dart-ext:x';!]
-      int f() native 'string';
-      ```
-
-      #### Common fixes
-
-      Rewrite the code to use `dart:ffi` as a way of invoking the contents of the
-      native library.
 LanguageCode:
   IMPLICIT_DYNAMIC_FIELD:
     problemMessage: "Missing field type for '{0}'."
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 91e4e01..a1cdefa 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -2358,28 +2358,6 @@
 ''');
   }
 
-  test_nativeConstConstructor() async {
-    await assertErrorsInCode(r'''
-import 'dart-ext:x';
-class Foo {
-  const Foo() native 'Foo_Foo';
-  const factory Foo.foo() native 'Foo_Foo_foo';
-}
-''', [
-      error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 20),
-      error(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, 47, 6),
-    ]);
-  }
-
-  test_nativeFunctionBodyInNonSDKCode_function() async {
-    await assertErrorsInCode(r'''
-import 'dart-ext:x';
-int m(a) native 'string';
-''', [
-      error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 20),
-    ]);
-  }
-
   test_newWithAbstractClass_factory() async {
     await assertNoErrorsInCode(r'''
 abstract class A {
diff --git a/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart b/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart
index 47202d9..6cf3fea 100644
--- a/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:typed_data';
+
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -13,8 +15,8 @@
   });
 }
 
-List<int> _b(int length) {
-  return List<int>.filled(length, 0);
+Uint8List _b(int length) {
+  return Uint8List(length);
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/analysis/file_byte_store_test.dart b/pkg/analyzer/test/src/dart/analysis/file_byte_store_test.dart
index c767dce..5b59568 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_byte_store_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_byte_store_test.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:typed_data';
+
 import 'package:analyzer/src/dart/analysis/file_byte_store.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -17,20 +19,20 @@
   final validator = FileByteStoreValidator();
 
   test_get_bad_notEnoughBytes() {
-    List<int> bytes = <int>[1, 2, 3];
+    var bytes = Uint8List.fromList([1, 2, 3]);
     var data = validator.getData(bytes);
     expect(data, isNull);
   }
 
   test_get_bad_notEnoughBytes_zero() {
-    List<int> bytes = <int>[];
+    var bytes = Uint8List.fromList([]);
     var data = validator.getData(bytes);
     expect(data, isNull);
   }
 
   test_get_bad_wrongChecksum() {
-    List<int> data = <int>[1, 2, 3];
-    List<int> bytes = validator.wrapData(data);
+    var data = Uint8List.fromList([1, 2, 3]);
+    var bytes = validator.wrapData(data);
 
     // Damage the checksum.
     expect(bytes[bytes.length - 1], isNot(42));
@@ -41,22 +43,24 @@
   }
 
   test_get_bad_wrongVersion() {
-    List<int> bytes = <int>[0xBA, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
+    var bytes = Uint8List.fromList(
+      [0xBA, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+    );
     var data = validator.getData(bytes);
     expect(data, isNull);
   }
 
   test_get_good() {
-    List<int> data = <int>[1, 2, 3];
-    List<int> bytes = validator.wrapData(data);
+    var data = Uint8List.fromList([1, 2, 3]);
+    var bytes = validator.wrapData(data);
     var data2 = validator.getData(bytes);
     expect(data2, hasLength(3));
     expect(data2, data);
   }
 
   test_get_good_zeroBytesData() {
-    List<int> data = <int>[];
-    List<int> bytes = validator.wrapData(data);
+    var data = Uint8List.fromList([]);
+    var bytes = validator.wrapData(data);
     var data2 = validator.getData(bytes);
     expect(data2, hasLength(0));
     expect(data2, data);
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 29fcbe1..a4da5db 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -619,7 +619,7 @@
     expect(file.unlinked2, isNotNull);
 
     // Make the unlinked unit in the byte store zero-length, damaged.
-    byteStore.put(file.test.unlinkedKey, <int>[]);
+    byteStore.put(file.test.unlinkedKey, Uint8List(0));
 
     // Refresh should not fail, zero bytes in the store are ignored.
     file.refresh();
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index c2ad9fe..f2dd07e 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -317,6 +318,137 @@
     );
   }
 
+  test_instanceCreationExpression_redirecting_typeParameter() async {
+    await resolveTestCode('''
+class A<T> {
+  final Object f;
+  const A(): this.named(T);
+  const A.named(Object t): f = t;
+}
+const a = const A<int>();
+''');
+    var result = _evaluateConstant('a');
+    expect(result, isNotNull);
+  }
+
+  test_instanceCreationExpression_typeParameter() async {
+    await resolveTestCode('''
+class A<T> {
+  final Object f;
+  const A(): f = T;
+}
+const a = const A<int>();
+''');
+    var result = _evaluateConstant('a');
+    var aElement = findElement.class_('A');
+    var expectedType = aElement.instantiate(
+        typeArguments: [typeProvider.intType],
+        nullabilitySuffix: NullabilitySuffix.none);
+    expect(result.type, expectedType);
+  }
+
+  test_instanceCreationExpression_typeParameter_implicitTypeArgs() async {
+    await resolveTestCode('''
+class A<T> {
+  final Object f;
+  const A(): f = T;
+}
+const a = const A();
+''');
+    var result = _evaluateConstant('a');
+    var aElement = findElement.class_('A');
+    var expectedType = aElement.instantiate(
+        typeArguments: [typeProvider.dynamicType],
+        nullabilitySuffix: NullabilitySuffix.none);
+    expect(result.type, expectedType);
+  }
+
+  test_instanceCreationExpression_typeParameter_super() async {
+    await resolveTestCode('''
+class A<T> {
+  final Object f;
+  const A(Object t): f = t;
+}
+class B<T> extends A<T> {
+  const B(): super(T);
+}
+const a = const B<int>();
+''');
+    var result = _evaluateConstant('a');
+    var bElement = findElement.class_('B');
+    var expectedType = bElement.instantiate(
+        typeArguments: [typeProvider.intType],
+        nullabilitySuffix: NullabilitySuffix.none);
+    expect(result.type, expectedType);
+  }
+
+  test_instanceCreationExpression_typeParameter_superNonGeneric() async {
+    await resolveTestCode('''
+class A {
+  final Object f;
+  const A(Object t): f = t;
+}
+class B<T> extends A {
+  const B(): super(T);
+}
+const a = const B<int>();
+''');
+    var result = _evaluateConstant('a');
+    expect(result, isNotNull);
+  }
+
+  test_instanceCreationExpression_typeParameter_typeAlias() async {
+    await resolveTestCode('''
+class A<T, U> {
+  final Object f, g;
+  const A(): f = T, g = U;
+}
+typedef B<S> = A<int, S>;
+const a = const B<String>();
+''');
+    var result = _evaluateConstant('a');
+    var aElement = findElement.class_('A');
+    var expectedType = aElement.instantiate(
+        typeArguments: [typeProvider.intType, typeProvider.stringType],
+        nullabilitySuffix: NullabilitySuffix.none);
+    expect(result.type, expectedType);
+  }
+
+  test_instanceCreationExpression_typeParameter_withoutConstructorTearoffs() async {
+    await resolveTestCode('''
+// @dart=2.12
+class A<T> {
+  final Object f;
+  const A(): f = T;
+}
+const a = const A<int>();
+''');
+    var result = _evaluateConstant('a', errorCodes: [
+      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
+      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
+    ]);
+    var aElement = findElement.class_('A');
+    var expectedType = aElement.instantiate(
+        typeArguments: [typeProvider.intType],
+        nullabilitySuffix: NullabilitySuffix.none);
+    expect(result.type, expectedType);
+  }
+
+  test_typeParameter() async {
+    await resolveTestCode('''
+class A<X> {
+  const A();
+  void m() {
+    const x = X;
+  }
+}
+''');
+    var result = _evaluateConstantLocal('x', errorCodes: [
+      CompileTimeErrorCode.INVALID_CONSTANT,
+    ]);
+    expect(result, isNull);
+  }
+
   test_visitAsExpression_potentialConstType() async {
     await assertNoErrorsInCode('''
 const num three = 3;
diff --git a/pkg/analyzer/test/src/diagnostics/export_internal_library_test.dart b/pkg/analyzer/test/src/diagnostics/export_internal_library_test.dart
index e4a7206..c4eea53 100644
--- a/pkg/analyzer/test/src/diagnostics/export_internal_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/export_internal_library_test.dart
@@ -19,7 +19,8 @@
     await assertErrorsInCode('''
 export 'dart:_internal';
 ''', [
-      error(CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, 0, 24),
+      error(CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, 0, 24,
+          messageContains: "library 'dart:_internal' "),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/export_of_non_library_test.dart b/pkg/analyzer/test/src/diagnostics/export_of_non_library_test.dart
index 4c4ef49..fc0bf97 100644
--- a/pkg/analyzer/test/src/diagnostics/export_of_non_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/export_of_non_library_test.dart
@@ -23,7 +23,8 @@
 library L;
 export 'lib1.dart';
 ''', [
-      error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 18, 11),
+      error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 18, 11,
+          messageContains: "library 'lib1.dart' "),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/import_of_non_library_test.dart b/pkg/analyzer/test/src/diagnostics/import_of_non_library_test.dart
index 7a0dca2..d5ffe46 100644
--- a/pkg/analyzer/test/src/diagnostics/import_of_non_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/import_of_non_library_test.dart
@@ -25,7 +25,8 @@
 import 'lib1.dart' deferred as p;
 var a = new p.A();
 ''', [
-      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 20, 11),
+      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 20, 11,
+          messageContains: "library 'lib1.dart' "),
     ]);
   }
 
@@ -39,7 +40,8 @@
 import 'part.dart';
 A a = A();
 ''', [
-      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 20, 11),
+      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 20, 11,
+          messageContains: "library 'part.dart' "),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/uri_does_not_exist_test.dart b/pkg/analyzer/test/src/diagnostics/uri_does_not_exist_test.dart
index 4ae834a..ceca9ef 100644
--- a/pkg/analyzer/test/src/diagnostics/uri_does_not_exist_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/uri_does_not_exist_test.dart
@@ -88,31 +88,4 @@
       error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 18, 14),
     ]);
   }
-
-  test_valid_dll() async {
-    newFile("$testPackageLibPath/lib.dll");
-    await assertErrorsInCode('''
-import 'dart-ext:lib';
-''', [
-      error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 22),
-    ]);
-  }
-
-  test_valid_dylib() async {
-    newFile("$testPackageLibPath/lib.dylib");
-    await assertErrorsInCode('''
-import 'dart-ext:lib';
-''', [
-      error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 22),
-    ]);
-  }
-
-  test_valid_so() async {
-    newFile("$testPackageLibPath/lib.so");
-    await assertErrorsInCode('''
-import 'dart-ext:lib';
-''', [
-      error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 22),
-    ]);
-  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/use_of_native_extension_test.dart b/pkg/analyzer/test/src/diagnostics/use_of_native_extension_test.dart
index e172765..8a89fab 100644
--- a/pkg/analyzer/test/src/diagnostics/use_of_native_extension_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/use_of_native_extension_test.dart
@@ -19,8 +19,7 @@
     await assertErrorsInCode(r'''
 export 'dart-ext:x';
 ''', [
-      error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 20),
-      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 12),
+      error(CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION, 7, 12),
     ]);
   }
 
@@ -28,8 +27,7 @@
     await assertErrorsInCode(r'''
 import 'dart-ext:x';
 ''', [
-      // TODO(srawlins): Why does this file not have a URI_DOES_NOT_EXIST error?
-      error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 20),
+      error(CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION, 7, 12),
     ]);
   }
 }
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 9c1892b..fc014beb 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -15374,8 +15374,7 @@
 is being imported using a scheme of `dart-ext`:
 
 {% prettify dart tag=pre+code %}
-[!import 'dart-ext:x';!]
-int f() native 'string';
+import [!'dart-ext:x'!];
 {% endprettify %}
 
 #### Common fixes
diff --git a/pkg/dds/lib/src/dap/adapters/dart.dart b/pkg/dds/lib/src/dap/adapters/dart.dart
index b585cd5..67be4b5 100644
--- a/pkg/dds/lib/src/dap/adapters/dart.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart.dart
@@ -1666,10 +1666,10 @@
     }
   }
 
-  void _logTraffic(String data) {
-    logger?.call(data);
+  void _logTraffic(String message) {
+    logger?.call(message);
     if (sendLogsToClient) {
-      sendEvent(RawEventBody(data), eventType: 'dart.log');
+      sendEvent(RawEventBody({"message": message}), eventType: 'dart.log');
     }
   }
 
diff --git a/pkg/dds/test/dap/integration/debug_logging_test.dart b/pkg/dds/test/dap/integration/debug_logging_test.dart
index 27578f5..02685fb 100644
--- a/pkg/dds/test/dap/integration/debug_logging_test.dart
+++ b/pkg/dds/test/dap/integration/debug_logging_test.dart
@@ -5,6 +5,7 @@
 import 'package:test/test.dart';
 
 import 'test_client.dart';
+import 'test_scripts.dart';
 import 'test_support.dart';
 
 main() {
@@ -15,6 +16,33 @@
   tearDown(() => dap.tearDown());
 
   group('debug mode', () {
+    test('sends dart.log events when sendLogsToClient=true', () async {
+      final testFile = dap.createTestFile(simpleArgPrintingProgram);
+
+      final logOutputs = dap.client
+          .events('dart.log')
+          .map((event) => event.body as Map<String, Object?>)
+          .map((body) => body['message'] as String);
+
+      await Future.wait([
+        expectLater(
+          logOutputs,
+          // Check for a known VM Service packet.
+          emitsThrough(
+            contains('"method":"streamListen","params":{"streamId":"Debug"}'),
+          ),
+        ),
+        dap.client.start(
+          file: testFile,
+          launch: () => dap.client.launch(
+            testFile.path,
+            sendLogsToClient: true,
+          ),
+        ),
+      ]);
+      await dap.client.terminate();
+    });
+
     test('prints messages from dart:developer log()', () async {
       final testFile = dap.createTestFile(r'''
 import 'dart:developer';
diff --git a/pkg/dds/test/dap/integration/test_client.dart b/pkg/dds/test/dap/integration/test_client.dart
index 78b145d..66f44da 100644
--- a/pkg/dds/test/dap/integration/test_client.dart
+++ b/pkg/dds/test/dap/integration/test_client.dart
@@ -227,6 +227,7 @@
     bool? debugExternalPackageLibraries,
     bool? evaluateGettersInDebugViews,
     bool? evaluateToStringInDebugViews,
+    bool? sendLogsToClient,
   }) {
     return sendRequest(
       DartLaunchRequestArguments(
@@ -243,7 +244,7 @@
         // When running out of process, VM Service traffic won't be available
         // to the client-side logger, so force logging on which sends VM Service
         // traffic in a custom event.
-        sendLogsToClient: captureVmServiceTraffic,
+        sendLogsToClient: sendLogsToClient ?? captureVmServiceTraffic,
       ),
       // We can't automatically pick the command when using a custom type
       // (DartLaunchRequestArguments).
diff --git a/pkg/dds/tool/dap/README.md b/pkg/dds/tool/dap/README.md
index 6ba9e91..216d648 100644
--- a/pkg/dds/tool/dap/README.md
+++ b/pkg/dds/tool/dap/README.md
@@ -100,7 +100,9 @@
 {
 	"type": "event",
 	"event": "dart.log",
-	"body": "<log message or json string>"
+	"body": {
+		"message": "<log message or json string>"
+	}
 }
 ```
 
diff --git a/runtime/observatory/lib/src/elements/process_snapshot.dart b/runtime/observatory/lib/src/elements/process_snapshot.dart
index 4aef2cf..6e87923 100644
--- a/runtime/observatory/lib/src/elements/process_snapshot.dart
+++ b/runtime/observatory/lib/src/elements/process_snapshot.dart
@@ -602,6 +602,7 @@
         ..onChange.listen((_) {
           _snapshotA = _loadedSnapshots[s.selectedIndex];
           selection = null;
+          diffSelection = null;
           _r.dirty();
         })
     ];
@@ -622,6 +623,7 @@
         ..onChange.listen((_) {
           _snapshotB = _loadedSnapshots[s.selectedIndex];
           selection = null;
+          diffSelection = null;
           _r.dirty();
         })
     ];
diff --git a/runtime/tests/vm/dart/regress_47425_test.dart b/runtime/tests/vm/dart/regress_47425_test.dart
new file mode 100644
index 0000000..f8d6576
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_47425_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/47425.
+// Verifies that Type.operator== works on generic types which
+// classes are not finalized.
+
+import 'package:expect/expect.dart';
+
+void testTypesEquality<A, B>(bool expected) {
+  Expect.equals(expected, A == B);
+}
+
+void withNewBox() {
+  Box();
+  testTypesEquality<Box<num>, Box<int>>(false);
+}
+
+void withoutNewBox() {
+  testTypesEquality<Box<num>, Box<int>>(false);
+}
+
+class Box<T> {}
+
+void main() {
+  testTypesEquality<num, int>(false);
+  testTypesEquality<Box<num>, Box<int>>(false);
+  testTypesEquality<Box<num>, Box<num>>(true);
+
+  withoutNewBox();
+  withNewBox();
+  withoutNewBox();
+
+  testTypesEquality<Box<num>, Box<int>>(false);
+  testTypesEquality<Box<num>, Box<num>>(true);
+}
diff --git a/runtime/tests/vm/dart_2/regress_47425_test.dart b/runtime/tests/vm/dart_2/regress_47425_test.dart
new file mode 100644
index 0000000..7cd3cfa
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_47425_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/47425.
+// Verifies that Type.operator== works on generic types which
+// classes are not finalized.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+void testTypesEquality<A, B>(bool expected) {
+  Expect.equals(expected, A == B);
+}
+
+void withNewBox() {
+  Box();
+  testTypesEquality<Box<num>, Box<int>>(false);
+}
+
+void withoutNewBox() {
+  testTypesEquality<Box<num>, Box<int>>(false);
+}
+
+class Box<T> {}
+
+void main() {
+  testTypesEquality<num, int>(false);
+  testTypesEquality<Box<num>, Box<int>>(false);
+  testTypesEquality<Box<num>, Box<num>>(true);
+
+  withoutNewBox();
+  withNewBox();
+  withoutNewBox();
+
+  testTypesEquality<Box<num>, Box<int>>(false);
+  testTypesEquality<Box<num>, Box<num>>(true);
+}
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index f29a90a..8a97dd4 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -1210,20 +1210,19 @@
 }
 
 // Compares cid1 and cid2 to see if they're syntactically equivalent. If this
-// can be determined by this fast path, it jumps to either equal or not_equal,
-// if equal but belonging to a generic class, it falls through with the scratch
-// register containing host_type_arguments_field_offset_in_words,
-// otherwise it jumps to normal_ir_body. May clobber scratch.
+// can be determined by this fast path, it jumps to either equal_* or not_equal.
+// If classes are equivalent but may be generic, then jumps to
+// equal_may_be_generic. Clobbers scratch.
 static void EquivalentClassIds(Assembler* assembler,
                                Label* normal_ir_body,
-                               Label* equal,
+                               Label* equal_may_be_generic,
+                               Label* equal_not_generic,
                                Label* not_equal,
                                Register cid1,
                                Register cid2,
                                Register scratch,
                                bool testing_instance_cids) {
-  Label different_cids, equal_cids_but_generic, not_integer,
-      not_integer_or_string, not_integer_or_string_or_list;
+  Label not_integer, not_integer_or_string, not_integer_or_string_or_list;
 
   // Check if left hand side is a closure. Closures are handled in the runtime.
   __ CompareImmediate(cid1, kClosureCid);
@@ -1233,25 +1232,11 @@
   // considered equivalent (e.g. multiple string implementation classes map to a
   // single String type).
   __ cmp(cid1, Operand(cid2));
-  __ b(&different_cids, NE);
-
-  // Types have the same class and neither is a closure type.
-  // Check if there are no type arguments. In this case we can return true.
-  // Otherwise fall through into the runtime to handle comparison.
-  __ LoadClassById(scratch, cid1);
-  __ ldr(
-      scratch,
-      FieldAddress(
-          scratch,
-          target::Class::host_type_arguments_field_offset_in_words_offset()));
-  __ CompareImmediate(scratch, target::Class::kNoTypeArguments);
-  __ b(&equal_cids_but_generic, NE);
-  __ b(equal);
+  __ b(equal_may_be_generic, EQ);
 
   // Class ids are different. Check if we are comparing two string types (with
   // different representations), two integer types, two list types or two type
   // types.
-  __ Bind(&different_cids);
   __ CompareImmediate(cid1, kNumPredefinedCids);
   __ b(not_equal, HI);
 
@@ -1259,7 +1244,7 @@
   JumpIfNotInteger(assembler, cid1, scratch, &not_integer);
 
   // First type is an integer. Check if the second is an integer too.
-  JumpIfInteger(assembler, cid2, scratch, equal);
+  JumpIfInteger(assembler, cid2, scratch, equal_not_generic);
   // Integer types are only equivalent to other integer types.
   __ b(not_equal);
 
@@ -1269,7 +1254,7 @@
                   testing_instance_cids ? &not_integer_or_string : not_equal);
 
   // First type is String. Check if the second is a string too.
-  JumpIfString(assembler, cid2, scratch, equal);
+  JumpIfString(assembler, cid2, scratch, equal_not_generic);
   // String types are only equivalent to other String types.
   __ b(not_equal);
 
@@ -1282,8 +1267,7 @@
     JumpIfNotList(assembler, cid2, scratch, not_equal);
     ASSERT(compiler::target::Array::type_arguments_offset() ==
            compiler::target::GrowableObjectArray::type_arguments_offset());
-    __ LoadImmediate(scratch, compiler::target::Array::type_arguments_offset());
-    __ b(&equal_cids_but_generic);
+    __ b(equal_may_be_generic);
 
     __ Bind(&not_integer_or_string_or_list);
     // Check if the first type is a Type. If it is not then types are not
@@ -1292,13 +1276,10 @@
     JumpIfNotType(assembler, cid1, scratch, not_equal);
 
     // First type is a Type. Check if the second is a Type too.
-    JumpIfType(assembler, cid2, scratch, equal);
+    JumpIfType(assembler, cid2, scratch, equal_not_generic);
     // Type types are only equivalent to other Type types.
     __ b(not_equal);
   }
-
-  // The caller must compare the type arguments.
-  __ Bind(&equal_cids_but_generic);
 }
 
 void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
@@ -1307,10 +1288,24 @@
   __ LoadClassIdMayBeSmi(R1, R1);
   __ LoadClassIdMayBeSmi(R2, R2);
 
-  Label equal, not_equal;
-  EquivalentClassIds(assembler, normal_ir_body, &equal, &not_equal, R1, R2, R0,
+  Label equal_may_be_generic, equal, not_equal;
+  EquivalentClassIds(assembler, normal_ir_body, &equal_may_be_generic, &equal,
+                     &not_equal, R1, R2, R0,
                      /* testing_instance_cids = */ true);
 
+  __ Bind(&equal_may_be_generic);
+  // Classes are equivalent and neither is a closure class.
+  // Check if there are no type arguments. In this case we can return true.
+  // Otherwise fall through into the runtime to handle comparison.
+  __ LoadClassById(R0, R1);
+  __ ldr(
+      R0,
+      FieldAddress(
+          R0,
+          target::Class::host_type_arguments_field_offset_in_words_offset()));
+  __ CompareImmediate(R0, target::Class::kNoTypeArguments);
+  __ b(&equal, EQ);
+
   // Compare type arguments, host_type_arguments_field_offset_in_words in R0.
   __ ldm(IA, SP, (1 << R1 | 1 << R2));
   __ AddImmediate(R1, -kHeapObjectTag);
@@ -1352,7 +1347,7 @@
 
 void AsmIntrinsifier::Type_equality(Assembler* assembler,
                                     Label* normal_ir_body) {
-  Label equal, not_equal, equiv_cids, check_legacy;
+  Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
 
   __ ldm(IA, SP, (1 << R1 | 1 << R2));
   __ cmp(R1, Operand(R2));
@@ -1370,9 +1365,11 @@
   __ ldr(R4, FieldAddress(R2, target::Type::type_class_id_offset()));
   __ SmiUntag(R4);
   // We are not testing instance cids, but type class cids of Type instances.
-  EquivalentClassIds(assembler, normal_ir_body, &equiv_cids, &not_equal, R3, R4,
-                     R0, /* testing_instance_cids = */ false);
+  EquivalentClassIds(assembler, normal_ir_body, &equiv_cids_may_be_generic,
+                     &equiv_cids, &not_equal, R3, R4, R0,
+                     /* testing_instance_cids = */ false);
 
+  __ Bind(&equiv_cids_may_be_generic);
   // Compare type arguments in Type instances.
   __ ldr(R3, FieldAddress(R1, target::Type::arguments_offset()));
   __ ldr(R4, FieldAddress(R2, target::Type::arguments_offset()));
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 66a1480..1b2a819 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -1355,20 +1355,19 @@
 }
 
 // Compares cid1 and cid2 to see if they're syntactically equivalent. If this
-// can be determined by this fast path, it jumps to either equal or not_equal,
-// if equal but belonging to a generic class, it falls through with the scratch
-// register containing host_type_arguments_field_offset_in_words,
-// otherwise it jumps to normal_ir_body. May clobber scratch.
+// can be determined by this fast path, it jumps to either equal_* or not_equal.
+// If classes are equivalent but may be generic, then jumps to
+// equal_may_be_generic. Clobbers scratch.
 static void EquivalentClassIds(Assembler* assembler,
                                Label* normal_ir_body,
-                               Label* equal,
+                               Label* equal_may_be_generic,
+                               Label* equal_not_generic,
                                Label* not_equal,
                                Register cid1,
                                Register cid2,
                                Register scratch,
                                bool testing_instance_cids) {
-  Label different_cids, equal_cids_but_generic, not_integer,
-      not_integer_or_string, not_integer_or_string_or_list;
+  Label not_integer, not_integer_or_string, not_integer_or_string_or_list;
 
   // Check if left hand side is a closure. Closures are handled in the runtime.
   __ CompareImmediate(cid1, kClosureCid);
@@ -1378,25 +1377,11 @@
   // considered equivalent (e.g. multiple string implementation classes map to a
   // single String type).
   __ cmp(cid1, Operand(cid2));
-  __ b(&different_cids, NE);
-
-  // Types have the same class and neither is a closure type.
-  // Check if there are no type arguments. In this case we can return true.
-  // Otherwise fall through into the runtime to handle comparison.
-  __ LoadClassById(scratch, cid1);
-  __ ldr(scratch,
-         FieldAddress(
-             scratch,
-             target::Class::host_type_arguments_field_offset_in_words_offset()),
-         kFourBytes);
-  __ CompareImmediate(scratch, target::Class::kNoTypeArguments);
-  __ b(&equal_cids_but_generic, NE);
-  __ b(equal);
+  __ b(equal_may_be_generic, EQ);
 
   // Class ids are different. Check if we are comparing two string types (with
   // different representations), two integer types, two list types or two type
   // types.
-  __ Bind(&different_cids);
   __ CompareImmediate(cid1, kNumPredefinedCids);
   __ b(not_equal, HI);
 
@@ -1404,7 +1389,7 @@
   JumpIfNotInteger(assembler, cid1, scratch, &not_integer);
 
   // First type is an integer. Check if the second is an integer too.
-  JumpIfInteger(assembler, cid2, scratch, equal);
+  JumpIfInteger(assembler, cid2, scratch, equal_not_generic);
   // Integer types are only equivalent to other integer types.
   __ b(not_equal);
 
@@ -1414,7 +1399,7 @@
                   testing_instance_cids ? &not_integer_or_string : not_equal);
 
   // First type is String. Check if the second is a string too.
-  JumpIfString(assembler, cid2, scratch, equal);
+  JumpIfString(assembler, cid2, scratch, equal_not_generic);
   // String types are only equivalent to other String types.
   __ b(not_equal);
 
@@ -1427,8 +1412,7 @@
     JumpIfNotList(assembler, cid2, scratch, not_equal);
     ASSERT(compiler::target::Array::type_arguments_offset() ==
            compiler::target::GrowableObjectArray::type_arguments_offset());
-    __ LoadImmediate(scratch, compiler::target::Array::type_arguments_offset());
-    __ b(&equal_cids_but_generic);
+    __ b(equal_may_be_generic);
 
     __ Bind(&not_integer_or_string_or_list);
     // Check if the first type is a Type. If it is not then types are not
@@ -1437,13 +1421,10 @@
     JumpIfNotType(assembler, cid1, scratch, not_equal);
 
     // First type is a Type. Check if the second is a Type too.
-    JumpIfType(assembler, cid2, scratch, equal);
+    JumpIfType(assembler, cid2, scratch, equal_not_generic);
     // Type types are only equivalent to other Type types.
     __ b(not_equal);
   }
-
-  // The caller must compare the type arguments.
-  __ Bind(&equal_cids_but_generic);
 }
 
 void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
@@ -1452,10 +1433,24 @@
   __ LoadClassIdMayBeSmi(R2, R1);
   __ LoadClassIdMayBeSmi(R1, R0);
 
-  Label equal, not_equal;
-  EquivalentClassIds(assembler, normal_ir_body, &equal, &not_equal, R1, R2, R0,
+  Label equal_may_be_generic, equal, not_equal;
+  EquivalentClassIds(assembler, normal_ir_body, &equal_may_be_generic, &equal,
+                     &not_equal, R1, R2, R0,
                      /* testing_instance_cids = */ true);
 
+  __ Bind(&equal_may_be_generic);
+  // Classes are equivalent and neither is a closure class.
+  // Check if there are no type arguments. In this case we can return true.
+  // Otherwise fall through into the runtime to handle comparison.
+  __ LoadClassById(R0, R1);
+  __ ldr(R0,
+         FieldAddress(
+             R0,
+             target::Class::host_type_arguments_field_offset_in_words_offset()),
+         kFourBytes);
+  __ CompareImmediate(R0, target::Class::kNoTypeArguments);
+  __ b(&equal, EQ);
+
   // Compare type arguments, host_type_arguments_field_offset_in_words in R0.
   __ ldp(R1, R2, Address(SP, 0 * target::kWordSize, Address::PairOffset));
   __ AddImmediate(R1, -kHeapObjectTag);
@@ -1501,7 +1496,7 @@
 
 void AsmIntrinsifier::Type_equality(Assembler* assembler,
                                     Label* normal_ir_body) {
-  Label equal, not_equal, equiv_cids, check_legacy;
+  Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
 
   __ ldp(R1, R2, Address(SP, 0 * target::kWordSize, Address::PairOffset));
   __ CompareObjectRegisters(R1, R2);
@@ -1521,9 +1516,11 @@
                        FieldAddress(R2, target::Type::type_class_id_offset()));
   __ SmiUntag(R4);
   // We are not testing instance cids, but type class cids of Type instances.
-  EquivalentClassIds(assembler, normal_ir_body, &equiv_cids, &not_equal, R3, R4,
-                     R0, /* testing_instance_cids = */ false);
+  EquivalentClassIds(assembler, normal_ir_body, &equiv_cids_may_be_generic,
+                     &equiv_cids, &not_equal, R3, R4, R0,
+                     /* testing_instance_cids = */ false);
 
+  __ Bind(&equiv_cids_may_be_generic);
   // Compare type arguments in Type instances.
   __ LoadCompressed(R3, FieldAddress(R1, target::Type::arguments_offset()));
   __ LoadCompressed(R4, FieldAddress(R2, target::Type::arguments_offset()));
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index 7cb2f54..91a1794 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -1311,20 +1311,19 @@
 }
 
 // Compares cid1 and cid2 to see if they're syntactically equivalent. If this
-// can be determined by this fast path, it jumps to either equal or not_equal,
-// if equal but belonging to a generic class, it falls through with the scratch
-// register containing host_type_arguments_field_offset_in_words,
-// otherwise it jumps to normal_ir_body. May clobber scratch.
+// can be determined by this fast path, it jumps to either equal_* or not_equal.
+// If classes are equivalent but may be generic, then jumps to
+// equal_may_be_generic. Clobbers scratch.
 static void EquivalentClassIds(Assembler* assembler,
                                Label* normal_ir_body,
-                               Label* equal,
+                               Label* equal_may_be_generic,
+                               Label* equal_not_generic,
                                Label* not_equal,
                                Register cid1,
                                Register cid2,
                                Register scratch,
                                bool testing_instance_cids) {
-  Label different_cids, equal_cids_but_generic, not_integer,
-      not_integer_or_string, not_integer_or_string_or_list;
+  Label not_integer, not_integer_or_string, not_integer_or_string_or_list;
 
   // Check if left hand side is a closure. Closures are handled in the runtime.
   __ cmpl(cid1, Immediate(kClosureCid));
@@ -1334,25 +1333,11 @@
   // considered equivalent (e.g. multiple string implementation classes map to a
   // single String type).
   __ cmpl(cid1, cid2);
-  __ j(NOT_EQUAL, &different_cids);
-
-  // Types have the same class and neither is a closure type.
-  // Check if there are no type arguments. In this case we can return true.
-  // Otherwise fall through into the runtime to handle comparison.
-  __ LoadClassById(scratch, cid1);
-  __ movl(
-      scratch,
-      FieldAddress(
-          scratch,
-          target::Class::host_type_arguments_field_offset_in_words_offset()));
-  __ cmpl(scratch, Immediate(target::Class::kNoTypeArguments));
-  __ j(NOT_EQUAL, &equal_cids_but_generic);
-  __ jmp(equal);
+  __ j(EQUAL, equal_may_be_generic);
 
   // Class ids are different. Check if we are comparing two string types (with
   // different representations), two integer types, two list types or two type
   // types.
-  __ Bind(&different_cids);
   __ cmpl(cid1, Immediate(kNumPredefinedCids));
   __ j(ABOVE_EQUAL, not_equal);
 
@@ -1362,7 +1347,7 @@
 
   // First type is an integer. Check if the second is an integer too.
   __ movl(scratch, cid2);
-  JumpIfInteger(assembler, scratch, equal);
+  JumpIfInteger(assembler, scratch, equal_not_generic);
   // Integer types are only equivalent to other integer types.
   __ jmp(not_equal);
 
@@ -1374,7 +1359,7 @@
 
   // First type is a String. Check if the second is a String too.
   __ movl(scratch, cid2);
-  JumpIfString(assembler, scratch, equal);
+  JumpIfString(assembler, scratch, equal_not_generic);
   // String types are only equivalent to other String types.
   __ jmp(not_equal);
 
@@ -1389,24 +1374,21 @@
     JumpIfNotList(assembler, scratch, not_equal);
     ASSERT(compiler::target::Array::type_arguments_offset() ==
            compiler::target::GrowableObjectArray::type_arguments_offset());
-    __ movl(scratch,
-            Immediate(compiler::target::Array::type_arguments_offset()));
-    __ jmp(&equal_cids_but_generic, Assembler::kNearJump);
+    __ jmp(equal_may_be_generic);
 
     __ Bind(&not_integer_or_string_or_list);
     // Check if the first type is a Type. If it is not then types are not
     // equivalent because they have different class ids and they are not String
     // or integer or List or Type.
-    JumpIfNotType(assembler, cid1, not_equal);
+    __ movl(scratch, cid1);
+    JumpIfNotType(assembler, scratch, not_equal);
 
     // First type is a Type. Check if the second is a Type too.
-    JumpIfType(assembler, cid2, equal);
+    __ movl(scratch, cid2);
+    JumpIfType(assembler, scratch, equal_not_generic);
     // Type types are only equivalent to other Type types.
     __ jmp(not_equal);
   }
-
-  // The caller must compare the type arguments.
-  __ Bind(&equal_cids_but_generic);
 }
 
 void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
@@ -1417,9 +1399,23 @@
   __ movl(EAX, Address(ESP, +2 * target::kWordSize));
   __ LoadClassIdMayBeSmi(EBX, EAX);
 
-  Label equal, not_equal;
-  EquivalentClassIds(assembler, normal_ir_body, &equal, &not_equal, EDI, EBX,
-                     EAX, /* testing_instance_cids = */ true);
+  Label equal_may_be_generic, equal, not_equal;
+  EquivalentClassIds(assembler, normal_ir_body, &equal_may_be_generic, &equal,
+                     &not_equal, EDI, EBX, EAX,
+                     /* testing_instance_cids = */ true);
+
+  __ Bind(&equal_may_be_generic);
+  // Classes are equivalent and neither is a closure class.
+  // Check if there are no type arguments. In this case we can return true.
+  // Otherwise fall through into the runtime to handle comparison.
+  __ LoadClassById(EAX, EDI);
+  __ movl(
+      EAX,
+      FieldAddress(
+          EAX,
+          target::Class::host_type_arguments_field_offset_in_words_offset()));
+  __ cmpl(EAX, Immediate(target::Class::kNoTypeArguments));
+  __ j(EQUAL, &equal);
 
   // Compare type arguments, host_type_arguments_field_offset_in_words in EAX.
   __ movl(EDI, Address(ESP, +1 * target::kWordSize));
@@ -1465,7 +1461,7 @@
 
 void AsmIntrinsifier::Type_equality(Assembler* assembler,
                                     Label* normal_ir_body) {
-  Label equal, not_equal, equiv_cids, check_legacy;
+  Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
 
   __ movl(EDI, Address(ESP, +1 * target::kWordSize));
   __ movl(EBX, Address(ESP, +2 * target::kWordSize));
@@ -1484,9 +1480,11 @@
   __ movl(EDX, FieldAddress(EBX, target::Type::type_class_id_offset()));
   __ SmiUntag(EDX);
   // We are not testing instance cids, but type class cids of Type instances.
-  EquivalentClassIds(assembler, normal_ir_body, &equiv_cids, &not_equal, ECX,
-                     EDX, EAX, /* testing_instance_cids = */ false);
+  EquivalentClassIds(assembler, normal_ir_body, &equiv_cids_may_be_generic,
+                     &equiv_cids, &not_equal, ECX, EDX, EAX,
+                     /* testing_instance_cids = */ false);
 
+  __ Bind(&equiv_cids_may_be_generic);
   // Compare type arguments in Type instances.
   __ movl(ECX, FieldAddress(EDI, target::Type::arguments_offset()));
   __ movl(EDX, FieldAddress(EBX, target::Type::arguments_offset()));
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 8a57264..0b84166 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -1212,20 +1212,19 @@
 }
 
 // Compares cid1 and cid2 to see if they're syntactically equivalent. If this
-// can be determined by this fast path, it jumps to either equal or not_equal,
-// if equal but belonging to a generic class, it falls through with the scratch
-// register containing host_type_arguments_field_offset_in_words,
-// otherwise it jumps to normal_ir_body. May clobber scratch.
+// can be determined by this fast path, it jumps to either equal_* or not_equal.
+// If classes are equivalent but may be generic, then jumps to
+// equal_may_be_generic. Clobbers scratch.
 static void EquivalentClassIds(Assembler* assembler,
                                Label* normal_ir_body,
-                               Label* equal,
+                               Label* equal_may_be_generic,
+                               Label* equal_not_generic,
                                Label* not_equal,
                                Register cid1,
                                Register cid2,
                                Register scratch,
                                bool testing_instance_cids) {
-  Label different_cids, equal_cids_but_generic, not_integer,
-      not_integer_or_string, not_integer_or_string_or_list;
+  Label not_integer, not_integer_or_string, not_integer_or_string_or_list;
 
   // Check if left hand side is a closure. Closures are handled in the runtime.
   __ cmpq(cid1, Immediate(kClosureCid));
@@ -1235,25 +1234,11 @@
   // considered equivalent (e.g. multiple string implementation classes map to a
   // single String type).
   __ cmpq(cid1, cid2);
-  __ j(NOT_EQUAL, &different_cids);
-
-  // Types have the same class and neither is a closure type.
-  // Check if there are no type arguments. In this case we can return true.
-  // Otherwise fall through into the runtime to handle comparison.
-  __ LoadClassById(scratch, cid1);
-  __ movl(
-      scratch,
-      FieldAddress(
-          scratch,
-          target::Class::host_type_arguments_field_offset_in_words_offset()));
-  __ cmpl(scratch, Immediate(target::Class::kNoTypeArguments));
-  __ j(NOT_EQUAL, &equal_cids_but_generic);
-  __ jmp(equal);
+  __ j(EQUAL, equal_may_be_generic);
 
   // Class ids are different. Check if we are comparing two string types (with
   // different representations), two integer types, two list types or two type
   // types.
-  __ Bind(&different_cids);
   __ cmpq(cid1, Immediate(kNumPredefinedCids));
   __ j(ABOVE_EQUAL, not_equal);
 
@@ -1263,7 +1248,7 @@
 
   // First type is an integer. Check if the second is an integer too.
   __ movq(scratch, cid2);
-  JumpIfInteger(assembler, scratch, equal);
+  JumpIfInteger(assembler, scratch, equal_not_generic);
   // Integer types are only equivalent to other integer types.
   __ jmp(not_equal);
 
@@ -1275,7 +1260,7 @@
 
   // First type is a String. Check if the second is a String too.
   __ movq(scratch, cid2);
-  JumpIfString(assembler, scratch, equal);
+  JumpIfString(assembler, scratch, equal_not_generic);
   // String types are only equivalent to other String types.
   __ jmp(not_equal);
 
@@ -1290,24 +1275,21 @@
     JumpIfNotList(assembler, scratch, not_equal);
     ASSERT(compiler::target::Array::type_arguments_offset() ==
            compiler::target::GrowableObjectArray::type_arguments_offset());
-    __ movq(scratch,
-            Immediate(compiler::target::Array::type_arguments_offset()));
-    __ jmp(&equal_cids_but_generic, Assembler::kNearJump);
+    __ jmp(equal_may_be_generic);
 
     __ Bind(&not_integer_or_string_or_list);
     // Check if the first type is a Type. If it is not then types are not
     // equivalent because they have different class ids and they are not String
     // or integer or List or Type.
-    JumpIfNotType(assembler, cid1, not_equal);
+    __ movq(scratch, cid1);
+    JumpIfNotType(assembler, scratch, not_equal);
 
     // First type is a Type. Check if the second is a Type too.
-    JumpIfType(assembler, cid2, equal);
+    __ movq(scratch, cid2);
+    JumpIfType(assembler, scratch, equal_not_generic);
     // Type types are only equivalent to other Type types.
     __ jmp(not_equal);
   }
-
-  // The caller must compare the type arguments.
-  __ Bind(&equal_cids_but_generic);
 }
 
 void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
@@ -1318,9 +1300,23 @@
   __ movq(RAX, Address(RSP, +2 * target::kWordSize));
   __ LoadClassIdMayBeSmi(RDX, RAX);
 
-  Label equal, not_equal;
-  EquivalentClassIds(assembler, normal_ir_body, &equal, &not_equal, RCX, RDX,
-                     RAX, /* testing_instance_cids = */ true);
+  Label equal_may_be_generic, equal, not_equal;
+  EquivalentClassIds(assembler, normal_ir_body, &equal_may_be_generic, &equal,
+                     &not_equal, RCX, RDX, RAX,
+                     /* testing_instance_cids = */ true);
+
+  __ Bind(&equal_may_be_generic);
+  // Classes are equivalent and neither is a closure class.
+  // Check if there are no type arguments. In this case we can return true.
+  // Otherwise fall through into the runtime to handle comparison.
+  __ LoadClassById(RAX, RCX);
+  __ movl(
+      RAX,
+      FieldAddress(
+          RAX,
+          target::Class::host_type_arguments_field_offset_in_words_offset()));
+  __ cmpl(RAX, Immediate(target::Class::kNoTypeArguments));
+  __ j(EQUAL, &equal);
 
   // Compare type arguments, host_type_arguments_field_offset_in_words in RAX.
   __ movq(RCX, Address(RSP, +1 * target::kWordSize));
@@ -1370,7 +1366,7 @@
 
 void AsmIntrinsifier::Type_equality(Assembler* assembler,
                                     Label* normal_ir_body) {
-  Label equal, not_equal, equiv_cids, check_legacy;
+  Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
 
   __ movq(RCX, Address(RSP, +1 * target::kWordSize));
   __ movq(RDX, Address(RSP, +2 * target::kWordSize));
@@ -1391,9 +1387,11 @@
                        FieldAddress(RDX, target::Type::type_class_id_offset()));
   __ SmiUntag(RSI);
   // We are not testing instance cids, but type class cids of Type instances.
-  EquivalentClassIds(assembler, normal_ir_body, &equiv_cids, &not_equal, RDI,
-                     RSI, RAX, /* testing_instance_cids = */ false);
+  EquivalentClassIds(assembler, normal_ir_body, &equiv_cids_may_be_generic,
+                     &equiv_cids, &not_equal, RDI, RSI, RAX,
+                     /* testing_instance_cids = */ false);
 
+  __ Bind(&equiv_cids_may_be_generic);
   // Compare type arguments in Type instances.
   __ LoadCompressed(RDI, FieldAddress(RCX, target::Type::arguments_offset()));
   __ LoadCompressed(RSI, FieldAddress(RDX, target::Type::arguments_offset()));
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index ac65f6d..6d300fb 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -83,12 +83,11 @@
 // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sys_icache_invalidate.3.html
 #if defined(DART_HOST_OS_IOS)
   sys_icache_invalidate(reinterpret_cast<void*>(start), size);
-#elif defined(__linux__) && !defined(ANDROID)
-  extern void __clear_cache(char*, char*);
+#elif defined(DART_HOST_OS_LINUX)
   char* beg = reinterpret_cast<char*>(start);
   char* end = reinterpret_cast<char*>(start + size);
-  ::__clear_cache(beg, end);
-#elif defined(ANDROID)
+  __builtin___clear_cache(beg, end);
+#elif defined(DART_HOST_OS_ANDROID)
   cacheflush(start, start + size, 0);
 #else
 #error FlushICache only tested/supported on Linux, Android and iOS
diff --git a/runtime/vm/cpu_arm64.cc b/runtime/vm/cpu_arm64.cc
index d193d23..23e9fee 100644
--- a/runtime/vm/cpu_arm64.cc
+++ b/runtime/vm/cpu_arm64.cc
@@ -45,10 +45,9 @@
 #if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
   sys_icache_invalidate(reinterpret_cast<void*>(start), size);
 #elif defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX)
-  extern void __clear_cache(char*, char*);
   char* beg = reinterpret_cast<char*>(start);
   char* end = reinterpret_cast<char*>(start + size);
-  ::__clear_cache(beg, end);
+  __builtin___clear_cache(beg, end);
 #elif defined(DART_HOST_OS_FUCHSIA)
   zx_status_t result = zx_cache_flush(reinterpret_cast<const void*>(start),
                                       size, ZX_CACHE_FLUSH_INSN);
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index fc47a29..bffde99 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -556,11 +556,12 @@
 
   /// Terminates the current isolate synchronously.
   ///
-  /// This operations is potentially dangerous and should be used judiciously.
-  /// The isolate stops operating *immediately*. It throws if optional [message]
-  /// does not adhere to the limitation on what can be send from one isolate to
-  /// another. It also throws if a [finalMessagePort] is associated with an
-  /// isolate spawned outside of current isolate group, spawned via [spawnUri].
+  /// This operation is potentially dangerous and should be used judiciously.
+  /// The isolate stops operating *immediately*. It throws if the optional
+  /// [message] does not adhere to the limitations on what can be sent from one
+  /// isolate to another. It also throws if a [finalMessagePort] is associated
+  /// with an isolate spawned outside of current isolate group, spawned via
+  /// [spawnUri].
   ///
   /// If successful, a call to this method does not return. Pending `finally`
   /// blocks are not executed, control flow will not go back to the event loop,
@@ -574,10 +575,10 @@
   /// the current isolate. The isolate terminates immediately after
   /// that [SendPort.send] call returns.
   ///
-  /// (If the port is a native port, one provided by [ReceivePort.sendPort]
-  /// or [RawReceivePort.sendPort], the system may be able to send this final
+  /// If the port is a native port -- one provided by [ReceivePort.sendPort] or
+  /// [RawReceivePort.sendPort] -- the system may be able to send this final
   /// message more efficiently than normal port communication between live
-  /// isolates.)
+  /// isolates.
   external static Never exit([SendPort? finalMessagePort, Object? message]);
 }
 
diff --git a/tests/language/const/constant_type_variable_error_test.dart b/tests/language/const/constant_type_variable_error_test.dart
index c0e7770..6e2438b 100644
--- a/tests/language/const/constant_type_variable_error_test.dart
+++ b/tests/language/const/constant_type_variable_error_test.dart
@@ -8,41 +8,49 @@
 // constant expressions or potentially constant type expressions.
 
 class A<X> {
-  final Object x1, x2, x3, x4, x5, x6, x7, x8, x9;
+  final Object x1, x2, x3, x4, x5, x6, x7, x8;
 
   const A()
       : x1 = const [X],
         //^
         // [analyzer] unspecified
-        // [cfe] unspecified
+        //          ^
+        // [cfe] Type variables can't be used as constants.
         x2 = const <X>[],
         //^
         // [analyzer] unspecified
-        // [cfe] unspecified
+        //          ^
+        // [cfe] Type variables can't be used as constants.
         x3 = const {X},
         //^
         // [analyzer] unspecified
-        // [cfe] unspecified
+        //          ^
+        // [cfe] Type variables can't be used as constants.
         x4 = const <X>{},
         //^
         // [analyzer] unspecified
-        // [cfe] unspecified
+        //          ^
+        // [cfe] Type variables can't be used as constants.
         x5 = const {X: null},
         //^
         // [analyzer] unspecified
-        // [cfe] unspecified
+        //          ^
+        // [cfe] Type variables can't be used as constants.
         x6 = const <X, String?>{},
         //^
         // [analyzer] unspecified
-        // [cfe] unspecified
+        //          ^
+        // [cfe] Type variables can't be used as constants.
         x7 = const B<X>(),
         //^
         // [analyzer] unspecified
-        // [cfe] unspecified
+        //           ^
+        // [cfe] Type variables can't be used as constants.
         x8 = const C(X);
   //^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  //                 ^
+  // [cfe] Type variables can't be used as constants.
 }
 
 class B<X> {
diff --git a/tools/VERSION b/tools/VERSION
index d089db4..c6199a3 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 211
+PRERELEASE 212
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/gn.py b/tools/gn.py
index cecd030..3090333 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -212,6 +212,7 @@
 
     # Use tcmalloc only when targeting Linux and when not using ASAN.
     gn_args['dart_use_tcmalloc'] = ((gn_args['target_os'] == 'linux') and
+                                    (gn_args['target_cpu'] != 'arm') and
                                     sanitizer == 'none')
 
     if gn_args['target_os'] == 'linux':