Commit 24a43b3c authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Fix reloading register spilled multiple times

Since register can be used multiple times on the stack, they can also
be spilled into multiple stack slots. At merge points, we then might
have to reload the spilled slots. A DCHECK currently checks that each
register is only loaded once. Instead of failing, just load the first
stack slot, the others are statically known to contain the same value
anyways.

R=ahaas@chromium.org

Bug: v8:6600, chromium:919533
Change-Id: Ic0c806238b2997f006829b4b509a50468a55befa
Reviewed-on: https://chromium-review.googlesource.com/c/1403124Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58676}
parent 49a526ac
......@@ -201,7 +201,12 @@ class StackTransferRecipe {
void LoadStackSlot(LiftoffRegister dst, uint32_t stack_index,
ValueType type) {
DCHECK(!load_dst_regs_.has(dst));
if (load_dst_regs_.has(dst)) {
// It can happen that we spilled the same register to different stack
// slots, and then we reload them later into the same dst register.
// In that case, it is enough to load one of the stack slots.
return;
}
load_dst_regs_.set(dst);
if (dst.is_pair()) {
DCHECK_EQ(kWasmI64, type);
......@@ -216,7 +221,12 @@ class StackTransferRecipe {
void LoadI64HalfStackSlot(LiftoffRegister dst, uint32_t stack_index,
RegPairHalf half) {
DCHECK(!load_dst_regs_.has(dst));
if (load_dst_regs_.has(dst)) {
// It can happen that we spilled the same register to different stack
// slots, and then we reload them later into the same dst register.
// In that case, it is enough to load one of the stack slots.
return;
}
load_dst_regs_.set(dst);
*register_load(dst) = RegisterLoad::HalfStack(stack_index, half);
}
......
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
load('test/mjsunit/wasm/wasm-constants.js');
load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addFunction(undefined, kSig_v_v).addBody([]);
builder.addFunction(undefined, kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 0,
// Stack now contains two copies of the first param register.
// Start a loop to create a merge point (values still in registers).
kExprLoop, kWasmStmt,
// The call spills all values.
kExprCallFunction, 0,
// Break to the loop. Now the spilled values need to be loaded back *into
// the same register*.
kExprBr, 0,
kExprEnd,
kExprDrop
]);
builder.instantiate();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment