Version 2.17.1

* Cherry-pick 9fa681712f6184565ab3e6b9aec11ab09be93594 to stable
* Cherry-pick e418026d74b6c666a7fcb30278a2b10ed97fdb29 to stable
* Cherry-pick 4e520ec7a7ceb903da0c4ec04da7eeb635524748 to stable
* Cherry-pick d2e2c95cb6397fdf4e07b351ae50d1fa85e421e1 to stable
* Cherry-pick 9fb27f9842cd7bb3f2a1c4c84c9934f1952bed83 to stable
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fefe254..ce4c26d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,16 @@
-## 2.17.0
+## 2.17.1 - 2022-05-18
+
+This is a patch release that fixes:
+
+- an analyzer plugin crash (issue [#48682][]).
+- Dart FFI support for `late` `Finalizable` variables (issue [#49024]).
+- `dart compile` on macOS 10.15 (issue [#49010][]).
+
+[#48682]: https://github.com/dart-lang/sdk/issues/48682
+[#49024]: https://github.com/dart-lang/sdk/issues/49024
+[#49010]: https://github.com/dart-lang/sdk/issues/49010
+
+## 2.17.0 - 2022-05-11
 
 ### Language
 
@@ -151,6 +163,24 @@
 
 - Add `ref=` and `[]=` methods to the `StructPointer` and `UnionPointer`
   extensions. They copy a compound instance into a native memory region.
+- Add `AbiSpecificInteger`s for common C types:
+  - `char`
+  - `unsigned char`
+  - `signed char`
+  - `short`
+  - `unsigned short`
+  - `int`
+  - `unsigned int`
+  - `long`
+  - `unsigned long`
+  - `long long`
+  - `unsigned long long`
+  - `uintptr_t`
+  - `size_t`
+  - `wchar_t`
+- Add `NativeFinalizer` which can potentially detect when objects are
+  "garbage collected". `NativeFinalizer`s run native code where `dart:core`'s
+  `Finalizer`s run Dart code on finalization.
 
 #### `dart:html`
 
@@ -305,6 +335,11 @@
   error with an existing stack trace, instead of creating
   a new stack trace.
 
+#### `dart:ffi`
+
+- Add `Abi` and `AbiSpecificInteger`. These enable specifying integers which
+  have different sizes/signs per ABI (hardware and OS combination).
+
 #### `dart:io`
 
 - **Security advisory**
@@ -747,6 +782,10 @@
   Code catching the class should move to catching `Error` instead
   (or, for integers, check first for whether it's dividing by zero).
 
+#### `dart:ffi`
+
+- Add `Bool` native type.
+
 #### `dart:io`
 
 - **Breaking change** [#46875](https://github.com/dart-lang/sdk/issues/46875):
@@ -1051,8 +1090,9 @@
 
 #### `dart:ffi`
 
-- Adds the `DynamicLibrary.providesSymbol` function to check whether a symbol is
+- Add the `DynamicLibrary.providesSymbol` function to check whether a symbol is
   available in a dynamic library.
+- Add `Union` native type for interacting with unions in native memory.
 
 #### `dart:html`
 
@@ -1349,6 +1389,11 @@
 
 - Added `serverWebSocketUri` property to `ServiceProtocolInfo`.
 
+#### `dart:ffi`
+
+- Add `Packed` for interacting with packed structs in native memory.
+- Add `Array` for interacting with structs with inline arrays.
+
 ### Dart VM
 
 ### Tools
@@ -1489,6 +1534,26 @@
 - Add `Set.unmodifiable()` constructor, which allows users to create
   unmodifiable `Set` instances.
 
+#### `dart:ffi`
+
+- **Breaking change** [#44621][]: Invocations with a generic `T` of `sizeOf<T>`,
+  `Pointer<T>.elementAt()`, `Pointer<T extends Struct>.ref`, and
+  `Pointer<T extends Struct>[]` are being deprecated in the current stable
+  release (2.12), and are planned to be fully removed in the following stable
+  release (2.13). Consequently, `allocate` in `package:ffi` will no longer be
+  able to invoke `sizeOf<T>` generically, and will be deprecated as well.
+  Instead, the `Allocator` it is introduced to `dart:ffi`, and also requires a
+  constant `T` on invocations. For migration notes see the breaking change
+  request.
+
+- **Breaking change** [#44622][]: Subtypes of `Struct` without any native member
+  are being deprecated in the current stable release (2.12), and are planned to
+  be fully removed in the following stable release (2.13). Migrate opaque types
+  to extend `Opaque` rather than `Struct`.
+
+[#44621]: https://github.com/dart-lang/sdk/issues/44621
+[#44622]: https://github.com/dart-lang/sdk/issues/44622
+
 #### `dart:io`
 
 - `HttpRequest` now correctly follows HTTP 308 redirects
@@ -1524,26 +1589,6 @@
 
 [#42312]: https://github.com/dart-lang/sdk/issues/42312
 
-### Foreign Function Interface (`dart:ffi`)
-
-- **Breaking change** [#44621][]: Invocations with a generic `T` of `sizeOf<T>`,
-  `Pointer<T>.elementAt()`, `Pointer<T extends Struct>.ref`, and
-  `Pointer<T extends Struct>[]` are being deprecated in the current stable
-  release (2.12), and are planned to be fully removed in the following stable
-  release (2.13). Consequently, `allocate` in `package:ffi` will no longer be
-  able to invoke `sizeOf<T>` generically, and will be deprecated as well.
-  Instead, the `Allocator` it is introduced to `dart:ffi`, and also requires a
-  constant `T` on invocations. For migration notes see the breaking change
-  request.
-
-- **Breaking change** [#44622][]: Subtypes of `Struct` without any native member
-  are being deprecated in the current stable release (2.12), and are planned to
-  be fully removed in the following stable release (2.13). Migrate opaque types
-  to extend `Opaque` rather than `Struct`.
-
-[#44621]: https://github.com/dart-lang/sdk/issues/44621
-[#44622]: https://github.com/dart-lang/sdk/issues/44622
-
 ### Dart2JS
 
 - Remove `--no-defer-class-types` and `--no-new-deferred-split`.
@@ -2167,6 +2212,19 @@
   parameter provided in the constructor. This will be used by tooling to allow
   for better filtering of timeline events.
 
+#### `dart:ffi`
+
+- **Breaking change**: Changed `Pointer.asFunction()` and
+  `DynamicLibrary.lookupFunction()` to extension methods. Invoking them
+  dynamically previously already threw an exception, so the runtime behavior
+  stays the same. However, the extension methods are only visible if `dart:ffi`
+  is imported directly. This breaks code where `dart:ffi` is not directly
+  imported. To fix, add:
+
+  ```dart
+  import 'dart:ffi';
+  ```
+
 #### `dart:html`
 
 - **Breaking change** [#39627][]: Changed the return type of several HTML native
@@ -2306,19 +2364,6 @@
   - `Dart_IsNonNullableType()`
   - `Dart_IsNullableType()`
 
-### Foreign Function Interface (`dart:ffi`)
-
-- **Breaking change**: Changed `Pointer.asFunction()` and
-  `DynamicLibrary.lookupFunction()` to extension methods. Invoking them
-  dynamically previously already threw an exception, so the runtime behavior
-  stays the same. However, the extension methods are only visible if `dart:ffi`
-  is imported directly. This breaks code where `dart:ffi` is not directly
-  imported. To fix, add:
-
-  ```dart
-  import 'dart:ffi';
-  ```
-
 ### Tools
 
 #### Dart Dev Compiler (DDC)
@@ -2700,18 +2745,7 @@
 - Added optional `parent` parameter to `TimelineTask` constructor to allow for
   linking of asynchronous timeline events in the DevTools timeline view.
 
-#### `dart:io`
-
-- Added `enableTimelineLogging` property to `HttpClient` which, when enabled,
-  will post HTTP connection and request information to the developer timeline
-  for all `HttpClient` instances.
-
-### Dart VM
-
-- Added a new tool for AOT compiling Dart programs to native, self-contained
-  executables. See https://dart.dev/tools/dart2native for additional details.
-
-### Foreign Function Interface (`dart:ffi`)
+#### `dart:ffi`
 
 - **Breaking change**: The API now makes use of static extension members. Static
   extension members enable the `dart:ffi` API to be more precise with types, and
@@ -2731,6 +2765,17 @@
 - The dartanalyzer (commandline and IDEs) now reports `dart:ffi` static errors.
 - Callbacks are now supported in AOT (ahead-of-time) compiled code.
 
+#### `dart:io`
+
+- Added `enableTimelineLogging` property to `HttpClient` which, when enabled,
+  will post HTTP connection and request information to the developer timeline
+  for all `HttpClient` instances.
+
+### Dart VM
+
+- Added a new tool for AOT compiling Dart programs to native, self-contained
+  executables. See https://dart.dev/tools/dart2native for additional details.
+
 ### Dart for the Web
 
 #### Dart Dev Compiler (DDC)
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
index ae25ec1..7dc3e98 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
@@ -632,13 +632,8 @@
         .getChildAssumingFolder(file_paths.dotDartTool)
         .getChildAssumingFile(file_paths.packageConfigJson);
     if (pubCommand != null) {
-      var vmPath = Platform.executable;
-      var pubPath = path.join(path.dirname(vmPath), 'pub');
-      if (Platform.isWindows) {
-        // Process.run requires the `.bat` suffix on Windows
-        pubPath = '$pubPath.bat';
-      }
-      var result = Process.runSync(pubPath, <String>[pubCommand],
+      var result = Process.runSync(
+          Platform.executable, <String>['pub', pubCommand],
           stderrEncoding: utf8,
           stdoutEncoding: utf8,
           workingDirectory: pluginFolder.path,
diff --git a/pkg/dart2native/lib/dart2native_macho.dart b/pkg/dart2native/lib/dart2native_macho.dart
index eefaf9d..1c45d13 100644
--- a/pkg/dart2native/lib/dart2native_macho.dart
+++ b/pkg/dart2native/lib/dart2native_macho.dart
@@ -265,6 +265,32 @@
   return numWritten;
 }
 
+class _MacOSVersion {
+  final int? _major;
+  final int? _minor;
+
+  static final _regexp = RegExp(r'Version (?<major>\d+).(?<minor>\d+)');
+  static const _parseFailure = 'Could not determine macOS version';
+
+  const _MacOSVersion._internal(this._major, this._minor);
+
+  static const _unknown = _MacOSVersion._internal(null, null);
+
+  factory _MacOSVersion() {
+    if (!Platform.isMacOS) return _unknown;
+    final match =
+        _regexp.matchAsPrefix(Platform.operatingSystemVersion) as RegExpMatch?;
+    if (match == null) return _unknown;
+    final minor = int.tryParse(match.namedGroup('minor')!);
+    final major = int.tryParse(match.namedGroup('major')!);
+    return _MacOSVersion._internal(major, minor);
+  }
+
+  bool get isValid => _major != null;
+  int get major => _major ?? (throw _parseFailure);
+  int get minor => _minor ?? (throw _parseFailure);
+}
+
 // Writes an "appended" dart runtime + script snapshot file in a format
 // compatible with MachO executables.
 Future writeAppendedMachOExecutable(
@@ -312,17 +338,39 @@
   await stream.close();
 
   if (machOFile.hasCodeSignature) {
+    if (!Platform.isMacOS) {
+      throw 'Cannot sign MachO binary on non-macOS platform';
+    }
+
     // After writing the modified file, we perform ad-hoc signing (no identity)
-    // similar to the linker (the linker-signed option flag) to ensure that any
-    // LC_CODE_SIGNATURE block has the correct CD hashes. This is necessary for
-    // platforms where signature verification is always on (e.g., OS X on M1).
+    // to ensure that any LC_CODE_SIGNATURE block has the correct CD hashes.
+    // This is necessary for platforms where signature verification is always on
+    // (e.g., OS X on M1).
     //
     // We use the `-f` flag to force signature overwriting as the official
     // Dart binaries (including dartaotruntime) are fully signed.
-    final signingProcess = await Process.run(
-        'codesign', ['-f', '-o', 'linker-signed', '-s', '-', outputPath]);
+    final args = ['-f', '-s', '-', outputPath];
+
+    // If running on macOS >=11.0, then the linker-signed option flag can be
+    // used to create a signature that does not need to be force overridden.
+    final version = _MacOSVersion();
+    if (version.isValid && version.major >= 11) {
+      final signingProcess =
+          await Process.run('codesign', ['-o', 'linker-signed', ...args]);
+      if (signingProcess.exitCode == 0) {
+        return;
+      }
+      print('Failed to add a linker signed signature, '
+          'adding a regular signature instead.');
+    }
+
+    // If that fails or we're running on an older or undetermined version of
+    // macOS, we fall back to signing without the linker-signed option flag.
+    // Thus, to sign the binary, the developer must force signature overwriting.
+    final signingProcess = await Process.run('codesign', args);
     if (signingProcess.exitCode != 0) {
-      print('Subcommand terminated with exit code ${signingProcess.exitCode}.');
+      print('Failed to replace the dartaotruntime signature, ');
+      print('subcommand terminated with exit code ${signingProcess.exitCode}.');
       if (signingProcess.stdout.isNotEmpty) {
         print('Subcommand stdout:');
         print(signingProcess.stdout);
diff --git a/pkg/dartdev/test/commands/compile_test.dart b/pkg/dartdev/test/commands/compile_test.dart
index e5c15b0..0d497b4 100644
--- a/pkg/dartdev/test/commands/compile_test.dart
+++ b/pkg/dartdev/test/commands/compile_test.dart
@@ -187,7 +187,7 @@
     expect(result.stdout, contains('2: foo'));
   });
 
-  test('Compile and run executable', () async {
+  Future<void> basicCompileTest() async {
     final p = project(mainSrc: 'void main() { print("I love executables"); }');
     final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
     final outFile = path.canonicalize(path.join(p.dirPath, 'lib', 'main.exe'));
@@ -213,7 +213,9 @@
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
     expect(result.stdout, contains('I love executables'));
-  }, skip: isRunningOnIA32);
+  }
+
+  test('Compile and run executable', basicCompileTest, skip: isRunningOnIA32);
 
   test('Compile to executable disabled on IA32', () async {
     final p = project(mainSrc: 'void main() { print("I love executables"); }');
@@ -1112,4 +1114,33 @@
     expect(result.stderr, contains('Warning:'));
     expect(result.exitCode, 0);
   });
+
+  if (Platform.isMacOS) {
+    test('Compile and run executable from signed dartaotruntime', () async {
+      // Either the locally built dartaotruntime is already linker signed
+      // (on M1) or it is unsigned (on X64). For this test, sign the
+      // dartaotruntime executable with a non-linker signed adhoc signature,
+      // which won't cause issues with any other tests that use it. This
+      // ensures the code signing path in dart2native is exercised on X64
+      // (macOS <11.0), and also mimics the case for end users that are using
+      // the published Dart SDK (which is fully signed, not linker signed).
+      final Directory binDir = File(Platform.resolvedExecutable).parent;
+      final String originalRuntimePath =
+          path.join(binDir.path, 'dartaotruntime');
+      final codeSigningProcess = await Process.start('codesign', [
+        '-o',
+        'runtime',
+        '-s',
+        '-',
+        originalRuntimePath,
+      ]);
+
+      final signingResult = await codeSigningProcess.exitCode;
+      expect(signingResult, 0);
+
+      // Now perform the same basic compile and run test with the signed
+      // dartaotruntime.
+      await basicCompileTest();
+    }, skip: isRunningOnIA32);
+  }
 }
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_late.dart b/pkg/vm/testcases/transformations/ffi/finalizable_late.dart
new file mode 100644
index 0000000..048ae94
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_late.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2022, 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.
+
+// @dart=2.16
+
+import 'dart:ffi';
+
+class Foo implements Finalizable {}
+
+void main() {
+  late Foo foo;
+  // Generates a reachability fence between the constructor call and assignment.
+  // That reachability fence should not trigger a late initialization error.
+  foo = Foo();
+  print(foo);
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_late.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_late.dart.expect
new file mode 100644
index 0000000..45321de
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_late.dart.expect
@@ -0,0 +1,22 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class Foo extends core::Object implements ffi::Finalizable {
+  synthetic constructor •() → self::Foo
+    : super core::Object::•()
+    ;
+}
+static method main() → void {
+  late self::Foo foo;
+  foo = block {
+    final self::Foo :expressionValueWrappedFinalizable = new self::Foo::•();
+    _in::reachabilityFence(foo);
+  } =>:expressionValueWrappedFinalizable;
+  core::print(foo);
+  _in::reachabilityFence(foo);
+}
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 0af255f..7e93579 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -2048,28 +2048,35 @@
   return Fragment();
 }
 
-Fragment StreamingFlowGraphBuilder::BuildVariableGet(TokenPosition* position) {
+Fragment StreamingFlowGraphBuilder::BuildVariableGet(
+    TokenPosition* position,
+    bool allow_late_uninitialized) {
   const TokenPosition pos = ReadPosition();
   if (position != nullptr) *position = pos;
   intptr_t variable_kernel_position = ReadUInt();  // read kernel position.
   ReadUInt();              // read relative variable index.
   SkipOptionalDartType();  // read promoted type.
-  return BuildVariableGetImpl(variable_kernel_position, pos);
+  return BuildVariableGetImpl(variable_kernel_position, pos,
+                              allow_late_uninitialized);
 }
 
-Fragment StreamingFlowGraphBuilder::BuildVariableGet(uint8_t payload,
-                                                     TokenPosition* position) {
+Fragment StreamingFlowGraphBuilder::BuildVariableGet(
+    uint8_t payload,
+    TokenPosition* position,
+    bool allow_late_uninitialized) {
   const TokenPosition pos = ReadPosition();
   if (position != nullptr) *position = pos;
   intptr_t variable_kernel_position = ReadUInt();  // read kernel position.
-  return BuildVariableGetImpl(variable_kernel_position, pos);
+  return BuildVariableGetImpl(variable_kernel_position, pos,
+                              allow_late_uninitialized);
 }
 
 Fragment StreamingFlowGraphBuilder::BuildVariableGetImpl(
     intptr_t variable_kernel_position,
-    TokenPosition position) {
+    TokenPosition position,
+    bool allow_late_uninitialized) {
   LocalVariable* variable = LookupVariable(variable_kernel_position);
-  if (!variable->is_late()) {
+  if (!variable->is_late() || allow_late_uninitialized) {
     return LoadLocal(variable);
   }
 
@@ -3432,6 +3439,8 @@
   switch (recognized_kind) {
     case MethodRecognizer::kNativeEffect:
       return BuildNativeEffect();
+    case MethodRecognizer::kReachabilityFence:
+      return BuildReachabilityFence();
     case MethodRecognizer::kFfiAsFunctionInternal:
       return BuildFfiAsFunctionInternal();
     case MethodRecognizer::kFfiNativeCallbackFunction:
@@ -5549,6 +5558,45 @@
   return code;
 }
 
+Fragment StreamingFlowGraphBuilder::BuildReachabilityFence() {
+  const intptr_t argc = ReadUInt();               // Read argument count.
+  ASSERT(argc == 1);                              // LoadField, can be late.
+  const intptr_t list_length = ReadListLength();  // Read types list length.
+  ASSERT(list_length == 0);
+
+  const intptr_t positional_count = ReadListLength();
+  ASSERT(positional_count == 1);
+
+  // The CFE transform only generates a subset of argument expressions:
+  // either variable get or `this`.
+  uint8_t payload = 0;
+  Tag tag = ReadTag(&payload);
+  TokenPosition* position = nullptr;
+  const bool allow_late_uninitialized = true;
+  Fragment code;
+  switch (tag) {
+    case kVariableGet:
+      code = BuildVariableGet(position, allow_late_uninitialized);
+      break;
+    case kSpecializedVariableGet:
+      code = BuildVariableGet(payload, position, allow_late_uninitialized);
+      break;
+    case kThisExpression:
+      code = BuildThisExpression(position);
+      break;
+    default:
+      // The transformation should not be generating anything else.
+      FATAL1("Unexpected tag %i", tag);
+  }
+
+  const intptr_t named_args_len = ReadListLength();
+  ASSERT(named_args_len == 0);
+
+  code <<= new (Z) ReachabilityFenceInstr(Pop());
+  code += NullConstant();  // Return type is void.
+  return code;
+}
+
 static void ReportIfNotNull(const char* error) {
   if (error != nullptr) {
     const auto& language_error = Error::Handle(
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index cc8a1f9..29adbcd 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -272,10 +272,14 @@
   Fragment BuildArgumentsFromActualArguments(Array* argument_names);
 
   Fragment BuildInvalidExpression(TokenPosition* position);
-  Fragment BuildVariableGet(TokenPosition* position);
-  Fragment BuildVariableGet(uint8_t payload, TokenPosition* position);
+  Fragment BuildVariableGet(TokenPosition* position,
+                            bool allow_late_uninitialized = false);
+  Fragment BuildVariableGet(uint8_t payload,
+                            TokenPosition* position,
+                            bool allow_late_uninitialized = false);
   Fragment BuildVariableGetImpl(intptr_t variable_kernel_position,
-                                TokenPosition position);
+                                TokenPosition position,
+                                bool allow_late_uninitialized = false);
   Fragment BuildVariableSet(TokenPosition* position);
   Fragment BuildVariableSet(uint8_t payload, TokenPosition* position);
   Fragment BuildVariableSetImpl(TokenPosition position,
@@ -365,6 +369,10 @@
   // Build flow graph for '_nativeEffect'.
   Fragment BuildNativeEffect();
 
+  // Build the call-site manually, to avoid doing initialization checks
+  // for late fields.
+  Fragment BuildReachabilityFence();
+
   // Build flow graph for '_loadAbiSpecificInt' and
   // '_loadAbiSpecificIntAtIndex', '_storeAbiSpecificInt', and
   // '_storeAbiSpecificIntAtIndex' call sites.
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 905570f..c0c5be2 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -949,7 +949,6 @@
     case MethodRecognizer::kCopyRangeFromUint8ListToOneByteString:
     case MethodRecognizer::kImmutableLinkedHashBase_setIndexStoreRelease:
     case MethodRecognizer::kFfiAbi:
-    case MethodRecognizer::kReachabilityFence:
     case MethodRecognizer::kUtf8DecoderScan:
     case MethodRecognizer::kHas63BitSmis:
 #define CASE(method, slot) case MethodRecognizer::k##method:
@@ -1279,12 +1278,6 @@
       body += Utf8Scan();
       body += Box(kUnboxedIntPtr);
       break;
-    case MethodRecognizer::kReachabilityFence:
-      ASSERT_EQUAL(function.NumParameters(), 1);
-      body += LoadLocal(parsed_function_->RawParameterVariable(0));
-      body += ReachabilityFence();
-      body += NullConstant();
-      break;
     case MethodRecognizer::kFfiAbi:
       ASSERT_EQUAL(function.NumParameters(), 0);
       body += IntConstant(static_cast<int64_t>(compiler::ffi::TargetAbi()));
diff --git a/tests/language/vm/regress_49005_test.dart b/tests/language/vm/regress_49005_test.dart
new file mode 100644
index 0000000..619aa12
--- /dev/null
+++ b/tests/language/vm/regress_49005_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, 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:ffi';
+
+class Foo implements Finalizable {}
+
+void main() {
+  late Foo foo;
+  foo = Foo();
+  print(foo);
+}
diff --git a/tools/VERSION b/tools/VERSION
index f5f3e2f56..c67ab37 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -26,6 +26,6 @@
 CHANNEL stable
 MAJOR 2
 MINOR 17
-PATCH 0
+PATCH 1
 PRERELEASE 0
 PRERELEASE_PATCH 0
\ No newline at end of file