Commit 7d844bdb authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm][liftoff] Fix reftype parameter handling

LiftoffCompiler::ProcessParameter assumed that by processing parameters
in the order of their index, register parameters get
processed first, and that for processing stack parameters it can already
use all registers as temp registers. This is not true with reference
type parameters, because registers always first get assigned to value
type parameters even when there is a reference type parameter with a
lower index. Because of this incorrect assumption register parameters
were overwritten by reference type parameters on the stack that got
processed first.

With this CL, only those registers get used as temp registers for
reference type parameters that are not used for parameters.

CC=jkummerow@chromium.org, clemensb@chromium.org
R=thibaudm@chromium.org

Bug: v8:11596
Change-Id: I30ed7f073147df0bd81b9ef4d2b2a54d7badc937
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2784560
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73635}
parent f613ad38
......@@ -594,6 +594,14 @@ class LiftoffCompiler {
}
}
constexpr LiftoffRegList RegsUnusedByParams() {
LiftoffRegList regs = kGpCacheRegList;
for (auto reg : kGpParamRegisters) {
regs.clear(reg);
}
return regs;
}
// Returns the number of inputs processed (1 or 2).
uint32_t ProcessParameter(ValueKind kind, uint32_t input_idx) {
const bool needs_pair = needs_gp_reg_pair(kind);
......@@ -608,7 +616,12 @@ class LiftoffCompiler {
location.AsRegister());
}
DCHECK(location.IsCallerFrameSlot());
LiftoffRegister reg = __ GetUnusedRegister(rc, pinned);
// For reference type parameters we have to use registers that were not
// used for parameters because some reference type stack parameters may
// get processed before some value type register parameters.
LiftoffRegister reg = is_reference(reg_kind)
? __ GetUnusedRegister(RegsUnusedByParams())
: __ GetUnusedRegister(rc, pinned);
__ LoadCallerFrameSlot(reg, -location.AsCallerFrameSlot(), reg_kind);
return reg;
};
......
......@@ -1163,6 +1163,48 @@ WASM_COMPILED_EXEC_TEST(CallRef) {
tester.CheckResult(caller, 47, 5);
}
WASM_COMPILED_EXEC_TEST(CallReftypeParameters) {
WasmGCTester tester(execution_tier);
byte type_index = tester.DefineStruct({F(wasm::kWasmI32, true)});
ValueType kRefType{optref(type_index)};
ValueType sig_types[] = {kWasmI32, kRefType, kRefType, kRefType, kRefType,
kWasmI32, kWasmI32, kWasmI32, kWasmI32};
FunctionSig sig(1, 8, sig_types);
byte adder = tester.DefineFunction(
&sig, {},
{WASM_I32_ADD(
WASM_STRUCT_GET(type_index, 0, WASM_LOCAL_GET(0)),
WASM_I32_ADD(
WASM_STRUCT_GET(type_index, 0, WASM_LOCAL_GET(1)),
WASM_I32_ADD(
WASM_STRUCT_GET(type_index, 0, WASM_LOCAL_GET(2)),
WASM_I32_ADD(
WASM_STRUCT_GET(type_index, 0, WASM_LOCAL_GET(3)),
WASM_I32_ADD(
WASM_LOCAL_GET(4),
WASM_I32_ADD(WASM_LOCAL_GET(5),
WASM_I32_ADD(WASM_LOCAL_GET(6),
WASM_LOCAL_GET(7)))))))),
kExprEnd});
byte caller = tester.DefineFunction(
tester.sigs.i_v(), {},
{WASM_CALL_FUNCTION(adder,
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(2),
WASM_RTT_CANON(type_index)),
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(4),
WASM_RTT_CANON(type_index)),
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(8),
WASM_RTT_CANON(type_index)),
WASM_STRUCT_NEW_WITH_RTT(type_index, WASM_I32V(16),
WASM_RTT_CANON(type_index)),
WASM_I32V(32), WASM_I32V(64), WASM_I32V(128),
WASM_I32V(256)),
kExprEnd});
tester.CompileModule();
tester.CheckResult(caller, 510);
}
WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
WasmGCTester tester(execution_tier);
......
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