[maglev] Spill values when freeing a register at-end

DropRegisterAtEnd is used to free a register, to make space for the
result of a node. Normally this frees up an input that is dead at the
end of the node's lifetime, but under high local variable pressure, we
might not have a dead value to drop.

In these cases we have to spill a register through the normal spilling
mechanism. Additionally, allow freeing up a blocked free register (i.e.
a temporary) if this is possible.

Bug: v8:7700
Change-Id: I0099751918cf5cb65c2a09337a3f080eb2c4dd14
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3769833
Reviewed-by: Victor Gomes <victorgomes@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81804}
This commit is contained in:
Leszek Swirski 2022-07-19 10:39:58 +02:00 committed by V8 LUCI CQ
parent cdf548dacc
commit 0ec8f227b6

View File

@ -505,14 +505,17 @@ void StraightForwardRegisterAllocator::AllocateNode(Node* node) {
template <typename RegisterT> template <typename RegisterT>
void StraightForwardRegisterAllocator::DropRegisterValueAtEnd(RegisterT reg) { void StraightForwardRegisterAllocator::DropRegisterValueAtEnd(RegisterT reg) {
RegisterFrameState<RegisterT>& list = GetRegisterFrameState<RegisterT>(); RegisterFrameState<RegisterT>& list = GetRegisterFrameState<RegisterT>();
list.unblock(reg);
if (!list.free().has(reg)) { if (!list.free().has(reg)) {
ValueNode* node = list.GetValue(reg); ValueNode* node = list.GetValue(reg);
// If the is not live after the current node, just remove its value.
if (node->live_range().end == current_node_->id()) { if (node->live_range().end == current_node_->id()) {
node->RemoveRegister(reg); node->RemoveRegister(reg);
list.AddToFree(reg); } else {
DropRegisterValue(list, reg);
} }
list.AddToFree(reg);
} }
list.unblock(reg);
} }
void StraightForwardRegisterAllocator::AllocateNodeResult(ValueNode* node) { void StraightForwardRegisterAllocator::AllocateNodeResult(ValueNode* node) {
@ -1185,7 +1188,14 @@ template <typename RegisterT>
void StraightForwardRegisterAllocator::EnsureFreeRegisterAtEnd() { void StraightForwardRegisterAllocator::EnsureFreeRegisterAtEnd() {
RegisterFrameState<RegisterT>& registers = GetRegisterFrameState<RegisterT>(); RegisterFrameState<RegisterT>& registers = GetRegisterFrameState<RegisterT>();
// If we still have free registers, pick one of those. // If we still have free registers, pick one of those.
if (!registers.free().is_empty()) return; if (!registers.free().is_empty()) {
// Make sure that at least one of the free registers is not blocked; this
// effectively means freeing up a temporary.
if (registers.unblocked_free().is_empty()) {
registers.unblock(registers.free().first());
}
return;
}
// If the current node is a last use of an input, pick a register containing // If the current node is a last use of an input, pick a register containing
// the input. // the input.