Version 2.17.0-247.0.dev

Merge commit '1f1f7dbe087c3489cbe1b63a846af71a299b4b81' into 'dev'
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 6cdb353..e0e89e3 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -1438,9 +1438,6 @@
     /// [ClassBuilder]s for the macro classes.
     Map<Uri, List<ClassBuilder>> macroLibraries = {};
 
-    /// Libraries containing precompiled macro classes.
-    Set<Uri> precompiledMacroLibraries = {};
-
     Map<Uri, Uri> precompiledMacroUris =
         target.context.options.precompiledMacroUris;
 
@@ -1457,8 +1454,6 @@
                       .macroDeclarations[libraryUri] ??= [])
                   .add(builder.name);
             }
-          } else {
-            precompiledMacroLibraries.add(libraryUri);
           }
         }
       }
@@ -1519,9 +1514,11 @@
     }
 
     for (LibraryBuilder builder in _builders.values) {
-      if (builder.loader != this) {
+      if (builder.importUri.isScheme("dart") && !builder.isSynthetic) {
+        // Assume the platform is precompiled.
         addPrecompiledLibrary(builder.importUri);
-      } else if (precompiledMacroLibraries.contains(builder.importUri)) {
+      } else if (precompiledMacroUris.containsKey(builder.importUri)) {
+        // The precompiled macros given are also precompiled.
         assert(
             !macroLibraries.containsKey(builder.importUri),
             "Macro library ${builder.importUri} is only partially "
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
index 874fc40..b64cce3 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
@@ -52,6 +52,7 @@
   ffi::Bool,
   ffi::BoolArray,
   ffi::BoolPointer,
+  ffi::Char,
   ffi::DartRepresentationOf,
   ffi::Dart_CObject,
   ffi::Double,
@@ -144,6 +145,7 @@
   ffi::Bool,
   ffi::BoolArray,
   ffi::BoolPointer,
+  ffi::Char,
   ffi::DartRepresentationOf,
   ffi::Dart_CObject,
   ffi::Double,
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
index 6fb54df..e760406 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
@@ -52,6 +52,7 @@
   ffi::Bool,
   ffi::BoolArray,
   ffi::BoolPointer,
+  ffi::Char,
   ffi::DartRepresentationOf,
   ffi::Dart_CObject,
   ffi::Double,
@@ -144,6 +145,7 @@
   ffi::Bool,
   ffi::BoolArray,
   ffi::BoolPointer,
+  ffi::Char,
   ffi::DartRepresentationOf,
   ffi::Dart_CObject,
   ffi::Double,
diff --git a/pkg/kernel/lib/src/standard_bounds.dart b/pkg/kernel/lib/src/standard_bounds.dart
index d929862..6da56b3 100644
--- a/pkg/kernel/lib/src/standard_bounds.dart
+++ b/pkg/kernel/lib/src/standard_bounds.dart
@@ -1223,12 +1223,12 @@
       //     where B1a is the greatest closure of B1 with respect to X1,
       //     as defined in [inference.md].
       if (isSubtypeOf(type1, type2, SubtypeCheckMode.withNullabilities)) {
-        return type2.withDeclaredNullability(uniteNullabilities(
-            type1.declaredNullability, type2.declaredNullability));
+        return type2.withDeclaredNullability(
+            uniteNullabilities(type1.declaredNullability, type2.nullability));
       }
       if (isSubtypeOf(type2, type1, SubtypeCheckMode.withNullabilities)) {
-        return type1.withDeclaredNullability(uniteNullabilities(
-            type1.declaredNullability, type2.declaredNullability));
+        return type1.withDeclaredNullability(
+            uniteNullabilities(type1.declaredNullability, type2.nullability));
       }
       NullabilityAwareTypeVariableEliminator eliminator =
           new NullabilityAwareTypeVariableEliminator(
@@ -1244,7 +1244,7 @@
           .withDeclaredNullability(uniteNullabilities(
               type1.declaredNullability,
               uniteNullabilities(type1.parameter.bound.declaredNullability,
-                  type2.declaredNullability)));
+                  type2.nullability)));
     } else {
       // UP(X1 & B1, T2) =
       //   T2 if X1 <: T2
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index c0acbff..83239a8 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -6271,6 +6271,38 @@
 #endif
 }
 
+ASSEMBLER_TEST_GENERATE(MoveByteRunTest, assembler) {
+  __ pushq(Immediate(0x1234567887654321));
+  // RAX / AL
+  __ xorq(CallingConventions::kReturnReg, CallingConventions::kReturnReg);
+  __ movb(ByteRegisterOf(CallingConventions::kReturnReg), Address(RSP, 0));
+  // RBX / BH
+  __ pushq(RBX);
+  __ xorq(RBX, RBX);
+  __ movb(BH, Address(RSP, target::kWordSize));
+  __ shrq(RBX, Immediate(8));
+  __ addq(CallingConventions::kReturnReg, RBX);
+  __ popq(RBX);
+  // R8 / R8B
+  ASSERT((CallingConventions::kVolatileCpuRegisters & (1 << R8)) != 0);
+  __ xorq(R8, R8);
+  __ movb(R8B, Address(RSP, 0));
+  __ addq(CallingConventions::kReturnReg, R8);
+  // RDI / DIL
+  __ pushq(RDI);
+  __ xorq(RDI, RDI);
+  __ movb(DIL, Address(RSP, target::kWordSize));
+  __ addq(CallingConventions::kReturnReg, RDI);
+  __ popq(RDI);
+  __ Drop(1);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(MoveByteRunTest, test) {
+  intptr_t res = test->InvokeWithCodeAndThread<intptr_t>();
+  EXPECT_EQ(0x21 + 0x21 + 0x21 + 0x21, res);
+}
+
 }  // namespace compiler
 }  // namespace dart
 
