[vm] Speed up the ARM simulators.

Cf. 01a7f207c3.

TEST=ci
Change-Id: I8b6f9b827c1725d85013de70a1346303bdd9129e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/283200
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2023-07-21 19:06:43 +00:00 committed by Commit Queue
parent 37581cb79e
commit d29235cdb5
4 changed files with 106 additions and 76 deletions

View file

@ -3478,42 +3478,51 @@ void Simulator::InstructionDecode(Instr* instr) {
}
void Simulator::Execute() {
if (LIKELY(FLAG_stop_sim_at == ULLONG_MAX &&
FLAG_trace_sim_after == ULLONG_MAX)) {
ExecuteNoTrace();
} else {
ExecuteTrace();
}
}
void Simulator::ExecuteNoTrace() {
// Get the PC to simulate. Cannot use the accessor here as we need the
// raw PC value and not the one used as input to arithmetic instructions.
uword program_counter = get_pc();
if (FLAG_stop_sim_at == ULLONG_MAX && FLAG_trace_sim_after == ULLONG_MAX) {
// Fast version of the dispatch loop without checking whether the simulator
// should be stopping at a particular executed instruction.
while (program_counter != kEndSimulatingPC) {
Instr* instr = reinterpret_cast<Instr*>(program_counter);
icount_++;
if (IsIllegalAddress(program_counter)) {
HandleIllegalAccess(program_counter, instr);
} else {
InstructionDecodeImpl(instr);
}
program_counter = get_pc();
}
} else {
// FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
// we reach the particular instruction count or address.
while (program_counter != kEndSimulatingPC) {
Instr* instr = reinterpret_cast<Instr*>(program_counter);
icount_++;
if (icount_ == FLAG_stop_sim_at) {
SimulatorDebugger dbg(this);
dbg.Stop(instr, "Instruction count reached");
} else if (reinterpret_cast<uint64_t>(instr) == FLAG_stop_sim_at) {
SimulatorDebugger dbg(this);
dbg.Stop(instr, "Instruction address reached");
} else if (IsIllegalAddress(program_counter)) {
HandleIllegalAccess(program_counter, instr);
} else {
InstructionDecode(instr);
}
program_counter = get_pc();
// Fast version of the dispatch loop without checking whether the simulator
// should be stopping at a particular executed instruction.
while (program_counter != kEndSimulatingPC) {
Instr* instr = reinterpret_cast<Instr*>(program_counter);
icount_++;
InstructionDecodeImpl(instr);
program_counter = get_pc();
}
}
void Simulator::ExecuteTrace() {
// Get the PC to simulate. Cannot use the accessor here as we need the
// raw PC value and not the one used as input to arithmetic instructions.
uword program_counter = get_pc();
// FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
// we reach the particular instruction count or address.
while (program_counter != kEndSimulatingPC) {
Instr* instr = reinterpret_cast<Instr*>(program_counter);
icount_++;
if (icount_ == FLAG_stop_sim_at) {
SimulatorDebugger dbg(this);
dbg.Stop(instr, "Instruction count reached");
} else if (reinterpret_cast<uint64_t>(instr) == FLAG_stop_sim_at) {
SimulatorDebugger dbg(this);
dbg.Stop(instr, "Instruction address reached");
} else if (IsIllegalAddress(program_counter)) {
HandleIllegalAccess(program_counter, instr);
} else {
InstructionDecode(instr);
}
program_counter = get_pc();
}
}

View file

@ -232,6 +232,8 @@ class Simulator {
// Executes ARM instructions until the PC reaches kEndSimulatingPC.
void Execute();
void ExecuteNoTrace();
void ExecuteTrace();
void ClobberVolatileRegisters();

View file

@ -1894,6 +1894,7 @@ void Simulator::DecodeUnconditionalBranchReg(Instr* instr) {
}
}
DART_FORCE_INLINE
void Simulator::DecodeCompareBranch(Instr* instr) {
if (instr->IsCompareAndBranchOp()) {
DecodeCompareAndBranch(instr);
@ -2400,6 +2401,7 @@ void Simulator::DecodeAtomicMemory(Instr* instr) {
}
}
DART_FORCE_INLINE
void Simulator::DecodeLoadStore(Instr* instr) {
if (instr->IsAtomicMemoryOp()) {
DecodeAtomicMemory(instr);
@ -3703,25 +3705,16 @@ void Simulator::DecodeDPSimd2(Instr* instr) {
}
// Executes the current instruction.
void Simulator::InstructionDecode(Instr* instr) {
DART_FORCE_INLINE
void Simulator::InstructionDecodeImpl(Instr* instr) {
pc_modified_ = false;
if (IsTracingExecution()) {
THR_Print("%" Pu64 " ", icount_);
const uword start = reinterpret_cast<uword>(instr);
const uword end = start + Instr::kInstrSize;
if (FLAG_support_disassembler) {
Disassembler::Disassemble(start, end);
} else {
THR_Print("Disassembler not supported in this mode.\n");
}
}
if (instr->IsDPImmediateOp()) {
if (instr->IsLoadStoreOp()) {
DecodeLoadStore(instr);
} else if (instr->IsDPImmediateOp()) {
DecodeDPImmediate(instr);
} else if (instr->IsCompareBranchOp()) {
DecodeCompareBranch(instr);
} else if (instr->IsLoadStoreOp()) {
DecodeLoadStore(instr);
} else if (instr->IsDPRegisterOp()) {
DecodeDPRegister(instr);
} else if (instr->IsDPSimd1Op()) {
@ -3737,43 +3730,66 @@ void Simulator::InstructionDecode(Instr* instr) {
}
}
void Simulator::InstructionDecode(Instr* instr) {
if (IsTracingExecution()) {
THR_Print("%" Pu64 " ", icount_);
const uword start = reinterpret_cast<uword>(instr);
const uword end = start + Instr::kInstrSize;
if (FLAG_support_disassembler) {
Disassembler::Disassemble(start, end);
} else {
THR_Print("Disassembler not supported in this mode.\n");
}
}
InstructionDecodeImpl(instr);
}
void Simulator::Execute() {
if (LIKELY(FLAG_stop_sim_at == ULLONG_MAX &&
FLAG_trace_sim_after == ULLONG_MAX)) {
ExecuteNoTrace();
} else {
ExecuteTrace();
}
}
void Simulator::ExecuteNoTrace() {
// Get the PC to simulate. Cannot use the accessor here as we need the
// raw PC value and not the one used as input to arithmetic instructions.
uword program_counter = get_pc();
if (FLAG_stop_sim_at == ULLONG_MAX) {
// Fast version of the dispatch loop without checking whether the simulator
// should be stopping at a particular executed instruction.
while (program_counter != kEndSimulatingPC) {
Instr* instr = reinterpret_cast<Instr*>(program_counter);
icount_++;
if (IsIllegalAddress(program_counter)) {
HandleIllegalAccess(program_counter, instr);
} else {
InstructionDecode(instr);
}
program_counter = get_pc();
}
} else {
// FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
// we reach the particular instruction count or address.
while (program_counter != kEndSimulatingPC) {
Instr* instr = reinterpret_cast<Instr*>(program_counter);
icount_++;
if (icount_ == FLAG_stop_sim_at) {
SimulatorDebugger dbg(this);
dbg.Stop(instr, "Instruction count reached");
} else if (reinterpret_cast<uint64_t>(instr) == FLAG_stop_sim_at) {
SimulatorDebugger dbg(this);
dbg.Stop(instr, "Instruction address reached");
} else if (IsIllegalAddress(program_counter)) {
HandleIllegalAccess(program_counter, instr);
} else {
InstructionDecode(instr);
}
program_counter = get_pc();
// Fast version of the dispatch loop without checking whether the simulator
// should be stopping at a particular executed instruction.
while (program_counter != kEndSimulatingPC) {
Instr* instr = reinterpret_cast<Instr*>(program_counter);
icount_++;
InstructionDecodeImpl(instr);
program_counter = get_pc();
}
}
void Simulator::ExecuteTrace() {
// Get the PC to simulate. Cannot use the accessor here as we need the
// raw PC value and not the one used as input to arithmetic instructions.
uword program_counter = get_pc();
// FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
// we reach the particular instruction count or address.
while (program_counter != kEndSimulatingPC) {
Instr* instr = reinterpret_cast<Instr*>(program_counter);
icount_++;
if (icount_ == FLAG_stop_sim_at) {
SimulatorDebugger dbg(this);
dbg.Stop(instr, "Instruction count reached");
} else if (reinterpret_cast<uint64_t>(instr) == FLAG_stop_sim_at) {
SimulatorDebugger dbg(this);
dbg.Stop(instr, "Instruction address reached");
} else if (IsIllegalAddress(program_counter)) {
HandleIllegalAccess(program_counter, instr);
} else {
InstructionDecode(instr);
}
program_counter = get_pc();
}
}

View file

@ -233,12 +233,15 @@ class Simulator {
// Decode instructions.
void InstructionDecode(Instr* instr);
void InstructionDecodeImpl(Instr* instr);
#define DECODE_OP(op) void Decode##op(Instr* instr);
APPLY_OP_LIST(DECODE_OP)
#undef DECODE_OP
// Executes ARM64 instructions until the PC reaches kEndSimulatingPC.
void Execute();
void ExecuteNoTrace();
void ExecuteTrace();
void ClobberVolatileRegisters();