Version 2.17.0-238.0.dev

Merge commit 'e3c1042d74a556796ecedd3cbad32cf7abb0e521' into 'dev'
diff --git a/pkg/analyzer/lib/dart/analysis/analysis_options.dart b/pkg/analyzer/lib/dart/analysis/analysis_options.dart
new file mode 100644
index 0000000..3f961bb
--- /dev/null
+++ b/pkg/analyzer/lib/dart/analysis/analysis_options.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2014, 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.
+
+import 'dart:typed_data';
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/source/error_processor.dart';
+import 'package:analyzer/src/services/lint.dart';
+import 'package:pub_semver/src/version_constraint.dart';
+
+/// A set of analysis options used to control the behavior of an analysis
+/// context.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class AnalysisOptions {
+  /// A flag indicating whether to run checks on AndroidManifest.xml file to
+  /// see if it is complaint with Chrome OS.
+  bool get chromeOsManifestChecks;
+
+  /// The set of features that are globally enabled for this context.
+  FeatureSet get contextFeatures;
+
+  /// Return a list of the names of the packages for which, if they define a
+  /// plugin, the plugin should be enabled.
+  List<String> get enabledPluginNames;
+
+  /// Return a list of error processors that are to be used when reporting
+  /// errors in some analysis context.
+  List<ErrorProcessor> get errorProcessors;
+
+  /// Return a list of exclude patterns used to exclude some sources from
+  /// analysis.
+  List<String> get excludePatterns;
+
+  /// Return `true` if analysis is to generate hint results (e.g. type inference
+  /// based information and pub best practices).
+  bool get hint;
+
+  /// Return `true` if analysis is to generate lint warnings.
+  bool get lint;
+
+  /// Return a list of the lint rules that are to be run in an analysis context
+  /// if [lint] returns `true`.
+  List<Linter> get lintRules;
+
+  /// The version range for the SDK specified in `pubspec.yaml`, or `null` if
+  /// there is no `pubspec.yaml` or if it does not contain an SDK range.
+  VersionConstraint? get sdkVersionConstraint;
+
+  /// Return the opaque signature of the options.
+  Uint32List get signature;
+
+  /// Return `true` the lint with the given [name] is enabled.
+  bool isLintEnabled(String name);
+
+  /// Determine whether two signatures returned by [signature] are equal.
+  static bool signaturesEqual(Uint32List a, Uint32List b) {
+    if (a.length != b.length) {
+      return false;
+    }
+    for (int i = 0; i < a.length; i++) {
+      if (a[i] != b[i]) {
+        return false;
+      }
+    }
+    return true;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
index a645d81..6867d3b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
@@ -171,26 +171,10 @@
         contextType: contextType,
         whyNotPromotedList: whyNotPromotedList,
         identicalInfo: identicalInfo,
-        substitution: substitution);
+        substitution: substitution,
+        inferrer: inferrer);
 
     if (inferrer != null) {
-      // Get the parameters that correspond to the uninstantiated generic.
-      List<ParameterElement?> rawParameters =
-          ResolverVisitor.resolveArgumentsToParameters(
-        argumentList: argumentList,
-        parameters: rawType!.parameters,
-      );
-
-      List<ParameterElement> params = <ParameterElement>[];
-      List<DartType> argTypes = <DartType>[];
-      for (int i = 0, length = rawParameters.length; i < length; i++) {
-        ParameterElement? parameter = rawParameters[i];
-        if (parameter != null) {
-          params.add(parameter);
-          argTypes.add(argumentList.arguments[i].typeOrThrow);
-        }
-      }
-      inferrer.constrainArguments(parameters: params, argumentTypes: argTypes);
       typeArgumentTypes = inferrer.upwardsInfer();
     }
     FunctionType? invokeType = typeArgumentTypes != null
@@ -398,7 +382,8 @@
       required DartType? contextType,
       required List<WhyNotPromotedGetter> whyNotPromotedList,
       List<EqualityInfo<PromotableElement, DartType>?>? identicalInfo,
-      Substitution? substitution}) {
+      Substitution? substitution,
+      GenericInferrer? inferrer}) {
     assert(whyNotPromotedList.isEmpty);
     var parameters = rawType?.parameters;
     var namedParameters = <String, ParameterElement>{};
@@ -445,6 +430,10 @@
             ?.add(flow.equalityOperand_end(argument, argument.typeOrThrow));
         whyNotPromotedList.add(flow.whyNotPromoted(argument));
       }
+      if (parameter != null) {
+        inferrer?.constrainArgument(
+            argument.typeOrThrow, parameter.type, parameter.name);
+      }
     }
   }
 
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index bc9aba5..6f6bf17 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -5,6 +5,7 @@
 import 'dart:typed_data';
 
 import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart';
+import 'package:analyzer/dart/analysis/analysis_options.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
@@ -16,6 +17,7 @@
 import 'package:analyzer/src/summary/api_signature.dart';
 import 'package:pub_semver/pub_semver.dart';
 
+export 'package:analyzer/dart/analysis/analysis_options.dart';
 export 'package:analyzer/error/listener.dart' show RecordingErrorListener;
 export 'package:analyzer/src/generated/timestamped_data.dart'
     show TimestampedData;
@@ -148,69 +150,6 @@
 
 /// A set of analysis options used to control the behavior of an analysis
 /// context.
