[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: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73635}
This commit is contained in:
Andreas Haas 2021-03-24 12:17:58 +01:00 committed by Commit Bot
parent f613ad3871
commit 7d844bdbb0
2 changed files with 56 additions and 1 deletions

View File

@ -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). // Returns the number of inputs processed (1 or 2).
uint32_t ProcessParameter(ValueKind kind, uint32_t input_idx) { uint32_t ProcessParameter(ValueKind kind, uint32_t input_idx) {
const bool needs_pair = needs_gp_reg_pair(kind); const bool needs_pair = needs_gp_reg_pair(kind);
@ -608,7 +616,12 @@ class LiftoffCompiler {
location.AsRegister()); location.AsRegister());
} }
DCHECK(location.IsCallerFrameSlot()); 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); __ LoadCallerFrameSlot(reg, -location.AsCallerFrameSlot(), reg_kind);
return reg; return reg;
}; };

View File

@ -1163,6 +1163,48 @@ WASM_COMPILED_EXEC_TEST(CallRef) {
tester.CheckResult(caller, 47, 5); 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) { WASM_COMPILED_EXEC_TEST(AbstractTypeChecks) {
WasmGCTester tester(execution_tier); WasmGCTester tester(execution_tier);