[vm, compiler] Create a proper frame in the FFI callback trampoline.
TEST=ci Bug: https://github.com/dart-lang/sdk/issues/62932 Change-Id: I2b8de8555b3810e4838f4ac36d590a24159291ec Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/490740 Reviewed-by: Alexander Aprelev <aam@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
committed by
Commit Queue
parent
0b9b70a81b
commit
91cef061c7
@@ -2445,6 +2445,27 @@ void Assembler::PopRegisters(const RegisterSet& regs) {
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::PushRegistersAligned(const RegisterSet& register_set,
|
||||
intptr_t space) {
|
||||
PushRegisters(register_set);
|
||||
intptr_t aligned_space = Utils::RoundUp(register_set.SpillSize() + space,
|
||||
OS::ActivationFrameAlignment()) -
|
||||
register_set.SpillSize();
|
||||
if (aligned_space != 0) {
|
||||
sub(SP, SP, Operand(aligned_space));
|
||||
}
|
||||
}
|
||||
void Assembler::PopRegistersAligned(const RegisterSet& register_set,
|
||||
intptr_t space) {
|
||||
intptr_t aligned_space = Utils::RoundUp(register_set.SpillSize() + space,
|
||||
OS::ActivationFrameAlignment()) -
|
||||
register_set.SpillSize();
|
||||
if (aligned_space != 0) {
|
||||
add(SP, SP, Operand(aligned_space));
|
||||
}
|
||||
PopRegisters(register_set);
|
||||
}
|
||||
|
||||
void Assembler::PushRegistersInOrder(std::initializer_list<Register> regs) {
|
||||
// Collect the longest descending sequences of registers and
|
||||
// push them with a single STMDB instruction.
|
||||
|
||||
@@ -1280,6 +1280,8 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
void PushRegisters(const RegisterSet& regs);
|
||||
void PopRegisters(const RegisterSet& regs);
|
||||
void PushRegistersAligned(const RegisterSet& registers, intptr_t space);
|
||||
void PopRegistersAligned(const RegisterSet& registers, intptr_t space);
|
||||
|
||||
void PushRegistersInOrder(std::initializer_list<Register> regs);
|
||||
|
||||
|
||||
@@ -2406,6 +2406,27 @@ void Assembler::PopRegisters(const RegisterSet& regs) {
|
||||
ASSERT(vprev == kNoVRegister);
|
||||
}
|
||||
|
||||
void Assembler::PushRegistersAligned(const RegisterSet& register_set,
|
||||
intptr_t space) {
|
||||
PushRegisters(register_set);
|
||||
intptr_t aligned_space = Utils::RoundUp(register_set.SpillSize() + space,
|
||||
OS::ActivationFrameAlignment()) -
|
||||
register_set.SpillSize();
|
||||
if (aligned_space != 0) {
|
||||
sub(SP, SP, Operand(aligned_space));
|
||||
}
|
||||
}
|
||||
void Assembler::PopRegistersAligned(const RegisterSet& register_set,
|
||||
intptr_t space) {
|
||||
intptr_t aligned_space = Utils::RoundUp(register_set.SpillSize() + space,
|
||||
OS::ActivationFrameAlignment()) -
|
||||
register_set.SpillSize();
|
||||
if (aligned_space != 0) {
|
||||
add(SP, SP, Operand(aligned_space));
|
||||
}
|
||||
PopRegisters(register_set);
|
||||
}
|
||||
|
||||
void Assembler::PushRegistersInOrder(std::initializer_list<Register> regs) {
|
||||
// Use STP to push registers in pairs.
|
||||
Register pending_reg = kNoRegister;
|
||||
|
||||
@@ -459,6 +459,8 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
void PushRegisters(const RegisterSet& registers);
|
||||
void PopRegisters(const RegisterSet& registers);
|
||||
void PushRegistersAligned(const RegisterSet& registers, intptr_t space);
|
||||
void PopRegistersAligned(const RegisterSet& registers, intptr_t space);
|
||||
|
||||
void PushRegistersInOrder(std::initializer_list<Register> regs);
|
||||
|
||||
|
||||
@@ -3147,6 +3147,27 @@ void Assembler::PopRegisters(const RegisterSet& regs) {
|
||||
addi(SP, SP, size);
|
||||
}
|
||||
|
||||
void Assembler::PushRegistersAligned(const RegisterSet& register_set,
|
||||
intptr_t space) {
|
||||
PushRegisters(register_set);
|
||||
intptr_t aligned_space = Utils::RoundUp(register_set.SpillSize() + space,
|
||||
OS::ActivationFrameAlignment()) -
|
||||
register_set.SpillSize();
|
||||
if (aligned_space != 0) {
|
||||
subi(SP, SP, aligned_space);
|
||||
}
|
||||
}
|
||||
void Assembler::PopRegistersAligned(const RegisterSet& register_set,
|
||||
intptr_t space) {
|
||||
intptr_t aligned_space = Utils::RoundUp(register_set.SpillSize() + space,
|
||||
OS::ActivationFrameAlignment()) -
|
||||
register_set.SpillSize();
|
||||
if (aligned_space != 0) {
|
||||
addi(SP, SP, aligned_space);
|
||||
}
|
||||
PopRegisters(register_set);
|
||||
}
|
||||
|
||||
void Assembler::PushRegistersInOrder(std::initializer_list<Register> regs) {
|
||||
intptr_t offset = regs.size() * target::kWordSize;
|
||||
subi(SP, SP, offset);
|
||||
|
||||
@@ -1030,6 +1030,8 @@ class Assembler : public MicroAssembler {
|
||||
|
||||
void PushRegisters(const RegisterSet& registers);
|
||||
void PopRegisters(const RegisterSet& registers);
|
||||
void PushRegistersAligned(const RegisterSet& registers, intptr_t space);
|
||||
void PopRegistersAligned(const RegisterSet& registers, intptr_t space);
|
||||
|
||||
void PushRegistersInOrder(std::initializer_list<Register> regs);
|
||||
|
||||
|
||||
@@ -2022,6 +2022,27 @@ void Assembler::PopRegisters(const RegisterSet& register_set) {
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::PushRegistersAligned(const RegisterSet& register_set,
|
||||
intptr_t space) {
|
||||
PushRegisters(register_set);
|
||||
intptr_t aligned_space = Utils::RoundUp(register_set.SpillSize() + space,
|
||||
OS::ActivationFrameAlignment()) -
|
||||
register_set.SpillSize();
|
||||
if (aligned_space != 0) {
|
||||
subq(RSP, Immediate(aligned_space));
|
||||
}
|
||||
}
|
||||
void Assembler::PopRegistersAligned(const RegisterSet& register_set,
|
||||
intptr_t space) {
|
||||
intptr_t aligned_space = Utils::RoundUp(register_set.SpillSize() + space,
|
||||
OS::ActivationFrameAlignment()) -
|
||||
register_set.SpillSize();
|
||||
if (aligned_space != 0) {
|
||||
addq(RSP, Immediate(aligned_space));
|
||||
}
|
||||
PopRegisters(register_set);
|
||||
}
|
||||
|
||||
void Assembler::PushRegistersInOrder(std::initializer_list<Register> regs) {
|
||||
for (Register reg : regs) {
|
||||
PushRegister(reg);
|
||||
|
||||
@@ -951,6 +951,8 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
void PushRegisters(const RegisterSet& registers);
|
||||
void PopRegisters(const RegisterSet& registers);
|
||||
void PushRegistersAligned(const RegisterSet& registers, intptr_t space);
|
||||
void PopRegistersAligned(const RegisterSet& registers, intptr_t space);
|
||||
|
||||
void PushRegistersInOrder(std::initializer_list<Register> regs);
|
||||
|
||||
|
||||
@@ -326,9 +326,8 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
for (intptr_t i = 0; i < FfiCallbackMetadata::NumCallbackTrampolinesPerPage();
|
||||
++i) {
|
||||
// The FfiCallbackMetadata table is keyed by the trampoline entry point. So
|
||||
// look up the current PC, then jump to the shared section. The PC is offset
|
||||
// by Instr::kPCReadOffset, which is subtracted below.
|
||||
__ mov(TMP, Operand(PC));
|
||||
// look up the current PC, then jump to the shared section.
|
||||
__ sub(TMP, PC, Operand(Instr::kPCReadOffset));
|
||||
__ b(&body);
|
||||
}
|
||||
|
||||
@@ -340,30 +339,24 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
|
||||
const intptr_t shared_stub_start = __ CodeSize();
|
||||
|
||||
// Save THR (callee-saved), R4 & R5 (temporaries, callee-saved), and LR.
|
||||
// Save LR, FP, THR (callee-saved) & R4 (temporaries, callee-saved).
|
||||
COMPILE_ASSERT(FfiCallbackMetadata::kNativeCallbackTrampolineStackDelta == 4);
|
||||
SPILLS_LR_TO_FRAME(
|
||||
__ PushList((1 << LR) | (1 << THR) | (1 << R4) | (1 << R5)));
|
||||
|
||||
// The PC is in TMP, but is offset by kPCReadOffset. To get the actual
|
||||
// trampoline entry point we need to subtract that.
|
||||
__ sub(R4, TMP, Operand(Instr::kPCReadOffset));
|
||||
SPILLS_LR_TO_FRAME(__ EnterFrame((1 << FP) | (1 << LR), 0));
|
||||
__ PushList((1 << THR) | (1 << R4));
|
||||
|
||||
COMPILE_ASSERT(IsCalleeSavedRegister(R4));
|
||||
COMPILE_ASSERT(!IsArgumentRegister(THR));
|
||||
|
||||
RegisterSet argument_registers;
|
||||
argument_registers.AddAllArgumentRegisters();
|
||||
__ PushRegisters(argument_registers);
|
||||
|
||||
// Load the thread, verify the callback ID and exit the safepoint.
|
||||
//
|
||||
// We exit the safepoint inside DLRT_GetFfiCallbackMetadata in order to save
|
||||
// code size on this shared stub.
|
||||
{
|
||||
__ EnterFrame(1 << FP, 0);
|
||||
__ ReserveAlignedFrameSpace(3 * target::kWordSize);
|
||||
__ mov(R0, Operand(R4));
|
||||
__ PushRegistersAligned(argument_registers, 3 * target::kWordSize);
|
||||
__ mov(R0, Operand(TMP));
|
||||
__ mov(R1, Operand(SP));
|
||||
|
||||
GenerateLoadFfiCallbackMetadataRuntimeFunction(
|
||||
@@ -372,37 +365,35 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
__ blx(R4);
|
||||
__ mov(THR, Operand(R0));
|
||||
|
||||
__ ldr(TMP, Address(SP, 0 * target::kWordSize)); // entry_point
|
||||
__ ldr(R4, Address(SP, 1 * target::kWordSize)); // is_tail
|
||||
__ ldr(R5, Address(SP, 2 * target::kWordSize)); // epilogue
|
||||
__ ldr(TMP, Address(SP, 0 * target::kWordSize)); // entry_point
|
||||
CLOBBERS_LR(__ ldr(LR, Address(SP, 1 * target::kWordSize))); // is_tail
|
||||
__ ldr(R4, Address(SP, 2 * target::kWordSize)); // epilogue
|
||||
|
||||
__ LeaveFrame(1 << FP);
|
||||
__ PopRegistersAligned(argument_registers, 3 * target::kWordSize);
|
||||
}
|
||||
|
||||
__ PopRegisters(argument_registers);
|
||||
|
||||
Label tail;
|
||||
__ cmp(R4, Operand(0));
|
||||
CLOBBERS_LR(__ cmp(LR, Operand(0)));
|
||||
__ b(&tail, NOT_ZERO);
|
||||
|
||||
const RegisterSet return_registers(
|
||||
(1 << CallingConventions::kReturnReg) |
|
||||
(1 << CallingConventions::kSecondReturnReg),
|
||||
1 << CallingConventions::kReturnFpuReg);
|
||||
ASSERT(Utils::IsAligned(return_registers.SpillSize(), 8));
|
||||
|
||||
{
|
||||
__ blx(TMP); // entry_point
|
||||
__ PushRegisters(return_registers);
|
||||
__ PushRegistersAligned(return_registers, 0);
|
||||
__ mov(R0, Operand(THR));
|
||||
__ blx(R5); // DLRT_ExitSyncCallback, etc
|
||||
__ blx(R4); // DLRT_ExitSyncCallback, etc
|
||||
if (FLAG_target_memory_sanitizer) {
|
||||
__ blx(R0); // dart_msan_unpoison_retval
|
||||
}
|
||||
__ PopRegisters(return_registers);
|
||||
__ PopRegistersAligned(return_registers, 0);
|
||||
__ PopList((1 << THR) | (1 << R4));
|
||||
// Returns.
|
||||
RESTORES_LR_FROM_FRAME(
|
||||
__ PopList((1 << PC) | (1 << THR) | (1 << R4) | (1 << R5)));
|
||||
RESTORES_LR_FROM_FRAME(__ PopList((1 << PC) | (1 << FP)));
|
||||
__ Breakpoint();
|
||||
}
|
||||
|
||||
{
|
||||
@@ -410,9 +401,9 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
__ Bind(&tail);
|
||||
__ blx(TMP); // entry_point
|
||||
__ mov(R0, Operand(THR));
|
||||
__ mov(R1, Operand(R5));
|
||||
RESTORES_LR_FROM_FRAME(
|
||||
__ PopList((1 << LR) | (1 << THR) | (1 << R4) | (1 << R5)));
|
||||
__ mov(R1, Operand(R4));
|
||||
__ PopList((1 << THR) | (1 << R4));
|
||||
RESTORES_LR_FROM_FRAME(__ PopList((1 << LR) | (1 << FP)));
|
||||
// Tail-call DLRT_ExitTemporaryIsolate. It is not safe to return to this
|
||||
// stub, since it might be deleted once DLRT_ExitTemporaryIsolate proceeds
|
||||
// enough for VM shutdown.
|
||||
|
||||
@@ -499,14 +499,15 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
// aligned.
|
||||
COMPILE_ASSERT(FfiCallbackMetadata::kNativeCallbackTrampolineStackDelta == 4);
|
||||
SPILLS_LR_TO_FRAME(__ stp(
|
||||
THR, LR, Address(CSP, -2 * target::kWordSize, Address::PairPreIndex)));
|
||||
__ stp(R20, R21, Address(CSP, -2 * target::kWordSize, Address::PairPreIndex));
|
||||
FP, LR, Address(CSP, -2 * target::kWordSize, Address::PairPreIndex)));
|
||||
__ mov(FP, CSP);
|
||||
__ stp(R20, THR, Address(CSP, -2 * target::kWordSize, Address::PairPreIndex));
|
||||
|
||||
COMPILE_ASSERT(!IsArgumentRegister(THR));
|
||||
|
||||
RegisterSet all_registers;
|
||||
all_registers.AddAllArgumentRegisters();
|
||||
all_registers.Add(Location::RegisterLocation(
|
||||
RegisterSet argument_registers;
|
||||
argument_registers.AddAllArgumentRegisters();
|
||||
argument_registers.Add(Location::RegisterLocation(
|
||||
CallingConventions::kPointerToReturnStructRegisterCall));
|
||||
|
||||
// Load the thread, verify the callback ID and exit the safepoint.
|
||||
@@ -514,14 +515,9 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
// We exit the safepoint inside DLRT_GetFfiCallbackMetadata in order to save
|
||||
// code size on this shared stub.
|
||||
{
|
||||
__ SetupDartSP();
|
||||
|
||||
__ EnterFrame(0);
|
||||
__ mov(SP, CSP);
|
||||
// This saves too much: we only need the D half of Q registers.
|
||||
__ PushRegisters(all_registers);
|
||||
|
||||
__ EnterFrame(0);
|
||||
__ ReserveAlignedFrameSpace(3 * target::kWordSize);
|
||||
__ PushRegistersAligned(argument_registers, 3 * target::kWordSize);
|
||||
__ mov(R0, R9);
|
||||
__ mov(R1, SP);
|
||||
|
||||
@@ -549,18 +545,17 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
__ mov(THR, R0);
|
||||
COMPILE_ASSERT(!IsCalleeSavedRegister(R10) && !IsArgumentRegister(R10));
|
||||
__ ldr(R10, Address(CSP, 0 * target::kWordSize)); // entry_point
|
||||
__ ldr(R20, Address(CSP, 1 * target::kWordSize)); // is_tail
|
||||
__ ldr(R21, Address(CSP, 2 * target::kWordSize)); // epilogue
|
||||
COMPILE_ASSERT(!IsCalleeSavedRegister(R11) && !IsArgumentRegister(R11));
|
||||
__ ldr(R11, Address(CSP, 1 * target::kWordSize)); // is_tail
|
||||
COMPILE_ASSERT(IsCalleeSavedRegister(R20));
|
||||
__ ldr(R20, Address(CSP, 2 * target::kWordSize)); // epilogue
|
||||
|
||||
__ LeaveFrame();
|
||||
__ PopRegisters(all_registers);
|
||||
__ LeaveFrame();
|
||||
|
||||
__ RestoreCSP();
|
||||
__ PopRegistersAligned(argument_registers, 3 * target::kWordSize);
|
||||
__ mov(CSP, SP);
|
||||
}
|
||||
|
||||
Label tail;
|
||||
__ cbnz(&tail, R20);
|
||||
__ cbnz(&tail, R11);
|
||||
|
||||
{
|
||||
__ blr(R10); // entry_point
|
||||
@@ -568,17 +563,17 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
__ fstp(V0, V1, Address(CSP, -2 * 8, Address::PairPreIndex), kDWord);
|
||||
__ fstp(V2, V3, Address(CSP, -2 * 8, Address::PairPreIndex), kDWord);
|
||||
__ mov(R0, THR);
|
||||
__ blr(R21); // DLRT_ExitSyncCallback, etc
|
||||
__ blr(R20); // DLRT_ExitSyncCallback, etc
|
||||
if (FLAG_target_memory_sanitizer) {
|
||||
__ blr(R0); // dart_msan_unpoison_retval
|
||||
}
|
||||
__ fldp(V2, V3, Address(CSP, 2 * 8, Address::PairPostIndex), kDWord);
|
||||
__ fldp(V0, V1, Address(CSP, 2 * 8, Address::PairPostIndex), kDWord);
|
||||
__ ldp(R0, R1, Address(CSP, 2 * target::kWordSize, Address::PairPostIndex));
|
||||
__ ldp(R20, R21,
|
||||
__ ldp(R20, THR,
|
||||
Address(CSP, 2 * target::kWordSize, Address::PairPostIndex));
|
||||
RESTORES_LR_FROM_FRAME(__ ldp(
|
||||
THR, LR, Address(CSP, 2 * target::kWordSize, Address::PairPostIndex)));
|
||||
FP, LR, Address(CSP, 2 * target::kWordSize, Address::PairPostIndex)));
|
||||
__ ret();
|
||||
}
|
||||
|
||||
@@ -587,11 +582,11 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
__ Bind(&tail);
|
||||
__ blr(R10);
|
||||
__ mov(R0, THR);
|
||||
__ mov(R1, R21);
|
||||
__ ldp(R20, R21,
|
||||
__ mov(R1, R20);
|
||||
__ ldp(R20, THR,
|
||||
Address(CSP, 2 * target::kWordSize, Address::PairPostIndex));
|
||||
RESTORES_LR_FROM_FRAME(__ ldp(
|
||||
THR, LR, Address(CSP, 2 * target::kWordSize, Address::PairPostIndex)));
|
||||
FP, LR, Address(CSP, 2 * target::kWordSize, Address::PairPostIndex)));
|
||||
// Tail-call DLRT_ExitTemporaryIsolate. It is not safe to return to this
|
||||
// stub, since it might be deleted once DLRT_ExitTemporaryIsolate proceeds
|
||||
// enough for VM shutdown.
|
||||
|
||||
@@ -325,6 +325,15 @@ void StubCodeCompiler::GenerateLoadFfiCallbackMetadataRuntimeFunction(
|
||||
FfiCallbackMetadata::RuntimeFunctionOffset(function_index));
|
||||
}
|
||||
|
||||
static const RegisterSet kArgumentRegisterSet(
|
||||
CallingConventions::kArgumentRegisters,
|
||||
CallingConventions::kFpuArgumentRegisters);
|
||||
static const RegisterSet kReturnRegisterSet(
|
||||
(1 << CallingConventions::kReturnReg) |
|
||||
(1 << CallingConventions::kSecondReturnReg),
|
||||
(1 << CallingConventions::kReturnFpuReg) |
|
||||
(1 << CallingConventions::kSecondReturnFpuReg));
|
||||
|
||||
void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
#if defined(DART_INCLUDE_SIMULATOR) && !defined(DART_PRECOMPILER)
|
||||
// TODO(37299): FFI is not supported in SIMRISCV32/64.
|
||||
@@ -350,10 +359,13 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
|
||||
__ Bind(&body);
|
||||
|
||||
// Save THR (callee-saved) and RA. Keeps stack aligned.
|
||||
COMPILE_ASSERT(FfiCallbackMetadata::kNativeCallbackTrampolineStackDelta == 4);
|
||||
__ PushRegisterPair(RA, THR);
|
||||
__ PushRegisterPair(S2, S3);
|
||||
__ subi(SP, SP, 4 * target::kWordSize);
|
||||
__ sx(RA, Address(SP, 3 * target::kWordSize));
|
||||
__ sx(FP, Address(SP, 2 * target::kWordSize));
|
||||
__ sx(THR, Address(SP, 1 * target::kWordSize));
|
||||
__ sx(S2, Address(SP, 0 * target::kWordSize));
|
||||
__ addi(FP, SP, 4 * target::kWordSize);
|
||||
COMPILE_ASSERT(!IsArgumentRegister(THR));
|
||||
|
||||
// Load the thread, verify the callback ID and exit the safepoint.
|
||||
@@ -361,21 +373,7 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
// We exit the safepoint inside DLRT_GetFfiCallbackMetadata in order to save
|
||||
// code size on this shared stub.
|
||||
{
|
||||
// Push arguments and callback id.
|
||||
__ subi(SP, SP, 12 * target::kWordSize);
|
||||
__ sx(A7, Address(SP, 11 * target::kWordSize));
|
||||
__ sx(A6, Address(SP, 10 * target::kWordSize));
|
||||
__ sx(A5, Address(SP, 9 * target::kWordSize));
|
||||
__ sx(A4, Address(SP, 8 * target::kWordSize));
|
||||
__ sx(A3, Address(SP, 7 * target::kWordSize));
|
||||
__ sx(A2, Address(SP, 6 * target::kWordSize));
|
||||
__ sx(A1, Address(SP, 5 * target::kWordSize));
|
||||
__ sx(A0, Address(SP, 4 * target::kWordSize));
|
||||
// 3 - alignment gap
|
||||
// 2 - Out.epilogue
|
||||
// 1 - Out.is_tail
|
||||
// 0 - Out.entry_point
|
||||
|
||||
__ PushRegistersAligned(kArgumentRegisterSet, 3 * target::kWordSize);
|
||||
__ mv(A0, T1);
|
||||
__ mv(A1, SP);
|
||||
|
||||
@@ -411,42 +409,29 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
__ jalr(T1);
|
||||
__ mv(THR, A0);
|
||||
__ lx(T2, Address(SP, 0 * target::kWordSize)); // entry_point
|
||||
__ lx(S2, Address(SP, 1 * target::kWordSize)); // is_tail
|
||||
__ lx(S3, Address(SP, 2 * target::kWordSize)); // epilogue
|
||||
__ lx(T3, Address(SP, 1 * target::kWordSize)); // is_tail
|
||||
__ lx(S2, Address(SP, 2 * target::kWordSize)); // epilogue
|
||||
|
||||
__ lx(A0, Address(SP, 4 * target::kWordSize));
|
||||
__ lx(A1, Address(SP, 5 * target::kWordSize));
|
||||
__ lx(A2, Address(SP, 6 * target::kWordSize));
|
||||
__ lx(A3, Address(SP, 7 * target::kWordSize));
|
||||
__ lx(A4, Address(SP, 8 * target::kWordSize));
|
||||
__ lx(A5, Address(SP, 9 * target::kWordSize));
|
||||
__ lx(A6, Address(SP, 10 * target::kWordSize));
|
||||
__ lx(A7, Address(SP, 11 * target::kWordSize));
|
||||
__ addi(SP, SP, 12 * target::kWordSize);
|
||||
__ PopRegistersAligned(kArgumentRegisterSet, 3 * target::kWordSize);
|
||||
}
|
||||
|
||||
Label tail;
|
||||
__ bnez(S2, &tail, Assembler::kNearJump);
|
||||
__ bnez(T3, &tail, Assembler::kNearJump);
|
||||
|
||||
{
|
||||
__ jalr(T2); // entry_point
|
||||
__ subi(SP, SP, 32); // Not using word size to keep RV32 stack aligned.
|
||||
__ sx(A0, Address(SP, 24));
|
||||
__ sx(A1, Address(SP, 16));
|
||||
__ fsd(FA0, Address(SP, 8));
|
||||
__ fsd(FA1, Address(SP, 0));
|
||||
__ jalr(T2); // entry_point
|
||||
__ PushRegistersAligned(kReturnRegisterSet, 0);
|
||||
__ mv(A0, THR);
|
||||
__ jalr(S3); // DLRT_ExitSyncCallback, etc
|
||||
__ jalr(S2); // DLRT_ExitSyncCallback, etc
|
||||
if (FLAG_target_memory_sanitizer) {
|
||||
__ jalr(A0); // dart_msan_unpoison_retval
|
||||
}
|
||||
__ fld(FA1, Address(SP, 0));
|
||||
__ fld(FA0, Address(SP, 8));
|
||||
__ lx(A1, Address(SP, 16));
|
||||
__ lx(A0, Address(SP, 24));
|
||||
__ addi(SP, SP, 32);
|
||||
__ PopRegisterPair(S2, S3);
|
||||
__ PopRegisterPair(RA, THR);
|
||||
__ PopRegistersAligned(kReturnRegisterSet, 0);
|
||||
__ lx(S2, Address(SP, 0 * target::kWordSize));
|
||||
__ lx(THR, Address(SP, 1 * target::kWordSize));
|
||||
__ lx(FP, Address(SP, 2 * target::kWordSize));
|
||||
__ lx(RA, Address(SP, 3 * target::kWordSize));
|
||||
__ addi(SP, SP, 4 * target::kWordSize);
|
||||
__ ret();
|
||||
}
|
||||
|
||||
@@ -454,9 +439,12 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
__ Bind(&tail);
|
||||
__ jalr(T2); // entry_point
|
||||
__ mv(A0, THR);
|
||||
__ mv(A1, S3);
|
||||
__ PopRegisterPair(S2, S3);
|
||||
__ PopRegisterPair(RA, THR);
|
||||
__ mv(A1, S2);
|
||||
__ lx(S2, Address(SP, 0 * target::kWordSize));
|
||||
__ lx(THR, Address(SP, 1 * target::kWordSize));
|
||||
__ lx(FP, Address(SP, 2 * target::kWordSize));
|
||||
__ lx(RA, Address(SP, 3 * target::kWordSize));
|
||||
__ addi(SP, SP, 4 * target::kWordSize);
|
||||
// Tail-call DLRT_ExitTemporaryIsolate. It is not safe to return to this
|
||||
// stub, since it might be deleted once DLRT_ExitTemporaryIsolate proceeds
|
||||
// enough for VM shutdown.
|
||||
|
||||
@@ -536,23 +536,22 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
const intptr_t shared_stub_start = __ CodeSize();
|
||||
|
||||
// Save THR which is callee-saved.
|
||||
__ EnterFrame(0);
|
||||
__ pushq(THR);
|
||||
__ pushq(R12);
|
||||
__ pushq(R13);
|
||||
|
||||
// 4 = return address, THR, R12, R13
|
||||
// 4 = return address, FP, THR, R12
|
||||
COMPILE_ASSERT(4 == FfiCallbackMetadata::kNativeCallbackTrampolineStackDelta);
|
||||
|
||||
// Save all registers which might hold arguments.
|
||||
__ PushRegisters(kArgumentRegisterSet);
|
||||
|
||||
// Load the thread, verify the callback ID and exit the safepoint.
|
||||
//
|
||||
// We exit the safepoint inside DLRT_GetFfiCallbackMetadata in order to save
|
||||
// code size of this shared stub.
|
||||
{
|
||||
// Save all registers which might hold arguments.
|
||||
__ PushRegistersAligned(kArgumentRegisterSet, 3 * target::kWordSize);
|
||||
COMPILE_ASSERT(RAX != CallingConventions::kArg1Reg);
|
||||
__ movq(CallingConventions::kArg1Reg, RAX);
|
||||
__ movq(CallingConventions::kArg2Reg, RSP);
|
||||
|
||||
#if defined(DART_TARGET_OS_FUCHSIA)
|
||||
// TODO(https://dartbug.com/52579): Remove.
|
||||
@@ -568,25 +567,19 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
FfiCallbackMetadata::kGetFfiCallbackMetadata, RAX);
|
||||
#endif // defined(DART_TARGET_OS_FUCHSIA)
|
||||
|
||||
__ EnterFrame(0);
|
||||
__ ReserveAlignedFrameSpace(3 * target::kWordSize);
|
||||
__ movq(CallingConventions::kArg2Reg, RSP);
|
||||
|
||||
__ CallCFunction(RAX, /*restore_rsp=*/true);
|
||||
__ movq(THR, RAX);
|
||||
|
||||
__ movq(RAX, Address(RSP, 0 * target::kWordSize)); // entry_point
|
||||
__ movq(R12, Address(RSP, 1 * target::kWordSize)); // is_tail
|
||||
__ movq(R13, Address(RSP, 2 * target::kWordSize)); // epilogue
|
||||
__ movq(TMP, Address(RSP, 1 * target::kWordSize)); // is_tail
|
||||
__ movq(R12, Address(RSP, 2 * target::kWordSize)); // epilogue
|
||||
|
||||
__ LeaveFrame();
|
||||
// Restore the arguments.
|
||||
__ PopRegistersAligned(kArgumentRegisterSet, 3 * target::kWordSize);
|
||||
}
|
||||
|
||||
// Restore the arguments.
|
||||
__ PopRegisters(kArgumentRegisterSet);
|
||||
|
||||
Label tail;
|
||||
__ cmpq(R12, Immediate(0));
|
||||
__ cmpq(TMP, Immediate(0));
|
||||
__ j(NOT_ZERO, &tail);
|
||||
|
||||
const RegisterSet return_registers(
|
||||
@@ -597,16 +590,16 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
|
||||
{
|
||||
__ call(RAX); // entry_point
|
||||
__ PushRegisters(return_registers);
|
||||
__ PushRegistersAligned(return_registers, 0);
|
||||
__ movq(CallingConventions::kArg1Reg, THR);
|
||||
__ CallCFunction(R13, /*restore_rsp=*/true); // DLRT_ExitSyncCallback, etc
|
||||
__ CallCFunction(R12, /*restore_rsp=*/true); // DLRT_ExitSyncCallback, etc
|
||||
if (FLAG_target_memory_sanitizer) {
|
||||
__ CallCFunction(RAX, /*restore_rsp=*/true); // dart_msan_unpoison_retval
|
||||
}
|
||||
__ PopRegisters(return_registers);
|
||||
__ popq(R13);
|
||||
__ PopRegistersAligned(return_registers, 0);
|
||||
__ popq(R12);
|
||||
__ popq(THR);
|
||||
__ LeaveFrame();
|
||||
__ ret();
|
||||
}
|
||||
|
||||
@@ -614,10 +607,10 @@ void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() {
|
||||
__ Bind(&tail);
|
||||
__ call(RAX); // entry_point
|
||||
__ movq(CallingConventions::kArg1Reg, THR);
|
||||
__ movq(RAX, R13);
|
||||
__ popq(R13);
|
||||
__ movq(RAX, R12);
|
||||
__ popq(R12);
|
||||
__ popq(THR);
|
||||
__ LeaveFrame();
|
||||
// Tail-call DLRT_ExitTemporaryIsolate. It is not safe to return to this
|
||||
// stub, since it might be deleted once DLRT_ExitTemporaryIsolate proceeds
|
||||
// enough for VM shutdown.
|
||||
|
||||
@@ -341,15 +341,15 @@ class FfiCallbackMetadata {
|
||||
static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 4;
|
||||
#elif defined(TARGET_ARCH_ARM64)
|
||||
static constexpr intptr_t kNativeCallbackTrampolineSize = 8;
|
||||
static constexpr intptr_t kNativeCallbackSharedStubSize = 268;
|
||||
static constexpr intptr_t kNativeCallbackSharedStubSize = 232;
|
||||
static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 4;
|
||||
#elif defined(TARGET_ARCH_RISCV32)
|
||||
static constexpr intptr_t kNativeCallbackTrampolineSize = 8;
|
||||
static constexpr intptr_t kNativeCallbackSharedStubSize = 154;
|
||||
static constexpr intptr_t kNativeCallbackSharedStubSize = 186;
|
||||
static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 4;
|
||||
#elif defined(TARGET_ARCH_RISCV64)
|
||||
static constexpr intptr_t kNativeCallbackTrampolineSize = 8;
|
||||
static constexpr intptr_t kNativeCallbackSharedStubSize = 154;
|
||||
static constexpr intptr_t kNativeCallbackSharedStubSize = 186;
|
||||
static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 4;
|
||||
#else
|
||||
#error What architecture?
|
||||
|
||||
Reference in New Issue
Block a user