-abstract class AnalysisOptions {
-  /// A flag indicating whether to run checks on AndroidManifest.xml file to
-  /// see if it is complaint with Chrome OS.
-  bool get chromeOsManifestChecks;
-
-  /// The set of features that are globally enabled for this context.
-  FeatureSet get contextFeatures;
-
-  /// Return a list of the names of the packages for which, if they define a
-  /// plugin, the plugin should be enabled.
-  List<String> get enabledPluginNames;
-
-  /// Return `true` if timing data should be gathered during execution.
-  bool get enableTiming;
-
-  /// Return a list of error processors that are to be used when reporting
-  /// errors in some analysis context.
-  List<ErrorProcessor> get errorProcessors;
-
-  /// Return a list of exclude patterns used to exclude some sources from
-  /// analysis.
-  List<String> get excludePatterns;
-
-  /// Return `true` if analysis is to generate hint results (e.g. type inference
-  /// based information and pub best practices).
-  bool get hint;
-
-  /// Return `true` if analysis is to generate lint warnings.
-  bool get lint;
-
-  /// Return a list of the lint rules that are to be run in an analysis context
-  /// if [lint] returns `true`.
-  List<Linter> get lintRules;
-
-  /// The version range for the SDK specified in `pubspec.yaml`, or `null` if
-  /// there is no `pubspec.yaml` or if it does not contain an SDK range.
-  VersionConstraint? get sdkVersionConstraint;
-
-  /// Return the opaque signature of the options.
-  Uint32List get signature;
-
-  /// Return `true` if analyzer should use the Dart 2.0 Front End parser.
-  bool get useFastaParser;
-
-  /// Return `true` the lint with the given [name] is enabled.
-  bool isLintEnabled(String name);
-
-  /// Determine whether two signatures returned by [signature] are equal.
-  static bool signaturesEqual(Uint32List a, Uint32List b) {
-    if (a.length != b.length) {
-      return false;
-    }
-    for (int i = 0; i < a.length; i++) {
-      if (a[i] != b[i]) {
-        return false;
-      }
-    }
-    return true;
-  }
-}
-
-/// A set of analysis options used to control the behavior of an analysis
-/// context.
 class AnalysisOptionsImpl implements AnalysisOptions {
   /// The cached [unlinkedSignature].
   Uint32List? _unlinkedSignature;
@@ -246,7 +185,7 @@
   @override
   List<String> enabledPluginNames = const <String>[];
 
-  @override
+  /// Return `true` if timing data should be gathered during execution.
   bool enableTiming = false;
 
   /// A list of error processors that are to be used when reporting errors in
@@ -266,9 +205,6 @@
   /// `true`.
   List<Linter>? _lintRules;
 
-  @override
-  bool useFastaParser = true;
-
   /// A flag indicating whether implicit casts are allowed in [strongMode]
   /// (they are always allowed in Dart 1.0 mode).
   ///
@@ -320,14 +256,13 @@
   AnalysisOptionsImpl.from(AnalysisOptions options) {
     contextFeatures = options.contextFeatures;
     enabledPluginNames = options.enabledPluginNames;
-    enableTiming = options.enableTiming;
     errorProcessors = options.errorProcessors;
     excludePatterns = options.excludePatterns;
     hint = options.hint;
     lint = options.lint;
     lintRules = options.lintRules;
-    useFastaParser = options.useFastaParser;
     if (options is AnalysisOptionsImpl) {
+      enableTiming = options.enableTiming;
       implicitCasts = options.implicitCasts;
       implicitDynamic = options.implicitDynamic;
       propagateLinterExceptions = options.propagateLinterExceptions;
@@ -393,7 +328,6 @@
       buffer.addBool(strictCasts);
       buffer.addBool(strictInference);
       buffer.addBool(strictRawTypes);
-      buffer.addBool(useFastaParser);
 
       // Append features.
       buffer.addInt(ExperimentStatus.knownFeatures.length);
@@ -449,9 +383,6 @@
     if (_unlinkedSignature == null) {
       ApiSignature buffer = ApiSignature();
 
-      // Append boolean flags.
-      buffer.addBool(useFastaParser);
-
       // Append the current language version.
       buffer.addInt(ExperimentStatus.currentVersion.major);
       buffer.addInt(ExperimentStatus.currentVersion.minor);
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index e2bf8ca..2cb8c14 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -134,6 +134,8 @@
           unitInfo.genericTypeAliases,
           _applyToGenericTypeAlias,
         );
+      } else {
+        unitElement.lineInfo = LineInfo([0]);
       }
     }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index f6e1433..b5bbf7d 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -95,7 +95,6 @@
   }
 
   AnalysisOptionsImpl createAnalysisOptions() => AnalysisOptionsImpl()
-    ..useFastaParser = true
     ..contextFeatures = FeatureSet.latestLanguageVersion();
 
   int findOffset(String search) {
diff --git a/pkg/dev_compiler/lib/src/js_ast/builder.dart b/pkg/dev_compiler/lib/src/js_ast/builder.dart
index 8044d9f..a7ba76a 100644
--- a/pkg/dev_compiler/lib/src/js_ast/builder.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/builder.dart
@@ -1618,7 +1618,7 @@
     return Try(body, catchPart, finallyPart);
   }
 
-  SwitchCase parseSwitchClause() {
+  SwitchClause parseSwitchClause() {
     Expression expression;
     if (acceptString('case')) {
       expression = parseExpression();
@@ -1635,7 +1635,9 @@
         lastToken != 'default') {
       statements.add(parseStatement());
     }
-    return SwitchCase(expression, Block(statements));
+    return expression == null
+        ? Default(Block(statements))
+        : Case(expression, Block(statements));
   }
 
   Statement parseWhile() {
@@ -1662,7 +1664,7 @@
     Expression key = parseExpression();
     expectCategory(RPAREN);
     expectCategory(LBRACE);
-    var clauses = <SwitchCase>[];
+    var clauses = <SwitchClause>[];
     while (lastCategory != RBRACE) {
       clauses.add(parseSwitchClause());
     }
diff --git a/pkg/dev_compiler/lib/src/js_ast/nodes.dart b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
index 6155510..70ff407 100644
--- a/pkg/dev_compiler/lib/src/js_ast/nodes.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
@@ -37,7 +37,8 @@
   T visitTry(Try node);
   T visitCatch(Catch node);
   T visitSwitch(Switch node);
-  T visitSwitchCase(SwitchCase node);
+  T visitCase(Case node);
+  T visitDefault(Default node);
   T visitFunctionDeclaration(FunctionDeclaration node);
   T visitLabeledStatement(LabeledStatement node);
   T visitLiteralStatement(LiteralStatement node);
@@ -159,7 +160,9 @@
   @override
   T visitCatch(Catch node) => visitNode(node);
   @override
-  T visitSwitchCase(SwitchCase node) => visitNode(node);
+  T visitCase(Case node) => visitNode(node);
+  @override
+  T visitDefault(Default node) => visitNode(node);
 
   T visitExpression(Expression node) => visitNode(node);
 
@@ -775,7 +778,7 @@
 
 class Switch extends Statement {
   final Expression key;
-  final List<SwitchCase> cases;
+  final List<SwitchClause> cases;
 
   Switch(this.key, this.cases);
 
@@ -794,26 +797,43 @@
   Switch _clone() => Switch(key, cases);
 }
 
-class SwitchCase extends Node {
-  final Expression expression;
+abstract class SwitchClause extends Node {
   final Block body;
 
-  SwitchCase(this.expression, this.body);
-  SwitchCase.defaultCase(this.body) : expression = null;
+  SwitchClause(this.body);
+}
 
-  bool get isDefault => expression == null;
+class Case extends SwitchClause {
+  final Expression expression;
+
+  Case(this.expression, Block body) : super(body);
 
   @override
-  T accept<T>(NodeVisitor<T> visitor) => visitor.visitSwitchCase(this);
+  T accept<T>(NodeVisitor<T> visitor) => visitor.visitCase(this);
 
   @override
   void visitChildren(NodeVisitor visitor) {
-    expression?.accept(visitor);
+    expression.accept(visitor);
     body.accept(visitor);
   }
 
   @override
-  SwitchCase _clone() => SwitchCase(expression, body);
+  Case _clone() => Case(expression, body);
+}
+
+class Default extends SwitchClause {
+  Default(Block body) : super(body);
+
+  @override
+  T accept<T>(NodeVisitor<T> visitor) => visitor.visitDefault(this);
+
+  @override
+  void visitChildren(NodeVisitor visitor) {
+    body.accept(visitor);
+  }
+
+  @override
+  Default _clone() => Default(body);
 }
 
 class FunctionDeclaration extends Statement {
diff --git a/pkg/dev_compiler/lib/src/js_ast/printer.dart b/pkg/dev_compiler/lib/src/js_ast/printer.dart
index 357dee6..1c5767b 100644
--- a/pkg/dev_compiler/lib/src/js_ast/printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/printer.dart
@@ -11,6 +11,7 @@
 // ignore_for_file: prefer_final_fields
 // ignore_for_file: prefer_initializing_formals
 // ignore_for_file: prefer_interpolation_to_compose_strings
+// ignore_for_file: prefer_is_not_empty
 // ignore_for_file: prefer_single_quotes
 // ignore_for_file: unnecessary_const
 // ignore_for_file: use_function_type_syntax_for_parameters
@@ -563,18 +564,26 @@
   }
 
   @override
-  visitSwitchCase(SwitchCase node) {
-    if (node.isDefault) {
-      outIndentLn("default:");
-    } else {
-      outIndent("case");
-      pendingSpace = true;
-      visitNestedExpression(node.expression, EXPRESSION,
-          newInForInit: false, newAtStatementBegin: false);
-      outLn(":");
+  visitCase(Case node) {
+    outIndent("case");
+    pendingSpace = true;
+    visitNestedExpression(node.expression, EXPRESSION,
+        newInForInit: false, newAtStatementBegin: false);
+    outLn(":");
+    if (!node.body.statements.isEmpty) {
+      indentMore();
+      blockOutWithoutBraces(node.body);
+      indentLess();
     }
-    if (node.body.statements.isNotEmpty) {
-      blockOut(node.body, true, true);
+  }
+
+  @override
+  visitDefault(Default node) {
+    outIndentLn("default:");
+    if (!node.body.statements.isEmpty) {
+      indentMore();
+      blockOutWithoutBraces(node.body);
+      indentLess();
     }
   }
 
@@ -1589,7 +1598,9 @@
   @override
   bool visitSwitch(Switch node) => false;
   @override
-  bool visitSwitchCase(SwitchCase node) => false;
+  bool visitCase(Case node) => false;
+  @override
+  bool visitDefault(Default node) => false;
   @override
   bool visitFunctionDeclaration(FunctionDeclaration node) => false;
   @override
diff --git a/pkg/dev_compiler/lib/src/js_ast/template.dart b/pkg/dev_compiler/lib/src/js_ast/template.dart
index dd51310..792d32b 100644
--- a/pkg/dev_compiler/lib/src/js_ast/template.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/template.dart
@@ -497,17 +497,25 @@
   @override
   Instantiator<Switch> visitSwitch(Switch node) {
     var makeKey = visit(node.key) as Instantiator<Expression>;
-    var makeCases = node.cases.map(visitSwitchCase).toList();
+    var makeCases =
+        node.cases.map((c) => visit(c) as Instantiator<SwitchClause>);
     return (a) => Switch(makeKey(a), makeCases.map((m) => m(a)).toList());
   }
 
   @override
-  Instantiator<SwitchCase> visitSwitchCase(SwitchCase node) {
-    var makeExpression =
-        visitNullable(node.expression) as Instantiator<Expression>;
+  Instantiator visitCase(Case node) {
+    var makeExpression = visit(node.expression) as Instantiator<Expression>;
     var makeBody = visit(node.body) as Instantiator<Block>;
     return (arguments) {
-      return SwitchCase(makeExpression(arguments), makeBody(arguments));
+      return Case(makeExpression(arguments), makeBody(arguments));
+    };
+  }
+
+  @override
+  Instantiator visitDefault(Default node) {
+    var makeBody = visit(node.body) as Instantiator<Block>;
+    return (arguments) {
+      return Default(makeBody(arguments));
     };
   }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 29d4048..adb167d 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -4279,7 +4279,7 @@
     var previous = _inLabeledContinueSwitch;
     _inLabeledContinueSwitch = hasLabeledContinue(node);
 
-    var cases = <js_ast.SwitchCase>[];
+    var cases = <js_ast.SwitchClause>[];
 
     if (_inLabeledContinueSwitch) {
       var labelState = _emitTemporaryId('labelState');
@@ -4320,13 +4320,13 @@
 
   /// Helper for visiting a SwitchCase statement.
   ///
-  /// lastSwitchCase is only used when the current switch statement contains
+  /// [lastSwitchCase] is only used when the current switch statement contains
   /// labeled continues. Dart permits the final case to implicitly break, but
   /// switch statements with labeled continues must explicitly break/continue
   /// to escape the surrounding infinite loop.
-  List<js_ast.SwitchCase> _visitSwitchCase(SwitchCase node,
+  List<js_ast.SwitchClause> _visitSwitchCase(SwitchCase node,
       {bool lastSwitchCase = false}) {
-    var cases = <js_ast.SwitchCase>[];
+    var cases = <js_ast.SwitchClause>[];
     var emptyBlock = js_ast.Block.empty();
     // TODO(jmesserly): make sure we are statically checking fall through
     var body = _visitStatement(node.body).toBlock();
@@ -4335,10 +4335,10 @@
         expressions.isNotEmpty && !node.isDefault ? expressions.last : null;
     for (var e in expressions) {
       var jsExpr = _visitExpression(e);
-      cases.add(js_ast.SwitchCase(jsExpr, e == lastExpr ? body : emptyBlock));
+      cases.add(js_ast.Case(jsExpr, e == lastExpr ? body : emptyBlock));
     }
     if (node.isDefault) {
-      cases.add(js_ast.SwitchCase.defaultCase(body));
+      cases.add(js_ast.Default(body));
     }
     // Switch statements with continue labels must explicitly break from their
     // last case to escape the additional loop around the switch.
@@ -4347,7 +4347,10 @@
       assert(_switchLabelStates.containsKey(node.parent));
       var breakStmt = js_ast.Break(_switchLabelStates[node.parent].label);
       var switchBody = js_ast.Block(cases.last.body.statements..add(breakStmt));
-      var updatedSwitch = js_ast.SwitchCase(cases.last.expression, switchBody);
+      var lastCase = cases.last;
+      var updatedSwitch = lastCase is js_ast.Case
+          ? js_ast.Case(lastCase.expression, switchBody)
+          : js_ast.Default(switchBody);
       cases.removeLast();
       cases.add(updatedSwitch);
     }
diff --git a/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart b/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart
index c3ff180..f926b9d 100644
--- a/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart
+++ b/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart
@@ -16,10 +16,10 @@
   Abi.iosX64: Uint32(),
   Abi.linuxArm: Uint32(),
   Abi.linuxArm64: Uint32(),
-  Abi.linuxIA32: Uint32(),
-  Abi.linuxX64: Uint32(),
-  Abi.linuxRiscv32: Uint32(),
-  Abi.linuxRiscv64: Uint32(),
+  Abi.linuxIA32: Int32(),
+  Abi.linuxX64: Int32(),
+  Abi.linuxRiscv32: Int32(),
+  Abi.linuxRiscv64: Int32(),
   Abi.macosArm64: Uint32(),
   Abi.macosX64: Uint32(),
   Abi.windowsArm64: Uint16(),
diff --git a/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart.expect b/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart.expect
index 63b991b..b3b2291 100644
--- a/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart.expect
+++ b/pkg/vm/testcases/transformations/ffi/abi_specific_int.dart.expect
@@ -7,17 +7,17 @@
 
 import "dart:ffi";
 
-@#C55
-@#C62
+@#C56
+@#C64
 class WChar extends ffi::AbiSpecificInteger /*hasConstConstructor*/  {
   const constructor •() → self::WChar
     : super ffi::AbiSpecificInteger::•()
     ;
-  @#C65
+  @#C67
   static get #sizeOf() → core::int*
-    return #C67.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+    return #C69.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
 }
-@#C72
+@#C74
 class WCharStruct extends ffi::Struct {
   synthetic constructor •() → self::WCharStruct
     : super ffi::Struct::•()
@@ -25,23 +25,23 @@
   constructor #fromTypedDataBase(core::Object #typedDataBase) → self::WCharStruct
     : super ffi::Struct::_fromTypedDataBase(#typedDataBase)
     ;
-  @#C73
+  @#C75
   get a0() → core::int
-    return ffi::_loadAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C74.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
-  @#C73
+    return ffi::_loadAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C76.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
+  @#C75
   set a0(core::int #externalFieldValue) → void
-    return ffi::_storeAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C74.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
-  @#C73
+    return ffi::_storeAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C76.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
+  @#C75
   get a1() → core::int
-    return ffi::_loadAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C67.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
-  @#C73
+    return ffi::_loadAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C69.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
+  @#C75
   set a1(core::int #externalFieldValue) → void
-    return ffi::_storeAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C67.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
-  @#C65
+    return ffi::_storeAbiSpecificInt<self::WChar>(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C69.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue);
+  @#C67
   static get #sizeOf() → core::int*
-    return #C76.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+    return #C78.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
 }
-@#C81
+@#C83
 class WCharArrayStruct extends ffi::Struct {
   synthetic constructor •() → self::WCharArrayStruct
     : super ffi::Struct::•()
@@ -49,31 +49,31 @@
   constructor #fromTypedDataBase(core::Object #typedDataBase) → self::WCharArrayStruct
     : super ffi::Struct::_fromTypedDataBase(#typedDataBase)
     ;
-  @#C82
+  @#C84
   get a0() → ffi::Array<self::WChar>
     return new ffi::Array::_<self::WChar>( block {
       core::Object #typedDataBase = this.{ffi::_Compound::_typedDataBase}{core::Object};
-      core::int #offset = #C74.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
-    } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} ffi::_fromAddress<self::WChar>(#typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}(#typedData.{typ::TypedData::offsetInBytes}{core::int}.{core::num::+}(#offset){(core::num) → core::num}, #C86.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}){([core::int, core::int?]) → typ::Uint8List}, #C77, #C87);
-  @#C82
+      core::int #offset = #C76.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+    } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} ffi::_fromAddress<self::WChar>(#typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}(#typedData.{typ::TypedData::offsetInBytes}{core::int}.{core::num::+}(#offset){(core::num) → core::num}, #C88.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}){([core::int, core::int?]) → typ::Uint8List}, #C79, #C89);
+  @#C84
   set a0(ffi::Array<self::WChar> #externalFieldValue) → void
-    return ffi::_memCopy(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C74.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue.{ffi::Array::_typedDataBase}{core::Object}, #C1, #C86.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
-  @#C65
+    return ffi::_memCopy(this.{ffi::_Compound::_typedDataBase}{core::Object}, #C76.{core::List::[]}(ffi::_abi()){(core::int) → core::int*}, #externalFieldValue.{ffi::Array::_typedDataBase}{core::Object}, #C1, #C88.{core::List::[]}(ffi::_abi()){(core::int) → core::int*});
+  @#C67
   static get #sizeOf() → core::int*
-    return #C86.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
+    return #C88.{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
 }
 class _DummyAllocator extends core::Object implements ffi::Allocator /*hasConstConstructor*/  {
   const constructor •() → self::_DummyAllocator
     : super core::Object::•()
     ;
-  @#C88
-  method allocate<T extends ffi::NativeType>(core::int byteCount, {core::int? alignment = #C64}) → ffi::Pointer<self::_DummyAllocator::allocate::T> {
+  @#C90
+  method allocate<T extends ffi::NativeType>(core::int byteCount, {core::int? alignment = #C66}) → ffi::Pointer<self::_DummyAllocator::allocate::T> {
     return ffi::Pointer::fromAddress<self::_DummyAllocator::allocate::T>(0);
   }
-  @#C88
+  @#C90
   method free(ffi::Pointer<ffi::NativeType> pointer) → void {}
 }
-static const field self::_DummyAllocator noAlloc = #C89;
+static const field self::_DummyAllocator noAlloc = #C91;
 static method main() → void {
   self::testSizeOf();
   self::testStoreLoad();
@@ -86,29 +86,29 @@
   core::print(size);
 }
 static method testStoreLoad() → void {
-  final ffi::Pointer<self::WChar> p = #C89.{ffi::Allocator::allocate}<self::WChar>(self::WChar::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WChar>};
+  final ffi::Pointer<self::WChar> p = #C91.{ffi::Allocator::allocate}<self::WChar>(self::WChar::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WChar>};
   ffi::_storeAbiSpecificInt<self::WChar>(p, #C1, 10);
   core::print(ffi::_loadAbiSpecificInt<self::WChar>(p, #C1));
-  #C89.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
+  #C91.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
 }
 static method testStoreLoadIndexed() → void {
-  final ffi::Pointer<self::WChar> p = #C89.{ffi::Allocator::allocate}<self::WChar>(2.{core::num::*}(self::WChar::#sizeOf){(core::num) → core::num}){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WChar>};
+  final ffi::Pointer<self::WChar> p = #C91.{ffi::Allocator::allocate}<self::WChar>(2.{core::num::*}(self::WChar::#sizeOf){(core::num) → core::num}){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WChar>};
   ffi::_storeAbiSpecificIntAtIndex<self::WChar>(p, 0, 10);
   ffi::_storeAbiSpecificIntAtIndex<self::WChar>(p, 1, 3);
   core::print(ffi::_loadAbiSpecificIntAtIndex<self::WChar>(p, 0));
   core::print(ffi::_loadAbiSpecificIntAtIndex<self::WChar>(p, 1));
-  #C89.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
+  #C91.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
 }
 static method testStruct() → void {
-  final ffi::Pointer<self::WCharStruct> p = #C89.{ffi::Allocator::allocate}<self::WCharStruct>(self::WCharStruct::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WCharStruct>};
+  final ffi::Pointer<self::WCharStruct> p = #C91.{ffi::Allocator::allocate}<self::WCharStruct>(self::WCharStruct::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WCharStruct>};
   new self::WCharStruct::#fromTypedDataBase(p!).{self::WCharStruct::a0} = 1;
   core::print(new self::WCharStruct::#fromTypedDataBase(p!).{self::WCharStruct::a0}{core::int});
   new self::WCharStruct::#fromTypedDataBase(p!).{self::WCharStruct::a0} = 2;
   core::print(new self::WCharStruct::#fromTypedDataBase(p!).{self::WCharStruct::a0}{core::int});
-  #C89.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
+  #C91.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
 }
 static method testInlineArray() → void {
-  final ffi::Pointer<self::WCharArrayStruct> p = #C89.{ffi::Allocator::allocate}<self::WCharArrayStruct>(self::WCharArrayStruct::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WCharArrayStruct>};
+  final ffi::Pointer<self::WCharArrayStruct> p = #C91.{ffi::Allocator::allocate}<self::WCharArrayStruct>(self::WCharArrayStruct::#sizeOf){(core::int, {alignment: core::int?}) → ffi::Pointer<self::WCharArrayStruct>};
   final ffi::Array<self::WChar> array = new self::WCharArrayStruct::#fromTypedDataBase(p!).{self::WCharArrayStruct::a0}{ffi::Array<self::WChar>};
   for (core::int i = 0; i.{core::num::<}(100){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int}) {
     ffi::_storeAbiSpecificIntAtIndex<self::WChar>(array.{ffi::Array::_typedDataBase}{core::Object}, i, i);
@@ -116,7 +116,7 @@
   for (core::int i = 0; i.{core::num::<}(100){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int}) {
     core::print(ffi::_loadAbiSpecificIntAtIndex<self::WChar>(array.{ffi::Array::_typedDataBase}{core::Object}, i));
   }
-  #C89.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
+  #C91.{self::_DummyAllocator::free}(p){(ffi::Pointer<ffi::NativeType>) → void};
 }
 constants  {
   #C1 = 0
@@ -153,59 +153,61 @@
   #C32 = ffi::Abi {_os:#C31, _architecture:#C5}
   #C33 = ffi::Abi {_os:#C31, _architecture:#C10}
   #C34 = ffi::Abi {_os:#C31, _architecture:#C14}
-  #C35 = ffi::Abi {_os:#C31, _architecture:#C18}
-  #C36 = 4
-  #C37 = "riscv32"
-  #C38 = ffi::_Architecture {index:#C36, _name:#C37}
-  #C39 = ffi::Abi {_os:#C31, _architecture:#C38}
-  #C40 = 5
-  #C41 = "riscv64"
-  #C42 = ffi::_Architecture {index:#C40, _name:#C41}
-  #C43 = ffi::Abi {_os:#C31, _architecture:#C42}
-  #C44 = "macos"
-  #C45 = ffi::_OS {index:#C36, _name:#C44}
-  #C46 = ffi::Abi {_os:#C45, _architecture:#C10}
-  #C47 = ffi::Abi {_os:#C45, _architecture:#C18}
-  #C48 = "windows"
-  #C49 = ffi::_OS {index:#C40, _name:#C48}
-  #C50 = ffi::Abi {_os:#C49, _architecture:#C10}
-  #C51 = ffi::Uint16 {}
-  #C52 = ffi::Abi {_os:#C49, _architecture:#C14}
-  #C53 = ffi::Abi {_os:#C49, _architecture:#C18}
-  #C54 = <ffi::Abi*, ffi::NativeType*>{#C6:#C7, #C11:#C7, #C15:#C7, #C19:#C7, #C22:#C23, #C24:#C7, #C27:#C7, #C28:#C7, #C29:#C7, #C32:#C7, #C33:#C7, #C34:#C7, #C35:#C7, #C39:#C7, #C43:#C7, #C46:#C7, #C47:#C7, #C50:#C51, #C52:#C51, #C53:#C51)
-  #C55 = ffi::AbiSpecificIntegerMapping {mapping:#C54}
-  #C56 = "vm:ffi:abi-specific-mapping"
-  #C57 = TypeLiteralConstant(ffi::Uint32)
-  #C58 = TypeLiteralConstant(ffi::Uint64)
-  #C59 = TypeLiteralConstant(ffi::Uint16)
-  #C60 = <core::Type?>[#C57, #C57, #C57, #C57, #C58, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C57, #C59, #C59, #C59]
-  #C61 = ffi::_FfiAbiSpecificMapping {nativeTypes:#C60}
-  #C62 = core::pragma {name:#C56, options:#C61}
-  #C63 = "vm:prefer-inline"
-  #C64 = null
-  #C65 = core::pragma {name:#C63, options:#C64}
-  #C66 = 8
-  #C67 = <core::int*>[#C36, #C36, #C36, #C36, #C66, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C36, #C12, #C12, #C12]
-  #C68 = "vm:ffi:struct-fields"
-  #C69 = TypeLiteralConstant(self::WChar)
-  #C70 = <core::Type>[#C69, #C69]
-  #C71 = ffi::_FfiStructLayout {fieldTypes:#C70, packing:#C64}
-  #C72 = core::pragma {name:#C68, options:#C71}
-  #C73 = self::WChar {}
-  #C74 = <core::int*>[#C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1]
-  #C75 = 16
-  #C76 = <core::int*>[#C66, #C66, #C66, #C66, #C75, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C66, #C36, #C36, #C36]
-  #C77 = 100
-  #C78 = ffi::_FfiInlineArray {elementType:#C69, length:#C77}
-  #C79 = <core::Type>[#C78]
-  #C80 = ffi::_FfiStructLayout {fieldTypes:#C79, packing:#C64}
-  #C81 = core::pragma {name:#C68, options:#C80}
-  #C82 = ffi::_ArraySize<ffi::NativeType*> {dimension1:#C77, dimension2:#C64, dimension3:#C64, dimension4:#C64, dimension5:#C64, dimensions:#C64}
-  #C83 = 400
-  #C84 = 800
-  #C85 = 200
-  #C86 = <core::int*>[#C83, #C83, #C83, #C83, #C84, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C83, #C85, #C85, #C85]
-  #C87 = <core::int*>[]
-  #C88 = core::_Override {}
-  #C89 = self::_DummyAllocator {}
+  #C35 = ffi::Int32 {}
+  #C36 = ffi::Abi {_os:#C31, _architecture:#C18}
+  #C37 = 4
+  #C38 = "riscv32"
+  #C39 = ffi::_Architecture {index:#C37, _name:#C38}
+  #C40 = ffi::Abi {_os:#C31, _architecture:#C39}
+  #C41 = 5
+  #C42 = "riscv64"
+  #C43 = ffi::_Architecture {index:#C41, _name:#C42}
+  #C44 = ffi::Abi {_os:#C31, _architecture:#C43}
+  #C45 = "macos"
+  #C46 = ffi::_OS {index:#C37, _name:#C45}
+  #C47 = ffi::Abi {_os:#C46, _architecture:#C10}
+  #C48 = ffi::Abi {_os:#C46, _architecture:#C18}
+  #C49 = "windows"
+  #C50 = ffi::_OS {index:#C41, _name:#C49}
+  #C51 = ffi::Abi {_os:#C50, _architecture:#C10}
+  #C52 = ffi::Uint16 {}
+  #C53 = ffi::Abi {_os:#C50, _architecture:#C14}
+  #C54 = ffi::Abi {_os:#C50, _architecture:#C18}
+  #C55 = <ffi::Abi*, ffi::NativeType*>{#C6:#C7, #C11:#C7, #C15:#C7, #C19:#C7, #C22:#C23, #C24:#C7, #C27:#C7, #C28:#C7, #C29:#C7, #C32:#C7, #C33:#C7, #C34:#C35, #C36:#C35, #C40:#C35, #C44:#C35, #C47:#C7, #C48:#C7, #C51:#C52, #C53:#C52, #C54:#C52)
+  #C56 = ffi::AbiSpecificIntegerMapping {mapping:#C55}
+  #C57 = "vm:ffi:abi-specific-mapping"
+  #C58 = TypeLiteralConstant(ffi::Uint32)
+  #C59 = TypeLiteralConstant(ffi::Uint64)
+  #C60 = TypeLiteralConstant(ffi::Int32)
+  #C61 = TypeLiteralConstant(ffi::Uint16)
+  #C62 = <core::Type?>[#C58, #C58, #C58, #C58, #C59, #C58, #C58, #C58, #C58, #C58, #C58, #C60, #C60, #C60, #C60, #C58, #C58, #C61, #C61, #C61]
+  #C63 = ffi::_FfiAbiSpecificMapping {nativeTypes:#C62}
+  #C64 = core::pragma {name:#C57, options:#C63}
+  #C65 = "vm:prefer-inline"
+  #C66 = null
+  #C67 = core::pragma {name:#C65, options:#C66}
+  #C68 = 8
+  #C69 = <core::int*>[#C37, #C37, #C37, #C37, #C68, #C37, #C37, #C37, #C37, #C37, #C37, #C37, #C37, #C37, #C37, #C37, #C37, #C12, #C12, #C12]
+  #C70 = "vm:ffi:struct-fields"
+  #C71 = TypeLiteralConstant(self::WChar)
+  #C72 = <core::Type>[#C71, #C71]
+  #C73 = ffi::_FfiStructLayout {fieldTypes:#C72, packing:#C66}
+  #C74 = core::pragma {name:#C70, options:#C73}
+  #C75 = self::WChar {}
+  #C76 = <core::int*>[#C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1, #C1]
+  #C77 = 16
+  #C78 = <core::int*>[#C68, #C68, #C68, #C68, #C77, #C68, #C68, #C68, #C68, #C68, #C68, #C68, #C68, #C68, #C68, #C68, #C68, #C37, #C37, #C37]
+  #C79 = 100
+  #C80 = ffi::_FfiInlineArray {elementType:#C71, length:#C79}
+  #C81 = <core::Type>[#C80]
+  #C82 = ffi::_FfiStructLayout {fieldTypes:#C81, packing:#C66}
+  #C83 = core::pragma {name:#C70, options:#C82}
+  #C84 = ffi::_ArraySize<ffi::NativeType*> {dimension1:#C79, dimension2:#C66, dimension3:#C66, dimension4:#C66, dimension5:#C66, dimensions:#C66}
+  #C85 = 400
+  #C86 = 800
+  #C87 = 200
+  #C88 = <core::int*>[#C85, #C85, #C85, #C85, #C86, #C85, #C85, #C85, #C85, #C85, #C85, #C85, #C85, #C85, #C85, #C85, #C85, #C87, #C87, #C87]
+  #C89 = <core::int*>[]
+  #C90 = core::_Override {}
+  #C91 = self::_DummyAllocator {}
 }
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc
index 04e3b77..ff77b69 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.cc
+++ b/runtime/vm/compiler/assembler/assembler_riscv.cc
@@ -2946,37 +2946,6 @@
   fsd(src, Address(base, offset));
 }
 
-void Assembler::LoadUnboxedDouble(FpuRegister dst,
-                                  Register base,
-                                  int32_t offset) {
-  fld(dst, Address(base, offset));
-}
-void Assembler::StoreUnboxedDouble(FpuRegister src,
-                                   Register base,
-                                   int32_t offset) {
-  fsd(src, Address(base, offset));
-}
-void Assembler::MoveUnboxedDouble(FpuRegister dst, FpuRegister src) {
-  fmvd(dst, src);
-}
-
-void Assembler::LoadCompressed(Register dest, const Address& slot) {
-  lx(dest, slot);
-}
-void Assembler::LoadCompressedFromOffset(Register dest,
-                                         Register base,
-                                         int32_t offset) {
-  lx(dest, Address(base, offset));
-}
-void Assembler::LoadCompressedSmi(Register dest, const Address& slot) {
-  lx(dest, slot);
-}
-void Assembler::LoadCompressedSmiFromOffset(Register dest,
-                                            Register base,
-                                            int32_t offset) {
-  lx(dest, Address(base, offset));
-}
-
 // Store into a heap object and apply the generational and incremental write
 // barriers. All stores into heap objects must pass through this function or,
 // if the value can be proven either Smi or old-and-premarked, its NoBarrier
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h
index af0af5c..582a8ae 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.h
+++ b/runtime/vm/compiler/assembler/assembler_riscv.h
@@ -1022,16 +1022,30 @@
     StoreDToOffset(src, base, offset - kHeapObjectTag);
   }
 
-  void LoadUnboxedDouble(FpuRegister dst, Register base, int32_t offset);
-  void StoreUnboxedDouble(FpuRegister src, Register base, int32_t offset);
-  void MoveUnboxedDouble(FpuRegister dst, FpuRegister src);
+  void LoadUnboxedDouble(FpuRegister dst, Register base, int32_t offset) {
+    LoadDFromOffset(dst, base, offset);
+  }
+  void StoreUnboxedDouble(FpuRegister src, Register base, int32_t offset) {
+    StoreDToOffset(src, base, offset);
+  }
+  void MoveUnboxedDouble(FpuRegister dst, FpuRegister src) {
+    fmvd(dst, src);
+  }
 
-  void LoadCompressed(Register dest, const Address& slot);
-  void LoadCompressedFromOffset(Register dest, Register base, int32_t offset);
-  void LoadCompressedSmi(Register dest, const Address& slot);
+  void LoadCompressed(Register dest, const Address& slot) {
+    lx(dest, slot);
+  }
+  void LoadCompressedFromOffset(Register dest, Register base, int32_t offset) {
+    LoadFromOffset(dest, base, offset);
+  }
+  void LoadCompressedSmi(Register dest, const Address& slot) {
+    lx(dest, slot);
+  }
   void LoadCompressedSmiFromOffset(Register dest,
                                    Register base,
-                                   int32_t offset);
+                                   int32_t offset) {
+    LoadFromOffset(dest, base, offset);
+  }
 
   // Store into a heap object and apply the generational and incremental write
   // barriers. All stores into heap objects must pass through this function or,
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index 42239a0..c0acbff 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -6271,31 +6271,6 @@
 #endif
 }
 
-ASSEMBLER_TEST_GENERATE(MoveByteRunTest, assembler) {
-  __ pushq(Immediate(0x1234567887654321));
-  __ xorq(CallingConventions::kReturnReg, CallingConventions::kReturnReg);
-  __ movb(ByteRegisterOf(CallingConventions::kReturnReg), Address(RSP, 0));
-  __ pushq(RBX);
-  __ xorq(RBX, RBX);
-  __ movb(BH, Address(RSP, target::kWordSize));
-  __ shrq(RBX, Immediate(8));
-  __ addq(CallingConventions::kReturnReg, RBX);
-  __ popq(RBX);
-  __ xorq(R8, R8);
-  __ movb(R8B, Address(RSP, 0));
-  __ addq(CallingConventions::kReturnReg, R8);
-  __ xorq(RDI, RDI);
-  __ movb(DIL, Address(RSP, 0));
-  __ addq(CallingConventions::kReturnReg, RDI);
-  __ popq(TMP);
-  __ 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/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 7677166..967b525 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -3437,6 +3437,12 @@
   // If the location, payload, and container are equal, we're done.
   if (source.Equals(destination) && src_payload_type.Equals(dst_payload_type) &&
       src_container_type.Equals(dst_container_type)) {
+#if defined(TARGET_ARCH_RISCV64)
+    // Except we might still need to adjust for the difference between C's
+    // representation of uint32 (sign-extended to 64 bits) and Dart's
+    // (zero-extended).
+    EmitNativeMoveArchitecture(destination, source);
+#endif
     return;
   }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
index 11b6467..6abae73 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
@@ -931,7 +931,16 @@
       ASSERT(dst.num_regs() == 1);
       const auto dst_reg = WithIntermediateMarshalling(dst.reg_at(0));
       if (!sign_or_zero_extend) {
-        __ mv(dst_reg, src_reg);
+#if XLEN == 32
+        __ MoveRegister(dst_reg, src_reg);
+#else
+        if (src_size <= 4) {
+          // Signed-extended to XLEN, even unsigned types.
+          __ addiw(dst_reg, src_reg, 0);
+        } else {
+          __ MoveRegister(dst_reg, src_reg);
+        }
+#endif
       } else {
         switch (src_type.AsPrimitive().representation()) {
           // Calling convention: scalars are extended according to the sign of
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index e93d920..f9e6f0e 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -6681,7 +6681,8 @@
     if (is_leaf_) {
       __ LoadMemoryValue(temp0, FPREG, typed_data_loc.ToStackSlotOffset());
     } else {
-      __ LoadMemoryValue(temp0, FPREG, 0);
+      __ LoadMemoryValue(
+          temp0, FPREG, kSavedCallerFpSlotFromFp * compiler::target::kWordSize);
       __ LoadMemoryValue(temp0, temp0, typed_data_loc.ToStackSlotOffset());
     }
     __ LoadField(temp0,
diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc
index a73d757..9068abb 100644
--- a/runtime/vm/compiler/backend/il_riscv.cc
+++ b/runtime/vm/compiler/backend/il_riscv.cc
@@ -4519,13 +4519,13 @@
   } else if (!CanDeoptimize()) {
     compiler::Label done;
     __ SmiUntag(out, value);
-    __ BranchIfSmi(value, &done);
+    __ BranchIfSmi(value, &done, compiler::Assembler::kNearJump);
     LoadInt32FromMint(compiler, value, out, NULL);
     __ Bind(&done);
   } else {
     compiler::Label done;
     __ SmiUntag(out, value);
-    __ BranchIfSmi(value, &done);
+    __ BranchIfSmi(value, &done, compiler::Assembler::kNearJump);
     __ CompareClassId(value, kMintCid, TMP);
     __ BranchIf(NE, deopt);
     LoadInt32FromMint(compiler, value, out, out_of_range);
@@ -4551,13 +4551,13 @@
     ASSERT(is_truncating());
     compiler::Label done;
     __ SmiUntag(out, value);
-    __ BranchIfSmi(value, &done);
+    __ BranchIfSmi(value, &done, compiler::Assembler::kNearJump);
     __ LoadFieldFromOffset(out, value, Mint::value_offset());
     __ Bind(&done);
   } else {
     compiler::Label done;
     __ SmiUntag(out, value);
-    __ BranchIfSmi(value, &done);
+    __ BranchIfSmi(value, &done, compiler::Assembler::kNearJump);
     __ CompareClassId(value, kMintCid, TMP);
     __ BranchIf(NE, deopt);
     __ LoadFieldFromOffset(out, value, Mint::value_offset());
diff --git a/runtime/vm/compiler/ffi/unit_tests/floatx20/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/floatx20/riscv64_linux.expect
index b8030e0..af69d91 100644
--- a/runtime/vm/compiler/ffi/unit_tests/floatx20/riscv64_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/floatx20/riscv64_linux.expect
@@ -15,8 +15,8 @@
 a6 int64[float]
 a7 int64[float]
 S+0 float
-S+4 float
 S+8 float
-S+12 float
+S+16 float
+S+24 float
 =>
 fa0 float
diff --git a/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv32_linux.expect
index 71c8bd7..78c4aad 100644
--- a/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv32_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv32_linux.expect
@@ -7,6 +7,6 @@
 a6 int32[int8]
 a7 int32[int8]
 S+0 int8
-S+1 int8
+S+4 int8
 =>
 a0 int32[int8]
diff --git a/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv64_linux.expect
index 71c8bd7..bbb5b73 100644
--- a/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv64_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/int8x10/riscv64_linux.expect
@@ -7,6 +7,6 @@
 a6 int32[int8]
 a7 int32[int8]
 S+0 int8
-S+1 int8
+S+8 int8
 =>
 a0 int32[int8]
diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/riscv64_linux.expect
index eee3c90..929c3d7 100644
--- a/runtime/vm/compiler/ffi/unit_tests/structPacked/riscv64_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/riscv64_linux.expect
@@ -10,6 +10,6 @@
 M(S+16 int64, S+24 int64) Struct(size: 9)
 S+32 double
 S+40 int32
-S+44 int32
+S+48 int32
 =>
 fa0 double
diff --git a/runtime/vm/compiler/ffi/unit_tests/struct_VeryLargeStruct/riscv32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/struct_VeryLargeStruct/riscv32_linux.expect
index e8eafe5..bcaefe3 100644
--- a/runtime/vm/compiler/ffi/unit_tests/struct_VeryLargeStruct/riscv32_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/struct_VeryLargeStruct/riscv32_linux.expect
@@ -1,4 +1,4 @@
-Struct(size: 72, field alignment: 8, stack alignment: 8, members: {
+Struct(size: 72, field alignment: 8, stack alignment: 4, members: {
   0: int8,
   2: int16,
   4: int32,
diff --git a/runtime/vm/compiler/ffi/unit_tests/struct_floatarray/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/struct_floatarray/riscv64_linux.expect
index 21f9c56..728e016 100644
--- a/runtime/vm/compiler/ffi/unit_tests/struct_floatarray/riscv64_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/struct_floatarray/riscv64_linux.expect
@@ -1,3 +1,3 @@
-Struct(size: 16, field alignment: 4, stack alignment: 4, members: {
-  0: Array(element type: Struct(size: 8, field alignment: 4, stack alignment: 4, members: {0: Array(element type: float, length: 2)}), length: 2)
+Struct(size: 16, field alignment: 4, stack alignment: 8, members: {
+  0: Array(element type: Struct(size: 8, field alignment: 4, stack alignment: 8, members: {0: Array(element type: float, length: 2)}), length: 2)
 })
diff --git a/runtime/vm/compiler/ffi/unit_tests/struct_floatx4/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/struct_floatx4/riscv64_linux.expect
index a753409..c065867 100644
--- a/runtime/vm/compiler/ffi/unit_tests/struct_floatx4/riscv64_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/struct_floatx4/riscv64_linux.expect
@@ -1,4 +1,4 @@
-Struct(size: 16, field alignment: 4, stack alignment: 4, members: {
+Struct(size: 16, field alignment: 4, stack alignment: 8, members: {
   0: float,
   4: float,
   8: float,
diff --git a/runtime/vm/compiler/ffi/unit_tests/struct_int8array/riscv32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/struct_int8array/riscv32_linux.expect
index b2249b0..bf40a47 100644
--- a/runtime/vm/compiler/ffi/unit_tests/struct_int8array/riscv32_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/struct_int8array/riscv32_linux.expect
@@ -1,3 +1,3 @@
-Struct(size: 8, field alignment: 1, stack alignment: 1, members: {
+Struct(size: 8, field alignment: 1, stack alignment: 4, members: {
   0: Array(element type: int8, length: 8)
 })
diff --git a/runtime/vm/compiler/ffi/unit_tests/struct_int8array/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/struct_int8array/riscv64_linux.expect
index b2249b0..02a0124 100644
--- a/runtime/vm/compiler/ffi/unit_tests/struct_int8array/riscv64_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/struct_int8array/riscv64_linux.expect
@@ -1,3 +1,3 @@
-Struct(size: 8, field alignment: 1, stack alignment: 1, members: {
+Struct(size: 8, field alignment: 1, stack alignment: 8, members: {
   0: Array(element type: int8, length: 8)
 })
diff --git a/runtime/vm/compiler/ffi/unit_tests/struct_int8x10/riscv32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/struct_int8x10/riscv32_linux.expect
index cba532d..c11d2ed 100644
--- a/runtime/vm/compiler/ffi/unit_tests/struct_int8x10/riscv32_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/struct_int8x10/riscv32_linux.expect
@@ -1,4 +1,4 @@
-Struct(size: 10, field alignment: 1, stack alignment: 1, members: {
+Struct(size: 10, field alignment: 1, stack alignment: 4, members: {
   0: int8,
   1: int8,
   2: int8,
diff --git a/runtime/vm/compiler/ffi/unit_tests/struct_int8x10/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/struct_int8x10/riscv64_linux.expect
index cba532d..e2ae57e 100644
--- a/runtime/vm/compiler/ffi/unit_tests/struct_int8x10/riscv64_linux.expect
+++ b/runtime/vm/compiler/ffi/unit_tests/struct_int8x10/riscv64_linux.expect
@@ -1,4 +1,4 @@
-Struct(size: 10, field alignment: 1, stack alignment: 1, members: {
+Struct(size: 10, field alignment: 1, stack alignment: 8, members: {
   0: int8,
   1: int8,
   2: int8,
diff --git a/runtime/vm/constants_riscv.h b/runtime/vm/constants_riscv.h
index ea4bc12..30a720f 100644
--- a/runtime/vm/constants_riscv.h
+++ b/runtime/vm/constants_riscv.h
@@ -450,7 +450,7 @@
 
   // How stack arguments are aligned.
   static constexpr AlignmentStrategy kArgumentStackAlignment =
-      kAlignedToValueSize;
+      kAlignedToWordSize;
 
   // How fields in compounds are aligned.
   static constexpr AlignmentStrategy kFieldAlignment = kAlignedToValueSize;
diff --git a/sdk/lib/ffi/c_type.dart b/sdk/lib/ffi/c_type.dart
index b1bc764..5edffad 100644
--- a/sdk/lib/ffi/c_type.dart
+++ b/sdk/lib/ffi/c_type.dart
@@ -490,8 +490,8 @@
   Abi.linuxArm64: Uint32(),
   Abi.linuxIA32: Int32(),
   Abi.linuxX64: Int32(),
-  Abi.linuxRiscv32: Uint32(),
-  Abi.linuxRiscv64: Uint32(),
+  Abi.linuxRiscv32: Int32(),
+  Abi.linuxRiscv64: Int32(),
   Abi.macosArm64: Int32(),
   Abi.macosX64: Int32(),
   Abi.windowsArm64: Uint16(),
diff --git a/tools/VERSION b/tools/VERSION
index 52e4fd5..36ee48e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 237
+PRERELEASE 238
 PRERELEASE_PATCH 0
\ No newline at end of file