Skip to content

Commit 7fbec00

Browse files
rmacnak-googleCommit Queue
authored andcommitted
[vm, simarm64] Handle FFI callouts.
TEST=ci Bug: #60204 Change-Id: I2a7546cea0886b05873dbc59f5c9f049aad963c7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/411960 Reviewed-by: Daco Harkes <[email protected]> Commit-Queue: Ryan Macnak <[email protected]>
1 parent 961aa05 commit 7fbec00

File tree

13 files changed

+171
-9
lines changed

13 files changed

+171
-9
lines changed

runtime/BUILD.gn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ config("dart_arch_config") {
149149
}
150150
if (dart_force_simulator) {
151151
defines += [ "USING_SIMULATOR" ]
152+
if (dart_target_arch == "arm64") {
153+
defines += [ "SIMULATOR_FFI" ]
154+
}
152155
}
153156
}
154157

runtime/lib/ffi_dynamic_library.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@
2929

3030
namespace dart {
3131

32-
#if defined(USING_SIMULATOR) || (defined(DART_PRECOMPILER) && !defined(TESTING))
32+
#if (defined(USING_SIMULATOR) && !defined(SIMULATOR_FFI)) || \
33+
(defined(DART_PRECOMPILER) && !defined(TESTING))
3334

3435
DART_NORETURN static void SimulatorUnsupported() {
3536
#if defined(USING_SIMULATOR)
36-
Exceptions::ThrowUnsupportedError(
37-
"Not supported on simulated architectures.");
37+
Exceptions::ThrowUnsupportedError("Not supported on this simulator.");
3838
#else
3939
Exceptions::ThrowUnsupportedError("Not supported in precompiler.");
4040
#endif
@@ -516,7 +516,7 @@ DEFINE_NATIVE_ENTRY(Ffi_GetFfiNativeResolver, 1, 0) {
516516
return Pointer::New(reinterpret_cast<intptr_t>(FfiResolve));
517517
}
518518

519-
#endif // defined(USING_SIMULATOR) || \
519+
#endif // (defined(USING_SIMULATOR) && !defined (SIMULATOR_FFI)) || \
520520
// (defined(DART_PRECOMPILER) && !defined(TESTING))
521521

522522
} // namespace dart

runtime/tests/vm/vm.status

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ cc/Service_Profile: SkipByDesign
196196
dart/ffi_structs_optimizations_il_test: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
197197
dart/gc/splay_c_finalizer_test: SkipByDesign # No FFI on simulators
198198
dart/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
199+
dart/isolates/many_isolates_blocked_at_monitor_test: SkipByDesign # https://dartbug.com/37299 FFI not supported on simulator
199200
dart/isolates/regress_54528_test: SkipByDesign # Invokes gen_kernel/gen_snapshot
200201
dart/isolates/shared_test: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
201202
dart/isolates/thread_pool_test: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.

runtime/vm/BUILD.gn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ library_for_all_configs("libdart_vm") {
202202
# uses different assembler syntax.
203203
sources += [ "thread_interrupter_android_arm.S" ]
204204
}
205+
if (!is_win) {
206+
sources += [ "simulator_arm64_trampolines.S" ]
207+
}
205208
include_dirs = [ ".." ]
206209
}
207210

runtime/vm/compiler/backend/il_arm64.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,6 +1428,10 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
14281428
__ mov(temp_csp, CSP);
14291429
__ mov(CSP, SP);
14301430

1431+
#if defined(SIMULATOR_FFI)
1432+
__ Emit(Instr::kSimulatorFfiRedirectInstruction);
1433+
ASSERT(branch == R9);
1434+
#endif
14311435
__ blr(branch);
14321436

14331437
// Restore the Dart stack pointer.

