[vm, ffi] Remove special case for simulator FFI callback thunks.

TEST=ci
Bug: https://dartbug.com/52579
Change-Id: I488af082d5d9db39da38c9ff1e8ac984454bff54
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/493921
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Liam Appelbe <liama@google.com>
This commit is contained in:
Ryan Macnak
2026-04-08 16:43:09 -07:00
committed by Commit Queue
parent fb732a570d
commit 68e2512ace
4 changed files with 56 additions and 91 deletions
+18 -68
View File
@@ -29,28 +29,26 @@ void FfiCallbackMetadata::EnsureStubPageLocked() {
ASSERT_LESS_OR_EQUAL(VirtualMemory::PageSize(), kPageSize);
uword code_start, code_end, code_size;
#if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)
uword code_start, code_end, page_start;
if (FLAG_use_simulator) {
code_start = reinterpret_cast<uword>(SimulatorFfiCallbackTrampoline);
code_end = reinterpret_cast<uword>(SimulatorFfiCallbackTrampolineEnd);
page_start = code_start & ~(VirtualMemory::PageSize() - 1);
code_size = code_end - code_start;
} else {
const Code& trampoline_code = StubCode::FfiCallbackTrampoline();
code_start = trampoline_code.EntryPoint();
code_end = code_start + trampoline_code.Size();
page_start = code_start & ~(VirtualMemory::PageSize() - 1);
ASSERT_LESS_OR_EQUAL((code_start - page_start) + trampoline_code.Size(),
RXMappingSize());
code_size = trampoline_code.Size();
}
#else
const Code& trampoline_code = StubCode::FfiCallbackTrampoline();
const uword code_start = trampoline_code.EntryPoint();
const uword code_end = code_start + trampoline_code.Size();
const uword page_start = code_start & ~(VirtualMemory::PageSize() - 1);
ASSERT_LESS_OR_EQUAL((code_start - page_start) + trampoline_code.Size(),
RXMappingSize());
code_start = trampoline_code.EntryPoint();
code_end = code_start + trampoline_code.Size();
code_size = trampoline_code.Size();
#endif
const uword page_start = code_start & ~(VirtualMemory::PageSize() - 1);
ASSERT_LESS_OR_EQUAL((code_start - page_start) + code_size, RXMappingSize());
// Stub page uses a tight (unaligned) bound for the end of the code area.
// Otherwise we can read past the end of the code area when doing DuplicateRX.
@@ -58,19 +56,6 @@ void FfiCallbackMetadata::EnsureStubPageLocked() {
code_end - page_start);
offset_of_first_trampoline_in_page_ = code_start - page_start;
#if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)
if (FLAG_use_simulator) {
original_metadata_page_ = VirtualMemory::AllocateAligned(
MappingSize(), MappingAlignment(), /*is_executable=*/false,
/*is_compressed=*/false, "FfiCallbackMetadata::TrampolinePage");
MetadataEntry* metadata_entry = reinterpret_cast<MetadataEntry*>(
original_metadata_page_->start() + MetadataOffset());
for (intptr_t i = 0; i < NumCallbackTrampolinesPerPage(); ++i) {
AddToFreeListLocked(&metadata_entry[i]);
}
}
#endif // defined(DART_TARGET_OS_FUCHSIA)
}
FfiCallbackMetadata::~FfiCallbackMetadata() {
@@ -79,11 +64,6 @@ FfiCallbackMetadata::~FfiCallbackMetadata() {
for (intptr_t i = 0; i < trampoline_pages_.length(); ++i) {
delete trampoline_pages_[i];
}
#if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)
// TODO(https://dartbug.com/52579): Remove.
delete original_metadata_page_;
#endif // defined(DART_TARGET_OS_FUCHSIA)
}
void FfiCallbackMetadata::Init() {
@@ -117,13 +97,6 @@ void FfiCallbackMetadata::FillRuntimeFunction(VirtualMemory* page,
}
VirtualMemory* FfiCallbackMetadata::AllocateTrampolinePage() {
#if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)
if (FLAG_use_simulator) {
UNREACHABLE();
return nullptr;
}
#endif
#if defined(DART_HOST_OS_MACOS) && defined(DART_PRECOMPILED_RUNTIME)
const bool should_remap_stub_page = true;
#else
@@ -196,6 +169,12 @@ VirtualMemory* FfiCallbackMetadata::AllocateTrampolinePage() {
return new_page;
}
#if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)
struct CallbackContext;
extern "C" void DoRedirectedFfiCallback(CallbackContext* ctxt,
uword trampoline);
#endif
void FfiCallbackMetadata::EnsureFreeListNotEmptyLocked() {
ASSERT(lock_.IsOwnedByCurrentThread());
EnsureStubPageLocked();
@@ -213,6 +192,10 @@ void FfiCallbackMetadata::EnsureFreeListNotEmptyLocked() {
// Fill in the runtime functions.
FillRuntimeFunction(new_page, kGetFfiCallbackMetadata,
reinterpret_cast<void*>(DLRT_GetFfiCallbackMetadata));
#if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)
FillRuntimeFunction(new_page, kDoRedirectedFfiCallback,
reinterpret_cast<void*>(DoRedirectedFfiCallback));
#endif
// Add all the trampolines to the free list.
const intptr_t trampolines_per_page = NumCallbackTrampolinesPerPage();
@@ -416,44 +399,12 @@ FfiCallbackMetadata::Trampoline FfiCallbackMetadata::TrampolineOfMetadataEntry(
MetadataEntry* metadata_entries =
reinterpret_cast<MetadataEntry*>(start + MetadataOffset());
const uword index = metadata_entry - metadata_entries;
#if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)
if (FLAG_use_simulator) {
return reinterpret_cast<uword>(SimulatorFfiCallbackTrampoline) +
index * kNativeCallbackTrampolineSize;
} else {
return start + offset_of_first_trampoline_in_page_ +
index * kNativeCallbackTrampolineSize;
}
#else
return start + offset_of_first_trampoline_in_page_ +
index * kNativeCallbackTrampolineSize;
#endif
}
FfiCallbackMetadata::MetadataEntry*
FfiCallbackMetadata::MetadataEntryOfTrampoline(Trampoline trampoline) const {
#if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)
if (FLAG_use_simulator) {
const uword page_start =
Utils::RoundDown(trampoline - offset_of_first_trampoline_in_page_,
VirtualMemory::PageSize());
const uword index =
(trampoline - offset_of_first_trampoline_in_page_ - page_start) /
kNativeCallbackTrampolineSize;
ASSERT(index < NumCallbackTrampolinesPerPage());
MetadataEntry* metadata_etnry_table = reinterpret_cast<MetadataEntry*>(
original_metadata_page_->start() + MetadataOffset());
return metadata_etnry_table + index;
} else {
const uword start = MappingStart(trampoline);
MetadataEntry* metadata_entries =
reinterpret_cast<MetadataEntry*>(start + MetadataOffset());
const uword index =
(trampoline - start - offset_of_first_trampoline_in_page_) /
kNativeCallbackTrampolineSize;
return &metadata_entries[index];
}
#else
const uword start = MappingStart(trampoline);
MetadataEntry* metadata_entries =
reinterpret_cast<MetadataEntry*>(start + MetadataOffset());
@@ -461,7 +412,6 @@ FfiCallbackMetadata::MetadataEntryOfTrampoline(Trampoline trampoline) const {
(trampoline - start - offset_of_first_trampoline_in_page_) /
kNativeCallbackTrampolineSize;
return &metadata_entries[index];
#endif
}
FfiCallbackMetadata::Metadata
+1 -13
View File
@@ -62,10 +62,7 @@ class FfiCallbackMetadata {
enum RuntimeFunctions {
kGetFfiCallbackMetadata,
kExitTemporaryIsolate,
kExitIsolateGroupBoundIsolate,
kExitSyncCallbackTargetIsolate,
kExitSyncCallback,
kDoRedirectedFfiCallback,
kNumRuntimeFunctions,
};
@@ -397,15 +394,6 @@ class FfiCallbackMetadata {
MetadataEntry* free_list_head_ = nullptr;
MetadataEntry* free_list_tail_ = nullptr;
#if (defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64))
// TODO(https://dartbug.com/52579): Remove.
// On simulator FFI, SimulatorFfiCallbackTrampoline cannot be duplicated
// because it contains a PC-relative call. It would need to be replaced with
// something like normal stub's PC-relative loading to a corresponding data
// page, or if we can assume the initial-exec code model a TLS load.
VirtualMemory* original_metadata_page_ = nullptr;
#endif // defined(DART_TARGET_OS_FUCHSIA)
DISALLOW_COPY_AND_ASSIGN(FfiCallbackMetadata);
};
+26 -10
View File
@@ -6,6 +6,12 @@
// This is not written as VM stub because we need it be executable in contexts where we cannot JIT.
// (Alternatively, we could start requiring the VM snapshot to be provided in every mode.)
#if defined(__APPLE__)
#define LOCAL_SYMBOL(x) L##x
#else
#define LOCAL_SYMBOL(x) .L##x
#endif
#if defined(__aarch64__) && (defined(SIMULATOR_FFI) || (defined(DART_DYNAMIC_MODULES) && !defined(DART_PRECOMPILED_RUNTIME)))
.text
@@ -31,11 +37,11 @@ FfiCallTrampoline:
// Copy top frame from Dart stack to C stack
ldr x0, [x19, #0] // FfiCallArguments.stack_area
ldr x1, [x19, #8] // FfiCallArguments.stack_area_end
.Lcopy1:
LOCAL_SYMBOL(copy1):
ldp x2, x3, [x1, #-16]! // From stack_area
stp x2, x3, [sp, #-16]! // To C SP
cmp x1, x0
b.gt .Lcopy1
b.gt LOCAL_SYMBOL(copy1)
// Load the ABI argument registers. Note that Dart FFI does not support
// full 128-bit SIMD arguments, so we don't need to set the full V
@@ -92,11 +98,11 @@ SimulatorFfiCalloutTrampoline:
ldr x1, [x19, #24] // CalloutContext.simulator_frame_pointer
add x1, x1, 15 // Round up the frame pointer, since the Dart frame pointer
and x1, x1, ~15 // is not double-word aligned.
.Lcopy2:
LOCAL_SYMBOL(copy2):
ldp x2, x3, [x1, #-16]! // From Dart FP
stp x2, x3, [sp, #-16]! // To C SP
cmp x1, x0
b.gt .Lcopy2
b.gt LOCAL_SYMBOL(copy2)
// Load the ABI argument registers. Note that Dart FFI does not support
// full 128-bit SIMD arguments, so we don't need to set the full V
@@ -137,12 +143,16 @@ _SimulatorFfiCallbackTrampoline:
.type SimulatorFfiCallbackTrampoline, %function
SimulatorFfiCallbackTrampoline:
#endif
// FfiCallbackMetadata::NumCallbackTrampolinesPerPage() == 8150
.rept 8150
LOCAL_SYMBOL(start):
#if defined(__APPLE__)
.rept 2019 // FfiCallbackMetadata::NumCallbackTrampolinesPerPage()
#else
.rept 8163 // FfiCallbackMetadata::NumCallbackTrampolinesPerPage()
#endif
adr x9, 0
b .Lbody
b LOCAL_SYMBOL(body)
.endr
.Lbody:
LOCAL_SYMBOL(body):
mov x10, sp
stp fp, lr, [sp, #-16]!
mov fp, sp
@@ -164,11 +174,17 @@ SimulatorFfiCallbackTrampoline:
// Pass arguments registers and thunk address to the runtime.
mov x0, sp
mov x1, x9 // I.e., which callback.
adr x2, LOCAL_SYMBOL(start)
#if defined(__APPLE__)
bl _DoRedirectedFfiCallback
and x2, x2, ~(0x4000-1) // FfiCallbackMetadata::kPageSize = 16k
add x2, x2, 0x8000
#else
bl DoRedirectedFfiCallback
and x2, x2, ~(0x10000-1) // FfiCallbackMetadata::kPageSize = 64k
add x2, x2, 0x20000
#endif
ldr x2, [x2, #8] // FfiCallbackMetadata::kDoRedirectedFfiCallback
blr x2 // DoRedirectedFfiCallback
// Load ABI result registers.
ldp x0, x1, [sp, #0] // CallbackContext.integer_arguments[0]
+11
View File
@@ -1831,6 +1831,17 @@ struct CallbackContext {
extern "C" void DoRedirectedFfiCallback(CallbackContext* ctxt,
uword trampoline) {
// Assumptions in ffi_trampolines_arm64.S
COMPILE_ASSERT(sizeof(CallbackContext) == 144);
COMPILE_ASSERT(FfiCallbackMetadata::kDoRedirectedFfiCallback == 1);
#if defined(DART_TARGET_OS_MACOS)
COMPILE_ASSERT(FfiCallbackMetadata::kPageSize == 16 * KB);
COMPILE_ASSERT(FfiCallbackMetadata::NumCallbackTrampolinesPerPage() == 2019);
#else
COMPILE_ASSERT(FfiCallbackMetadata::kPageSize == 64 * KB);
COMPILE_ASSERT(FfiCallbackMetadata::NumCallbackTrampolinesPerPage() == 8163);
#endif
CallbackMetadata out;
Thread* thread = DLRT_GetFfiCallbackMetadata(trampoline, &out);
if (thread == nullptr) {