[vm/aot] Fix retaining of targets of FFI callbacks in precompiler
Account for the fact that a Function could be only reachable via
FfiTrampolineData in the FFI trampoline function.
TEST=ffi_2/function_callbacks_test
Fixes https://github.com/dart-lang/sdk/issues/45510
Change-Id: I2db81c7730ae48d1f1355aa236339e54562ee6c4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193893
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Tess Strickland <sstrickl@google.com>
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index e84949f..4eddc2e 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -144,6 +144,8 @@
static constexpr const char* kLocalParent = "parent of a local function";
// The object has an entry point pragma that requires it be retained.
static constexpr const char* kEntryPointPragma = "entry point pragma";
+ // The function is a target of FFI callback.
+ static constexpr const char* kFfiCallbackTarget = "ffi callback target";
};
class RetainedReasonsWriter : public ValueObject {
@@ -935,6 +937,13 @@
// Local closure function.
const auto& target = Function::Cast(entry);
AddFunction(target, RetainReasons::kLocalClosure);
+ if (target.IsFfiTrampoline()) {
+ const auto& callback_target =
+ Function::Handle(Z, target.FfiCallbackTarget());
+ if (!callback_target.IsNull()) {
+ AddFunction(callback_target, RetainReasons::kFfiCallbackTarget);
+ }
+ }
} else if (entry.IsCode()) {
const auto& target_code = Code::Cast(entry);
if (target_code.IsAllocationStubCode()) {
diff --git a/tests/ffi/function_callbacks_test.dart b/tests/ffi/function_callbacks_test.dart
index 11baff6..e9a853c 100644
--- a/tests/ffi/function_callbacks_test.dart
+++ b/tests/ffi/function_callbacks_test.dart
@@ -13,6 +13,7 @@
// VMOptions=--use-slow-path --enable-testing-pragmas --write-protect-code --no-dual-map-code
// VMOptions=--use-slow-path --enable-testing-pragmas --write-protect-code --no-dual-map-code --stacktrace-every=100
// VMOptions=--use-bare-instructions=false
+// VMOptions=--enable-testing-pragmas --dwarf_stack_traces --no-retain_function_objects --no-retain_code_objects
// SharedObjects=ffi_test_functions
import 'dart:ffi';
diff --git a/tests/ffi_2/function_callbacks_test.dart b/tests/ffi_2/function_callbacks_test.dart
index 11baff6..e9a853c 100644
--- a/tests/ffi_2/function_callbacks_test.dart
+++ b/tests/ffi_2/function_callbacks_test.dart
@@ -13,6 +13,7 @@
// VMOptions=--use-slow-path --enable-testing-pragmas --write-protect-code --no-dual-map-code
// VMOptions=--use-slow-path --enable-testing-pragmas --write-protect-code --no-dual-map-code --stacktrace-every=100
// VMOptions=--use-bare-instructions=false
+// VMOptions=--enable-testing-pragmas --dwarf_stack_traces --no-retain_function_objects --no-retain_code_objects
// SharedObjects=ffi_test_functions
import 'dart:ffi';