runtime/vm/compiler/backend/locations.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,9 @@ class RegisterSet : public ValueObject {
712712
if (reg == PC) continue;
713713
#elif defined(TARGET_ARCH_ARM64)
714714
if (reg == R31) continue;
715+
#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_WINDOWS)
716+
if (reg == R18) continue;
717+
#endif
715718
#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
716719
if (reg == ZR || reg == TP || reg == GP) continue;
717720
#endif

runtime/vm/compiler/stub_code_compiler_arm64.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,9 @@ void StubCodeCompiler::GenerateCallNativeThroughSafepointStub() {
433433
__ Bind(&done);
434434
#endif
435435

436+
#if defined(SIMULATOR_FFI)
437+
__ Emit(Instr::kSimulatorFfiRedirectInstruction);
438+
#endif
436439
__ blr(R9);
437440

438441
__ mov(SP, CSP);

runtime/vm/constants_arm64.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,8 @@ class Instr {
13361336
static constexpr int32_t kSimulatorBreakCode =
13371337
0xdeb2; // For breakpoint in sim.
13381338
static constexpr int32_t kSimulatorRedirectCode = 0xca11; // For redirection.
1339+
static constexpr int32_t kSimulatorFfiRedirectCode =
1340+
0xca12; // For redirection.
13391341

13401342
// Breakpoint instruction filling assembler code buffers in debug mode.
13411343
static constexpr int32_t kBreakPointInstruction = // brk(0xdeb0).
@@ -1350,6 +1352,8 @@ class Instr {
13501352
// Runtime call redirection instruction used by the simulator.
13511353
static constexpr int32_t kSimulatorRedirectInstruction =
13521354
HLT | (kSimulatorRedirectCode << kImm16Shift);
1355+
static constexpr int32_t kSimulatorFfiRedirectInstruction =
1356+
HLT | (kSimulatorFfiRedirectCode << kImm16Shift);
13531357

13541358
// Read one particular bit out of the instruction bits.
13551359
inline int Bit(int nr) const { return (InstructionBits() >> nr) & 1; }

runtime/vm/simulator_arm.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1421,7 +1421,7 @@ void Simulator::SupervisorCall(Instr* instr) {
14211421
Redirection* redirection = Redirection::FromSvcInstruction(instr);
14221422
uword external = redirection->external_function();
14231423
if (IsTracingExecution()) {
1424-
THR_Print("Call to host function at 0x%" Pd "\n", external);
1424+
THR_Print("Call to host function at 0x%" Px "\n", external);
14251425
}
14261426
if (redirection->call_kind() == kRuntimeCall) {
14271427
NativeArguments arguments;

runtime/vm/simulator_arm64.cc

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -950,8 +950,9 @@ void Simulator::set_register(Instr* instr,
950950
R31Type r31t) {
951951
// Register is in range.
952952
ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
953-
#if !defined(DART_TARGET_OS_FUCHSIA)
954-
ASSERT(instr == nullptr || reg != R18); // R18 is globally reserved on iOS.
953+
#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_WINDOWS)
954+
// R18 is globally reserved on macOS/iOS, the TEB pointer on Windows.
955+
ASSERT(instr == nullptr || reg != R18);
955956
#endif
956957

957958
if ((reg != R31) || (r31t != R31IsZR)) {
@@ -1682,7 +1683,7 @@ void Simulator::DoRedirectedCall(Instr* instr) {
16821683
Redirection* redirection = Redirection::FromHltInstruction(instr);
16831684
uword external = redirection->external_function();
16841685
if (IsTracingExecution()) {
1685-
THR_Print("Call to host function at 0x%" Pd "\n", external);
1686+
THR_Print("Call to host function at 0x%" Px "\n", external);
16861687
}
16871688

16881689
if (redirection->call_kind() == kRuntimeCall) {
@@ -1746,6 +1747,65 @@ void Simulator::DoRedirectedCall(Instr* instr) {
17461747
}
17471748
}
17481749

1750+
struct CalloutContext {
1751+
uword saved_stack_pointer;
1752+
uword saved_frame_pointer;
1753+
uword simulator_stack_pointer;
1754+
uword simulator_frame_pointer;
1755+
uword integer_arguments[8];
1756+
uword double_arguments[8];
1757+
uword r8;
1758+
uword target;
1759+
};
1760+
1761+
extern "C" void FfiCalloutTrampoline(CalloutContext*);
1762+
1763+
void Simulator::DoRedirectedFfiCall(Instr* instr) {
1764+
#if !defined(HOST_ARCH_ARM64)
1765+
FATAL("Unsupported FFI call");
1766+
#else
1767+
// We can't instrument the runtime.
1768+
memory_.FlushAll();
1769+
1770+
SimulatorSetjmpBuffer buffer(this);
1771+
if (!setjmp(buffer.buffer_)) {
1772+
int64_t saved_pc = get_pc();
1773+
uword external = get_register(R9);
1774+
if (IsTracingExecution()) {
1775+
THR_Print("Call to FFI function at 0x%" Px "\n", external);
1776+
}
1777+
1778+
CalloutContext ctxt;
1779+
ctxt.simulator_stack_pointer = get_register(R31);
1780+
ctxt.simulator_frame_pointer = get_register(FP);
1781+
for (intptr_t i = 0; i < 8; i++) {
1782+
ctxt.integer_arguments[i] = get_register(static_cast<Register>(R0 + i));
1783+
ctxt.double_arguments[i] =
1784+
get_vregisterd(static_cast<VRegister>(V0 + i), 0);
1785+
}
1786+
ctxt.r8 = get_register(R8);
1787+
ctxt.target = external;
1788+
1789+
FfiCalloutTrampoline(&ctxt);
1790+
1791+
if (IsTracingExecution()) {
1792+
THR_Print("Return from FFI function at 0x%" Px "\n", external);
1793+
}
1794+
1795+
ClobberVolatileRegisters();
1796+
set_register(instr, R0, ctxt.integer_arguments[0]);
1797+
set_register(instr, R1, ctxt.integer_arguments[1]);
1798+
set_vregisterd(V0, 0, ctxt.double_arguments[0]);
1799+
set_vregisterd(V1, 0, ctxt.double_arguments[1]);
1800+
1801+
// Skip over hlt and blr.
1802+
set_pc(saved_pc + 2 * Instr::kInstrSize);
1803+
} else {
1804+
// Coming via long jump from a throw. Continue to exception handler.
1805+
}
1806+
#endif
1807+
}
1808+
17491809
void Simulator::ClobberVolatileRegisters() {
17501810
// Clear atomic reservation.
17511811
exclusive_access_addr_ = exclusive_access_value_ = 0;
@@ -1787,6 +1847,8 @@ void Simulator::DecodeExceptionGen(Instr* instr) {
17871847
dbg.Stop(instr, "breakpoint");
17881848
} else if (imm == Instr::kSimulatorRedirectCode) {
17891849
DoRedirectedCall(instr);
1850+
} else if (imm == Instr::kSimulatorFfiRedirectCode) {
1851+
DoRedirectedFfiCall(instr);
17901852
} else {
17911853
UnimplementedInstruction(instr);
17921854
}

0 commit comments

Comments
 (0)