mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm] More thoroughly clobber volatile registers in the ARM simulators.
TEST=ci Change-Id: I04336abf00eed29e5301625ab91e63887cdaefbd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250762 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
parent
709c4202b5
commit
6bfe5c4d9b
|
@ -606,6 +606,7 @@ const RegList kAllFpuRegistersList = (1 << kNumberOfFpuRegisters) - 1;
|
|||
// C++ ABI call registers.
|
||||
const RegList kAbiArgumentCpuRegs =
|
||||
(1 << R0) | (1 << R1) | (1 << R2) | (1 << R3);
|
||||
const RegList kAbiVolatileCpuRegs = kAbiArgumentCpuRegs | (1 << IP) | (1 << LR);
|
||||
#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
|
||||
const RegList kAbiPreservedCpuRegs =
|
||||
(1 << R4) | (1 << R5) | (1 << R6) | (1 << R8) | (1 << R10) | (1 << R11);
|
||||
|
|
|
@ -451,9 +451,9 @@ const RegList kAllFpuRegistersList = 0xFFFFFFFF;
|
|||
// C++ ABI call registers.
|
||||
const RegList kAbiArgumentCpuRegs =
|
||||
R(R0) | R(R1) | R(R2) | R(R3) | R(R4) | R(R5) | R(R6) | R(R7);
|
||||
const RegList kAbiVolatileCpuRegs =
|
||||
kAbiArgumentCpuRegs | R(R8) | R(R9) | R(R10) | R(R11) | R(R12) | R(R13) |
|
||||
R(R14) | R(R15) | R(R16) | R(R17);
|
||||
const RegList kAbiVolatileCpuRegs = kAbiArgumentCpuRegs | R(R8) | R(R9) |
|
||||
R(R10) | R(R11) | R(R12) | R(R13) | R(R14) |
|
||||
R(R15) | R(R16) | R(R17) | R(LR);
|
||||
#if defined(DART_TARGET_OS_FUCHSIA)
|
||||
// We rely on R18 not being touched by Dart generated assembly or stubs at all.
|
||||
// We rely on that any calls into C++ also preserve R18.
|
||||
|
|
|
@ -449,8 +449,9 @@ const RegList kAllFpuRegistersList = 0xFFFFFFFF;
|
|||
|
||||
constexpr RegList kAbiArgumentCpuRegs =
|
||||
R(A0) | R(A1) | R(A2) | R(A3) | R(A4) | R(A5) | R(A6) | R(A7);
|
||||
constexpr RegList kAbiVolatileCpuRegs =
|
||||
kAbiArgumentCpuRegs | R(T0) | R(T1) | R(T2) | R(T3) | R(T4) | R(T5) | R(T6);
|
||||
constexpr RegList kAbiVolatileCpuRegs = kAbiArgumentCpuRegs | R(T0) | R(T1) |
|
||||
R(T2) | R(T3) | R(T4) | R(T5) | R(T6) |
|
||||
R(RA);
|
||||
constexpr RegList kAbiPreservedCpuRegs = R(S1) | R(S2) | R(S3) | R(S4) | R(S5) |
|
||||
R(S6) | R(S7) | R(S8) | R(S9) |
|
||||
R(S10) | R(S11);
|
||||
|
|
|
@ -1428,8 +1428,7 @@ void Simulator::SupervisorCall(Instr* instr) {
|
|||
SimulatorRuntimeCall target =
|
||||
reinterpret_cast<SimulatorRuntimeCall>(external);
|
||||
target(arguments);
|
||||
set_register(R0, icount_); // Zap result register from void function.
|
||||
set_register(R1, icount_);
|
||||
ClobberVolatileRegisters();
|
||||
} else if (redirection->call_kind() == kLeafRuntimeCall) {
|
||||
ASSERT((0 <= redirection->argument_count()) &&
|
||||
(redirection->argument_count() <= 5));
|
||||
|
@ -1441,8 +1440,8 @@ void Simulator::SupervisorCall(Instr* instr) {
|
|||
SimulatorLeafRuntimeCall target =
|
||||
reinterpret_cast<SimulatorLeafRuntimeCall>(external);
|
||||
r0 = InvokeLeafRuntime(target, r0, r1, r2, r3, r4);
|
||||
ClobberVolatileRegisters();
|
||||
set_register(R0, r0); // Set returned result from function.
|
||||
set_register(R1, icount_); // Zap unused result register.
|
||||
} else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
|
||||
ASSERT((0 <= redirection->argument_count()) &&
|
||||
(redirection->argument_count() <= 2));
|
||||
|
@ -1454,6 +1453,7 @@ void Simulator::SupervisorCall(Instr* instr) {
|
|||
double d0 = get_dregister(D0);
|
||||
double d1 = get_dregister(D1);
|
||||
d0 = InvokeFloatLeafRuntime(target, d0, d1);
|
||||
ClobberVolatileRegisters();
|
||||
set_dregister(D0, d0);
|
||||
} else {
|
||||
// If we're not doing "hardfp", we must be doing "soft" or "softfp",
|
||||
|
@ -1467,6 +1467,7 @@ void Simulator::SupervisorCall(Instr* instr) {
|
|||
double d0 = bit_cast<double, int64_t>(a0);
|
||||
double d1 = bit_cast<double, int64_t>(a1);
|
||||
d0 = InvokeFloatLeafRuntime(target, d0, d1);
|
||||
ClobberVolatileRegisters();
|
||||
a0 = bit_cast<int64_t, double>(d0);
|
||||
r0 = Utils::Low32Bits(a0);
|
||||
r1 = Utils::High32Bits(a0);
|
||||
|
@ -1482,29 +1483,9 @@ void Simulator::SupervisorCall(Instr* instr) {
|
|||
Dart_NativeFunction target_func =
|
||||
reinterpret_cast<Dart_NativeFunction>(get_register(R1));
|
||||
wrapper(arguments, target_func);
|
||||
set_register(R0, icount_); // Zap result register from void function.
|
||||
set_register(R1, icount_);
|
||||
ClobberVolatileRegisters();
|
||||
}
|
||||
|
||||
// Zap caller-saved registers, since the actual runtime call could have
|
||||
// used them.
|
||||
set_register(R2, icount_);
|
||||
set_register(R3, icount_);
|
||||
set_register(IP, icount_);
|
||||
set_register(LR, icount_);
|
||||
double zap_dvalue = static_cast<double>(icount_);
|
||||
// Do not zap D0, as it may contain a float result.
|
||||
for (int i = D1; i <= D7; i++) {
|
||||
set_dregister(static_cast<DRegister>(i), zap_dvalue);
|
||||
}
|
||||
// The above loop also zaps overlapping registers S2-S15.
|
||||
// Registers D8-D15 (overlapping with S16-S31) are preserved.
|
||||
#if defined(VFPv3_D32)
|
||||
for (int i = D16; i <= D31; i++) {
|
||||
set_dregister(static_cast<DRegister>(i), zap_dvalue);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return.
|
||||
set_pc(saved_lr);
|
||||
} else {
|
||||
|
@ -1525,6 +1506,29 @@ void Simulator::SupervisorCall(Instr* instr) {
|
|||
}
|
||||
}
|
||||
|
||||
void Simulator::ClobberVolatileRegisters() {
|
||||
// Clear atomic reservation.
|
||||
exclusive_access_addr_ = exclusive_access_value_ = 0;
|
||||
|
||||
for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
|
||||
if ((kAbiVolatileCpuRegs & (1 << i)) != 0) {
|
||||
registers_[i] = icount_;
|
||||
}
|
||||
}
|
||||
|
||||
double zap_dvalue = static_cast<double>(icount_);
|
||||
for (int i = D0; i <= D7; i++) {
|
||||
set_dregister(static_cast<DRegister>(i), zap_dvalue);
|
||||
}
|
||||
// The above loop also zaps overlapping registers S2-S15.
|
||||
// Registers D8-D15 (overlapping with S16-S31) are preserved.
|
||||
#if defined(VFPv3_D32)
|
||||
for (int i = D16; i <= D31; i++) {
|
||||
set_dregister(static_cast<DRegister>(i), zap_dvalue);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Handle execution based on instruction types.
|
||||
|
||||
// Instruction types 0 and 1 are both rolled into one function because they
|
||||
|
|
|
@ -233,6 +233,8 @@ class Simulator {
|
|||
// Executes ARM instructions until the PC reaches kEndSimulatingPC.
|
||||
void Execute();
|
||||
|
||||
void ClobberVolatileRegisters();
|
||||
|
||||
// Returns true if tracing of executed instructions is enabled.
|
||||
bool IsTracingExecution() const;
|
||||
|
||||
|
|
|
@ -1711,9 +1711,7 @@ void Simulator::DoRedirectedCall(Instr* instr) {
|
|||
SimulatorRuntimeCall target =
|
||||
reinterpret_cast<SimulatorRuntimeCall>(external);
|
||||
target(*arguments);
|
||||
// Zap result register from void function.
|
||||
set_register(instr, R0, icount_);
|
||||
set_register(instr, R1, icount_);
|
||||
ClobberVolatileRegisters();
|
||||
} else if (redirection->call_kind() == kLeafRuntimeCall) {
|
||||
ASSERT((0 <= redirection->argument_count()) &&
|
||||
(redirection->argument_count() <= 8));
|
||||
|
@ -1729,8 +1727,8 @@ void Simulator::DoRedirectedCall(Instr* instr) {
|
|||
const int64_t r7 = get_register(R7);
|
||||
const int64_t res =
|
||||
InvokeLeafRuntime(target, r0, r1, r2, r3, r4, r5, r6, r7);
|
||||
ClobberVolatileRegisters();
|
||||
set_register(instr, R0, res); // Set returned result from function.
|
||||
set_register(instr, R1, icount_); // Zap unused result register.
|
||||
} else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
|
||||
ASSERT((0 <= redirection->argument_count()) &&
|
||||
(redirection->argument_count() <= 8));
|
||||
|
@ -1746,6 +1744,7 @@ void Simulator::DoRedirectedCall(Instr* instr) {
|
|||
const double d7 = bit_cast<double, int64_t>(get_vregisterd(V7, 0));
|
||||
const double res =
|
||||
InvokeFloatLeafRuntime(target, d0, d1, d2, d3, d4, d5, d6, d7);
|
||||
ClobberVolatileRegisters();
|
||||
set_vregisterd(V0, 0, bit_cast<int64_t, double>(res));
|
||||
set_vregisterd(V0, 1, 0);
|
||||
} else {
|
||||
|
@ -1757,34 +1756,9 @@ void Simulator::DoRedirectedCall(Instr* instr) {
|
|||
Dart_NativeFunction target =
|
||||
reinterpret_cast<Dart_NativeFunction>(get_register(R1));
|
||||
wrapper(arguments, target);
|
||||
// Zap result register from void function.
|
||||
set_register(instr, R0, icount_);
|
||||
set_register(instr, R1, icount_);
|
||||
ClobberVolatileRegisters();
|
||||
}
|
||||
|
||||
// Zap caller-saved registers, since the actual runtime call could have
|
||||
// used them.
|
||||
set_register(NULL, R2, icount_);
|
||||
set_register(NULL, R3, icount_);
|
||||
set_register(NULL, R4, icount_);
|
||||
set_register(NULL, R5, icount_);
|
||||
set_register(NULL, R6, icount_);
|
||||
set_register(NULL, R7, icount_);
|
||||
set_register(NULL, R8, icount_);
|
||||
set_register(NULL, R9, icount_);
|
||||
set_register(NULL, R10, icount_);
|
||||
set_register(NULL, R11, icount_);
|
||||
set_register(NULL, R12, icount_);
|
||||
set_register(NULL, R13, icount_);
|
||||
set_register(NULL, R14, icount_);
|
||||
set_register(NULL, R15, icount_);
|
||||
set_register(NULL, IP0, icount_);
|
||||
set_register(NULL, IP1, icount_);
|
||||
set_register(NULL, R18, icount_);
|
||||
set_register(NULL, LR, icount_);
|
||||
|
||||
// TODO(zra): Zap caller-saved fpu registers.
|
||||
|
||||
// Return.
|
||||
set_pc(saved_lr);
|
||||
} else {
|
||||
|
@ -1792,6 +1766,24 @@ void Simulator::DoRedirectedCall(Instr* instr) {
|
|||
}
|
||||
}
|
||||
|
||||
void Simulator::ClobberVolatileRegisters() {
|
||||
// Clear atomic reservation.
|
||||
exclusive_access_addr_ = exclusive_access_value_ = 0;
|
||||
|
||||
for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
|
||||
if ((kAbiVolatileCpuRegs & (1 << i)) != 0) {
|
||||
registers_[i] = icount_;
|
||||
}
|
||||
}
|
||||
|
||||
for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
|
||||
if ((kAbiVolatileFpuRegs & (1 << i)) != 0) {
|
||||
vregisters_[i].bits.i64[0] = icount_;
|
||||
vregisters_[i].bits.i64[1] = icount_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Simulator::DecodeExceptionGen(Instr* instr) {
|
||||
if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) &&
|
||||
(instr->Bits(21, 3) == 0)) {
|
||||
|
|
|
@ -240,6 +240,8 @@ class Simulator {
|
|||
// Executes ARM64 instructions until the PC reaches kEndSimulatingPC.
|
||||
void Execute();
|
||||
|
||||
void ClobberVolatileRegisters();
|
||||
|
||||
// Returns true if tracing of executed instructions is enabled.
|
||||
bool IsTracingExecution() const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue