Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 762c507

Browse files
dcharkesCommit Queue
authored andcommitted
[vm/ffi] Outlining state transitions in AOT
For single argument FFI calls: - reduces trampoline size significantly (up to 50%, 150-170 bytes), - reduces the compressed size of GPay by 2.5kb on arm64, - regresses performance on arm64 (up to 2.5%). For more arguments, percentage-wise size gains and speed regressions are smaller. Only applied on arm and arm64, we care about code size for these. Note: On Raspberry Pie (arm), the performance regression on single- argument calls regresses up to 30%. TEST=tests/ffi/* Design doc: https://go/dart-ffi-outline-state-transitions Closes: dart-lang/sdk#50094 Change-Id: I8b8d7da45f69be6ac1432b11b695de71e56acfd1 Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,vm-ffi-android-debug-arm64c-try,vm-ffi-android-debug-arm-try,vm-kernel-nnbd-mac-debug-arm64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262343 Reviewed-by: Martin Kustermann <[email protected]> Commit-Queue: Daco Harkes <[email protected]>
1 parent c13676f commit 762c507

File tree

2 files changed

+22
-58
lines changed

2 files changed

+22
-58
lines changed

runtime/vm/compiler/backend/il_arm.cc

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,32 +1501,18 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
15011501
env());
15021502

15031503
// Update information in the thread object and enter a safepoint.
1504-
if (CanExecuteGeneratedCodeInSafepoint()) {
1505-
__ LoadImmediate(temp1, compiler::target::Thread::exit_through_ffi());
1506-
__ TransitionGeneratedToNative(branch, FPREG, temp1, saved_fp_or_sp,
1507-
/*enter_safepoint=*/true);
1508-
1509-
__ blx(branch);
1510-
1511-
// Update information in the thread object and leave the safepoint.
1512-
__ TransitionNativeToGenerated(saved_fp_or_sp, temp1,
1513-
/*leave_safepoint=*/true);
1514-
} else {
1515-
// We cannot trust that this code will be executable within a safepoint.
1516-
// Therefore we delegate the responsibility of entering/exiting the
1517-
// safepoint to a stub which in the VM isolate's heap, which will never
1518-
// lose execute permission.
1519-
__ ldr(temp1,
1520-
compiler::Address(
1521-
THR, compiler::target::Thread::
1522-
call_native_through_safepoint_entry_point_offset()));
1523-
1524-
// Calls R8 in a safepoint and clobbers R4 and NOTFP.
1525-
ASSERT(branch == R8);
1526-
static_assert((kReservedCpuRegisters & (1 << NOTFP)) != 0,
1527-
"NOTFP should be a reserved register");
1528-
__ blx(temp1);
1529-
}
1504+
// Outline state transition. In AOT, for code size. In JIT, because we
1505+
// cannot trust that code will be executable.
1506+
__ ldr(temp1,
1507+
compiler::Address(
1508+
THR, compiler::target::Thread::
1509+
call_native_through_safepoint_entry_point_offset()));
1510+
1511+
// Calls R8 in a safepoint and clobbers R4 and NOTFP.
1512+
ASSERT(branch == R8);
1513+
static_assert((kReservedCpuRegisters & (1 << NOTFP)) != 0,
1514+
"NOTFP should be a reserved register");
1515+
__ blx(temp1);
15301516

15311517
if (marshaller_.IsHandle(compiler::ffi::kResultIndex)) {
15321518
__ Comment("Check Dart_Handle for Error.");

runtime/vm/compiler/backend/il_arm64.cc

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,39 +1371,17 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
13711371

13721372
__ StoreToOffset(temp1, FPREG, kSavedCallerPcSlotFromFp * kWordSize);
13731373

1374-
if (CanExecuteGeneratedCodeInSafepoint()) {
1375-
// Update information in the thread object and enter a safepoint.
1376-
__ LoadImmediate(temp1, compiler::target::Thread::exit_through_ffi());
1377-
__ TransitionGeneratedToNative(branch, FPREG, temp1,
1378-
/*enter_safepoint=*/true);
1379-
1380-
// We are entering runtime code, so the C stack pointer must be restored
1381-
// from the stack limit to the top of the stack.
1382-
__ mov(temp_csp, CSP);
1383-
__ mov(CSP, SP);
1384-
1385-
__ blr(branch);
1386-
1387-
// Restore the Dart stack pointer.
1388-
__ mov(SP, CSP);
1389-
__ mov(CSP, temp_csp);
1390-
1391-
// Update information in the thread object and leave the safepoint.
1392-
__ TransitionNativeToGenerated(temp1, /*leave_safepoint=*/true);
1393-
} else {
1394-
// We cannot trust that this code will be executable within a safepoint.
1395-
// Therefore we delegate the responsibility of entering/exiting the
1396-
// safepoint to a stub which in the VM isolate's heap, which will never
1397-
// lose execute permission.
1398-
__ ldr(temp1,
1399-
compiler::Address(
1400-
THR, compiler::target::Thread::
1401-
call_native_through_safepoint_entry_point_offset()));
1374+
// Update information in the thread object and enter a safepoint.
1375+
// Outline state transition. In AOT, for code size. In JIT, because we
1376+
// cannot trust that code will be executable.
1377+
__ ldr(temp1,
1378+
compiler::Address(
1379+
THR, compiler::target::Thread::
1380+
call_native_through_safepoint_entry_point_offset()));
14021381

1403-
// Calls R9 and clobbers R19 (along with volatile registers).
1404-
ASSERT(branch == R9);
1405-
__ blr(temp1);
1406-
}
1382+
// Calls R9 and clobbers R19 (along with volatile registers).
1383+
ASSERT(branch == R9);
1384+
__ blr(temp1);
14071385

14081386
if (marshaller_.IsHandle(compiler::ffi::kResultIndex)) {
14091387
__ Comment("Check Dart_Handle for Error.");

0 commit comments

Comments
 (0)