[liftoff] Outline spilling and reloading code
The assumption is that {PopToRegister} most often finds a register stack slot (this is backed by data). Hence put all spilling-related code behind no-inline and preserve_most functions. Also, annotate some methods that are supposed to be inlined with V8_INLINE. This is not needed (they were already inlined before), but this documents the intend better. This saves some binary size and seems to also slightly improve performance. R=ahaas@chromium.org Bug: v8:13565, v8:13673 Change-Id: Ib4b8bd361ee19c29221263f6383034933fe7dff5 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4212407 Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/main@{#85629}
This commit is contained in:
parent
c07d8535f8
commit
99936e2de9
@ -678,22 +678,11 @@ LiftoffAssembler::~LiftoffAssembler() {
|
||||
}
|
||||
}
|
||||
|
||||
LiftoffRegister LiftoffAssembler::LoadToRegister(VarState slot,
|
||||
LiftoffRegList pinned) {
|
||||
if (slot.is_reg()) return slot.reg();
|
||||
LiftoffRegister reg = GetUnusedRegister(reg_class_for(slot.kind()), pinned);
|
||||
return LoadToRegister(slot, reg);
|
||||
}
|
||||
|
||||
LiftoffRegister LiftoffAssembler::LoadToRegister(VarState slot,
|
||||
LiftoffRegister reg) {
|
||||
if (slot.is_const()) {
|
||||
LoadConstant(reg, slot.constant());
|
||||
} else {
|
||||
DCHECK(slot.is_stack());
|
||||
Fill(reg, slot.offset(), slot.kind());
|
||||
}
|
||||
return reg;
|
||||
void LiftoffAssembler::LoadToRegister(VarState slot, LiftoffRegList pinned,
|
||||
LiftoffRegister* out_reg) {
|
||||
DCHECK(!slot.is_reg());
|
||||
*out_reg = GetUnusedRegister(reg_class_for(slot.kind()), pinned);
|
||||
LoadToFixedRegister(slot, *out_reg);
|
||||
}
|
||||
|
||||
LiftoffRegister LiftoffAssembler::LoadI64HalfIntoRegister(VarState slot,
|
||||
@ -718,9 +707,7 @@ LiftoffRegister LiftoffAssembler::PeekToRegister(int index,
|
||||
LiftoffRegList pinned) {
|
||||
DCHECK_LT(index, cache_state_.stack_state.size());
|
||||
VarState& slot = cache_state_.stack_state.end()[-1 - index];
|
||||
if (slot.is_reg()) {
|
||||
return slot.reg();
|
||||
}
|
||||
if (V8_LIKELY(slot.is_reg())) return slot.reg();
|
||||
LiftoffRegister reg = LoadToRegister(slot, pinned);
|
||||
cache_state_.inc_used(reg);
|
||||
slot.MakeRegister(reg);
|
||||
@ -1372,11 +1359,10 @@ bool LiftoffAssembler::ValidateCacheState() const {
|
||||
}
|
||||
#endif
|
||||
|
||||
LiftoffRegister LiftoffAssembler::SpillOneRegister(LiftoffRegList candidates) {
|
||||
// Spill one cached value to free a register.
|
||||
LiftoffRegister spill_reg = cache_state_.GetNextSpillReg(candidates);
|
||||
SpillRegister(spill_reg);
|
||||
return spill_reg;
|
||||
void LiftoffAssembler::SpillOneRegister(LiftoffRegList candidates,
|
||||
LiftoffRegister* spilled_reg) {
|
||||
*spilled_reg = cache_state_.GetNextSpillReg(candidates);
|
||||
SpillRegister(*spilled_reg);
|
||||
}
|
||||
|
||||
LiftoffRegister LiftoffAssembler::SpillAdjacentFpRegisters(
|
||||
|
@ -469,15 +469,41 @@ class LiftoffAssembler : public MacroAssembler {
|
||||
explicit LiftoffAssembler(std::unique_ptr<AssemblerBuffer>);
|
||||
~LiftoffAssembler() override;
|
||||
|
||||
LiftoffRegister LoadToRegister(VarState slot, LiftoffRegList pinned);
|
||||
// Load a cache slot to a free register.
|
||||
V8_INLINE LiftoffRegister LoadToRegister(VarState slot,
|
||||
LiftoffRegList pinned) {
|
||||
if (V8_LIKELY(slot.is_reg())) return slot.reg();
|
||||
// TODO(clemensb): Remove this hack once https://reviews.llvm.org/D141020 is
|
||||
// available.
|
||||
std::aligned_storage_t<sizeof(LiftoffRegister), alignof(LiftoffRegister)>
|
||||
reg_storage;
|
||||
LiftoffRegister* out_reg = reinterpret_cast<LiftoffRegister*>(®_storage);
|
||||
LoadToRegister(slot, pinned, out_reg);
|
||||
return *out_reg;
|
||||
}
|
||||
|
||||
LiftoffRegister LoadToRegister(VarState slot, LiftoffRegister dst);
|
||||
// Slow path called for the method above.
|
||||
// TODO(clemensb): Use a return value instead of output parameter once
|
||||
// https://reviews.llvm.org/D141020 is available.
|
||||
V8_NOINLINE V8_PRESERVE_MOST void LoadToRegister(VarState slot,
|
||||
LiftoffRegList pinned,
|
||||
LiftoffRegister* dst);
|
||||
|
||||
LiftoffRegister PopToRegister(LiftoffRegList pinned = {}) {
|
||||
// Load a non-register cache slot to a given (fixed) register.
|
||||
void LoadToFixedRegister(VarState slot, LiftoffRegister reg) {
|
||||
DCHECK(slot.is_const() || slot.is_stack());
|
||||
if (slot.is_const()) {
|
||||
LoadConstant(reg, slot.constant());
|
||||
} else {
|
||||
Fill(reg, slot.offset(), slot.kind());
|
||||
}
|
||||
}
|
||||
|
||||
V8_INLINE LiftoffRegister PopToRegister(LiftoffRegList pinned = {}) {
|
||||
DCHECK(!cache_state_.stack_state.empty());
|
||||
VarState slot = cache_state_.stack_state.back();
|
||||
cache_state_.stack_state.pop_back();
|
||||
if (slot.is_reg()) {
|
||||
if (V8_LIKELY(slot.is_reg())) {
|
||||
cache_state_.dec_used(slot.reg());
|
||||
return slot.reg();
|
||||
}
|
||||
@ -488,7 +514,7 @@ class LiftoffAssembler : public MacroAssembler {
|
||||
DCHECK(!cache_state_.stack_state.empty());
|
||||
VarState slot = cache_state_.stack_state.back();
|
||||
cache_state_.stack_state.pop_back();
|
||||
if (slot.is_reg()) {
|
||||
if (V8_LIKELY(slot.is_reg())) {
|
||||
cache_state_.dec_used(slot.reg());
|
||||
if (slot.reg() == reg) return;
|
||||
if (cache_state_.is_used(reg)) SpillRegister(reg);
|
||||
@ -496,7 +522,7 @@ class LiftoffAssembler : public MacroAssembler {
|
||||
return;
|
||||
}
|
||||
if (cache_state_.is_used(reg)) SpillRegister(reg);
|
||||
LoadToRegister(slot, reg);
|
||||
LoadToFixedRegister(slot, reg);
|
||||
}
|
||||
|
||||
// Use this to pop a value into a register that has no other uses, so it
|
||||
@ -576,7 +602,7 @@ class LiftoffAssembler : public MacroAssembler {
|
||||
cache_state_.stack_state.emplace_back(kind, NextSpillOffset(kind));
|
||||
}
|
||||
|
||||
void SpillRegister(LiftoffRegister);
|
||||
V8_NOINLINE V8_PRESERVE_MOST void SpillRegister(LiftoffRegister);
|
||||
|
||||
uint32_t GetNumUses(LiftoffRegister reg) const {
|
||||
return cache_state_.get_use_count(reg);
|
||||
@ -621,13 +647,19 @@ class LiftoffAssembler : public MacroAssembler {
|
||||
LiftoffRegister GetUnusedRegister(LiftoffRegList candidates) {
|
||||
DCHECK(!cache_state_.frozen);
|
||||
DCHECK(!candidates.is_empty());
|
||||
if (cache_state_.has_unused_register(candidates)) {
|
||||
if (V8_LIKELY(cache_state_.has_unused_register(candidates))) {
|
||||
return cache_state_.unused_register(candidates);
|
||||
}
|
||||
if (cache_state_.has_volatile_register(candidates)) {
|
||||
return cache_state_.take_volatile_register(candidates);
|
||||
}
|
||||
return SpillOneRegister(candidates);
|
||||
// TODO(clemensb): Remove this hack once https://reviews.llvm.org/D141020 is
|
||||
// available.
|
||||
std::aligned_storage_t<sizeof(LiftoffRegister), alignof(LiftoffRegister)>
|
||||
reg_storage;
|
||||
LiftoffRegister* out_reg = reinterpret_cast<LiftoffRegister*>(®_storage);
|
||||
SpillOneRegister(candidates, out_reg);
|
||||
return *out_reg;
|
||||
}
|
||||
|
||||
// Performs operations on locals and the top {arity} value stack entries
|
||||
@ -1655,7 +1687,11 @@ class LiftoffAssembler : public MacroAssembler {
|
||||
private:
|
||||
LiftoffRegister LoadI64HalfIntoRegister(VarState slot, RegPairHalf half);
|
||||
|
||||
V8_NOINLINE LiftoffRegister SpillOneRegister(LiftoffRegList candidates);
|
||||
// Spill one of the candidate registers.
|
||||
// TODO(clemensb): Use return value instead of output parameter once
|
||||
// https://reviews.llvm.org/D141020 is available.
|
||||
V8_NOINLINE V8_PRESERVE_MOST void SpillOneRegister(
|
||||
LiftoffRegList candidates, LiftoffRegister* spilled_reg);
|
||||
// Spill one or two fp registers to get a pair of adjacent fp registers.
|
||||
LiftoffRegister SpillAdjacentFpRegisters(LiftoffRegList pinned);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user