diff --git a/runtime/vm/type_testing_stubs_test.cc b/runtime/vm/type_testing_stubs_test.cc
index fe904d0..6d3d94b 100644
--- a/runtime/vm/type_testing_stubs_test.cc
+++ b/runtime/vm/type_testing_stubs_test.cc
@@ -2303,7 +2303,7 @@
 // during the checks that the instantiation of Y is int.
 ISOLATE_UNIT_TEST_CASE(TTS_Regress_CidRangeChecks) {
   // Bump this appropriately if the EXPECT_EQ below fails.
-  const intptr_t kNumUnrelated = 1185;
+  const intptr_t kNumUnrelated = 1186;
   TextBuffer buffer(1024);
   buffer.AddString(R"(
       abstract class B<X> {}
diff --git a/sdk/lib/ffi/c_type.dart b/sdk/lib/ffi/c_type.dart
index 5edffad..f6b7d8c 100644
--- a/sdk/lib/ffi/c_type.dart
+++ b/sdk/lib/ffi/c_type.dart
@@ -9,6 +9,44 @@
 /// these C types in this library.
 part of dart.ffi;
 
+/// The C `char` type.
+///
+/// Typically a signed or unsigned 8-bit integer.
+/// For a guaranteed 8-bit integer, use [Int8] with the C `int8_t` type
+/// or [Uint8] with the C `uint8_t` type.
+/// For a specifically `signed` or `unsigned` `char`, use [SignedChar] or
+/// [UnsignedChar].
+///
+/// The [Char] type is a native type, and should not be constructed in
+/// Dart code.
+/// It occurs only in native type signatures and as annotation on [Struct] and
+/// [Union] fields.
+@AbiSpecificIntegerMapping({
+  Abi.androidArm: Uint8(),
+  Abi.androidArm64: Uint8(),
+  Abi.androidIA32: Uint8(),
+  Abi.androidX64: Uint8(),
+  Abi.fuchsiaArm64: Int8(),
+  Abi.fuchsiaX64: Int8(),
+  Abi.iosArm: Uint8(),
+  Abi.iosArm64: Int8(),
+  Abi.iosX64: Int8(),
+  Abi.linuxArm: Uint8(),
+  Abi.linuxArm64: Int8(),
+  Abi.linuxIA32: Int8(),
+  Abi.linuxX64: Int8(),
+  Abi.linuxRiscv32: Int8(),
+  Abi.linuxRiscv64: Int8(),
+  Abi.macosArm64: Int8(),
+  Abi.macosX64: Int8(),
+  Abi.windowsArm64: Int8(),
+  Abi.windowsIA32: Int8(),
+  Abi.windowsX64: Int8(),
+})
+class Char extends AbiSpecificInteger {
+  const Char();
+}
+
 /// The C `signed char` type.
 ///
 /// Typically a signed 8-bit integer.
diff --git a/tests/ffi/c_types_test.dart b/tests/ffi/c_types_test.dart
index c132f3b..3c2e815 100644
--- a/tests/ffi/c_types_test.dart
+++ b/tests/ffi/c_types_test.dart
@@ -64,6 +64,11 @@
   String toString() => cRepresentation;
 }
 
+final char = CType(
+  sizeOf<Char>(),
+  'char',
+  ffiLoad: (Pointer p) => p.cast<Char>().value,
+);
 final uchar = CType(
   sizeOf<UnsignedChar>(),
   'char',
@@ -137,6 +142,7 @@
 );
 
 final cTypes = [
+  char,
   uchar,
   schar,
   short,
diff --git a/tests/ffi_2/c_types_test.dart b/tests/ffi_2/c_types_test.dart
index 032853c..7a651ce 100644
--- a/tests/ffi_2/c_types_test.dart
+++ b/tests/ffi_2/c_types_test.dart
@@ -66,6 +66,11 @@
   String toString() => cRepresentation;
 }
 
+final char = CType(
+  sizeOf<Char>(),
+  'char',
+  ffiLoad: (Pointer p) => p.cast<Char>().value,
+);
 final uchar = CType(
   sizeOf<UnsignedChar>(),
   'char',
@@ -139,6 +144,7 @@
 );
 
 final cTypes = [
+  char,
   uchar,
   schar,
   short,
diff --git a/tests/lib/mirrors/invocation_fuzz_test.dart b/tests/lib/mirrors/invocation_fuzz_test.dart
index ed8ba09..13aec04 100644
--- a/tests/lib/mirrors/invocation_fuzz_test.dart
+++ b/tests/lib/mirrors/invocation_fuzz_test.dart
@@ -38,6 +38,10 @@
   // Don't call private methods in dart.async as they may circumvent the zoned
   // error handling below.
   new RegExp(r"^dart\.async\._.*$"),
+
+  // Don't try to invoke FFI Natives on simulator.
+  // TODO(http://dartbug.com/48365): Support FFI in simulators.
+  'dart._internal.FinalizerEntry.setExternalSize',
 ];
 
 bool isDenylisted(Symbol qualifiedSymbol) {
diff --git a/tests/lib_2/mirrors/invocation_fuzz_test.dart b/tests/lib_2/mirrors/invocation_fuzz_test.dart
index 68360d1..d81a174 100644
--- a/tests/lib_2/mirrors/invocation_fuzz_test.dart
+++ b/tests/lib_2/mirrors/invocation_fuzz_test.dart
@@ -40,6 +40,10 @@
   // Don't call private methods in dart.async as they may circumvent the zoned
   // error handling below.
   new RegExp(r"^dart\.async\._.*$"),
+
+  // Don't try to invoke FFI Natives on simulator.
+  // TODO(http://dartbug.com/48365): Support FFI in simulators.
+  'dart._internal.FinalizerEntry.setExternalSize',
 ];
 
 bool isDenylisted(Symbol qualifiedSymbol) {
diff --git a/tools/VERSION b/tools/VERSION
index 02e0b9d..7ea497f3 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 246
+PRERELEASE 247
 PRERELEASE_PATCH 0
\ No newline at end of file